Discussion:
[OpenSCAD] Curved/bent conical tubing
pieterbos
2017-03-01 22:03:24 UTC
Permalink
I have designed a 3d-printed trombone using openSCAD. It requires a bit of
conical tubing. I have tried several approaches and I have a few very well
working trombones, but none worked well enough for my tastes:

- First attempt: sweeping a circle with list comprehension demos sweep, then
use difference with a smaller one to get a hollow tube.

It works relatively fast, but generates lots of warnings and often errors
when renderings.

- Second attempt: rendering two short cylinders a bit apart, one rotated
slightly from the other, hull them together. Put that in a for loop rotated
and translated along the desired path. then use difference with a smaller
one to get a hollow tube.

This works very well without warnings or errors, but it is really slow if
you want it rendered at enough detail for really smooth prints - the
previous method ran in 30-45 minutes, but now my trombone tuning slide has
been rendering for over 75 minutes and is still going, on an intel core i7
running at 3.4-3.6Ghz.

So does anyone have a better approach? Writing code to rendering polyhedrons
manually will probably work, but I think it will be a tricky, complicated
and time consuming thing to write...






--
View this message in context: http://forum.openscad.org/Curved-bent-conical-tubing-tp20686.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
Carsten Arnholm
2017-03-01 22:23:56 UTC
Permalink
Post by pieterbos
So does anyone have a better approach? Writing code to rendering polyhedrons
manually will probably work, but I think it will be a tricky, complicated
and time consuming thing to write...
Have you considered creating a 2d profile of one side of longitudinal
cross section and rotate_extrude that 360 degrees to create the conical
trombone shape? Then add the other parts as simpler tubes.

Carsten Arnholm
pieterbos
2017-03-01 22:50:09 UTC
Permalink
I use rotate extrude with a longitudinal profile for the bell of the trombone
and it works great. Project is at https://github.com/pieterbos/PrintBone if
you're interested.

But the bell is straight, and this is not. So I don't see how I can create a
bent conical tube with rotate_extrude: I cannot scale with rotate_extrude so
working with something like the following pattern will not work:

rotate_extrude()
difference() {
circle(r=outside_radius);
circle(r=inside_radius);
}

And I cannot rotate with linear_extrude. I could easily make a twisted
conical tube with linear extrude, but that would be creating a rather funky
looking trombone :)

To show what the part should look like, because CSG preview does work:

<Loading Image...>

of course with the tubes being hollow - that's a preview artifact.



--
View this message in context: http://forum.openscad.org/Curved-bent-conical-tubing-tp20686p20688.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
pieterbos
2017-03-01 23:11:19 UTC
Permalink
Of course after a long search I figured out that I needed different search
terms in google, and I found this:

http://stackoverflow.com/questions/28842419/linear-rotational-extrude-at-the-same-time

skin.scad. of course - that's much faster and no errors! and if that doesn't
work someone already did the python script to create polyhedrons. Should
work just fine now :)



--
View this message in context: http://forum.openscad.org/Curved-bent-conical-tubing-tp20686p20689.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
Ronaldo Persiano
2017-03-01 23:32:27 UTC
Permalink
That is the way. You may skin both interior and exterior surface in just
one skin polyhedron avoiding the difference operation. To do this, you only
need:
1) concatenate the interior and exterior profiles in a list caring that
they go in opposed directions;
2) concatenate the previous list with the first profile in the list, so
repeating it;
3) change skin.scad eliminating the two caps at the end:

start_cap = [range([0:P-1])];
end_cap = [range([P*N-1 : -1 : P*(N-1)])];

by changing them to void lists:

start_cap = [];
end_cap = [];

And that is all.
Post by pieterbos
Of course after a long search I figured out that I needed different search
http://stackoverflow.com/questions/28842419/linear-
rotational-extrude-at-the-same-time
skin.scad. of course - that's much faster and no errors! and if that doesn't
work someone already did the python script to create polyhedrons. Should
work just fine now :)
pieterbos
2017-03-02 09:22:08 UTC
Permalink
Post by Ronaldo Persiano
That is the way. You may skin both interior and exterior surface in just
one skin polyhedron avoiding the difference operation. To do this, you only
1) concatenate the interior and exterior profiles in a list caring that
they go in opposed directions;
2) concatenate the previous list with the first profile in the list, so
repeating it;
Exactly my toughts - not possible with sweep, easy with skin. I needed to
use a different circle that in shapes.scad, because it contained one point
too little.

