Macro to draw folding lines on a loft

Need help, or want to share a macro? Post here!
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
User avatar
nm2107
Posts: 42
Joined: Sun Feb 20, 2022 10:37 pm

Macro to draw folding lines on a loft

Post by nm2107 »

Hello,


First, thank you for FreeCAD and all the related projects out there :)
I'm currently trying to develop a tool to be able to unfold a loft, and to
see the folding lines, in order to print the flatten shape on a piece of paper,
cardboard, plastic or a sheet of metal, and be able to fold it back to the
3D shape.

Here are some images :
Screenshot from 2023-03-04 23-47-53.png
Screenshot from 2023-03-04 23-47-53.png (27.36 KiB) Viewed 1688 times
Screenshot from 2023-03-04 23-48-28.png
Screenshot from 2023-03-04 23-48-28.png (36.42 KiB) Viewed 1688 times
Screenshot from 2023-03-04 23-48-59.png
Screenshot from 2023-03-04 23-48-59.png (29.29 KiB) Viewed 1688 times

And a GIF about it : https://twitter.com/nm2107/status/1632365109342289920

This is my first attempt with the FreeCAD API, so the code may not be very state
of the art.

See this gist for the code : https://gist.github.com/nm2107/9598a87b ... a810f80054


How it works ?
First, select the top and bottom faces of the loft (i.e. the faces corresponding
to the loft sketches), and then invoke this macro.
The tool will fire some rays from the center of each faces to its outer edges,
at regular angles. For each rays, I look at the intersection point between
the ray and the outer edge. The point marks a fold end (the other end is on the
other selected face). When the point is on a straight line, I move it to
the closest line end as I don't want to place bends on a straight line
(i.e. it should remain straight).
Then, when a complete revolution is done, all the folding lines are computed
(they are on the 3D shape). The next step is to draw a flat representation of
such lines. This is done by looking at the folding lines length, and the
distance between each folding line ends. These lengths and distances are used
to draw the flat shape on the XY plane.

This is basically how I did it manually on paper, or in FreeCAD when I place the
folding lines by myself.


TODO :
- GUI to select the ray rotation angle
- GUI to have opts to show the rays and the lines on the 3D shape
- Be able to compute folding lines not only by fixed ray rotation, but also by
interval (i.e. max length) between folding lines (would be applied on the face
with the longest perimeter).
- support different selection ways (i.e. not only by selecting the top and bottom
faces)


Limitations
Plain solid lofts are nice to play with, but I don't usually use them at work.
I plan to use this tool on tube-like lofts, or cones, made of metal.
Usually, to have the flatten representation of the 3D shape that I later have to
cut and fold, I startd by modeling the 3D shape at it would be at final stage.
Then, I select the circular outer face of my 3D loft and I 3D offset it
(Part->3D offset) in order to have the neutral axis of my metal sheet
(e.g. if I have a tube-like loft which is 4mm thick, I offset the outer face by
-2mm to have the neutral axis).
Then, I use this offset face to draw or compute the flat representation of the
loft.
By doing so, my offset face doesn't have a top or a bottom face (i.e. it's not
a solid), so my tool doesn't work with it for now as it requires a top and bottom
faces to be selected.
Hence my question : do you see any way to improve this tool ? I'd like to be
able to select the offset face and to invoke the tool, but currently it would
require a way to determine where are the top and bottom planes.
Do you think working with such planes is a bad idea / bad design ?

Also, I'd like to be able to use this tool not only on loft related shapes, but also
on revolutions, and cylinders (i.e. by selecting the outer face or the top and bottom
wires).

Thank you for your help :)
edwilliams16
Veteran
Posts: 3108
Joined: Thu Sep 24, 2020 10:31 pm
Location: Hawaii
Contact:

Re: Macro to draw folding lines on a loft

Post by edwilliams16 »

Does your macro attempt to flatten surfaces that are not in fact developable? https://en.wikipedia.org/wiki/Developable_surface
Lofts between two curves are ruled surfaces, and all developable surfaces are ruled, but the converse is not the case. A simple example is the surface created by connecting two non-parallel straight lines is not developable.

The mesh Design WB has a Unwrap Mesh method. It tries to flatten with minimum deformation. You can see from the dimensions I added that the edge lengths are modified by the flattening operation.

In your image, it will work if the fold line group converge to points i.e the surfaces are generalized cones.
Attachments
Screenshot 2023-03-05 at 1.26.23 PM.png
Screenshot 2023-03-05 at 1.26.23 PM.png (53.56 KiB) Viewed 1636 times
notdevelopable.FCStd
(9.99 KiB) Downloaded 15 times
User avatar
nm2107
Posts: 42
Joined: Sun Feb 20, 2022 10:37 pm

Re: Macro to draw folding lines on a loft

Post by nm2107 »

Thank you for your answer !

This tool is aimed to be used with developable surfaces (although it can also be executed on non-developable surfaces I guess, but it will output non sense content).
I know about the mesh unwrap feature and have tried it already, but it doesn't fit my use case for the following points :
- no bend lines are added the unwrapped mesh (if I want some, I have to cut the solid before using the mesh feature, and then I have to make multiple meshes, i.e. one by little face).
- sometimes the unwrapped mesh is not very accurate (especially with small faces).

Let me add some precisions about the use case of this tool :
In a metal or sheet metal workshop, we can form 3D shapes from metal sheets. This can be done by rolling the metal sheet (e.g. to form cylinders or cones), or by bending it (to form boxes or simple bends). There is a bending technique which can be used to form cylinders, cones or more complex 3D shapes that can't be formed by rolling. This technique consists into making many small bends close to each other, it is called "bump forming" or "bump-bending" ("croquage" in French).
Some details about this technique here :
- https://www.youtube.com/watch?v=9kLNURDg2V8
- https://www.youtube.com/watch?v=8lzTeMZrqM8

For simple 3D shapes such as cylinders or cones, both bump forming and rolling can be used : we start by bump-form the meeting edges of the shape, and then roll the rest of the sheet (as the rolling operation always have a dead end zone, on the junction edges).

Having the bending lines (called "génératrices" in French) drawn on the metal sheet is a huge win when operating. For complex 3D shapes (i.e. lofts), such bending lines are mendatory to know when to bend the metal sheet.

Here are some videos of such fabrication technique modelized on a CAD software :
- https://www.youtube.com/watch?v=xWb3bjZ7Q9U
- https://www.youtube.com/watch?v=oROZ2gzFBCM
(note that on these videos, the actual 3D bends are represented, which is not the case with the macro, and I don't plan the macro to be able to change the 3D shape to represent such bends, or should I ?).


What I'd like to do is to be able to generate such bend lines, and to be able to flatten them (which is what's the macro currently doing, with a plain solid loft).
I'd like to be able to unroll the real surface of the loft (i.e. if it has holes in it, the flatten shape should also have holes). Then I would export the flatten shape as a DXF and sent it for laser cutting (the folding lines would be burnt only on the metal sheet, so I could know where to bend).

FWIK, the sheet metal WB doesn't have such feature.

What are your though on this point (i.e. how can we make such feature exist) ?

Tanks :)
edwilliams16
Veteran
Posts: 3108
Joined: Thu Sep 24, 2020 10:31 pm
Location: Hawaii
Contact:

Re: Macro to draw folding lines on a loft

Post by edwilliams16 »

You might look at Flatten Face in the Curves workbench. It handles cylindrical and conical faces, but last time I checked couldn't handle the generalized cone - ie loft to a point.
jfc4120
Posts: 448
Joined: Sat Jul 02, 2022 11:16 pm

Re: Macro to draw folding lines on a loft

Post by jfc4120 »

I usually triangulate such things: viewtopic.php?p=648798#p648798

And

viewtopic.php?p=610974#p610974 And viewtopic.php?t=71064

But you can make individual faces as well, they may not show on mesh unfold, but you can connect the segment back with lines to visualize.

Just example 1/4th pattern.
Attachments
ob_rnd2.png
ob_rnd2.png (9.91 KiB) Viewed 1445 times
ob_rnd1.png
ob_rnd1.png (9.92 KiB) Viewed 1445 times
edwilliams16
Veteran
Posts: 3108
Joined: Thu Sep 24, 2020 10:31 pm
Location: Hawaii
Contact:

Re: Macro to draw folding lines on a loft

Post by edwilliams16 »

Looking at the Solidworks videos, I see that the issue is that FreeCAD lofts aren't necessarily developable, even if they could be. Here's their example with a standard loft between the two sketches, and done again in a manner that creates developable surfaces. (loft on the right)
You can check the surfaces with

Code: Select all

#select a face and run
sel =Gui.Selection.getSelectionEx()[0]
face = sel.SubObjects[0]
u0,u1,v0,v1 = face.ParameterRange
print(f'Gaussian Curvature {face.Surface.curvature((u0 + u1)/2, (v0+v1)/2, "Gauss")}')
and confirm that the standard loft does not create developable surfaces.
Attachments
Screenshot 2023-03-06 at 3.14.53 PM.png
Screenshot 2023-03-06 at 3.14.53 PM.png (34.28 KiB) Viewed 1425 times
developableloft.FCStd
(24.24 KiB) Downloaded 15 times
User avatar
nm2107
Posts: 42
Joined: Sun Feb 20, 2022 10:37 pm

Re: Macro to draw folding lines on a loft

Post by nm2107 »

