Haha, it doesn’t represent a distance, just the index of the closest point.
First, we instantiate/create a point cloud that excludes the first point - hence
points[1:] -, which means get everything from
points starting at index 1. It’s called list slicing in Python.
We exclude the first index because, for each iteration of the
for loop, we first delete index 0 of the point cloud, to avoid the closest neighbor search to find the “real” closest point, because we want the second closest. However, the first iteration iteration is an exception. Here we’d have to delete index 0 and index 1. This could also be done with an
if statement inside the
for loop, but I find this more elegant. At the very first iteration, we have to delete index 0 to prevent the closest neighbor search to find
i is 0, meaning itself. The iterations after that, this isn’t a problem, because we already removed the current point with
pt_cloud.RemoveAt(0) at the previous iteration.
Your absolutely right that
pt_cloud is a sacrificial container, from which we delete items that we don’t need anymore.
for loop, we go through all the previously, sequentially by distance sorted points one by one.
First, we check if the point cloud has less than or equal to 1 point and if so break out of the entire loop. This is necessary because we need at least two points! The first one would be removed from the point cloud during the following step, and the second one would be the only possible second closest neighbor to the current point
As you noted correctly, now we search for a second closest point, but
pt_cloud.ClosestPoint(Points[i]) returns the index of the closest point in the point cloud, which is fine!
We don’t really need a distance, since only the second closest neighbor can be found in the first place. Remember, we removed the closest neighbor before, with
points[i] can’t find itself, because it was removed at the previous iteration or for
i is 0, already omitted while creating the point cloud.
All that remains, is to check whether
closest is greater than -1, because
pt_cloud.ClosestPoint(Points[i]) return -1, in case it didn’t find a closest point.
closest is a valid index, we append the closest point from the point cloud to the
sec_closest_pts is returned from the function.
return keyword is used to return data from a function or method. A method is also a function, but lives inside a class.
def add(a, b):
return a + b
result = add(1, 4) # result is 5
def add(a, b):
r = a + b
result = add(1, 4) # result is None
If you want to get something out of a function, you need to
return it at the end or even a strategic place inside the function. You can read more about
if __name__ == "__main__": executes the code after it, only if the Python file itself is run. If it is for instance executed as a part of another Python script, the code from the
if statement is not run.
It’s a nice convention to use it in Python, but not really necessary in the context of GHPython.
You can read up on it here, if you’re interested.
For GHPython and Rhino.Python, you can find some great resources here. There’s also a great variety of Grasshopper specific Python tutorials on YouTube.
For learning Python in general you should visit this site.
I just noticed a typo!!
closest = pt_cloud.ClosestPoint(Points[i]) should be lower case, like this
closest = pt_cloud.ClosestPoint(points[i]).
It still works because the input
Points is a global variable, but should be corrected to prevent future errors.