At $fn=200, for both the circles and number of input shapes to skin, CGAL
rendering time is 7 seconds! :)

Also eliminating the caps was not needed, that produces hollow walls and I
want solid walls.



--
View this message in context: http://forum.openscad.org/Curved-bent-conical-tubing-tp20686p20692.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
pieterbos
2017-03-02 09:27:11 UTC
Permalink
Except when I render the entire part and not just the bent tube, OpenSCAD
says this and doesn't render the bent conical tube:

Compiling design (CSG Tree generation)...
ECHO: "total bell height", -574.22
Rendering Polygon Mesh using CGAL...
ERROR: CGAL error in CGAL_Nef_polyhedron3(): CGAL ERROR: assertion
violation! Expr: e->incident_sface() != SFace_const_handle() File:
/Users/kintel/code/OpenSCAD/openscad/../libraries/install/include/CGAL/Nef_S2/SM_const_decorator.h
Line: 326

Might be possible to get rid of by using skin for the entire part, not just
the bow...




--
View this message in context: http://forum.openscad.org/Curved-bent-conical-tubing-tp20686p20693.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
Parkinbot
2017-03-02 12:23:50 UTC
Permalink
Try to view the skin with F12. If it gets purple, reverse the vertex order in
your circle.
Post by pieterbos
Except when I render the entire part and not just the bent tube, OpenSCAD
--
View this message in context: http://forum.openscad.org/Curved-bent-conical-tubing-tp20686p20694.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
Ronaldo
2017-03-02 13:21:49 UTC
Permalink
Post by pieterbos
Also eliminating the caps was not needed, that produces hollow walls and I
want solid walls.
If you keep the skin caps and repeat the first profile at end of the profile
list, skin.scad will produce a self-intersection that CGAL doesn't like.
This repetition makes the tube endless and no cap is needed.

That is what I got from a similar process:

<Loading Image...>

I have defined a series of circles to define the shape by B-splines and have
used a shape drawing module similar to Parkinbot's sweep.scad. In essence,
the model is a polyhedron with both the interior and exterior surfaces where
these surfaces are spliced by repetition of the first profile at the end.
There is no caps.

To easy the task the interior surface is computed from the exterior one by
reducing by a fixed amount the exterior surface radiuses. The mouthpiece was
modeled the same way and unioned to the main shape.




--
View this message in context: http://forum.openscad.org/Curved-bent-conical-tubing-tp20686p20695.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
Parkinbot
2017-03-02 15:53:43 UTC
Permalink
nice! Here some minimalistic "free style" interpolation code for playing
around.
use
<Naca_sweep.scad>
// http://www.thingiverse.com/thing:1208001
use
<splines.scad>
// http://www.thingiverse.com/thing:1208001
d = 2; // tube diameter
N=300; // interpolation points
// interpolation data for outer skin
A = [//Tx, Ty, Tz, rad, Rx, Ry
[0, 42, -100, 10, 0, 0 ], // mouthpiece part
[0, 42, -60, 10, 0, 0 ],
[0, 42, 0, 12, 0, 0 ],
[0, 42, 80, 15, -5, -20], // start loop
[40, 40, 120, 15, -20, -90], // 90°
[80, 25, 75, 17, -30, -180], // 180°
[60, 12, 0, 19, -10, -240], // 270°
[0, 5, 25, 20, 0, -360], // end loop
[0, 0, 100, 26, 0, -370], // cone start
[20, 0, 200, 40, 0, -370], // cone shift
[60, 0, 300, 70, 0, -420], // cone shift and bend
[68, 0, 310, 100, 0, -422], // cone end
[69, 0, 311, 100, 0, -422], // cone border
];
// view raw data
// sweep(gen_dat(A, N/3), showslices = true);
// inner skin data: reverse A with modified tube diameter
B = [for(i=[len(A)-1:-1:0]) [for(j=[0:len(A[0])-1]) A[i][j]-(j==3?d:0)]];
outer = gen_dat(nSpline(A,N), N/3); // outer skin
inner = gen_dat(nSpline(B,N), N/3); // inner skin
sweep(concat(outer, inner), close = true, slices = true);
function gen_dat(S, N=100) =
[ for (i=[0:len(S)-1])
let(dat = Tz_(S[i][2], // apply Tz
Rx_(S[i][4], // apply Rx
Ry_(S[i][5], // apply Ry
circle_(S[i][3], N))))) // generate circle data using rad
T_(S[i][0], S[i][1], 0, dat)]; // apply Tx and Ty
function circle_(r=10, N=30) = [for (i=[0:N-1]) [r*sin(i*360/N),
r*cos(i*360/N), 0]];
<Loading Image...>