Thank you all for your answers :)
You might look at Flatten Face in the Curves workbench
Yes I've tried this feature and it is great stuff to unfold cylinder and cones faces :) (it can also keep the holes in the unwrapped face, etc...). Unfortunately, there's no way to display folding lines with this tool (and also it doesn't support other kind of faces except cylinders and cones). But I agree that it can be a good source of knowledge !
I usually triangulate such things
Yes, this is actually how the part of the macro responsible of drawing the flatten shape on the XY plane works :) . See this part of the macro. I coded it as I would do it on a piece of paper, using a compass and reporting the folding lines length and the distance between points. It may not be the best way to do it programmatically (I mean there is maybe a math fn or technique that I don't know and would be appropriate to use here).
Following your links, I noticed a post about unwrapping faces where the in or out of the folded face isn't planar (i.e. not like a square to circle transition, but like a cut of two tubes instead). I'd also like to be able to support this kind of geometry, in a second time I guess.

I see that the issue is that FreeCAD lofts aren't necessarily developable, even if they could be.
Thanks, I'll try to reproduce your file to realize the difference.

Code: Select all

u0,u1,v0,v1 = face.ParameterRange
print(f'Gaussian Curvature {face.Surface.curvature((u0 + u1)/2, (v0+v1)/2, "Gauss")}')
I have to poke at this, thank you for the snippet !
User avatar
nm2107
Posts: 42
Joined: Sun Feb 20, 2022 10:37 pm

Re: Macro to draw folding lines on a loft

Post by nm2107 »

and confirm that the standard loft does not create developable surfaces.
Indeed, all the surfaces with the standard loft have a gaussian curvature, measured with your code snippet.

mh so it means it would be harder to exploit this geometry I guess
jfc4120
Posts: 448
Joined: Sat Jul 02, 2022 11:16 pm

Re: Macro to draw folding lines on a loft

Post by jfc4120 »

The oblong to round you show, the mid section is (should be) a flat triangle. And look over the link I gave about the square to round, there's a lot of code examples in there. @edwilliams16 used mesh, I use basic analytic geometry.

I have these in another cad program, I have been converting the code to python.

I am not clear on how to use your code, I tried to test, can you explain a little better? There's one place where you have 10 degrees, what is that also?

Also look at viewtopic.php?f=22&t=70443

Edit:

Also you mentioned cone. Here is code for a symmetrical cone.

Code: Select all

import FreeCAD, FreeCADGui
# -*- coding: utf-8 -*-
import FreeCAD, FreeCADGui
import Draft
import math
# from math import cos, sin, radians
from PySide import QtGui

convert = 25.4
reduct =  .039370078
TOTAL = 0
getDouble = QtGui.QInputDialog.getDouble
Vector, Placement = App.Vector, App.Placement
doc = App.ActiveDocument

start_point = Vector(0, 0, 0)
group = App.ActiveDocument.addObject("App::DocumentObjectGroupPython", "Group")


def line_length(x1=0, y1=0, z1=0, length=10, angle=0):
    x2 = x1 + length * math.cos(math.radians(angle))
    y2 = y1 + length * math.sin(math.radians(angle))
    z2 = z1
    #Draft.makeWire([Vector(x1, y1, z1), Vector(x2, y2, z2)])
    group.addObjects([Draft.makeWire([Vector(x1, y1, z1), Vector(x2, y2, z2)])])

def coord(x1=0, y1=0, z1=0, length=10, angle=0):
    x2 = x1 + length * math.cos(math.radians(angle))
    x2 = x2 * reduct
    y2 = y1 + length * math.sin(math.radians(angle))
    y2 = y2 * reduct
    z2 = z1
    #z2 = z2 * convert
    coo = [x2, y2, z2]
    return coo

D, dflag = getDouble(None, 'example', 'Large diameter', decimals=3)
C, cflag = getDouble(None, 'example', 'Small diameter', decimals=3)
B, bflag = getDouble(None, 'example', 'Height', decimals=3)
#D = 20  #base
#C = 10 #top
#B = 15 #height

R = math.sqrt((D * B / (D - C)) ** 2 + (D / 2) ** 2)
print(R)

RP = R * C / D

THETA = 180 * D / R
print(THETA)

zaxis = App.Vector(0, 0, 1)
p1 = App.Vector(0, 0, 0)
place1 = App.Placement(p1, App.Rotation(zaxis, 0))
circle1 = Draft.make_circle(R * convert, placement=place1, face=None, startangle=0, endangle=THETA, support=None)

p2 = App.Vector(0, 0, 0)
place2 = App.Placement(p1, App.Rotation(zaxis, 0))
circle2 = Draft.make_circle(RP * convert, placement=place1, face=None, startangle=0, endangle=THETA, support=None)

x1 = y1 = z1 = 0  # Edit coordinate origin
length = D
length = length * 25.4
angle = 180
line_length(x1, y1, z1, length, angle)
clist1 = coord(x1, y1, z1, length, angle)

x1 = (-1 * (D / 2)) + (C / 2)
x1 = x1 * convert

y1 = B * convert
z1 = 0  # Edit coordinate origin
length = C
length = length * 25.4
angle = 180
line_length(x1, y1, z1, length, angle)
clist2 = coord(x1, y1, z1, length, angle)

group.addObjects([Draft.makeWire([Vector(0, 0, 0), Vector(x1, y1, z1)])])

group.addObjects([Draft.makeWire([Vector(-D * convert, 0, 0), Vector(clist2[0] * convert, clist2[1] * convert, clist2[2] * convert)])])
ZP = R - RP

hline = Draft.make_line(Vector(RP * convert, 0, 0), Vector(R * convert, 0, 0))

X = ((RP * math.cos(math.radians(THETA))))
Y = ((RP * math.sin(math.radians(THETA))))
X1 = ((R * math.cos(math.radians(THETA))))
Y1 = ((R * math.sin(math.radians(THETA))))

hline = Draft.make_line(Vector(X * convert , Y * convert, 0), Vector(X1 * convert, Y1 * convert, 0))

I use inches, not MM.
Attachments
cone.png
cone.png (5.74 KiB) Viewed 1235 times
User avatar
nm2107
Posts: 42
Joined: Sun Feb 20, 2022 10:37 pm

Re: Macro to draw folding lines on a loft

Post by nm2107 »

I am not clear on how to use your code, I tried to test, can you explain a little better?
In order to use it, create an additive loft with the part design WB (e.g. oblong to circle), select the top and bottom faces (i.e. the circle and the oblong), and invoke the macro. This is more a like a POC for now.

There's one place where you have 10 degrees, what is that also?
This defines how much folding lines there would be. 360 / 10° = 36, which makes 36 folding lines. The smaller the angle, the higher the folding lines count.
The code is inspired of how I would do the flatten drawing by hand, if I would have to start with 2D views of the loft (i.e. top and face views, drawing w/o any computer). You can have an example here about how to draw it with this classic technique : https://www.youtube.com/watch?v=RzaOTPOwZyU .

I'm thinking about reworking how the macro computes the placement of the folding lines. For now, I'm firing rays from the center of the top and bottom faces of the loft to the outer wire, at every 10° (so 360/10 = 36 rays, c.f. this attachment) :
Screenshot from 2023-03-09 19-47-30.png
Screenshot from 2023-03-09 19-47-30.png (65.05 KiB) Viewed 1182 times
I use the intersection point of the ray and the outer wire as a point for the folding line. When the intersection point is on a straight line, I move it to the closest line extremity.
Once the rays for the bottom and top faces are fired, I connect the intersection points to make the folding lines (the points are the folding lines starts and ends).

But this ways of doing is not great as it can miss some important areas, such as (in yellow) :
Screenshot from 2023-03-09 19-52-17.png
Screenshot from 2023-03-09 19-52-17.png (47.82 KiB) Viewed 1182 times
You can see here that the rounded corners should have many folding lines, but the macro will not put as many on it, because not many rays will hit this zone.


Instead of shooting rays, I'm thinking about something like this to place the folding lines :
- for the top and bottom faces (I call them faceA and faceB, no matter the order), walk on the outer wire of the face. When we walk on a line, only consider its start and end as placement for a folding line point (as the line should remain straight). When walking on a circle arc, look at its angle to know how many folding lines points to place on it (e.g. a 90° arc should have 1/4 of the total amount of folding lines, as 90 = 360 * 1/4).
- once the points of the folding lines are placed on each faces, we have to connect them in order to form the folding lines. To know which point connect to which point, I'm thinking about a projection. I could project a point on the other face and look which point is the closest, which would be the point to use to connect the folding line.

EDIT : actually, the proposed solution above won't work if the wire contains a curve that is not a circle arc (e.g. an ellipsis arc or a bezier curve).
The folding lines points should be positioned on straight lines ends, and on edges that are not straight lines (on their ends and middle) :
Screenshot from 2023-03-09 21-31-41.png
Screenshot from 2023-03-09 21-31-41.png (12.44 KiB) Viewed 1145 times
We can deduce that such points are spaced across a subset of the total outer wire that have a length of `TotalWireLength - AllStraightLinesLength`. So when we walk on an edge that is curvy (i.e. not straight), we can look at its length and compute the amount of points it should contain, proportionally to the above formula. Then, we can place such points on this edge (evenly spaced I guess, in matter of walk length).
When walking on an edge that is not a straight line,
Post Reply