[Q] What i the best possible way to project points on to meshes using RhinoCommon?

I tried to use ProjectPointsToMeshes - but i quickly found out that it gives me all possible intersections instead of the first hit only (and there’s no option to pick how many hits i want to listen to) so i tried ProjectPointsToMeshesEx but here again i found out there’s no difference if ill pass for eg. Z dir or -Z dir and point indices don’t help much here to find out which point was first hit - besides i found out that indices correspond for each point hit but in reverse so first hit is always last - so i got lost how to use this here …

Closest point and pull points aren’t an option cause i need parallel projection on to mesh guided by axis.

Tried RayShoot but of course it doesn’t support meshes and finally there’s mesh ray but it returns only info if ray hit something.

Wanted to ask if somebody have idea how to achieve this before i’ll start writing own method for that from groundup.

Again in short i’m interested in red points:

Hi @D-W,

Basically, the Intersection.ProjectPointsToMeshes function does a bunch of mesh-line intersections that you can do, on your own, using Intersection.MeshLine.

After detecting the an intersecting, check the distance to each intersection point and keep the closest ones.

– Dale

Dale,

how i should determine half infinity line from point to satisfy MeshLine method ? Line has constructor of point and span of vector but when vector is unitzed line becomes only 1 unit long ? Oh i see theres another one with direction and length - however setting Line with length of infinity gives me not valid line.

Hi @D-W,

I could calculate the bounding box of the meshes you intend to intersect. Then, calculate a line that extends through the bounding box using a function like this:

/// <summary>
/// Find a colinear line that extends through a box.
/// </summary>
/// <param name="line">The original line.</param>
/// <param name="box">The box to extend through.</param>
/// <param name="outLine">The extended line</param>
/// <returns>true if successful, false otherwise.</returns>
private static bool ExtendLineThroughBox(Line line, BoundingBox box, out Line outLine)
{
  outLine = new Line();

  if (line.Length < RhinoMath.SqrtEpsilon)
    return false;

  var dir = line.Direction;
  dir.Unitize();

  var plane = new Plane(line.From, dir);

  var points = box.GetCorners();
  var min_distance = plane.DistanceTo(points[0]);
  var max_distance = min_distance;

  for (var i = 1; i < points.Length; i++)
  {
    var distance = plane.DistanceTo(points[i]);
    if (distance < min_distance)
      min_distance = distance;
    else if (distance > max_distance)
      max_distance = distance;
  }

  // +- 1.0 makes the line a little bigger than the box
  outLine.From = line.From + dir * (min_distance - 1.0);
  outLine.To = line.To + dir * (max_distance + 1.0);

  return true;
}

Use this extended line as the input to Intersection.MeshLine.

var box = mesh.GetBoundingBox(false);
var line = new Line(point, point + dir);

var rc = ExtendLineThroughBox(line, box, out Line out_line);
if (rc)
{
  int[] faceIds;
  var points = Intersection.MeshLine(mesh, line, out faceIds);
  // TODO...
}

– Dale

Thanks for tips. Yes bbox was the first thing where i tried however i prefer more condensed code and i made this like this:

        BoundingBox totalBb = new BoundingBox();
        Mesh mergedMesh = new Mesh();

        foreach (var msh in mshList)
        {
            totalBb.Union(msh.GetBoundingBox(false));
            mergedMesh.Append(msh);
        }

… and later …
var hits = Rhino.Geometry.Intersect.Intersection.MeshLine(mergedMesh, new Line(point, dir, totalBb.Diagonal.Length), out fid);

[Edit] And if points are far away there also could be sth like that:
var lineLength = pt.DistanceTo(totalBb.Center) + totalBb.Diagonal.Length;