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.
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;
}