--
View this message in context: http://forum.openscad.org/Curved-bent-conical-tubing-tp20686p20696.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
pieterbos
2017-03-02 19:55:02 UTC
Permalink
Very nice looking horn designs and nice tricks for creating shapes with very
little code!

I managed to get the basic shape with the skin with circles with holes as
input, but as soon as I attach other parts I keep getting the same error as
I got before. F12 shows no purple vertices.

So for now differencing two solid shapes created with skin() works and it
renders in just a few minutes. Perhaps I'll try the naca sweep later - it
looks very useful!

For the bell I currently use a straight profile, by creating a curve (list
of points) made from a combination of bessel curves, cones and cylinders.
I create a wall from the curve by translating along the normal vectors. Then
I apply rotate_extrude.

I can input the bessel curve parameters directly in the ART acoustics
simulator, giving me impedance curves. And there's a brass synthesizer
called NESS brass that I can actually input the profile and many other input
parameters that outputs sound. Nice for checking how in tune it is and

Your examples provide the benefit of allowing arbitrary shapes. I could
probably use it to make a trombone bell that's bent so it fits in my
printers 250x213x200mm volume and print it all in one part.







--
View this message in context: http://forum.openscad.org/Curved-bent-conical-tubing-tp20686p20699.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
pieterbos
2017-03-02 21:14:26 UTC
Permalink
So it works and renders - thanks a lot for your help! the entire thing
preview rendered now looks like this:

<Loading Image...>

The thing attached to the tuning slide is for printing without supports.
Let's hope that engraved text will print well and that it's sturdy enough :)



--
View this message in context: http://forum.openscad.org/Curved-bent-conical-tubing-tp20686p20700.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
Ronaldo
2017-03-02 23:26:48 UTC
Permalink
Post by Parkinbot
nice! Here some minimalistic "free style" interpolation code for playing
around.
Parkinbot: the minimalistic magician! :)

I tip my hat to your style but I am not able to adopt it. We have different
approaches. I am trying to create more sophisticated tools that require a
minimum amount of data to build a model. You start from a very basic but
powerful tools (sweep.scad, spline.scad, shortcuts, etc) and code the
generation of lots of data in a very concise (sometimes hard to read :) )
form. Your approach requires more understanding of the modeling process
resorting to a few flexible tools. Mine resorts to more specialized but less
flexible functions.

To shape a sax, for instance (I have modeled it before the bugle), I started
with a minimum of data:

//* sax shape
sax_path = [ [0,0,28],
[18,0,22.5],
[27,0,16],
[28.5,0,13],
[29,0,0],
[29,0,-15],
[29,0,-30],
[29,0,-45],
[30,0,-56],
[41,0,-56],
[44,0,-45],
[44,0,-30],
[44.2,0,-18],
[50,0,-11],
[50,0,-11],
];
sax_rads = [ 1.8, 2, 3.3, 3.7, 4, 4.2, 4.4, 4.6, 6.0, 6.5, 6.3, 6.3, 6.3,
8.7, 12];

sax_rim_size = 1;

The sax_path defines a spine for the sax and the sax_rads controls the
radiuses of the outer sax surface at each point in the path. There is no
user data to position the circles in the space except its center - the spine
points. To position the circles I have used the technique found in Linde's
sweep.scad, that is: find the spine tangent at each point and define the
circle plane as the one orthogonal to the tangent and passing about the
point (mapShapes2Path() bellow).

To define the surface, the positioned circles are taking as control points
of a B-spline. I tried with a spline interpolator first and gave up because
it is very hard to set the input data to get the shape you have in mind.
Spline interpolator usually oscillates more than the input data and produces
unexpected shapes.

So I have switched to B-splines. They are simpler to compute then
interpolator splines and easy to model with after you are used to it. That
was the result:

<Loading Image...>
<Loading Image...>

