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:
sc.doc.Objects.AddPoint(pt)
# redraw the views
sc.doc.Views.Redraw()
if __name__ == "__main__":
findPointsOnCurveByDistance()