 # Find shortest lines between curve points and mesh face centers with GHPython?

hi everyone
I create lines between the centroid(each face) and some point on mesh with limited distance.
my problem is, to some point created more 1 line and want shortest one,
anybody have an idea to help me?

model_point.gh (8.2 KB)model.3dm (64.3 KB)

To find the shortest line use sort list and choose the first item

1 Like

Here’s a purely pythonic version, if you’re interested.

It uses the RTree algorithm to first find the closest mesh face centers for each curve division point. The shortest distance between these face centers and the individual curve division point is then evaluated. A line is drawn for the shortest distance only. However, other than in @seghierkhaled’s solution, only one closest line gets drawn, when multiple potential connections have the same distance, and thus no clear closest one is discernible.

This is what the script looks like:

``````import Rhino.Geometry as rg
import Grasshopper as gh

# Get the curve division points (including the end points)
crv_points = [Curve.PointAt(t) for t in Curve.DivideByCount(Count, True)]

# Get the mesh face centers
face_centers = [Mesh.Faces.GetFaceCenter(i) for i in xrange(Mesh.Faces.Count)]

# Initialise an RTree
rtree = rg.RTree()

# Populate the RTree with the mesh face centers and indices
for i, center_pt in enumerate(face_centers):
rtree.Insert(center_pt, i)

# Evaluate the closest lines from each curve point to a mesh face center
lines = []
for pt in crv_points:
# Find the closest mesh faces within the search radius
closest_faces = [] # indices of closest faces
rtree_callback = lambda sender, args: closest_faces.append(args.Id)
rtree.Search(search_sphere, rtree_callback)
# Find the closest line
if len(closest_faces) > 0:
dists = [pt.DistanceTo(face_centers[i]) for i in closest_faces]
sorted_faces = [f for _, f in sorted(zip(dists, closest_faces))]
closest_line = rg.Line(pt, face_centers[sorted_faces])
lines.append(gh.Kernel.Types.GH_Line(closest_line))

# Outputs
a = lines
``````

And here’s the GH file:
model_point_v3.gh (7.2 KB)

1 Like

thank you for your reply. I need to lines that is shortest from point on mesh to centroid but some line in this way did not include the result.

thank you so much. it’s awesome. any way exist to assign number of the line created to centroid?

You’re welcome. Outside of the GHPython component you can get the face center with the End (End Points) component. The centroids are the end points of the lines, since these were drawn from the curve points to the face centers.

In Python, you can do the following:

``````import Rhino.Geometry as rg
import Grasshopper as gh

# Get the curve division points (including the end points)
crv_points = [Curve.PointAt(t) for t in Curve.DivideByCount(Count, True)]

# Get the mesh face centers
face_centers = [Mesh.Faces.GetFaceCenter(i) for i in xrange(Mesh.Faces.Count)]

# Initialise an RTree
rtree = rg.RTree()

# Populate the RTree with the mesh face centers and indices
for i, center_pt in enumerate(face_centers):
rtree.Insert(center_pt, i)

# Evaluate the closest lines from each curve point to a mesh face center
lines = []
faces = [] # face indices connected to by lines
for pt in crv_points:
# Find the closest mesh faces within the search radius
closest_faces = [] # indices of closest faces
rtree_callback = lambda sender, args: closest_faces.append(args.Id)
rtree.Search(search_sphere, rtree_callback)
# Find the closest line
if len(closest_faces) > 0:
dists = [pt.DistanceTo(face_centers[i]) for i in closest_faces]
sorted_faces = [f for _, f in sorted(zip(dists, closest_faces))]
closest_line = rg.Line(pt, face_centers[sorted_faces])
lines.append(gh.Kernel.Types.GH_Line(closest_line))
faces.append(sorted_faces)

# # Outputs
a = lines
b = [face_centers[f] for f in faces] # centroids
c = [f for f in faces] # face indices
``````

Yes, simply delete the line `crv_points = [Curve.PointAt(t) for t in Curve.DivideByCount(Count, True)]`, and substitute the line `for pt in crv_points:` with `for pt in >name_or_your_points_input<`.