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.
This will then produce the following output:
Download component
The following component is a user object that allows the input of a single polyline.
Points inside curve (Grasshopper user object component)
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; }
is there a similar component for multiple curves input? (i.e. list A returns points contained inside curves, list B returns points outside curves)
One solution would be to modify the code above slightly. You could add another loop which cycles through a list of curves. Something like:
int insideCount = 0;
foreach (var crv in curves)
{
if(IsInside(pt, crv)) insideCount++;
}
if(insideCount == curves.Count) inside.Add(pt);
if(insideCount == 0) outside.Add(pt);
This would go inside the foreach(Point3d pt in pts) brackets.
Thank you James. It’s very interesting. I have no programming notions though, so just in case it’s easy could you please provide me the edited code? Or give me hints on where to paste your new cycle. Thanks a lot
Just had a play. Take a look at this…
http://james-ramsden.com/download/check-whether-points-are-inside-polyline-curves-in-grasshopper/