 # Find point in a particular distance

Hi,
Greetings!
I have a problem, I need to find a point in a particular distance

example:
consider a curve which has points on it Consider this point on the curve, lets call A Suppose if i need to find all the points which are at a distance of 8mm to 11 mm, but along the curve like this but though the point D satisfy the condition, I dont want to be my output,
My expected output would be a list [B,C] This article would help to find length of points along curve: Get distance between 2 points on line

My input would be list of guids of all point and guid of point A, expected output to be guid of Point B and Point C

Requesting help from all on the forum

curve_with_equidistant_pts.stp (21.3 KB)

@Mahdiyar @pascal @Helvetosaur @diff-arch

I hope this help:

``````import rhinoscriptsyntax as rs
import Rhino.Geometry as rg
def disOnCrv(crv, pt1, pt2):
a = rs.CurveClosestPoint(crv, pt1)
b = rs.CurveClosestPoint(crv, pt2)
if a > b:
a , b = b , a
distance = rg.Curve.GetLength(rs.coercecurve(crv), rg.Interval(a, b))
return min(distance, rs.CurveLength(crv) - distance)

crv = rs.GetCurveObject("Curve")
pts = rs.GetObjects("All Points", rs.filter.point)
ptA = rs.GetObject("Point A", rs.filter.point)
minimum = rs.GetReal("minimum")
maximum = rs.GetReal("maximum")
indexes = []
for i in range(len(pts)):
d = disOnCrv(crv, ptA, pts[i])
if d >= minimum and d <= maximum:
indexes.append(i)
print indexes
rs.SelectObjects(pts[min(indexes): max(indexes)])
``````

Sumukha.py (741 Bytes)

Hi @Mahdiyar ,
The program behaves differently when chosen different starting point (ptA). Please let me know how i can tackle it.

Hello,

Did you know you can do this:

``````if minimum <= d <= maximum:
indexes.append(i)
``````

for even greater readability For more thinking on comparisons read here

1 Like
``````import rhinoscriptsyntax as rs
import Rhino.Geometry as rg
def disOnCrv(crv, pt1, pt2):
a = rs.CurveClosestPoint(crv, pt1)
b = rs.CurveClosestPoint(crv, pt2)
if a > b:
a , b = b , a
distance = rg.Curve.GetLength(rs.coercecurve(crv), rg.Interval(a, b))
return distance

crv = rs.GetCurveObject("Curve")
pts = rs.GetObjects("All Points", rs.filter.point)
ptA = rs.GetObject("Point A", rs.filter.point)
minimum = rs.GetReal("minimum")
maximum = rs.GetReal("maximum")
indexes = []
for i in range(len(pts)):
d = disOnCrv(crv, ptA, pts[i])
if minimum <= d <= maximum:
indexes.append(i)
print indexes
rs.SelectObjects(pts[min(indexes): max(indexes)])
``````

Sumuk.py (711 Bytes)

Hi @sumuk, my guess it you need to move the (closed) curve seam to your test point and make sure to pass in the parameters to build the domain for measuring the two lengths along the curve in increasing order. Then take the shorter length of both. If the length is larger than 8 and smaller than 11, the search point is within the required distance.

@Mahdiyar, i think your example only can work if the curve is properly parameterized and the seam is very close to the test point.
_
c.

find_pts.gh (9.9 KB)

Hi @sumuk,
Here is a sample using Rhinocommon which seems to work for all cases, at least in your given example. To avoid errors when close to the seam, the curve is copied in memory and the seam is moved away from the picked point, if needed.
See if this helps:

``````import Rhino
import scriptcontext as sc

def findPointsOnCurveByDistance():

# set distance
dMinDistance = 8
dMaxDistance = 11

# get tolerance from document
dTol = sc.doc.ModelAbsoluteTolerance

# empty list to hold points that match distance
arrPtsFound = []

# get point
rc, objRef = Rhino.Input.RhinoGet.GetOneObject("Pick start point on curve", False, Rhino.DocObjects.ObjectType.Point)
if rc != Rhino.Commands.Result.Success: return rc

ptPicked = objRef.Point().Location

# get curve
rc, objRef = Rhino.Input.RhinoGet.GetOneObject("Pick curve", False, Rhino.DocObjects.ObjectType.Curve)
if rc != Rhino.Commands.Result.Success: return rc

crvPicked = objRef.Curve()

# duplicate curve, as we might move its seam
crv = crvPicked.DuplicateCurve()

# test if closed
if crv.IsClosed:
# test if ptPicked is too close to the curve seam
if ptPicked.DistanceTo(crv.PointAtStart) <= dMaxDistance:
# change the seam, as this curve is just a copy, this is safe to do
crv.ChangeClosedCurveSeam(crv.Domain.Mid)

# get all points
rc, arrObjRefs = Rhino.Input.RhinoGet.GetMultipleObjects("Pick all points", False, Rhino.DocObjects.ObjectType.Point)
if rc != Rhino.Commands.Result.Success:
return rc

arrPtPicked = [obj.Point().Location for obj in arrObjRefs]

# determine length parameter of ptPicked along the curve
bSuccess, dPickedParam = crv.ClosestPoint(ptPicked, dTol)
if not bSuccess:
print "ERROR: Picked point was not on the picked curve!"
return Rhino.Commands.Result.Failure
dPickedLength = crv.GetLength(Rhino.Geometry.Interval(crv.Domain.Min, dPickedParam))

# iterate over all points
for pt in arrPtPicked:
# skip the picked point
if pt.EpsilonEquals(ptPicked, dTol): continue

# determine length parameter of pt along the curve
_, dParam = crv.ClosestPoint(pt, dTol)
dLength = crv.GetLength(Rhino.Geometry.Interval(crv.Domain.Min, dParam))

# check if dLength is close to dPickedLength
dDistanceToPicked = abs(dPickedLength - dLength)
if dMinDistance <= dDistanceToPicked <= dMaxDistance:
arrPtsFound.append(pt)

# add found points to doc
for pt in arrPtsFound: