Translating a line by overlapping along another line

Hi everyone,

I’m newbie in python and I’m trying to write a script which allows me to translate an input line (bar) by overlapping along another line and stopping translation if the condition is checked (remaining line < bar length) as shown in the image bellow

I made some progress but it’s not enough, and I got the following error…so pls help me fix it
image

import sys
import clr
import math
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

line_1 = IN[0]

bar = IN[1]

overlap_length = 1

St_point1 = line_1.StartPoint
End_point = line_1.EndPoint
St_point2 = Point.ByCoordinates(bar.Length-overlap_length, 0, 0)
line_2 = Line.ByStartPointEndPoint(St_point2, End_point)

out =[]
k = 0
while k < 20:
    lst = []
    k += 1
    St_point2 = Point.ByCoordinates(k*(bar.Length-overlap_length), 0, 0)
    lst.append(Geometry.Translate(bar, k*(bar.Length-overlap_length), 0, 0))
    lst.append(Line.ByStartPointEndPoint(St_point2, End_point))
    if math.ceil(line_2.Length) < bar.Length:
        out.append(line_2)
        break
OUT = out

Thanks.

What exactly is your end goal here? It seems like there’s no need to loop the new line creation and check when you can just mathematically determine how many “bars” fit your given line length and overlap length. Just calculate the number of bars and create them once.

1 Like

@Nick_Boyts
My goals are:
1- learning and mastering python under dynamo
2- In my different structural projects I need each time to split my rebars excedding 12m and overlap them according my design code, so I want to do that using a python script

I know that I can calculate number of bars at once , but as I said I need a python script that gives me their numbers and their lenghts.

Thanks.

From your example it seems like length is a known value since you have the length of the “bar” and that doesn’t seem to change. What I’m saying is that with a known bar length and a known overlap length you have the “net length” of a new bar which allows you to just add up the total number of whole bars that you can fit within your defined line length. With this information you can easily create a sequence of start/end points, cumulative lengths, bar positions, etc.

@Nick_Boyts
I agree with you…I can do it easly with a sequence of points but if it is possible and if you can help me I’ld like to do it with python in the purpous to learn it and using it later in more complex cases

Thanks.

This is what I mean by “end goal”. If you have a specific case where it makes sense to solve in this way then it’s worth discussing, but whether you use python or not, “looping” in this way is not the right solution for this problem. Python is definitely worth the time and effort but do not learn python through bad practices. In my opinion, this is bad practice.

That being said, you can absolutely still use python to create the sequence of values and curves that you need. Just change your solution to not be an iterative one.

2 Likes

Hello,

here is a solution (far from ideal, I’m a beginner)

script python: edit : Correction of a forgotten variable

# Charger les bibliothèques DesignScript et Standard Python
import sys
import clr
import math
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

# Les entrées effectuées dans ce noeud sont stockées sous forme de liste dans les variables IN."
Container=[]
Lb=IN[1]
L_cover=IN[2]
db=IN[3]
N_bar_ent=[]
Long_res=[]
Container_2=[]


#create list
if isinstance(IN[0],list):
	Lines = IN[0]
else:
	Lines = [IN[0]]
#Loop
for i in Lines:
    if i.Length<=Lb:
        Container.append(i)
    else:
        a=Line.ByStartPointDirectionLength(i.StartPoint,i.TangentAtParameter(0),Lb)
        Nb_bar_ent=math.floor(i.Length/(Lb-L_cover))
        L_res=i.Length-((Nb_bar_ent-1)*(Lb-L_cover)+Lb)
        N_bar_ent.append(Nb_bar_ent)
        Long_res.append(L_res)
        for j in range(Nb_bar_ent):
            temp=a.Translate(i.TangentAtParameter(0),(Lb-L_cover)*j)
            j=temp.Translate(i.NormalAtParameter(0),db/2*(-1)**j)
            Container.append(j)

        b=Line.ByStartPointDirectionLength(i.EndPoint,i.TangentAtParameter(0),-(L_res+L_cover))
        c=b.Translate(i.NormalAtParameter(0),db/2*(-1)**(Nb_bar_ent+2))
        Container_2.append(c)
        
# Affectez la sortie à la variable OUT.
OUT = Container,N_bar_ent,Long_res,Container_2,"You are too strong M. Poupin "+'\U0001f609'

cordially
christian.stan

2 Likes

With a while loop

line overlap

import sys
import clr
import math
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

line_1 = IN[0]
barre = IN[1]

overlap_length = 1
substractVector = line_1.Direction.Normalized().Scale(overlap_length)
offsetVector = substractVector.Cross(Vector.ByCoordinates(0, 0, 1))

out = [barre]
startPoint = line_1.StartPoint
finalEndPoint = line_1.EndPoint
currEndPoint = barre.EndPoint.Subtract(substractVector)
# initialize a counter to avoid an infinite loop during test
counter = 0 
a, b = 1, 0
future_end_Pt = currEndPoint.Add(barre.Direction)
# 
while startPoint.DistanceTo(future_end_Pt) < line_1.Length and counter < 50:
	counter += 1
	newLine = Line.ByStartPointDirectionLength(currEndPoint, line_1.Direction, barre.Length)
	# update the end point
	currEndPoint = newLine.EndPoint.Subtract(substractVector)
	# update the future end point
	future_end_Pt = currEndPoint.Add(barre.Direction)
	# translate the line
	newLine = newLine.Translate(offsetVector, a )
	out.append(newLine)
	# swap each loop
	a, b = b, a 
#
# compute the rest
rest_distace = currEndPoint.DistanceTo(finalEndPoint)
if rest_distace > 0.001:
	newLine = Line.ByStartPointDirectionLength(currEndPoint, line_1.Direction, rest_distace)
	# offset
	newLine = newLine.Translate(offsetVector, a )
	out.append(newLine)
OUT = out
2 Likes

Hi @christian.stan

You have chosen a general case with an inclined line…it’s perfect but why you start a line from the negative coordinates?

I didn’t fully understand your script due to the error below and I noticed that you used many inputs and data!!?

Can you share your dynamo file here?
Thanks for more explanations.

Hello,

1st question:
In fact it ends in negative coordinates (it was to check if my script is correct following 3 arbitrary directions, so confident I am about what I write :smile:)

2nd issue:
I brought corrective by transforming (in integer) particularity of Ironpython (a specialist should confirm)
I had written under dynamo 2.16.1 with Cpython
I transcribed in 2.3.

3rd issue:
When you start you don’t necessarily make a script worthy of someone experienced (unless you have a natural gift, sorry)
The Db (diameter of the bar) deliberately consistent here (worthy of the tree trunk :smiley:) to see if the bars alternate with respect to the axis of the support line.

4th issue:
no worries, here it is corrected with fix on math.floor.
script:
07 Janvier forum anglais.dyn (29.5 KB)

code python correction
# Charger les bibliothèques DesignScript et Standard Python
import sys
import clr
import math
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

# Les entrées effectuées dans ce noeud sont stockées sous forme de liste dans les variables IN."
Container=[]
Lb=IN[1]
L_cover=IN[2]
db=IN[3]
N_bar_ent=[]
Long_res=[]
Container_2=[]


#create list
if isinstance(IN[0],list):
	Lines = IN[0]
else:
	Lines = [IN[0]]
#Loop
for i in Lines:
    if i.Length<=Lb:
        Container.append(i)
    else:
        a=Line.ByStartPointDirectionLength(i.StartPoint,i.TangentAtParameter(0),Lb)
        Nb_bar_ent=int(math.floor(i.Length/(Lb-L_cover)))
        L_res=i.Length-((Nb_bar_ent-1)*(Lb-L_cover)+Lb)
        N_bar_ent.append(Nb_bar_ent)
        Long_res.append(L_res)
        for j in range(Nb_bar_ent):
            temp=a.Translate(i.TangentAtParameter(0),(Lb-L_cover)*j)
            j=temp.Translate(i.NormalAtParameter(0),db/2*(-1)**j)
            Container.append(j)

        b=Line.ByStartPointDirectionLength(i.EndPoint,i.TangentAtParameter(0),-(L_res+L_cover))
        c=b.Translate(i.NormalAtParameter(0),db/2*(-1)**(Nb_bar_ent+2))
        Container_2.append(c)
        
# Affectez la sortie à la variable OUT.
OUT = Container,N_bar_ent,Long_res,Container_2,"You are too strong M. Poupin "+ "\U0001f609"

remark:
Mr. Poupin’s script is surely better optimized and goes in the direction of your initial script.

edit:
“Normally” last fix that eliminates the special case where n bars are enough to cover the length without a cut bar
script:
07 Janvier forum anglais_ver3.dyn (29.7 KB)

Cordially
christian.stan

1 Like

@c.poupin
Thanks a lot :wink:…it’s exactly what I want
So the idea was to define a vector scaled to the (overlap length) which is the base to translate the line (barre) and calculate the remaining line…(this idea never crossed my mind :crazy_face: :crazy_face:)

I’ve some questions:
1- Why you haven’t use Break to stop the loop while ?
2- using the list out outside and inside the (while loop) allow always fill this liste without deleting previous lines?

Thanks.

@Nick_Boyts what you think about @c.poupin 's solution?

@REDO10

there are several ways to stop a loop

I think you should start learning Python, there are plenty of very accessible training courses

I always trust @c.poupin’s recommendations. He knows what he’s doing. I think he’d also agree that just because something is possible doesn’t mean it’s a good idea. Using a while loop to learn while loops is totally fine. But for real world solutions it’s always best to use the proper tools for the job. That’s all. :wink:

3 Likes