Check whether points are inside a polyline curve in Grasshopper with C#

Let’s say you have a polyline in Grasshopper. You also have some points, some of them inside the curve and some of them outside. You want to sort the points depending on whether they are inside or outside the curve.

This component allows you to do that. Input your polyline and your points to check. The ‘A’ list will contain the points inside the curve, and the ‘B’ list will contain the points outside the curve.

inside-curve-component

This will then produce the following output:

A check in Grasshopper to test whether points are inside a polyline curve

Download component

The following component is a user object that allows the input of a single polyline.



If you are working with multiple polylines, and want to check that points are inside or outside every polyline at once, have a look at this file instead.

Source code

If you prefer, you can use the source code directly from below. It is formatted for the C# component in Grasshopper, though of course it can be easily generalised.

private void RunScript(List<Point3d> pts, Polyline crv, ref object A, ref object B)
  {

    var inside = new List<Point3d>();
    var outside = new List<Point3d>();

    foreach (Point3d pt in pts)
    {
      if(IsInside(pt, crv))
      {
        inside.Add(pt);
      }
      else outside.Add(pt);
    }
    A = inside;
    B = outside;

  }

  // <Custom additional code> 

  bool IsInside (Point3d pt, Polyline crv)
  {
    Point3d pt1, pt2;
    bool oddNodes = false;

    for (int i = 0; i < crv.SegmentCount; i++) //for each contour line
    {

      pt1 = crv.SegmentAt(i).From; //get start and end pt
      pt2 = crv.SegmentAt(i).To;

      if ( (pt1[1] < pt[1] && pt2[1] >= pt[1] || pt2[1] < pt[1] && pt1[1] >= pt[1]) && (pt1[0] <= pt[0] || pt2[0] <= pt[0]) ) //if pt is between pts in y, and either of pts is before pt in x
        oddNodes ^= ( pt2[0] + (pt[1] - pt2[1]) * (pt1[0] - pt2[0]) / (pt1[1] - pt2[1]) < pt[0] ); //^= is xor
      //end.X + (pt-end).Y   * (start-end).X  /(start-end).Y   <   pt.X
    }


    if (!oddNodes)
    {
      double minDist = 1e10;
      for (int i = 0; i < crv.SegmentCount; i++) {
        Point3d cp = crv.SegmentAt(i).ClosestPoint(pt, true);
        //Point3d cp = mvContour[i].closestPoint(pt);
        //minDist = min(minDist, cp.distance(pt));
        minDist = Math.Min(minDist, cp.DistanceTo(pt));
      }
      if (minDist < 1e-10)
        return true;
    }

    if(oddNodes) return true;

    return false;
  }
4 Comments

Add a Comment

Your email address will not be published. Required fields are marked *

Time limit is exhausted. Please reload CAPTCHA.