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")[0]
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)])
Hi @Mahdiyar ,
Thank you for the reply,
The program behaves differently when chosen different starting point (ptA). Please let me know how i can tackle it.
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")[0]
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)])
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.
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()