# How to order a list of curves. Ideas?

Could anyone suggest an algorithm to arrange a set of curves where each curve is intersected only by two others in that list. I need to order this list like this:

even if drag-selecting them or selecting in scrambled order.

Not sure but my logic would be:
Pick one curve,
Find intersection with the rest
Gives two resulting curves,
Pick one of them and repeat, this gives you again two intersections but this time with curve 0 and another. Pick the other
Repeat â†’ gives intersection with curve 1 and another. Etc.

1 Like

How many curves per operation? How many operations?

in fact if you remove the intersected curve from the list each time then only one intersection will be found each time - the one you are looking for.

1 Like

not if you select the curves randomly you wonâ€™t

This is what I have so far:

``````############################
### ORDER LIST OF CURVES ###
############################
import System
import rhinoscriptsyntax as rs
import scriptcontext as sc
import Rhino
import time

tol = sc.doc.ModelAbsoluteTolerance

def order_curves(curves_ids = None):

if curves_ids == None:
curves_ids = rs.GetObjects("get curves: ",rs.filter.curve)
if curves_ids == None:return
curves = [rs.coercecurve(id) for id in curves_ids if id is not None]

tmp_curve_list = []

for i in range(-1,len(curves)-1):
#print curves[i]
curve_0 = curves[i-1]
curve_1 = curves[i]
curve_2 = curves[i+1]

if not curve_0 or not curve_1 or not curve_2: return

# Calculate the intersection
intersection_tolerance = tol
overlap_tolerance = 0.0
insect_event_01 = Rhino.Geometry.Intersect.Intersection.CurveCurve(curve_0, curve_1, intersection_tolerance, overlap_tolerance)
insect_event_12 = Rhino.Geometry.Intersect.Intersection.CurveCurve(curve_1, curve_2, intersection_tolerance, overlap_tolerance)
if insect_event_01.Count == 1:
if curve_0 not in tmp_curve_list:
tmp_curve_list.append(curve_0)
#print tmp_curve_list
#print len(tmp_curve_list)

if __name__ == "__main__":
ts = time.time()
#rs.EnableRedraw(False)

order_curves()

print "Elapsed time is {:.2f}".format(time.time()-ts)

``````

If the time taken is significant then you could wrap your logic in a `while curves:` loop, use `curves.pop()` to get the first curve, then search for an intersection, remove that curve, repeat until there are no more curves, your while loop exitsâ€¦

This avoids searching the whole list multiple times

1 Like

good idea @Dancergraham, thanks,

Iâ€™ll try it out, hope I wonâ€™t crash rhino with the while loop

1 Like

stupid +=1
if stupid >â€¦:
break

2 Likes

This seems to work:

``````############################
### ORDER LIST OF CURVES ###
############################
import System
import rhinoscriptsyntax as rs
import scriptcontext as sc
import Rhino
import time

tol = sc.doc.ModelAbsoluteTolerance

def order_curves_gk(curves_ids = None):

intersection_tolerance = tol
overlap_tolerance = 0.0

curves = [rs.coercecurve(id) for id in curves_ids if id is not None]
curve0 = curves.pop()
index = 0

while curves:
for i, curve1 in enumerate(curves):
insect_event = Rhino.Geometry.Intersect.Intersection.CurveCurve(curve0, curve1, intersection_tolerance, overlap_tolerance)
if insect_event.Count:
index += 1
curve0 = curves.pop(i)

break

if __name__ == "__main__":
curves_ids = rs.GetObjects("get curves: ",rs.filter.curve)

ts = time.time()
#rs.EnableRedraw(False)

order_curves_gk(curves_ids)

print "Elapsed time is {:.2f}".format(time.time()-ts)``````
2 Likes

Thanks @Dancergraham, thatâ€™s awesome

Another alternative. Not the most elegant but seems to work here and is OOPy-ish:

``````import Rhino as R
import rhinoscriptsyntax as rs
import scriptcontext as sc

def __init__(self, guid):
self.guid = guid
self.curve = rs.coercecurve(self.guid)
self.index = None

isect = R.Geometry.Intersect.Intersection.CurveCurve(self.curve, link.curve, sc.doc.ModelAbsoluteTolerance, sc.doc.ModelAbsoluteTolerance)
if isect:

def make_label(self, label):
label = R.Geometry.TextDot(label, self.curve.PointAtNormalizedLength(0.5))

class Chain:
def __init__(self):
self.ordered = []

guids = rs.GetObjects('select curves')
for guid in guids:

self.orderd = []
if i == 0:
continue
last = self.ordered[i-1]
break

def make_text_dots(self):

chain = Chain()