# Sort points by untangled lines

Hello Dynamo Community,

I need help with my current python script please.
I would like to annotate my 3D ortho view with tags but I don’t want to untangle all the tags after placement. I have added my python code below as well as snapshots of my dynamo script and 3D preview. My logic is to shuffle the lists until I get the right combination where the lines do not intersect and then OUT out those points, however I think this might be a bit extreme on memory. I have tried using iterations and started with the top right point and work my way down but that did not work unfortunately. If there is anybody who might have some good logic on how to do this, any feedback is greatly appreciated. I am currently studying python scripting so I am still a newbie.

Thanks

``````import clr
import random
from Autodesk.DesignScript.Geometry import Line

point1 = IN[0]
point2 = IN[1]

#if inputs are not lists, convert to list
if isinstance(point1, list):
pointlist1 = point1
else:
pointlist1 = [point1]

if isinstance(point2, list):
pointlist2 = point2
else:
pointlist2 = [point2]

new_point_list = []
while_count = 0
while while_count < 1000:	#count used to not enter infinite loop
lines = []	#reset line list
for p1, p2 in zip(pointlist1, pointlist2):
lines.append(Line.ByStartPointEndPoint(p1,p2))	#create lines from points in both lists

for line1 in lines:
for line2 in lines:
if line1 != line2: #filter out lines that intersect itself
if line1.DoesIntersect(line2):
random.shuffle(pointlist2)	#shuffle list2 if there is a clash
continue	#start loop again
else:
new_point_list = pointlist2
break

while_count += 1
OUT = new_point_list
``````

Hello,
Your initial points hooked to your elements must be classified in Z descending

Cordially
christian.stan

Hi Christian,

Thanks I have tried this but cannot sort the points by Z value as the plane is on all 3 axis.

You could the coordinatesystem of the plane to get all points residing on this plane.
From there you should be able to sort them by Z-value.

1 Like

Hi @Daan ,

I am able to do this but unfortunately this does not solve my problem. Because I have my leader tail points at different vertical positions, I cannot sort the points by coordinate Z value or surface V value. The snapshot below illustrates why:

The first 3 points are fine.
The next point in the Z or V value is the blue point, which casts to the 4th point on the right.
The next point in the Z or V value is the red point, which casts to the 5th point on the right causing the lines to cross.

I have managed to find a solution using the angles in relation to a fixed reference line.
Thanks for the help all.

``````import clr

from Autodesk.DesignScript.Geometry import *

point1 = IN[0]
point2 = IN[1]

#if inputs are not lists, convert to list
if isinstance(point1, list):
pointlist1 = point1
else:
pointlist1 = [point1]

if isinstance(point2, list):
pointlist2 = point2
else:
pointlist2 = [point2]

# get first and last point in the start list (Leader elbow)
start_point = pointlist1[0]
end_point = pointlist1[-1]
# create a line from the last point to the first and get the vector of that line
ref_line = Line.ByStartPointEndPoint(end_point,start_point)
ref_line_vector = Line.NormalAtParameter(ref_line,0)
# create result list
new_point_list = []
# iterate for each leader elbow point
# used range instead of items in list because I want to remove items in the list for each iteration
for a in range(len(pointlist1)):
# Set the first point as the active point
sp = pointlist1[0]
# create/reset lists
line_list = []
vector_list = []
angle_vector = []
# for each endpoint
for ep in pointlist2:
# create a line
ep_line = Line.ByStartPointEndPoint(sp,ep)
# get the vector of the line
ep_vector = Line.NormalAtParameter(ep_line,0)
# add the line to a list
line_list.append(ep_line)
# add the vector to a list
vector_list.append(ep_vector)
# for each vector in the vector list
for vec in vector_list:
# get the angle against the reference line vector and add to the list
angle_vector.append(Vector.AngleWithVector(ref_line_vector,vec))
# get the vector with the smallest angle
vector_min = min(angle_vector)
# index the minimum vector
vector_index = angle_vector.index(vector_min)
# add the point associated with the minimum angle to the output list
new_point_list.append(pointlist2[vector_index])
# remove the first index from the leader elbow list
pointlist1.pop(0)
#remove the returned point from the endpoint list so it does not get used again
pointlist2.pop(vector_index)

OUT = new_point_list
``````
4 Likes

Glad to hear that! Wouldn’t have come up with a solution involving relative angles!