havent tried and not in dyn, but probably alphashape could work, have sometimes work for me, in these situations
hi
Edit 2: Concave part
There’s a way around this (by drawing a spline around the part) and adapting the script; I’m not good enough at algorithms to write this one.
cordially
christian.stan
Hi, if any kind soul wants to help me correct my algorithm, you’re welcome.
The first three lines are in order, then something is a bit messy.
import sys
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
lin=IN[0]
fl=lin[0]
lin.pop(0)
stockorder=[]
stockorder.append(fl)
pext=fl.EndPoint
def reol(p,li,st):
a=[l.ClosestPointTo(p) for l in li]
b=[Geometry.DistanceTo(a,p) for a in a]
i=b.index(min(b))
st.append(li[i])
c=li[i].ParameterAtPoint(a[i])
li.pop(i)
if c==0:
return st[-1].PointAtParameter(1)
else:
return st[-1].PointAtParameter(0)
while len(lin)>1:
reol(reol(pext,lin,stockorder),lin,stockorder)
OUT = stockorder,lin
I start from a random line that I put in stock, I look at the point closest to the next line, I erase it from the stock then start again from the opposite point then from near to near in order to exhaust the quota of starting lines
Thank you.
Sincerely,
Christian.stan
I modified the script to make it work (concave or convex). There will likely be times when it won’t work.
Python script 1
import sys
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
lin=IN[0]
fl=lin[0]
lin.pop(0)
stockorder=[]
stockorder.append(fl)
pext=fl.EndPoint
def reol(p,li,st):
a=[l.ClosestPointTo(p) for l in li]
b=[Geometry.DistanceTo(a,p) for a in a]
i=b.index(min(b))
st.append(li[i])
c=li[i].ParameterAtPoint(a[i])
li.pop(i)
if c==0:
return st[-1].PointAtParameter(1)
else:
return st[-1].PointAtParameter(0)
b1=reol(pext,lin,stockorder)
boucles=[]
boucles.append(b1)
while len(lin)>0:
boucles.append(reol(boucles[-1],lin,stockorder))
stockorder.append(stockorder[0])
OUT = stockorder
Python Script 2
import sys
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
lin=IN[0]
def pint(l1,l2):
if round((l1.EndPoint.X - l1.StartPoint.X),3)==0:
c=round((l2.EndPoint.Y - l2.StartPoint.Y),5)/round((l2.EndPoint.X - l2.StartPoint.X),5)
d=l2.StartPoint.Y-c*l2.StartPoint.X
return Point.ByCoordinates(l1.StartPoint.X,c*(l1.StartPoint.X)+d,l1.StartPoint.Z)
if round((l2.EndPoint.X - l2.StartPoint.X),3)==0:
a=round((l1.EndPoint.Y - l1.StartPoint.Y),5)/round((l1.EndPoint.X - l1.StartPoint.X),5)
b=l1.StartPoint.Y-a*l1.StartPoint.X
return Point.ByCoordinates(l2.StartPoint.X,a*(l2.StartPoint.X)+b,l2.StartPoint.Z)
else:
a=round((l1.EndPoint.Y - l1.StartPoint.Y),5)/round((l1.EndPoint.X - l1.StartPoint.X),5)
b=l1.StartPoint.Y-a*l1.StartPoint.X
c=round((l2.EndPoint.Y - l2.StartPoint.Y),5)/round((l2.EndPoint.X - l2.StartPoint.X),5)
d=l2.StartPoint.Y-c*l2.StartPoint.X
return Point.ByCoordinates((d-b)/(a-c),a*(d-b)/(a-c)+b,l1.StartPoint.Z)
OUT = [pint(lin[i+1],lin[i]) for i in range(0,len(lin)-1)]
(A new post for greater clarity.)
Python scripts are certainly improvable (everyone does it with their own skills).
Sincerely,
christian.stan
Thank you so much for your help! I really appreciate that you took the time to assist me.
I tried running the script you shared, but I’m getting an error in the script 2 and I’m not quite sure why. I’ll attach a screenshot of the error here in case you can help me figure out what might be going wrong.
Thanks again for your time and effort!
Hi, did you copy and paste the code or did you retype it?
It’s weird, I deleted the division by zero thing for a line parallel to the y-axis. Do you have two successive lines in the same extension?
Send me a screenshot of your “pseudo zone.”
i tried it with this areas
edit:
I’m on the weekend in 5 minutes. I’ll check on Tuesday.
Have a good weekend everyone.
for this situation:
if i delete line //
Sincerely,
christian.stan
Hi,
a test using Equations of Lines
# Load the Python Standard and DesignScript Libraries
import sys
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
def compute_intersection(lineA, lineB):
"""Compute intersection point of 2 lines"""
x1, y1 = lineA.StartPoint.X, lineA.StartPoint.Y
x2, y2 = lineA.EndPoint.X, lineA.EndPoint.Y
x3, y3 = lineB.StartPoint.X, lineB.StartPoint.Y
x4, y4 = lineB.EndPoint.X, lineB.EndPoint.Y
denom = (x1 - x2)*(y3 - y4) - (y1 - y2)*(x3 - x4)
print(denom)
if abs(denom) < 0.001:
return None, None # lines are parallel
px = ((x1*y2 - y1*x2)*(x3 - x4) - (x1 - x2)*(x3*y4 - y3*x4)) / denom
py = ((x1*y2 - y1*x2)*(y3 - y4) - (y1 - y2)*(x3*y4 - y3*x4)) / denom
return px, py
def ordered_curves(lines):
ordered_curves = [lines.pop(0)]
n = 1
while lines and n < 200:
n += 1
lines.sort(key = lambda x : ordered_curves[-1].DistanceTo(x))
ordered_curves.append(lines.pop(0))
return ordered_curves
lines = IN[0]
perimeter_points = []
lines_ordered = ordered_curves(lines)
lines_ordered.append(lines_ordered[0])
for idx, lineB in enumerate(lines_ordered):
if idx > 0:
lineA = lines_ordered[idx - 1]
x, y = compute_intersection(lineA, lineB)
if x is None:
perimeter_points.extend([lineA.StartPoint, lineA.EndPoint, lineB.StartPoint, lineB.EndPoint])
else:
perimeter_points.append(Point.ByCoordinates(x, y, lineB.StartPoint.Z))
polygon = Polygon.ByPoints(perimeter_points)
OUT = polygon, perimeter_points
Hello and thank you for the code, better thought out and done, congratulations.
Sincerely
christian.stan
Hi, to avoid manual deletion, here’s PythonScript1, modified and nodes added (I had a problem with the pop and range methods).
Python script1
import sys
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
lin=IN[0]
fl=lin[0]
lin.pop(0)
stockorder=[]
stockorder.append(fl)
pext=fl.EndPoint
def reol(p,li,st):
a=[l.ClosestPointTo(p) for l in li]
b=[Geometry.DistanceTo(a,p) for a in a]
i=b.index(min(b))
st.append(li[i])
c=li[i].ParameterAtPoint(a[i])
li.pop(i)
if c==0:
return st[-1].PointAtParameter(1)
else:
return st[-1].PointAtParameter(0)
b1=reol(pext,lin,stockorder)
boucles=[]
boucles.append(b1)
while len(lin)>0:
boucles.append(reol(boucles[-1],lin,stockorder))
stockorder.append(stockorder[0])
idx=[i for i in range(len(stockorder)-1) if round(abs(Vector.AngleAboutAxis(stockorder[i].Direction,stockorder[i+1].Direction,Vector.ByCoordinates(0,0,1))),0)==0 or round(abs(Vector.AngleAboutAxis(stockorder[i].Direction,stockorder[i+1].Direction,Vector.ByCoordinates(0,0,1))),0)==180 ]
OUT =stockorder,idx
Python script2
import sys
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
lin=IN[0]
def pint(l1,l2):
if round((l1.EndPoint.X - l1.StartPoint.X),3)==0:
c=round((l2.EndPoint.Y - l2.StartPoint.Y),5)/round((l2.EndPoint.X - l2.StartPoint.X),5)
d=l2.StartPoint.Y-c*l2.StartPoint.X
return Point.ByCoordinates(l1.StartPoint.X,c*(l1.StartPoint.X)+d,l1.StartPoint.Z)
if round((l2.EndPoint.X - l2.StartPoint.X),3)==0:
a=round((l1.EndPoint.Y - l1.StartPoint.Y),5)/round((l1.EndPoint.X - l1.StartPoint.X),5)
b=l1.StartPoint.Y-a*l1.StartPoint.X
return Point.ByCoordinates(l2.StartPoint.X,a*(l2.StartPoint.X)+b,l2.StartPoint.Z)
else:
a=round((l1.EndPoint.Y - l1.StartPoint.Y),5)/round((l1.EndPoint.X - l1.StartPoint.X),5)
b=l1.StartPoint.Y-a*l1.StartPoint.X
c=round((l2.EndPoint.Y - l2.StartPoint.Y),5)/round((l2.EndPoint.X - l2.StartPoint.X),5)
d=l2.StartPoint.Y-c*l2.StartPoint.X
return Point.ByCoordinates((d-b)/(a-c),a*(d-b)/(a-c)+b,l1.StartPoint.Z)
OUT = [pint(lin[i+1],lin[i]) for i in range(0,len(lin)-1)]
Sincerely,
christian.stan