Closest Points in RhinoCommon/C#

Hi,
I was trying to recreate the closest Point component in c#.

It works for 1 Point as Attractor. How do I need to change for appying more than one?
Or is should it be done with a PointCloud? In this case, how do I get the distances? when the PointCloud is returning just the index of the closest point?

Thanks in advance!

file:closestPoints.gh (14.5 KB)

To find the (distance to the) closest point in a collection of points, you’d have to do something like this:

double minDistance = double.MaxValue;
for (int i = 0; i < points.Count; i++) 
// you could also use a foreach loop if you don't care about indices)
{
  double localDistance = locus.DistanceTo(points[i]);
  minDistance = Math.Min(minDistance, localDistance);
}
return minDistance;

However in RhinoCommon this functionality is readily available from the Point3dList class as ClosestIndex, ClosestIndexInList and ClosestPointInList. The latter two methods are static, meaning you can use them on other collections, such as List<Point3d>, Point3d[], ImmutableArray<Point3d>, etc.

Best to stay away from PointClouds in Grasshopper.

hi David,

thanks for explaining about the rhinoCommon.
I apologize for explaining myself badly!
My aim was repeating following in c# :


With one point as attractor I was able to reproduce, but I have no idea how it works with more than one.
I thought it was maybe a averaging of the points, but I couldnt find it out,
Maybe you could give me a hint. Would be really apreciated.

Thanks and nice monday!

Still the same code. It doesn’t matter how many points you’re measuring the distance to. You just have to iterate over all your points in the population, which is what you’re doing with the Closest Point component too. As you’ll see, the P input is of type ITEM and the C input (your attractors) are of type LIST.

Hi,

Sorry for asking again, but I am not able to apply the code.
I think I dont understand you well, my attempt harvests 200 Points now because of iterating 2 times over it.
Thanks again!


file:clPts.gh (6.8 KB)

You are missing parts of Davids code.

double minDistance = double.MaxValue;

minDistance = Math.Min(minDistance, localDistance);

Hi @Michael_Pryor,

you are right, I was trying out things and didnt placed the lines back, but even with them I have 200 distances.

Don’t build a list of all distance, just keep the smallest distance and output that single number.
Delete your distances variable and use A = minDistance after the loop.

oh I am so Sorry!

Thanks again ! I need to understand it completly. I just didnt!

Thanks!

Hi @DavidRutten,

Your code works really well.
But I wonder how to remap that value to specific range that I want (lets say from 0 to 1)?

Thanks,

In that case also keep track of the biggest distance. When your loop is done and you know both D_{min} and D_{max}, just divide the two to get a normalised value: D_{norm}=\frac{D_{min}}{D_{max}}

Hi David,

When I remap minDistance and compare it with normal value (minDistance/maxDistance), the result doesn’t look the same. Is there any way to get the min and max value from minDistance?

double minDistance = double.MaxValue;
double maxDistance = double.MinValue;

for(int i = 0; i < attrPts.Count; i++)
{
  double localDistance = attrPts[i].DistanceTo(pts);
  minDistance = Math.Min(minDistance, localDistance);
  maxDistance = Math.Max(maxDistance, localDistance);
}

double normalVal = minDistance / maxDistance;


A = normalVal;
B = minDistance;

Thanks,

Surely you’re not comparing the same numbers here? Inside the script you’re running the logic on the lists if points. Outside the script you’re taking only the results of the iterations into account. Those are wholly different number sets.

Hi David,

Sorry, I forgot to reply your message. my bad!

Thanks for the info, I will dig again my old code.

Thanks!

Can you please share the code, I can’t find it here.

thank you