In the image, the (translated) spine is represented in red and the
positioned circles in yellow. The small yellow blocks near the spine are the
sax_path positions. The blue blocks are the first points of each circle
showing that the surface twist is minimum. As it is apparent from the side
view, the dimensions of the shape does not equals the circle radiuses. But
the relation between the shape and the input circles is more predictable.

The code generating this model is relatively straightforward.
Post by Parkinbot
// the circular shapes - ctrl points of the spline
lshp = [ for(rad=rads) circle(r=rad) ];
// the inner surface radiuses
irads = [for(rad=rads) rad-0.5];
// the inner surface circular shapes
ilshp = [ for(rad=irads) circle(r=rad) ];
// the spine line of the sax
pts = BSplineCurve(path,3);
// maps the circles of the outer and inner surfaces to 3D space
shps = mapShapes2Path(lshp, path, cl=false);
ishps = mapShapes2Path(ilshp, path, cl=false);
// reverts the inner shape to concatenate it with the outer one
rishps = reverse(ishps);
// the outer shape
outer = loftBS(shps, n=floor(ln($fn)),cl=true);
// the inner shape
inner = loftBS(rishps, n=floor(ln($fn)), cl=true);
// the horn rim
horn_rim = _loftSurfacesG1(outer,inner,h1=rim_size,h2=rim_size,nu=20);
// the full model mesh
inout = concat(outer,horn_rim,inner,[outer[0]] );
// build the mesh polyhedron
color("gold")
mesh(inout);
This is a test code. My intention is to wrap almost all the code above in a
function.

Far from minimalistic though.



--
View this message in context: http://forum.openscad.org/Curved-bent-conical-tubing-tp20686p20703.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
Parkinbot
2017-03-03 11:28:40 UTC
Permalink
Post by Ronaldo
I tip my hat to your style but I am not able to adopt it. We have
different approaches.
Ronaldo, what you showed is again a very nice design. Basically we follow
the same way and I perfectly agree with you about programming styles. I also
almost hate it to read other peoples code, especially when the code is
lenghty, badly structured, and uses variable names like
"the_inner_diameter_of_the_upper_part" are used that mess up the code
outline. A few days ago I downloaded some pulley design code having a very
high like count, because I wanted to save time. In the end I spent more than
three hours to understand what's going on until I finally got to the point I
wanted to adopt it to my needs. Thus my intention here is to give simplistic
examples and approaches for adressing complex problems, and to show up
coding styles that go beyond the usual aggregates of union, intersection,
difference, translation, scale and rotation. Refinement should/can be done
after selecting the right approach. Starting with a wrong approach, is like
buying too cheap. You will be annoyed sooner or later.

I also agree that B-splines are much more intuitive and carefree in use,
because they don't overshoot. I haven't implemented them yet, because I
hardly ever need interpolation. Of course it makes up a good approach to
keep the interpolation scheme interchangeable. So we should put our stuff
together one day to compose a good interpolation library using a common
interface. But for now I won't spend time on that, until I really get hands
on the vertex data of OpenSCAD objects.




--
View this message in context: http://forum.openscad.org/Curved-bent-conical-tubing-tp20686p20707.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

Parkinbot
2017-03-02 09:21:47 UTC
Permalink
Sorry, I didn't read this post earlier. Your problem has a classical
solution: a general sweep() or skin(). Try this code piece to get a conical
tube:
<Loading Image...>
use
<Naca_sweep.scad>
http://www.thingiverse.com/thing:1208001
outer = conicbow_traj();
inner = conicbow_traj(r=100, a1=180, a2 = 0, r1=18, r2=8, N=100);
sweep(concat(outer, inner), close = true);
function conicbow_traj(r=100, a1=0, a2 = 180, r1=10, r2=20, N=100) =
[for (i=[0:N-1]) let(R = r1+i*(r2-r1)/N) Rx_(a1+i*(a2-a1)/(N-1), Ty_(r,
circle_(R)))];
function circle_(r=10, N=30) =
[for (i=[0:N-1]) [r*sin(i*360/N), r*cos(i*360/N), 0]];
If you dig a bit deeper into http://www.thingiverse.com/thing:1208001 you
will find an interpolation scheme that lets you describe any curvature by
just defining a few "slices".




--
View this message in context: http://forum.openscad.org/Curved-bent-conical-tubing-tp20686p20691.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
Continue reading on narkive:
Loading...