Discussion:
[OpenSCAD] Non-Linear Transformations
Trygon
2015-11-16 15:11:33 UTC
Permalink
OpenSCAD currently supports a whole range of specific linear transformations
such as translate(), rotate() and scale(), in addition to the generic linear
transformation multmatrix().

OpenSCAD does not provide support for non-linear transformations. I think
support for non-linear transformations would be very useful and this could
be accomplished with a new transformation command:

transform(x_expression, y_expression, z_expression)

reserved names within transform() expressions: x, y & z, these represent the
vertex being processed

The examples below use this syntax.

Equivalent Linear Transformations:

1) pass data through, no change to vertices
transform(x, y, z) { ... }

2) scale([xf,yf,zf]) { ... } <-> transform(xf*x, yf*y, zf*z) { ... }

3) translate([x1,y1,z1]) { ... } <-> transform(x+x1, y+y1, z+z1) { ... }

4) multmatrix([[xx, xy, xz, xc], [yx, yy, yz, yc], [zx, zy, zz, zc], [0, 0,
0, 1]) { ... } <->
transform(xx*x+xy*y+xz*z+xc, yx*x+yy*y+yz*z+yc, zx*x+zy*y+zz*z+zc) { ...
}

Non-Linear Transformations:

1) exponential x scaling
transform(x*x, y, z) { ... }

2) "conic" expansion in x-y plane, scale factor=1 for z=20
transform(x*z/20 ,y*z/20 ,z) cylinder(h=40, r=10);

3) scale specific co-ordinate ranges
transform(x>0?2*x:x, abs(y)>50?3*y:y, z) { ... }

4) insert "gap" of 40mm centred on y=0
transform(x ,y>0?y+20:y-20, z) cylinder(h=20, r=10);

Comments please!

Cheers,
Trygon




--
View this message in context: http://forum.openscad.org/Non-Linear-Transformations-tp14539.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
Marius Kintel
2015-11-16 15:29:01 UTC
Permalink
Post by Trygon
OpenSCAD does not provide support for non-linear transformations. I think
support for non-linear transformations would be very useful and this could
Would this be conceptually similar to the proposed bend modifier?

https://github.com/openscad/openscad/issues/815

-Marius
Trygon
2015-11-16 18:09:33 UTC
Permalink
Yes this could be used to bend objects, I think this would work:

transform(y*sin(x), y*cos(x), z)

As noted in the proposed bend modifier discussion, unless the object has
sufficient vertices it will just deform (unpleasantly), e.g. a simple cube
with 8 vertices would not work well. However this is a different issue.

If the use of x, y & z as reserved names makes the "syntax looks as if
conventional parameters were passed", perhaps x(), y() & z() could be used
instead as reserved functions, such that "the arguments need to
be...functions"?

The above example would become:

transform( y()*sin(x()), y()*cos(x()), z() )

-Trygon




--
View this message in context: http://forum.openscad.org/Non-Linear-Transformations-tp14539p14551.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
Trygon
2015-11-16 18:36:58 UTC
Permalink
// non-linear transformation: 2D bend demo

x1=-40;
x2=40;
y1=30;
y2=40;
step=10;

p1=concat([for(i=[x1:step:x2]) [i,y1]],[for(i=[x2:-step:x1]) [i,y2]]);
polygon(p1);

// translate([0,-20,0]) transform(y*sin(x),y*cos(x)) polygon(p1);
p2=[for(i=p1) [i[1]*sin(i[0]),i[1]*cos(i[0])]];
translate ([0,-20,0]) polygon(p2);




--
View this message in context: http://forum.openscad.org/Non-Linear-Transformations-tp14539p14554.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
Trygon
2015-11-16 22:34:57 UTC
Permalink
1) Given that a transform function could be defined in OpenSCAD as:

function transform(v)=let(x=v[0], y=v[1], z=v[2]) [x*z/20, y*z/20, z];

which maps a single vertex to a new position (as per doug.moen: vector in,
vector out), perhaps a better syntax would be:

transform()=[x*z/20, y*z/20, z] { ... }

2) I have been using non affine transformations in my code for a while and
the world has not ended. Yes they do have to be used with care, but are
useful. The main issue is that they can only be used at present when all the
geometry data has been computed directly so that the vertex data is visible.

-Trygon



--
View this message in context: http://forum.openscad.org/Non-Linear-Transformations-tp14539p14585.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
Neon22
2015-11-17 00:16:09 UTC
Permalink
I applaud the approach of use mathematical equations to define the curve.
However IMHO we also want to easily support the user making the curve
manually. (current list-comprehensions and paths, lofts not quite easy
enough to use IMHO)

E.g.
A 2D polygon (profile) extruded along its (face) normal by D. Then rotated
around its center by Rz degrees.
Loop this N times to get an extruded "twist" of the profile.
E.g.
Same as above but also rotating Rx each increment around the X axis (on edge
of profile shape).
Changing the above into a twisted arch.
E.g
Same as above but starting profile is a square and ending profile is a
pentagon.
Changing the above into a more complex mesh.

So critical aspects are:
- Derived normal per iteration, so we tell which direction vector to move
along.
- Looping construct around the outside for N steps. (for)
- Local transformation, so rotating around edge of profile has new
location(globally) but same location(locally) when in middle of the
sequence.
- Ideally a way to interpolate an intermediate shape between two shapes with
different numbers of vertices.
Either by:
- sampling the edges intitially and making more intermediate points, then
moving each vertex in linear interp(say) at each step.
- AND/OR by auto-triangulation when increasing number of vertices.

These are the aspects I would like to see in OpenSCAD, to make it easy to
make many more complex useful objects in an incremental, rather than math
function, way.



--
View this message in context: http://forum.openscad.org/Non-Linear-Transformations-tp14539p14588.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
ctchin
2015-11-17 05:44:53 UTC
Permalink
kintel spoted my mistake, x*z is non-affine so, sorry I was wrong on that
point. I was thinking (I forgot the proper term until doug gave it) about
perspective transformation which can be represented by a 4x4 matrix but not
supported in OpenSCAD.
Post by Marius Kintel
don’t support non-affine transformations because CGAL doesn’t.
So yes, now that I've been better educated I remember at one point needing
perspective transformation desperately and cursing OpenSCAD for not doing it
for me. But after some attempts, I switch track to trying to solve my
problem by some ways other than transformation. Of course there's no
general solution to substituting a general perspective transformation with
legal OpenSCAD commands, but I found a way to do exactly what I wanted to
design at the time, printed it, published it and be done with it.

I see OpenSCAD as a toy, a fantastic toy (hope no one takes offense). But
it's not a proper programming language. If my design involves some complex
math or algorithm, I would rather do the math in a language I normally use
for math and engineering problems. I have written a ton of codes in Matlab,
C, VC, Java, perl, python, Basic, Fortran and even a few scripting languages
on Unix. Even if OpenSCAD+ or OpenSCAD2 adopt function pointers (I use them
extensively in Matlab and C), typedef, object/solid handle/pointers, mutable
variables, etc etc. Things that make OpenSCAD not nearly as convenient as
conventional procedural languages. It's actually re-assuring OpenSCAD is
handicapped. It motivates me to keep using the languages I'm familiar with
for math and engineering. And only use OpenSCAD for 3D (printing) output.

If another still remember PostScript, I remember learning a tiny of of its
syntax and some commands. I remember being told PostScript can do
"anything". And I remember tell myself, don't get sucked in, just fix the
thesis (so that the printer can accept it) and graduate and get out of
school.

In my work, I am making a prototype which involves over a hundred hexagons
arranged in a way based on the geodesic dome. Now I don't know if it's
possible to realize this hexagonal geodesic in OpenSCAD. Even if it's
possible I know for sure I can do it faster and more powerful in Matlab, so
I use Matlab to calculate the hexagons, have Matlab generate a module
hexs.scad which contain 100+ hexagonal cylinders. And then a prototype.scad
that use<hexs.scad> and add the structural support, base, drill holes for
mounting screws and even imprint a logo on the base.

For my own selfish purpose, I'd rather spend time hacking together a
solution with all the available tools (of which OpenSCAD is but one)
((another being KraGle)) than prodding or telling someone smarter than me
how to do their things my way.

When I choose a tool, I look not only at its (advertised) features and
functions, I more often make a judgement on the user community + development
team. OpenJSCAD and various other similar programmatic CAD may have more
powerful features, but OpenSCAD is the only one enjoying a wide(ish) user
base and actively maintained and supported. And I fear that some of the
radical changes being requested will destroy it. Not due to technical
merits but human/societal factors.



--
View this message in context: http://forum.openscad.org/Non-Linear-Transformations-tp14539p14591.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
Alan Cox
2015-11-17 10:05:14 UTC
Permalink
Post by ctchin
For my own selfish purpose, I'd rather spend time hacking together a
solution with all the available tools (of which OpenSCAD is but one)
((another being KraGle)) than prodding or telling someone smarter than me
how to do their things my way.
Likewise I mostly use other tools to output OpenSCAD object
representations. Having OpenSCAD to do the grunt work is brilliant and if
- ok when - I need to debug the results of my programs it the UI and the
integration are great. Some stuff I use ImplicitCAD for because OpenSCAD
really can't handle the object, but my choice is definitely OpenSCAD.

I could in theory do it all in OpenSCAD but it would be ugly and probably
I would need to add the ability to bend a 3D object to a path for some of
the stuff I generate.

I'd also rather keep the stranger things I need to do from messing up
OpenSCAD for novices, and losing its friendly, easy to get nature for
beginners - especially non programmers. Lots of people need a beginner 3D
design tool, not many people need tools for generating model railway
carriage shells to match etched brass sides 8)

Alan
Trygon
2015-11-17 11:37:01 UTC
Permalink
Just because a command exists, doesn't mean you have to use it.

If the command transform() existed in OpenSCAD, I wouldn't include it in an
example intended for a beginner, nor would I include multmatrix() which also
has immense geometry mangling capability!

If OpenSCAD was to be made "safe" for beginners, I think the polygon() &
polyhedron() commands would need to be removed for starters, since they
expose vertex data... where would this end?

Books on C programming don't start with pointer arithmetic. In fact
Kernighan & Ritchie state, "Pointers ... [are] a marvelous way to create
impossible-to-understand programs ... however, pointers can also be used to
achieve clarity and simplicity." I think this sums up the potential of an
OpenSCAD transform() command: powerful, but dangerous if used without care.

-Trygon




--
View this message in context: http://forum.openscad.org/Non-Linear-Transformations-tp14539p14596.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
clothbot
2015-11-17 14:01:12 UTC
Permalink
Post by Trygon
Just because a command exists, doesn't mean you have to use it.
If the command transform() existed in OpenSCAD, I wouldn't include it in
an example intended for a beginner, nor would I include multmatrix() which
also has immense geometry mangling capability!
I disagree, but with the qualification that translate(), rotate(), scale(),
mirror() and multmatrix() should be introduced in the context of forward
kinematics (see https://en.wikipedia.org/wiki/Forward_kinematics).

Side note: We *really* need a matrix inverse() function for completeness.
The eigen3 library which OpenSCAD makes use of has matrix inverse functions
(see
http://eigen.tuxfamily.org/dox/classEigen_1_1MatrixBase.html#aa2834da4c855fa35fed8c4030f79f9da),
along with other useful things like plane-to-plane intersection (see
http://eigen.tuxfamily.org/dox/classEigen_1_1Hyperplane.html#ad10ca15c93ee4d825f92a2c4563ed678).

The scale(), rotate(), mirror() and translate() operators can be thought of
as "convenience wrappers" for the general-purpose multmatrix() operator. I
find multi-axis rotate() operations are easier to get a handle on if you
understand the order in which successive matrix multiplications are
happening -
https://github.com/openscad/openscad/blob/master/src/transform.cc#L119 - but
more often than not I'll break them up into explicit, single-axis rotate()
operations to keep track of where things are going.

Andrew.




--
View this message in context: http://forum.openscad.org/Non-Linear-Transformations-tp14539p14599.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
Parkinbot
2015-11-17 12:30:11 UTC
Permalink
Having followed this thread now for a while, I can see that obviously many of
us are trying to merge stuff implemented in several languages with OpenSCAD
and vice versa. One might call it loony stuff, but isn't a programming
language meant for being able to do loony stuff, without being loony itself?

The usual affine (and also some non affine) stuff can also be done with
other CAD programs by people, who love to drag around things with their
mouse. So there is an urgent need for more flexibility in a programming
language. And to be honest, the way functions and loops are expressed in
OpenSCAD is even more loony than in most programming languages that have
crossed my way in 35 years of programming. Prolog seems to be closest to it,
but this code is somehow better readable. I know that declarative
programming has its pros and cons, so please don't understand this as severe
criticism. It has been done great job so far, and a steadily growing
community is a good proof for this.

But as we are talking here about new features, their impact to the language
and how to use and implement them, it gets more and more clear to me that
OpenSCAD either needs more expressive power in terms of function and include
flexibility or minimum an API-function allowing to access library stuff
implemented in other languages. This service could be started on the basis
of a function prototype allowing for input and output of vectors only (maybe
also for strings) and lead to a steadily growing OpenSCAD automation model
with client and server functionality.
For now people like Kintel and me output .scad files from Matlab or other
high level languages to at least import vectors or other programmatic stuff,
that cannot be expressed in OpenSCAD with reasonable effort.
I'm currently doing a hard job implementing multidimensional cubic spline
functionality in OpenSCAD, which you get in Matlab with three lines, using
cscvn() or with five lines using 2D cubic splines. My aim is to escape
affinity and to be able to sweep around parametrized 2D-airfoil data in 3D
space and get smooth transitions between different parameter sets, without
having to code it the very hard way, as I have done it in
http://www.thingiverse.com/thing:900137
<http://www.thingiverse.com/thing:900137>

This is what I get out of a 7 by 4 vector using spline interpolation to
sweep around circles:

<Loading Image...>

Loony stuff, especially when you think about using it n-dimensional for
other shapes like airfoils, gears and so on. But isn't it, what programmers
want to do and why programmers are programmers and not users?




--
View this message in context: http://forum.openscad.org/Non-Linear-Transformations-tp14539p14597.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
jon
2015-11-17 12:46:42 UTC
Permalink
I love the "organic" sense of the PNG you provided. While others in
this group have come up with organic shapes with apparent ease, this is
one area where I struggle. I look forward to learning more about the
tools you are using and creating.

Thank you!

Jon
Post by Parkinbot
Having followed this thread now for a while, I can see that obviously many of
us are trying to merge stuff implemented in several languages with OpenSCAD
and vice versa. One might call it loony stuff, but isn't a programming
language meant for being able to do loony stuff, without being loony itself?
The usual affine (and also some non affine) stuff can also be done with
other CAD programs by people, who love to drag around things with their
mouse. So there is an urgent need for more flexibility in a programming
language. And to be honest, the way functions and loops are expressed in
OpenSCAD is even more loony than in most programming languages that have
crossed my way in 35 years of programming. Prolog seems to be closest to it,
but this code is somehow better readable. I know that declarative
programming has its pros and cons, so please don't understand this as severe
criticism. It has been done great job so far, and a steadily growing
community is a good proof for this.
But as we are talking here about new features, their impact to the language
and how to use and implement them, it gets more and more clear to me that
OpenSCAD either needs more expressive power in terms of function and include
flexibility or minimum an API-function allowing to access library stuff
implemented in other languages. This service could be started on the basis
of a function prototype allowing for input and output of vectors only (maybe
also for strings) and lead to a steadily growing OpenSCAD automation model
with client and server functionality.
For now people like Kintel and me output .scad files from Matlab or other
high level languages to at least import vectors or other programmatic stuff,
that cannot be expressed in OpenSCAD with reasonable effort.
I'm currently doing a hard job implementing multidimensional cubic spline
functionality in OpenSCAD, which you get in Matlab with three lines, using
cscvn() or with five lines using 2D cubic splines. My aim is to escape
affinity and to be able to sweep around parametrized 2D-airfoil data in 3D
space and get smooth transitions between different parameter sets, without
having to code it the very hard way, as I have done it in
http://www.thingiverse.com/thing:900137
<http://www.thingiverse.com/thing:900137>
This is what I get out of a 7 by 4 vector using spline interpolation to
<http://forum.openscad.org/file/n14597/loony.png>
Loony stuff, especially when you think about using it n-dimensional for
other shapes like airfoils, gears and so on. But isn't it, what programmers
want to do and why programmers are programmers and not users?
--
View this message in context: http://forum.openscad.org/Non-Linear-Transformations-tp14539p14597.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
_______________________________________________
OpenSCAD mailing list
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
-----
No virus found in this message.
Checked by AVG - www.avg.com
Version: 2016.0.7227 / Virus Database: 4457/11015 - Release Date: 11/17/15
ctchin
2015-11-18 04:28:42 UTC
Permalink
Post by Parkinbot
Having followed this thread now for a while, I can see that obviously many
of us are trying to merge stuff implemented in several languages with
OpenSCAD and vice versa. One might call it loony stuff, but isn't a
programming language meant for being able to do loony stuff, without being
loony itself?
...
Loony stuff, especially when you think about using it n-dimensional for
other shapes like airfoils, gears and so on. But isn't it, what
programmers want to do and why programmers are programmers and not users?
Well not un-deliberately, my wording loony was a bit vague. I love the NACA
you created and Joukowski (that's how my fluid mech book spells it) airfoil
Trygon created. My point about loony isn't about amazing and beautiful
things that the users created (or better: may create) but too often some
users have some vague idea and expect OTHER people to do the hard work for
them.

In general conformal mapping is a powerful branch of math that make some
very useful shapes.

Especially you and Trygon's code showed the existing OpenSCAD commands are
powerful enough if only more people put some hard work into it. I'd invite
you to put some of your code into a library that I'm advocating.

Now yes... you have been convincing there are room to expand some sort of
distortion, transformation or something in OpenSCAD (like I hinted at, I've
been frustrated with it myself). But I'm not sure you have been convincing
enough that the core team should take on this task as priority, soon.

OpenSCAD is open source, there's an open invitation on the main website to
add new features. This "debate" would be a lot more substantial if someone
create a new transformation and make a pitch that it should be included into
the main branch.

After seeing some substantive response to the "loony" challenge... I was
thinking how to enable some of the "loony" ideas to progress without
unwanted side-effects. The answer seems obvious, create a plug-in
interface.

Surely it has been requested and discussed before... browsing the issues on
github... am I seeing it right? It's not been posted as a new feature
request? Wonder if I should open a new thread on it...




--
View this message in context: http://forum.openscad.org/Non-Linear-Transformations-tp14539p14611.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
Trygon
2015-11-18 08:58:42 UTC
Permalink
The dark art of non affine transformations part II - Art (?) :

// this does not actually work, there is no transform() command at present!
transform()=let(sf1=1+sin(12*atan2(y,x))/8, sf2=2+cos(z*1.1+70))
[x*sf1*sf2, y*sf1*sf2, z] cylinder(h=300, r=50, center=true, $fn=240);

-Trygon

<Loading Image...>



--
View this message in context: http://forum.openscad.org/Non-Linear-Transformations-tp14539p14615.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
Trygon
2015-11-18 09:28:19 UTC
Permalink
The same non affine transformation applied to a different solid:

// this does not actually work, there is no transform() command at present!
transform()=let(sf1=1+sin(12*atan2(y,x))/8, sf2=2+cos(z*1.1+70))
[x*sf1*sf2, y*sf1*sf2, z] cube(size=[100, 100, 300], center=true);

<Loading Image...>



--
View this message in context: http://forum.openscad.org/Non-Linear-Transformations-tp14539p14616.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
ctchin
2015-11-18 12:17:25 UTC
Permalink
You could also do some nice things without non-affine transformation.

Thanks to the warm discussion, I spent my day (not quite 7 hours of coding)
making the blood vessel I wanted 2 months ago. Sometimes all it take is
some determination.

~80 lines of code (with comments) gave me what I needed, without even
resorting to Matlab.

Pushing 200 lines of code if I kept all the debugging/evolving codes in
place. Note that the pipe diameter changes along the pipe length, the wall
thickness is very nearly uniform.

Plus now I have a new library for making cylinders and pipes along an
arbitrary (but not too crazy) curve.

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




--
View this message in context: http://forum.openscad.org/Non-Linear-Transformations-tp14539p14618.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
runsun
2015-11-18 14:47:52 UTC
Permalink
Post by ctchin
~80 lines of code (with comments) gave me what I needed, without even
resorting to Matlab.
Pushing 200 lines of code if I kept all the debugging/evolving codes in
place. Note that the pipe diameter changes along the pipe length, the
wall thickness is very nearly uniform.
Plus now I have a new library for making cylinders and pipes along an
arbitrary (but not too crazy) curve.
Can you share how you join the two tubes? partial code would be even better.




-----

$ Runsun Pan, PhD

$ libs:

doctest ,

faces ( git ),

offline doc ( git ),

runscad.py( 1 , 2 , git );


$ tips:

hash( 1 , 2 ),

sweep ,

var( 1 , 2 ),

lerp ,

animGif ,

precision








--
View this message in context: http://forum.openscad.org/Non-Linear-Transformations-tp14539p14620.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
ctchin
2015-11-18 19:03:01 UTC
Permalink
Heheh, I guess you have asked for the crucial trick. The question is how to
join two cylinders at an angle with a satisfactory "elbow". Once you
figured that, the rest is just putting the Lego pieces together to make
cylinders and pipes along any paths. Branching also becomes obvious.

The following code is robust, except for one factor: h=2*d0, the factor 2 is
arbitrary and will fail if angle is too small. It's easy enough to fix, but
I've decided to finish working on my branching vessels rather than fix a
problem that only happens with unnatural-looking kinks.

The color("red") is obviously unnecessary, it's just to show the important
"elbow".





--
View this message in context: http://forum.openscad.org/Non-Linear-Transformations-tp14539p14626.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
Parkinbot
2015-11-18 20:55:22 UTC
Permalink
If I was a pipe I'd prefer to be modelled like this (works for any angle ):





--
View this message in context: http://forum.openscad.org/Non-Linear-Transformations-tp14539p14627.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
ctchin
2015-11-19 06:20:07 UTC
Permalink
Parkinbot wrote

* SMACK FOREHEAD *

Doh of course you are right! My brain was stuck from a previous design for
which the sphere wouldn't work, but for cylinders of course a spherical
elbow is easier and prettier.

THANKS!

(anyway the model with the ugly angular joints already went and come back
from the printer)

<Loading Image...>



--
View this message in context: http://forum.openscad.org/Non-Linear-Transformations-tp14539p14639.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
runsun
2015-11-18 22:11:49 UTC
Permalink
Thx, ctchin. That's neat.

Since I spent most of design in polyhedron, what I am most interested in is
how two polyhedrons join/branch.





-----

$ Runsun Pan, PhD

$ libs:

doctest ,

faces ( git ),

offline doc ( git ),

runscad.py( 1 , 2 , git );


$ tips:

hash( 1 , 2 ),

sweep ,

var( 1 , 2 ),

lerp ,

animGif ,

precision








--
View this message in context: http://forum.openscad.org/Non-Linear-Transformations-tp14539p14633.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
runsun
2015-11-18 22:21:57 UTC
Permalink
btw, ctchin, posts in this thread, Bent rod
<http://forum.openscad.org/Bent-rod-tp14003p14004.html> , might give some
ideas. Among them, my version:

<Loading Image...>



-----

$ Runsun Pan, PhD

$ libs:

doctest ,

faces ( git ),

offline doc ( git ),

runscad.py( 1 , 2 , git );


$ tips:

hash( 1 , 2 ),

sweep ,

var( 1 , 2 ),

lerp ,

animGif ,

precision








--
View this message in context: http://forum.openscad.org/Non-Linear-Transformations-tp14539p14634.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
Parkinbot
2015-11-19 02:17:33 UTC
Permalink
Usually, an (implicit) union joins overlapping or matching (there is always a
numerical error!) objects. This happens also with polyhedrons. If you
calculate your own polyhedrons (your example doesn't look so) just provide
some very small overlapping.
BUT, when I try to implement your example along the "broadway", say, like
this:


I'm getting this:
<Loading Image...>

I remember that the convexity parameter of linear_extrude() never worked
properly with me, so in the end to get more out of it I implemented a
fullblown library to bypass it on the basis of hull(). Just have a look at:
http://www.thingiverse.com/thing:648813
Post by runsun
btw, ctchin, posts in this thread,
Bent rod <http://forum.openscad.org/Bent-rod-tp14003p14004.html>
<http://forum.openscad.org/file/n14004/20150925_bent_pipe.png>




--
View this message in context: http://forum.openscad.org/Non-Linear-Transformations-tp14539p14636.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
Neon22
2015-11-19 02:12:16 UTC
Permalink
Post by ctchin
Branching also becomes obvious.
If I was a pipe I'd prefer to be modelled like this (works for any angle
I was playing with these two approaches and tried to make a generalized tree
branching with fillets between.

Its working well for direct code but I wanted to use a list and a for loop.
Alas the for loop does an implied union() and so the children() is not
working.
My brain has frozen on how to get around it.
E.g. I have this: (images in forum)

use <fillet.scad>
// from clothbot
// - https://github.com/clothbot/ClothBotCreations/tree/master/utilities

d0 = 10;
h1 = 30;
h2 = 20;
angle = -66;

// Parkinbot approach (filleted)
translate([30,20,0])
fillet(r=2,steps=2) {
rotate([angle,0,0])
cylinder(h1, d=d0);
cylinder(h2, d=d0);
// join
color("red")
sphere(d0/2);
}



// ctchin approach (filleted)
translate([30,-20,0])
fillet(r=2,steps=4) {
rotate([angle,0,0]) cylinder(h1, d=d0);
cylinder(h2, d=d0);
// join
color("red")
intersection() {
rotate([angle,0,0])
translate([0,0,-2*d0])
cylinder(d=d0,h=2*d0);
translate([0,0,-2*d0])
cylinder(d=d0,h=2*d0);
}
}

//-----------------------------
// Each branch is a cylinder with [diameter, startpt, anglexyz, length]
// - startpt, anglexyz are triplets
// generalize later to use shape profile instead of circle (cylinder)
// (one day alllow random variation in deformation along length of the
branch object)
branches = [
[10, [0,0,0], [0,0,0], 40],
[10, [0,0,0], [45,0,0], 40],
[5, [0,0,30], [66,-22,0], 33],
[5, [0,0,25], [66,-22,250], 33],
];



module make_tree(branches=branches, blend=4, method="round") {
// add round/sharp in here
// how to get around implied union of for() ?
fillet(r=2,steps=4) {
for (b=branches) {
dia = b[0];
start = b[1];
angle = b[2];
dist = b[3];
translate(start)
rotate(angle)
cylinder(h=dist, d=dia);
}
}
}


make_tree();

To get a result like this:
<Loading Image...>

How do I pass all the results of the for loop to fillet() as children ?



--
View this message in context: http://forum.openscad.org/Non-Linear-Transformations-tp14539p14635.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
Parkinbot
2015-11-19 03:01:09 UTC
Permalink
@Neon: If something is against you, better try to befriend it.
OK, I know, this is more a work around than the solution you are seeking,
but I'm afraid you won't get rid of the implicit union.

<Loading Image...>





--
View this message in context: http://forum.openscad.org/Non-Linear-Transformations-tp14539p14637.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
Neon22
2015-11-19 05:10:05 UTC
Permalink
ok that's pretty nice.
I guess the disadvantage is the exponential work done as each fillet is
applied to the growing object and one new part.
Maybe in OpenSCAD2 .
Thanks...



--
View this message in context: http://forum.openscad.org/Non-Linear-Transformations-tp14539p14638.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
Parkinbot
2015-11-19 13:03:57 UTC
Permalink
You are right. A better solution would be the following approach. I didn't
present it, as I forgot how to express a partial array (Was it ever possible
in OpenSCAD to express a partial array like branches[2:4] ) Overcoming this
obstacle with the tail function, this is your proper and fast solution
ver2.0:

(By the way: a nice approach .)
Post by Neon22
I guess the disadvantage is the exponential work done as each fillet is
applied to the growing object and one new part.
--
View this message in context: http://forum.openscad.org/Non-Linear-Transformations-tp14539p14644.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
Mark Schafer
2015-11-19 22:18:14 UTC
Permalink
Yes I used this pattern
for (i=[1:len(branches)]) {
b = branches[i];
Post by Parkinbot
You are right. A better solution would be the following approach. I didn't
present it, as I forgot how to express a partial array (Was it ever possible
in OpenSCAD to express a partial array like branches[2:4] ) Overcoming this
obstacle with the tail function, this is your proper and fast solution
(By the way: a nice approach .)
doug moen
2015-11-19 23:04:37 UTC
Permalink
parkinbot: Was it ever possible in OpenSCAD to express a partial array like
branches[2:4]?

Currently you must write
[for(i=[2:4])branches[i]]

Many people have asked for a more direct 'slice' operator, but we don't
have one yet. Multiple syntaxes have been proposed.
Post by Parkinbot
You are right. A better solution would be the following approach. I didn't
present it, as I forgot how to express a partial array (Was it ever possible
in OpenSCAD to express a partial array like branches[2:4] ) Overcoming this
obstacle with the tail function, this is your proper and fast solution
(By the way: a nice approach .)
Post by Neon22
I guess the disadvantage is the exponential work done as each fillet is
applied to the growing object and one new part.
--
http://forum.openscad.org/Non-Linear-Transformations-tp14539p14644.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
_______________________________________________
OpenSCAD mailing list
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
doug moen
2015-11-18 14:13:33 UTC
Permalink
The proposed tranform() module is awesome, no doubt.

If this gets implemented before OpenSCAD2, then I would like the syntax to
be forward compatible with OpenSCAD2. Like this:

transform(
f(x,y,z)=
let (sf1=1+sin(12*atan2(y,x))/8, sf2=2+cos(z*1.1+70))
[x*sf1*sf2, y*sf1*sf2, z] )
cube(size=[100, 100, 300], center=true);
Post by Trygon
// this does not actually work, there is no transform() command at present!
transform()=let(sf1=1+sin(12*atan2(y,x))/8, sf2=2+cos(z*1.1+70))
[x*sf1*sf2, y*sf1*sf2, z] cube(size=[100, 100, 300], center=true);
<http://forum.openscad.org/file/n14616/TransformArt2.png>
--
http://forum.openscad.org/Non-Linear-Transformations-tp14539p14616.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
_______________________________________________
OpenSCAD mailing list
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Marius Kintel
2015-11-18 16:02:41 UTC
Permalink
Trygon,

We’ve been compiling some demos of what can be done in user space by manually managing vertices:
https://github.com/openscad/list-comprehension-demos

This is more of a playground to explore what sort of functionality should be built into OpenSCAD.

For these demos, we currently only use 2D object as basis, see https://github.com/openscad/scad-utils/blob/master/shapes.scad

It would be cool to add some of your experiments to this repository, for purpose of creating a join exploratory playground until we land on a good interface for this kind of functionality.

Cheers,

-Marius
Trygon
2015-12-06 21:52:32 UTC
Permalink
The dark art of non affine transformations part III, solution to:

http://forum.openscad.org/Wave-spring-tp14948.html

Cheers,
Trygon

PS for documentation on function fa() see
http://forum.openscad.org/fe-Tolerance-based-arc-approximation-tp14212.html

// Trygon Dec2015 - non affine transformation: washer -> spring washer

$fe=0.01;

ro=10; // outside radius
ri=5; // hole radius
h=1; // washer thickness
hw=2; // wave height
nw=3; // number of waves

washer=WasherObject(ro,ri,h);
polyhedron(TransformPoints(washer[0],hw,nw),washer[1]);

function WasherObject(ro,ri,h) = let(
n=ceil(360/fa(ro)), // number of segments
p0=[for(i=[0:n-1]) let(a=i*360/n) [ro*cos(a),ro*sin(a),h/2]],
p1=[for(i=p0) [i[0]*ri/ro,i[1]*ri/ro,i[2]]],
p2=[for(i=p0) [i[0],i[1],-h/2]],
p3=[for(i=p1) [i[0],i[1],-h/2]])
[concat(p0,p1,p2,p3), // vertices
Unpack([for(i=[0:n-1]) let(j=(i+1)%n) [ // triangles
[i,j,j+n],[i,j+n,i+n],
[i+2*n,j+3*n,j+2*n],[i+2*n,i+3*n,j+3*n],
[i+2*n,j+2*n,j],[i+2*n,j,i],
[i+3*n,j+n,j+3*n],[i+3*n,i+n,j+n]
]])];

function TransformPoints(p,hw,nw) = [for(i=p) WaveTransform(i,hw,nw)];

function WaveTransform(v,hw,nw) = let(x=v[0],y=v[1],z=v[2])
[x,y,z+hw*sin(nw*atan2(x,y))/2];

function Unpack(p) = [for(i=p) for(j=i) j];

function fa(r)=$fn>0?360/($fn>3?$fn:3):
$fe>0?$fe<r?min(45,2*acos(1-$fe/r)):45:
360/max(min(360/($fa>0.01?$fa:0.01),
2*PI*r/($fs>0.01?$fs:0.01)),5);







--
View this message in context: http://forum.openscad.org/Non-Linear-Transformations-tp14539p14991.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
Trygon
2015-12-06 22:23:29 UTC
Permalink
Sorry, I just realised that I had the triangles inverted (points
anticlockwise rather than clockwise). I have corrected the original post.

Thanks,
Trygon



--
View this message in context: http://forum.openscad.org/Non-Linear-Transformations-tp14539p14996.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
ctchin
2015-11-18 04:36:19 UTC
Permalink
a hard job implementing multidimensional cubic spline functionality in
OpenSCAD, which you get in Matlab with three lines, using cscvn() or with
five lines using 2D cubic splines.
Totally beside the point: two months ago I challenged my grad student to
create a parametric model of a branching blood vessel on the 3D printer.
There's no progress so I pretty much forgot about it.

But your response to my "loony" charge gave me some crucial hints, I think I
can figure out the break-thru and the student can do the rest. Hopefully I
will hold a model in my hands by Monday.

Thanks!




--
View this message in context: http://forum.openscad.org/Non-Linear-Transformations-tp14539p14612.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
doug moen
2015-11-16 15:36:05 UTC
Permalink
This is a good example of what OpenSCAD2 is designed to enable.

OpenSCAD2 supports functions as first class values: functions can be passed
as arguments and returned as results. So the 'transform' module would not
need to be implemented as magic syntax. It would just be an ordinary module
that is passed 3 functions as arguments.

The syntax would look something like this:

// "conic" expansion in x-y plane, scale factor=1 for z=20
transform(fx(x)=x*z/20, fy(y)=y*z/20, fz(z)=z) cylinder(h=40, r=10);

The identity function gets used a lot with your scheme, so maybe we
predefine it. This is OpenSCAD2 function definition syntax:

id(x) = x;

Then,
// exponential x scaling
transform(fx(x)=x*x, fy=id, fz=id) { ... }

or just
transform(fx(x)=x*x, id, id) { ... }
Post by Trygon
OpenSCAD currently supports a whole range of specific linear
transformations
such as translate(), rotate() and scale(), in addition to the generic linear
transformation multmatrix().
OpenSCAD does not provide support for non-linear transformations. I think
support for non-linear transformations would be very useful and this could
transform(x_expression, y_expression, z_expression)
reserved names within transform() expressions: x, y & z, these represent the
vertex being processed
The examples below use this syntax.
1) pass data through, no change to vertices
transform(x, y, z) { ... }
2) scale([xf,yf,zf]) { ... } <-> transform(xf*x, yf*y, zf*z) { ... }
3) translate([x1,y1,z1]) { ... } <-> transform(x+x1, y+y1, z+z1) { ... }
4) multmatrix([[xx, xy, xz, xc], [yx, yy, yz, yc], [zx, zy, zz, zc], [0, 0,
0, 1]) { ... } <->
transform(xx*x+xy*y+xz*z+xc, yx*x+yy*y+yz*z+yc, zx*x+zy*y+zz*z+zc) { ...
}
1) exponential x scaling
transform(x*x, y, z) { ... }
2) "conic" expansion in x-y plane, scale factor=1 for z=20
transform(x*z/20 ,y*z/20 ,z) cylinder(h=40, r=10);
3) scale specific co-ordinate ranges
transform(x>0?2*x:x, abs(y)>50?3*y:y, z) { ... }
4) insert "gap" of 40mm centred on y=0
transform(x ,y>0?y+20:y-20, z) cylinder(h=20, r=10);
Comments please!
Cheers,
Trygon
--
http://forum.openscad.org/Non-Linear-Transformations-tp14539.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
_______________________________________________
OpenSCAD mailing list
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Martin Herdieckerhoff
2015-11-16 15:36:53 UTC
Permalink
I like the idea of providing non-linear transformations.
However, the suggested approach seems to break the current treatment of
parameters.
The suggested syntax looks as if conventional parameters were passed,
but actually the arguments need to be treated in a very different way,
that is as functions.
Others will know better if that syntax fits into the language.
But I am afraid that it does not.
What about enhancing the language by functions as arguments to provide
the suggested functionality?
Post by Trygon
OpenSCAD currently supports a whole range of specific linear transformations
such as translate(), rotate() and scale(), in addition to the generic linear
transformation multmatrix().
OpenSCAD does not provide support for non-linear transformations. I think
support for non-linear transformations would be very useful and this could
transform(x_expression, y_expression, z_expression)
reserved names within transform() expressions: x, y & z, these represent the
vertex being processed
The examples below use this syntax.
1) pass data through, no change to vertices
transform(x, y, z) { ... }
2) scale([xf,yf,zf]) { ... } <-> transform(xf*x, yf*y, zf*z) { ... }
3) translate([x1,y1,z1]) { ... } <-> transform(x+x1, y+y1, z+z1) { ... }
4) multmatrix([[xx, xy, xz, xc], [yx, yy, yz, yc], [zx, zy, zz, zc], [0, 0,
0, 1]) { ... } <->
transform(xx*x+xy*y+xz*z+xc, yx*x+yy*y+yz*z+yc, zx*x+zy*y+zz*z+zc) { ...
}
1) exponential x scaling
transform(x*x, y, z) { ... }
2) "conic" expansion in x-y plane, scale factor=1 for z=20
transform(x*z/20 ,y*z/20 ,z) cylinder(h=40, r=10);
3) scale specific co-ordinate ranges
transform(x>0?2*x:x, abs(y)>50?3*y:y, z) { ... }
4) insert "gap" of 40mm centred on y=0
transform(x ,y>0?y+20:y-20, z) cylinder(h=20, r=10);
Comments please!
Cheers,
Trygon
--
View this message in context: http://forum.openscad.org/Non-Linear-Transformations-tp14539.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
_______________________________________________
OpenSCAD mailing list
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
**
ctchin
2015-11-16 17:35:41 UTC
Permalink
Post by Trygon
1) exponential x scaling
transform(x*x, y, z) { ... }
2) "conic" expansion in x-y plane, scale factor=1 for z=20
transform(x*z/20 ,y*z/20 ,z) cylinder(h=40, r=10);
3) scale specific co-ordinate ranges
transform(x>0?2*x:x, abs(y)>50?3*y:y, z) { ... }
4) insert "gap" of 40mm centred on y=0
transform(x ,y>0?y+20:y-20, z) cylinder(h=20, r=10);
1) exponential: it should better be called power law or polynomial.
It's a relatively unique requirement...

2) conic: I believe it's actually linear and doable with a
simple multmatrix()

3) scale specific co-ordinate ranges and 4) insert gap
both are easily doable with a smartly written module
using difference() and/or projection()

So only the x = x*x exponential (sic) is new, I'm not
very convinced it justifies inventing a whole new syntax
for it.




--
View this message in context: http://forum.openscad.org/Non-Linear-Transformations-tp14539p14548.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
doug moen
2015-11-16 18:02:26 UTC
Permalink
Another way to represent the transformation is as a single function that
maps a point [x,y,z] to another point.

If you think of this function as mapping every point in a 3D shape, then
this is extremely powerful, as you can model any conceivable spatial
transformation: twisting, bending, etc.

In practice, there are difficulties, as pointed out by
https://github.com/openscad/openscad/issues/815

The problem is that, with many of the more interesting transformations,
it's not enough to simply transform each vertex. You may need to subdivide
the mesh to create smaller faces, and then transform each vertex in the
subdivided mesh. An example would be applying a twist or bend
transformation to a cube, with just the 8 vertices.
Post by ctchin
Post by Trygon
1) exponential x scaling
transform(x*x, y, z) { ... }
2) "conic" expansion in x-y plane, scale factor=1 for z=20
transform(x*z/20 ,y*z/20 ,z) cylinder(h=40, r=10);
3) scale specific co-ordinate ranges
transform(x>0?2*x:x, abs(y)>50?3*y:y, z) { ... }
4) insert "gap" of 40mm centred on y=0
transform(x ,y>0?y+20:y-20, z) cylinder(h=20, r=10);
1) exponential: it should better be called power law or polynomial.
It's a relatively unique requirement...
2) conic: I believe it's actually linear and doable with a
simple multmatrix()
3) scale specific co-ordinate ranges and 4 insert gap
both are easily doable with a smartly written module
using difference() and/or projection()
So only the x = x*x exponential (sic) is new, I'm not
very convinced it justifies inventing a whole new syntax
for it.
--
http://forum.openscad.org/Non-Linear-Transformations-tp14539p14548.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
_______________________________________________
OpenSCAD mailing list
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
doug moen
2015-11-16 18:13:42 UTC
Permalink
Following up on the "subdivision problem".

I really like the proposal from Trygon last month of using a $fe variable
to specify the "maximal acceptable error" in a polygonal approximation of a
solid.

Having come to OpenSCAD primarily from a design engineering background I am
used to specifying tolerances for specific features, e.g. 20mm +/- 0.1mm.
Wanting to use this principle for arc approximation I have adopted the
approach set out below which I hope might be useful to others.

The maximum error for a facet occurs at it centre, when it is furthest from
the true circular arc that it approximates. I use variable $fe in my
OpenSCAD scripts to specify the maximum acceptable value of this error (the
distance from the centre of the facet to the true circular arc, measured
normal to the facet). I then use the following function to calculate a
value for $fa based on the arc radius and $fe:

So now I'm wondering if we can create an algorithm for optimally
subdividing a polygon, using the minimum number of subdivisions necessary
to keep the error below $fe, when applying one of Trygon's generalized
spatial tranformations. I think it makes sense. We transform all of the
vertexes in a face, then we perform a trial subdivision of that face,
transform the added vertexes, and measure if the added vertexes were
necessary.
Post by doug moen
Another way to represent the transformation is as a single function that
maps a point [x,y,z] to another point.
If you think of this function as mapping every point in a 3D shape, then
this is extremely powerful, as you can model any conceivable spatial
transformation: twisting, bending, etc.
In practice, there are difficulties, as pointed out by
https://github.com/openscad/openscad/issues/815
The problem is that, with many of the more interesting transformations,
it's not enough to simply transform each vertex. You may need to subdivide
the mesh to create smaller faces, and then transform each vertex in the
subdivided mesh. An example would be applying a twist or bend
transformation to a cube, with just the 8 vertices.
Post by ctchin
Post by Trygon
1) exponential x scaling
transform(x*x, y, z) { ... }
2) "conic" expansion in x-y plane, scale factor=1 for z=20
transform(x*z/20 ,y*z/20 ,z) cylinder(h=40, r=10);
3) scale specific co-ordinate ranges
transform(x>0?2*x:x, abs(y)>50?3*y:y, z) { ... }
4) insert "gap" of 40mm centred on y=0
transform(x ,y>0?y+20:y-20, z) cylinder(h=20, r=10);
1) exponential: it should better be called power law or polynomial.
It's a relatively unique requirement...
2) conic: I believe it's actually linear and doable with a
simple multmatrix()
3) scale specific co-ordinate ranges and 4 insert gap
both are easily doable with a smartly written module
using difference() and/or projection()
So only the x = x*x exponential (sic) is new, I'm not
very convinced it justifies inventing a whole new syntax
for it.
--
http://forum.openscad.org/Non-Linear-Transformations-tp14539p14548.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
_______________________________________________
OpenSCAD mailing list
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
ctchin
2015-11-16 18:35:35 UTC
Permalink
The more I read the more I understand the request, the more
I'm convinced there's a lot loony ideas being thrown around.

The syntax x(), whether it's built-in or not, is a function call
with no input parameters (adopting the default values if possible).

For non-linear or more precisely non-affine transformation to
work the way you imagine it, will require re-meshing the children
with some level of smartly selected resolution. Which spells...
no universally acceptable algorithm exists.

If it doesn't work sensibly on a cube() primitive, it's highly
questionable it ought to be added to OpenSCAD.




--
View this message in context: http://forum.openscad.org/Non-Linear-Transformations-tp14539p14553.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
doug moen
2015-11-16 18:50:49 UTC
Permalink
Post by ctchin
For non-linear or more precisely non-affine transformation to
work the way you imagine it, will require re-meshing the children
with some level of smartly selected resolution. Which spells...
no universally acceptable algorithm exists.
I just described (in a vague way) a smart re-meshing algorithm in a
previous post. I'd like to hear why my algorithm might not be acceptable.

Here it is again, in more detail. Let's assume the polyhedron mesh is made
of triangles. For each triangle, we transform the vertexes. Then, we
perform a trial subdivision of the triangle into 4 smaller triangles, by
bisecting each of the original edges. This adds 3 new vertexes. We
transform each vertex, and compute the height of the vertex above the
parent triangle, in the direction of the parent triangle's normal vector. A
height of 0 means the new vertex lies in the plane of the parent triangle.
If all of the 3 new vertexes have a height of < $fe, then we discard the
new vertexes. Otherwise, we keep the new vertexes, and iterate, subdividing
the newly created triangles.

Doug.
Post by ctchin
The more I read the more I understand the request, the more
I'm convinced there's a lot loony ideas being thrown around.
The syntax x(), whether it's built-in or not, is a function call
with no input parameters (adopting the default values if possible).
For non-linear or more precisely non-affine transformation to
work the way you imagine it, will require re-meshing the children
with some level of smartly selected resolution. Which spells...
no universally acceptable algorithm exists.
If it doesn't work sensibly on a cube() primitive, it's highly
questionable it ought to be added to OpenSCAD.
--
http://forum.openscad.org/Non-Linear-Transformations-tp14539p14553.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
_______________________________________________
OpenSCAD mailing list
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Parkinbot
2015-11-16 19:27:02 UTC
Permalink
You are perfectly right!

Anyway only ismorphic nonlinear transformations would make sense. Most of
them are not isomorphic in a general sense - but might be in a subset, as
the given examples.

A more general approach for this feature would be to get hands on the mesh
points, as requested in my topic "feature request: obj2vec(); bug report:
freeze on standby recovery (Windows)". Then, everyone is free to use his own
mappings even non-isomorphic ones and also responsible if the resulting
polyhedron will be malformed.
Post by ctchin
If it doesn't work sensibly on a cube() primitive, it's highly
questionable it ought to be added to OpenSCAD.
--
View this message in context: http://forum.openscad.org/Non-Linear-Transformations-tp14539p14565.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
doug moen
2015-11-16 19:58:31 UTC
Permalink
Parkinbot, could you explain your comment "Anyway only ismorphic nonlinear
transformations would make sense." What will go wrong if a non-isomorphic
transformation is specified?

Isomorphic means that the structure of the geometric object is preserved,
in the sense that there is a reverse transformation that takes the
transformed object back to the original.

I can imagine evil transformations that result in a non-manifold object, or
which cause my smart-remeshing algorithm to go into an infinite loop. I
think we'd want error checking to detect these situations and report an
error.

I'm not sure how to prove that all non-isomorphic transformations are evil.
My math is not as strong as some of the other people on this list. But you
seem to know this as a fact, so how do you know?
Post by Parkinbot
You are perfectly right!
Anyway only ismorphic nonlinear transformations would make sense. Most of
them are not isomorphic in a general sense - but might be in a subset, as
the given examples.
A more general approach for this feature would be to get hands on the mesh
freeze on standby recovery (Windows)". Then, everyone is free to use his own
mappings even non-isomorphic ones and also responsible if the resulting
polyhedron will be malformed.
Post by ctchin
If it doesn't work sensibly on a cube() primitive, it's highly
questionable it ought to be added to OpenSCAD.
--
http://forum.openscad.org/Non-Linear-Transformations-tp14539p14565.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
_______________________________________________
OpenSCAD mailing list
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Parkinbot
2015-11-16 21:18:22 UTC
Permalink
Well, a non-isomorphic map in R³->R³ will have singularities (points, lines
or planes) in the sense that more than one points will be mapped to the same
point - so no inverse map can be found. As bijectivity is lost, vertices and
triangles simply might get lost.
Restricting a non-isomorphic map to a region (partial isomorphism), say to
the unit cube, it might be locally isomorphic as long as the region does not
contain any fix points.
So if we have a (partial) isomorphism all points (of a region) will be
mapped to separate image points and no merging can occur (numerically yes,
which is still another severe problem). Also triangle orientation will be
mapped in the same sense, as a partial flip of orientation of a triangle
would need a singularity for separation.

But you are right. Proving that a map is a (partial) isomorphism will only
be a first step. Even then, non-intersecting triangles might intersect after
being mapped (think of simply mapping one axis to a vortex like the
Archimedian spiral), and demand some careful post processing.

To sum it up: Non-linear operations have many pitfalls.

I guess one could allow for some of them in very specific contexts, like
with extrusion operations. For linear_extrusion() instead of linear scaling
and twisting one could think of nonlinear stepping or allow for a vector
expressing an ordered list of values, which will be used as z-heights, while
scaling and twisting will be done in a linear fashion with equidistant
stepping as it is done now.






--
View this message in context: http://forum.openscad.org/Non-Linear-Transformations-tp14539p14578.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
Trygon
2015-11-17 09:23:37 UTC
Permalink
The dark art of non affine transformations ;-) :

// Joukowsky airfoil
// circle -> airfoil, using a non affine transformation
// Trygon Nov2015

n=40; // number of facets
s=20; // scale factor
l=250; // wing length
ro=s/40; // offset radius (used to thicken material around trailing edge
cusp)

x=-0.15;
y=0.15;
r=norm([1,0]-[x,y]);

/*
linear_extrude(height=200) offset(r=ro) scale([s,s,s])
transform()=[x*(x*x+y*y+1)/(x*x+y*y),y*(x*x+y*y-1)/(x*x+y*y)]
translate([x,y,0]) circle(r,$fn=n);
*/

// manually build vertex set for circle
p1=[for(i=[0:n-1]) let(a=i*360/n) [r*sin(a)+x,r*cos(a)+y]];

// transform vertex set
p2=[for(i=p1) [s*i[0]*(i[0]*i[0]+i[1]*i[1]+1)/(i[0]*i[0]+i[1]*i[1]),
s*i[1]*(i[0]*i[0]+i[1]*i[1]-1)/(i[0]*i[0]+i[1]*i[1])]];

linear_extrude(height=l) offset(r=ro) polygon(p2);




--
View this message in context: http://forum.openscad.org/Non-Linear-Transformations-tp14539p14593.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
Rob Ward
2015-11-17 11:34:25 UTC
Permalink
That is very cool!!!
Post by Trygon
// Joukowsky airfoil
// circle -> airfoil, using a non affine transformation
// Trygon Nov2015
n=40; // number of facets
s=20; // scale factor
l=250; // wing length
ro=s/40; // offset radius (used to thicken material around trailing edge
cusp)
x=-0.15;
y=0.15;
r=norm([1,0]-[x,y]);
/*
linear_extrude(height=200) offset(r=ro) scale([s,s,s])
transform()=[x*(x*x+y*y+1)/(x*x+y*y),y*(x*x+y*y-1)/(x*x+y*y)]
translate([x,y,0]) circle(r,$fn=n);
*/
// manually build vertex set for circle
p1=[for(i=[0:n-1]) let(a=i*360/n) [r*sin(a)+x,r*cos(a)+y]];
// transform vertex set
p2=[for(i=p1) [s*i[0]*(i[0]*i[0]+i[1]*i[1]+1)/(i[0]*i[0]+i[1]*i[1]),
s*i[1]*(i[0]*i[0]+i[1]*i[1]-1)/(i[0]*i[0]+i[1]*i[1])]];
linear_extrude(height=l) offset(r=ro) polygon(p2);
--
View this message in context: http://forum.openscad.org/Non-Linear-Transformations-tp14539p14593.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
_______________________________________________
OpenSCAD mailing list
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Trygon
2015-11-16 21:37:04 UTC
Permalink
@ctchin you said, "conic: I believe it's actually linear and doable with a
simple multmatrix()", with regard to:

transform(x*z/20 ,y*z/20 ,z)

This transformation would be really useful for a model that I am scripting
at present, I couldn't work out how to do it with multmatrix(), please could
you provide the affine transformation matrix to use.

Thanks,
Trygon




--
View this message in context: http://forum.openscad.org/Non-Linear-Transformations-tp14539p14579.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
Neon22
2015-11-16 21:45:26 UTC
Permalink
@Doug - This remeshing algorithm was designed specifically for this exact
purpose and worked very well at the time. (1992). May be worth a read:
- http://www.red3d.com/cwr/papers/1992/df.html




--
View this message in context: http://forum.openscad.org/Non-Linear-Transformations-tp14539p14581.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
doug moen
2015-11-16 21:56:59 UTC
Permalink
Oh, nice. This algorithm "removes excess detail in crowded regions where
the surface is contracting", which is more sophisticated than what I
specified.
Post by Neon22
@Doug - This remeshing algorithm was designed specifically for this exact
- http://www.red3d.com/cwr/papers/1992/df.html
--
http://forum.openscad.org/Non-Linear-Transformations-tp14539p14581.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
_______________________________________________
OpenSCAD mailing list
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
doug moen
2015-11-16 21:52:52 UTC
Permalink
Hi Trygon. Wikipedia uses the term "perspective transformation" for what
you call a conic transformation.

I tried using the perspective transformation matrix from wikipedia in
OpenSCAD and it didn't work, I got a run-time error. Don't remember the
details, it was a while ago. At the time, I concluded that we don't support
arbitrary affine transformations.

If someone has working code, I'd like to see it.
Post by Trygon
@ctchin you said, "conic: I believe it's actually linear and doable with a
transform(x*z/20 ,y*z/20 ,z)
This transformation would be really useful for a model that I am scripting
at present, I couldn't work out how to do it with multmatrix(), please could
you provide the affine transformation matrix to use.
Thanks,
Trygon
--
http://forum.openscad.org/Non-Linear-Transformations-tp14539p14579.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
_______________________________________________
OpenSCAD mailing list
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Marius Kintel
2015-11-16 22:13:56 UTC
Permalink
I tried using the perspective transformation matrix from wikipedia in OpenSCAD and it didn't work, I got a run-time error. Don't remember the details, it was a while ago. At the time, I concluded that we don't support arbitrary affine transformations.
The perspective transformation is not affine. We currently don’t support non-affine transformations because CGAL doesn’t.

-Marius
runsun
2015-11-16 22:37:35 UTC
Permalink
Post by doug moen
Hi Trygon. Wikipedia uses the term "perspective transformation" for what
you call a conic transformation.
I tried using the perspective transformation matrix from wikipedia in
OpenSCAD and it didn't work, I got a run-time error. Don't remember the
details, it was a while ago. At the time, I concluded that we don't support
arbitrary affine transformations.
If someone has working code, I'd like to see it.
What needed is a line-plane intersection function. As shown in the following
fig ( source
<http://www.geom.uiuc.edu/docs/reference/CRC-formulas/node16.html> ):

<Loading Image...>

Let p = a point on P, q= a point on Q. A projective transformation focusing
on point O can be obtained by calculating the intersection of line pO with
plane Q. This is achievable.






-----

$ Runsun Pan, PhD

$ libs: doctest , faces ( git ), offline doc ( git ),runscad.py( 1 , 2 , git );

$ tips: hash( 1 , 2 ), sweep , var , lerp , animGif






--
View this message in context: http://forum.openscad.org/Non-Linear-Transformations-tp14539p14586.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
wolf
2016-03-19 07:53:59 UTC
Permalink
Post by Trygon
OpenSCAD currently supports a whole range of specific
*
Post by Trygon
linear
*
Post by Trygon
transformations such as translate(), rotate() and scale(), in addition to
the generic
*
Post by Trygon
linear
*
Post by Trygon
transformation multmatrix().
OpenSCAD does not provide support for non-
*
Post by Trygon
linear
*
Post by Trygon
transformations.
Both statements are false. OpenSCAD currently provides both linear
transformations (x->a+bx, with a and b constants) and non-linear
transformations (for example: translate([sin20,cos(30),tan(10)]) is
perfectly legal, though not necessarily meaningful. Rotations are inherently
non-linear transformations, as they involve sines and cosines). Instead of
*linear*, Trygon should have used the term *affine* to describe current
OpenSCAD's capabilities.
But doing so has consequences: Since one of the properties of an affine
transformation is that straight lines are transformed into other straight
lines, this implies that as long as OpenSCAD wants to output .stl files, it
cannot support non-affine transformations.
After all, a .stl file is nothing but a [structured] list of vertices, which
are connected by straight lines, and not curved ones as is inevitable for
non-affine transformations.

BTW, doug.moen's algorithm does not have any value either. This is because
when, say, a square is subjected to an affine transformation, it must remain
a quadrangle (i.e. its vertex count remains unchanged), and it must remain
flat. That is part and parcel of an affine transformation. Thus there is no
need to create extra vertices.

Finally, the outcome of the multiplication of one or several vector(s) with
a matrix (that is what multmatrix() is) need not be restricted to affine
transformations. Some OpenSCAD shapes allow a twist parameter - the
restriction arises out of the need to produce .stl files. Twist is the
implemented as a succession of skew transformations.

wolf




--
View this message in context: http://forum.openscad.org/Non-Linear-Transformations-tp14539p16578.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
Carsten Arnholm
2016-03-19 09:41:41 UTC
Permalink
Post by wolf
After all, a .stl file is nothing but a [structured] list of vertices, which
are connected by straight lines,
This is somewhat misleading. STL files do not contain a lists of
vertices. STL files contain only a set of topologically disconnected
triangles with coordinates duplicated locally in every triangle. Every
would-be vertex has to be mentioned at least 3 times. This is one of the
reasons why why STL is an unfortunate standard.

Your description applies better to an AMF file or generally a polyhedron
mesh with a structured vector of vertices and where faces are defined
via indices into the vertex vector. This is much better as it removes
the possibility of ambiguities.
Post by wolf
Finally, the outcome of the multiplication of one or several vector(s) with
a matrix (that is what multmatrix() is) need not be restricted to affine
transformations.
Every transformation in OpenSCAD and most similar systems is eventually
expressed a 4x4 homogeneous coordinate transformation matrix,
multmatrix() is just the explicit form of that in OpenSCAD. Although
such matrices can express things like perspective, in CAD geometry it is
most commonly used to express just translation, scaling, mirroring and
rotation. Straight lines are preserved for these, but the curvature of
arcs can be affected by scaling.

Carsten Arnholm
doug moen
2016-03-19 15:46:10 UTC
Permalink
OpenSCAD supports affine transformations via multmatrix, but it does not
support the more general class of projective transformations (which
includes the perspective transformation), even though these can also be
represented by 4x4 matrixes.

I've looked at a number of solid modelling languages, in addition to
OpenSCAD, and the only one I've found that supports generalized projective
transformations is SGDL. SGDL is based on projective geometry, which is a
generalization of Euclidean geometry that includes points at infinity. In
SGDL, 3-space coordinates are always represented as homogenous coordinates:
[x,y,z,w], where the point is at infinity if w==0. SGDL also supports
infinitely large solids.

I'm not an expert on projective geometry, but I think the problem with
supporting general projective transformations in a Euclidean geometry
system like OpenSCAD is just that a projective transformation can map a
vertex to a point at infinity, and we have no way to deal with that in our
representation.

Does anybody on the list have a better understanding of this? What are all
the things that would go wrong if we tried to extend multmatrix to support
projective transformations?
Post by wolf
Post by Trygon
OpenSCAD currently supports a whole range of specific
*
Post by Trygon
linear
*
Post by Trygon
transformations such as translate(), rotate() and scale(), in addition
to
Post by Trygon
the generic
*
Post by Trygon
linear
*
Post by Trygon
transformation multmatrix().
OpenSCAD does not provide support for non-
*
Post by Trygon
linear
*
Post by Trygon
transformations.
Both statements are false. OpenSCAD currently provides both linear
transformations (x->a+bx, with a and b constants) and non-linear
transformations (for example: translate([sin20,cos(30),tan(10)]) is
perfectly legal, though not necessarily meaningful. Rotations are inherently
non-linear transformations, as they involve sines and cosines). Instead of
*linear*, Trygon should have used the term *affine* to describe current
OpenSCAD's capabilities.
But doing so has consequences: Since one of the properties of an affine
transformation is that straight lines are transformed into other straight
lines, this implies that as long as OpenSCAD wants to output .stl files, it
cannot support non-affine transformations.
After all, a .stl file is nothing but a [structured] list of vertices, which
are connected by straight lines, and not curved ones as is inevitable for
non-affine transformations.
BTW, doug.moen's algorithm does not have any value either. This is because
when, say, a square is subjected to an affine transformation, it must remain
a quadrangle (i.e. its vertex count remains unchanged), and it must remain
flat. That is part and parcel of an affine transformation. Thus there is no
need to create extra vertices.
Finally, the outcome of the multiplication of one or several vector(s) with
a matrix (that is what multmatrix() is) need not be restricted to affine
transformations. Some OpenSCAD shapes allow a twist parameter - the
restriction arises out of the need to produce .stl files. Twist is the
implemented as a succession of skew transformations.
wolf
--
http://forum.openscad.org/Non-Linear-Transformations-tp14539p16578.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
_______________________________________________
OpenSCAD mailing list
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Rogier Wolff
2016-03-19 18:00:49 UTC
Permalink
Post by doug moen
OpenSCAD supports affine transformations via multmatrix, but it does not
support the more general class of projective transformations (which
includes the perspective transformation), even though these can also be
represented by 4x4 matrixes.
I've looked at a number of solid modelling languages, in addition to
OpenSCAD, and the only one I've found that supports generalized projective
transformations is SGDL. SGDL is based on projective geometry, which is a
generalization of Euclidean geometry that includes points at infinity. In
[x,y,z,w], where the point is at infinity if w==0. SGDL also supports
infinitely large solids.
I took "computer graphics" at caltech from Prof. Jim Blinn in 1985....
He is a big proponent of this way of working.

Points in three-space are represented by [x, y, z, 1]. A projection
(in 4-space) towards the origin on the w=1 plane (ehh solid) happens
when you divide by w to "come back to 3-space". This also means you
can do 3D->2D projections.

Because you start with w=1, you have a constant that you can add to
xyz, to perform translations.

Everything is linear, so for example a rotation followed by a
translation can be done in one step by multiplying their matrices.

How all this applies to openscad, I don't know. I have too little
familiarity with the openscad internals.

Roger.
--
** ***@BitWizard.nl ** http://www.BitWizard.nl/ ** +31-15-2600998 **
** Delftechpark 26 2628 XH Delft, The Netherlands. KVK: 27239233 **
*-- BitWizard writes Linux device drivers for any device you may have! --*
The plan was simple, like my brother-in-law Phil. But unlike
Phil, this plan just might work.
wolf
2016-03-20 02:22:42 UTC
Permalink
When I researched, and made, my previous comment, I allowed myself to be
guided by conservation laws. Conservation laws are very powerful constructs,
as they tell you what you need not to bother with when planning a change,
and as such reduce the complexity of your task. They also permit you to
freely change the direction of your reasoning, going about designing first
the roof of your house or the foundations, or even the place where the
computer sits on which you do OpenSCAD. The result will always be the same,
but the traps you fall into when you do your planning will differ.
OpenSCAD's output is not a value in itself, but rather a tool to access the
capabilities of other tools, such as a 3D printer or a laser cutter. Thus,
it makes sense to start from the end, from the limitations that a .stl file
output places on OpenSCAD's internals.
If you open up the .stl of cube([1,1,1]) in a text editor, you get, after
the removal of some spaces and <newlines> (and sorting on the facet normal,
just to make the internal structure clearer), this table:

solid OpenSCAD_Model
facet normal -1 0 0 outer loop vertex 0 1 1 vertex 0 0 0 vertex
0 0 0 endloop endfacet
facet normal -1 0 0 outer loop vertex 0 0 0 vertex 0 1 1 vertex
0 1 1 endloop endfacet
facet normal 0 -1 0 outer loop vertex 1 0 1 vertex 0 0 0 vertex
0 0 0 endloop endfacet
facet normal 0 -1 0 outer loop vertex 0 0 0 vertex 1 0 1 vertex
1 0 1 endloop endfacet
facet normal 0 0 -1 outer loop vertex 1 1 0 vertex 0 0 0 vertex
0 0 0 endloop endfacet
facet normal 0 0 -1 outer loop vertex 0 0 0 vertex 1 1 0 vertex
1 1 0 endloop endfacet
facet normal 0 0 1 outer loop vertex 1 0 1 vertex 0 1 1 vertex
0 1 1 endloop endfacet
facet normal 0 0 1 outer loop vertex 0 1 1 vertex 1 0 1 vertex
1 0 1 endloop endfacet
facet normal 0 1 0 outer loop vertex 1 1 0 vertex 0 1 1 vertex
0 1 1 endloop endfacet
facet normal 0 1 0 outer loop vertex 0 1 1 vertex 1 1 0 vertex
1 1 0 endloop endfacet
facet normal 1 0 0 outer loop vertex 1 1 0 vertex 1 0 1 vertex
1 0 1 endloop endfacet
facet normal 1 0 0 outer loop vertex 1 0 1 vertex 1 1 0 vertex
1 1 0 endloop endfacet
endsolid OpenSCAD_Model

Unlike what Wikipedia https://en.wikipedia.org/wiki/STL_%28file_format%29
makes me expect, there are twice as many facets listed as a cube has faces,
and each facet points only to two vertices. I haven't investigated so far
whether this is due to an OpenSCAD bug or inappropriate Wikipedia
information.

As to the question on the usefulness of projective geometry extensions to
OpenSCAD, I fail to see the usefulness of it. Yes, the display looks nicer,
and you can easily program tapers, but how often is that used? So my vote is
against it, as is my vote against extensions to multmatrix(). Here I would
rather follow the philosophy projected with OpenSCAD2: simpler is better,
and deprecate multmatrix(), because it requires so much background in
mathematics to use it effectively. The useful portions of multmatrix() have
already been extracted into other transformations, as this program segment
shows:

TranslatMatrix= [ [1, 0, 0, 10],
[0, 1, 0, 20],
[0, 0, 1, 30],
[0, 0, 0, 1]
];
ScaleMatrix= [ [1, 0, 0, 0],
[0, 1/2, 0, 0],
[0, 0, 1/3, 0],
[0, 0, 0, 1]
];
Rotate_Around_X=[ [1, 0, 0, 0], //source:
https://en.wikipedia.org/wiki/Rotation_formalisms_in_three_dimensions
[0, cos(30), -sin(30), 0],
[0, sin(30), cos(30), 0],
[0, 0, 0, 1]
];
Rotate_Around_Y=[ [cos(30), 0, sin(30), 0],
[ 0, 1, 0, 0],
[-sin(30), 0,cos(30), 0],
[0, 0, 0, 1]
];
Rotate_Around_Z=[ [cos(30), -sin(30), 0, 0],
[sin(30), cos(30), 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1]
];
//SkewMatrix= // source:
https://en.wikipedia.org/wiki/Rotation_matrix#Skew_parameters_via_Cayley.27s_formula
// https://en.wikipedia.org/wiki/Cayley_transform
// https://en.wikipedia.org/wiki/Skew-symmetric_matrix

//T_Simple();
//T_mult();
//S_Simple();
//S_mult();
//R_X_Simple();
//R_X_mult();
//R_Y_mult();
R_Z_mult();


module T_Simple() //this is one way of doing a translation
translate([10,20,30])
cube([10,20,30]);
module T_mult() //this is another way of doing the same translation
multmatrix(m = TranslatMatrix)
cube([10,20,1/3]);
module S_Simple() //this is one way of doing scaling
scale([1,1/2,1/3])
cube([10,20,30]);
module S_mult() //this is another way of doing the same scaling
multmatrix(m = ScaleMatrix)
cube([10,20,30]);
module R_X_Simple() //this is one way of doing a rotation around the x
axis
rotate(30,[1,0,0])
cube([10,20,30]);
module R_X_mult() //this is another way of doing the same rotation around
the x axis
multmatrix(m = Rotate_Around_X)
cube([10,20,30]);
module R_Y_mult() //this is a rotation around the y axis
multmatrix(m = Rotate_Around_Y)
cube([10,20,30]);
module R_Z_mult() //this is a rotation around the z axis
multmatrix(m = Rotate_Around_Z)
cube([10,20,30]);

As far as I know, skew or shear transformations currently require the use of
multmatrix(), but then who uses them?
Because Marius Kintel asked for them, I outline here another transformation:
offset.

$fn=50;
Diameter=2; // diameter of sphere from which ellipsoid is created
Offset=0.1*Diameter;
MaxDim=[3*Diameter,1*Diameter,.5*Diameter]; // long axes of ellipsoid

MakeOffset();
MakeCutout();
TestPosition();

module MakeOffset()
scale([1-2*Offset/MaxDim[0],1-2*Offset/MaxDim[1],1-2*Offset/MaxDim[2]])
// for a true offset, MaxDim[...] needs to be replaced with the norm of each
vertex for the ellipsoid
Ellipsoid();
module TestPosition()
translate([MaxDim[0]/2-Offset/2,0,0]) sphere(d=Offset);
translate([0,-(MaxDim[1]/2-Offset/2),0]) sphere(d=Offset);
translate([0,0,MaxDim[2]/2-Offset/2]) sphere(d=Offset);
module MakeCutout()
difference()
{ Ellipsoid();
translate([0,-15,15]) cube([70,30,30], center=true);
}
module Ellipsoid()
scale([MaxDim[0]/Diameter,MaxDim[1]/Diameter,MaxDim[2]/Diameter])
sphere(d=Diameter);

It doesn't quite work in userspace, but comes pretty close. One line, as
commented, needs access to the vertex vectors, which OpenSCAD does not
readily provide. Work for someone with knowledge of the internals.
<Loading Image...>
The yellow color in the cutout indicates a problem OpenSCAD has with the
faces created by module MakeCutout(). Probably inside-out faces. They were
made with version 2015.03-1.

wolf




--
View this message in context: http://forum.openscad.org/Non-Linear-Transformations-tp14539p16588.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
doug moen
2016-03-20 03:42:26 UTC
Permalink
Wolf said: "Unlike what Wikipedia
https://en.wikipedia.org/wiki/STL_%28file_format%29
makes me expect, there are twice as many facets listed as a cube has faces,
and each facet points only to two vertices. I haven't investigated so far
whether this is due to an OpenSCAD bug or inappropriate Wikipedia
information."

The Wikipedia article is correct and this is not an OpenSCAD bug. An STL
file contains a list of triangles, each of which has 3 vertices. A cube has
6 square faces, and each square must be split into 2 triangles in order to
be represented by STL. So that's 6 * 2 = 12 triangles.

The wikipedia article addresses your point of confusing by stating this:"The
structure of the format suggests that other possibilities exist (e.g.,
facets with more than one "loop", or loops with more than three vertices).
In practice, however, all facets are simple triangles."
Post by wolf
When I researched, and made, my previous comment, I allowed myself to be
guided by conservation laws. Conservation laws are very powerful constructs,
as they tell you what you need not to bother with when planning a change,
and as such reduce the complexity of your task. They also permit you to
freely change the direction of your reasoning, going about designing first
the roof of your house or the foundations, or even the place where the
computer sits on which you do OpenSCAD. The result will always be the same,
but the traps you fall into when you do your planning will differ.
OpenSCAD's output is not a value in itself, but rather a tool to access the
capabilities of other tools, such as a 3D printer or a laser cutter. Thus,
it makes sense to start from the end, from the limitations that a .stl file
output places on OpenSCAD's internals.
If you open up the .stl of cube([1,1,1]) in a text editor, you get, after
the removal of some spaces and <newlines> (and sorting on the facet normal,
solid OpenSCAD_Model
facet normal -1 0 0 outer loop vertex 0 1 1 vertex 0 0 0 vertex
0 0 0 endloop endfacet
facet normal -1 0 0 outer loop vertex 0 0 0 vertex 0 1 1 vertex
0 1 1 endloop endfacet
facet normal 0 -1 0 outer loop vertex 1 0 1 vertex 0 0 0 vertex
0 0 0 endloop endfacet
facet normal 0 -1 0 outer loop vertex 0 0 0 vertex 1 0 1 vertex
1 0 1 endloop endfacet
facet normal 0 0 -1 outer loop vertex 1 1 0 vertex 0 0 0 vertex
0 0 0 endloop endfacet
facet normal 0 0 -1 outer loop vertex 0 0 0 vertex 1 1 0 vertex
1 1 0 endloop endfacet
facet normal 0 0 1 outer loop vertex 1 0 1 vertex 0 1 1 vertex
0 1 1 endloop endfacet
facet normal 0 0 1 outer loop vertex 0 1 1 vertex 1 0 1 vertex
1 0 1 endloop endfacet
facet normal 0 1 0 outer loop vertex 1 1 0 vertex 0 1 1 vertex
0 1 1 endloop endfacet
facet normal 0 1 0 outer loop vertex 0 1 1 vertex 1 1 0 vertex
1 1 0 endloop endfacet
facet normal 1 0 0 outer loop vertex 1 1 0 vertex 1 0 1 vertex
1 0 1 endloop endfacet
facet normal 1 0 0 outer loop vertex 1 0 1 vertex 1 1 0 vertex
1 1 0 endloop endfacet
endsolid OpenSCAD_Model
Unlike what Wikipedia https://en.wikipedia.org/wiki/STL_%28file_format%29
makes me expect, there are twice as many facets listed as a cube has faces,
and each facet points only to two vertices. I haven't investigated so far
whether this is due to an OpenSCAD bug or inappropriate Wikipedia
information.
As to the question on the usefulness of projective geometry extensions to
OpenSCAD, I fail to see the usefulness of it. Yes, the display looks nicer,
and you can easily program tapers, but how often is that used? So my vote is
against it, as is my vote against extensions to multmatrix(). Here I would
rather follow the philosophy projected with OpenSCAD2: simpler is better,
and deprecate multmatrix(), because it requires so much background in
mathematics to use it effectively. The useful portions of multmatrix() have
already been extracted into other transformations, as this program segment
TranslatMatrix= [ [1, 0, 0, 10],
[0, 1, 0, 20],
[0, 0, 1, 30],
[0, 0, 0, 1]
];
ScaleMatrix= [ [1, 0, 0, 0],
[0, 1/2, 0, 0],
[0, 0, 1/3, 0],
[0, 0, 0, 1]
];
https://en.wikipedia.org/wiki/Rotation_formalisms_in_three_dimensions
[0, cos(30), -sin(30), 0],
[0, sin(30), cos(30), 0],
[0, 0, 0, 1]
];
Rotate_Around_Y=[ [cos(30), 0, sin(30), 0],
[ 0, 1, 0, 0],
[-sin(30), 0,cos(30), 0],
[0, 0, 0, 1]
];
Rotate_Around_Z=[ [cos(30), -sin(30), 0, 0],
[sin(30), cos(30), 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1]
];
https://en.wikipedia.org/wiki/Rotation_matrix#Skew_parameters_via_Cayley.27s_formula
// https://en.wikipedia.org/wiki/Cayley_transform
// https://en.wikipedia.org/wiki/Skew-symmetric_matrix
//T_Simple();
//T_mult();
//S_Simple();
//S_mult();
//R_X_Simple();
//R_X_mult();
//R_Y_mult();
R_Z_mult();
module T_Simple() //this is one way of doing a translation
translate([10,20,30])
cube([10,20,30]);
module T_mult() //this is another way of doing the same translation
multmatrix(m = TranslatMatrix)
cube([10,20,1/3]);
module S_Simple() //this is one way of doing scaling
scale([1,1/2,1/3])
cube([10,20,30]);
module S_mult() //this is another way of doing the same scaling
multmatrix(m = ScaleMatrix)
cube([10,20,30]);
module R_X_Simple() //this is one way of doing a rotation around the x
axis
rotate(30,[1,0,0])
cube([10,20,30]);
module R_X_mult() //this is another way of doing the same rotation around
the x axis
multmatrix(m = Rotate_Around_X)
cube([10,20,30]);
module R_Y_mult() //this is a rotation around the y axis
multmatrix(m = Rotate_Around_Y)
cube([10,20,30]);
module R_Z_mult() //this is a rotation around the z axis
multmatrix(m = Rotate_Around_Z)
cube([10,20,30]);
As far as I know, skew or shear transformations currently require the use of
multmatrix(), but then who uses them?
Because Marius Kintel asked for them, I outline here another
offset.
$fn=50;
Diameter=2; // diameter of sphere from which ellipsoid is created
Offset=0.1*Diameter;
MaxDim=[3*Diameter,1*Diameter,.5*Diameter]; // long axes of ellipsoid
MakeOffset();
MakeCutout();
TestPosition();
module MakeOffset()
scale([1-2*Offset/MaxDim[0],1-2*Offset/MaxDim[1],1-2*Offset/MaxDim[2]])
// for a true offset, MaxDim[...] needs to be replaced with the norm of each
vertex for the ellipsoid
Ellipsoid();
module TestPosition()
translate([MaxDim[0]/2-Offset/2,0,0]) sphere(d=Offset);
translate([0,-(MaxDim[1]/2-Offset/2),0]) sphere(d=Offset);
translate([0,0,MaxDim[2]/2-Offset/2]) sphere(d=Offset);
module MakeCutout()
difference()
{ Ellipsoid();
translate([0,-15,15]) cube([70,30,30], center=true);
}
module Ellipsoid()
scale([MaxDim[0]/Diameter,MaxDim[1]/Diameter,MaxDim[2]/Diameter])
sphere(d=Diameter);
It doesn't quite work in userspace, but comes pretty close. One line, as
commented, needs access to the vertex vectors, which OpenSCAD does not
readily provide. Work for someone with knowledge of the internals.
<http://forum.openscad.org/file/n16588/Offset.jpg>
The yellow color in the cutout indicates a problem OpenSCAD has with the
faces created by module MakeCutout(). Probably inside-out faces. They were
made with version 2015.03-1.
wolf
--
http://forum.openscad.org/Non-Linear-Transformations-tp14539p16588.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
_______________________________________________
OpenSCAD mailing list
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Parkinbot
2016-03-22 13:51:35 UTC
Permalink
concerning you STL questions. What I get is different to what you pasted into
your post:

solid OpenSCAD_Model
facet normal -0 0 1 outer loop vertex 0 1 1 vertex 1 0 1 vertex 1 1 1
endloop
...

and I also get the expected 12 facets, two for each square face.

- Rudolf -





--
View this message in context: http://forum.openscad.org/Non-Linear-Transformations-tp14539p16657.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
Marius Kintel
2016-03-22 05:17:14 UTC
Permalink
Does anybody on the list have a better understanding of this? What are all the things that would go wrong if we tried to extend multmatrix to support projective transformations?
From the top of my head, I don’t think much can go wrong. It’s still just a linear transformation.
Mapping to infinity is only possible through a division by zero when normalizing the resulting homogeneous coordinate, right?
..so that’s roughly similar to having inf values in an affine transformation matrix.

Practically, we’re limited to affine transformation since that’s all CGAL supports for Nef polyhedrons.

-Marius
Parkinbot
2016-03-22 12:49:19 UTC
Permalink
A projection may be described by a multmatrix using a zero scale factor for
one dimension. So everything is fine. As Kintel says: CGAL is restricted to
affine transformations, so more general non-linear transformations can't be
offered as long as this restriction holds.

Well, linear_extrude() is not a transformation, rather a constructor. As
such it touches just the tip of the iceberg of what would be possible in
OpenSCAD, without even touching multmatrix. As Wolf wrote "Twist is
implemented as a succession of skew transformations." This is the door.

Earlier in this thread I've already opted for a nonlinear_extrude() or let's
say an "enhanced linear_extrude()" primitive that offers a *richer
prototype*. A first step would be to also allow for negative height values -
linear_extrude is not 'linear' in this point. That maybe already on the todo
list. A second (eady) one would be to allow to specify a vector along which
extrusion occurs.

But of course much more is possible between linear_extrude() and sweep()
without leaving the land of affine operations. While sweep(), depending on
its implemetation, more or less expects an explicit description of each
frame, also more implicit path and operation descriptions would be possible.
E.g. extrusion could follow (well-defaulted) path vectors, scale vectors and
even orientation (rotation) vectors.
From the other side, also rotate_extrude() could be enriched to allow for a
height argument (definition of screws) or a given height path (scews with
nonlinear slopes).

Once function arguments are possible xxx_extrude anyway should be prepared
to work with them.

- Rudolf -



--
View this message in context: http://forum.openscad.org/Non-Linear-Transformations-tp14539p16656.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
doug moen
2016-03-22 16:15:03 UTC
Permalink
Post by Parkinbot
A projection may be described by a multmatrix using a zero scale factor for
one dimension. So everything is fine. As Kintel says: CGAL is restricted to
affine transformations, so more general non-linear transformations can't be
offered as long as this restriction holds.
I want to clarify some terminology.

Yes, it's true that projection() is mathematically equivalent to
scale([1,1,0]). Thanks for pointing this out. Mathematically, a projection
is just a special case of a linear transformation! In OpenSCAD, these two
aren't actually equivalent, because projection() returns a 2D object, while
scale([1,1,0]) returns something that looks like the output of
projection(), and looks like a 2D object, but which is labelled internally
as 3D.

But a projection is not the same thing as a projective transformation.

There are 3 classes of matrix-based geometric transformations.

- The smallest class is linear transformations. These can be represented
by a 3x3 matrix (in 3D). Linear transformations include rotation,
reflection, scaling and shearing, but you can't perform a translation. The
point [0,0,0] is always mapped to [0,0,0].
- The next largest class is affine transformations, which are a superset
of linear transformations. This adds the ability to perform translations.
You need a 4x4 matrix, but there are restrictions on the matrix. The bottom
row consists of [0,0,0,1], and the right column is [tx,ty,tz,1], where
[tx,ty,tz] is the translation component of the affine transformation. The
top-left 3 rows and columns are the 3x3 matrix of the linear component of
the affine transformation.
- The largest class is projective transformations, which are a superset
of affine transformations. This adds the ability to map rectangles onto
trapezoids and perform perspective transformations. You can map points out
to infinity, so you can transform a finite object into an infinite object.
For example, you can map a finite circle to an infinite parabola. You can
also do the reverse, and map points at infinity to a finite range.
Projective transformations are represented by an arbitrary 4x4 matrix.


Be careful when you talk about non-linear transformations, because
translate() is a non-linear transformation. You might instead be referring
to a non-affine transformation.

The reason I brought up projective transformations is in response to a
comment by Wolf, who said: "Finally, the outcome of the multiplication of
one or several vector(s) with a matrix (that is what multmatrix() is) need
not be restricted to affine transformations."

I wanted to point out that there are some technical challenges in
generalizing multmatrix() to support arbitrary 4x4 matrices (projective
transformations).
Ronaldo
2016-03-22 19:29:29 UTC
Permalink
I tried once to perform a projective transformation with multmatrix. It
doesn't work. Multmatrix performs only affine transforms. If the last line
of the 4x4 matrix in multmatrix is [a, b, c, d], OpenSCAD seems to change
a,b,c to zero to avoid projective transforms. However, the last element d
is used and causes an (additional) overall uniform scale of 1/d, although
the OpenSCAD Manual says:

"the fourth row is used in 3D environments to define a view of the object.
it is not used in OpenSCAD and should be [0,0,0,1]"

. If d==0, nothing is done.



--
View this message in context: http://forum.openscad.org/Non-Linear-Transformations-tp14539p16667.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
Parkinbot
2016-03-22 21:31:59 UTC
Permalink
Doug, you are right in the sense of strict terminology. But also with respect
to the title of the thread I rather prefer the term non-linear
transformation instead of 'non-affine' transformation. The notion is
commonly used and understood to characterize functions that do not just
introduce a new cartesian coordinate system.

Neverless when we talk about 'non xxx' operations in CAD we have objects in
mind that maybe approximated by one (or many) shapes and a sequence of
affine transformations. You also mention the implementational difference
between 2D and 3D-shapes - which in my eyes is a strong restriction OpenSCAD
really should get rid of. Why shouldn't a 2D shape be allowed to live in 3D?
Therefore linear_extrude() is again a good candidate to see where
expectation and implementation clash and OpenSCAD's sematics gets unexpected
for newcomers.
linear_extrude(height = 10)
rotate([40, 0, 0]) // is applied but result is implicitly truncated to
xy
translate([10, 10, 20]) // z-shift is ignored
circle(10);
linear_extrude(height = 10)
sphere(10); // not projected, emits warning, but only on first F5
It was also mentioned by others, that rotate_extrude() does unexpectedly an
implicit rotation (and even a 'strange' z-shift, when an y-offset is used).
rotate_extrude()
translate([10, 20, 0]) // effects into a z-translate
circle(9); // implicit x-rotate
At least an axis argument like "x", "y", "z" defaulting to "z" would here be
helpful.

So, for what reason are linear_extrude() and rotate_extrude() restricted to
2D shapes being placed at z=0 at all? Why can't they also operate over 2D
objects living in 3D space or even 3D objects being placed anywhere? See
this example (which can't be fully implemented with current language means,
think of "twist"):

<Loading Image...>
linear_extrude3D()
myobj();
module linear_extrude3D(h = 10)
{
children([0]);
linear_extrude(height = h) projection() children([0]);
translate([0, 0, h]) children([0]);
}
module myobj()
difference()
{
sphere(10);
cylinder(r = 6, h = 21, center = true);
}
xxx_extrude() in my eyes are the mightiest features in OpenSCAD, but still
far away from what is possible - with current language means.




--
View this message in context: http://forum.openscad.org/Non-Linear-Transformations-tp14539p16670.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
doug moen
2016-03-22 23:09:19 UTC
Permalink
@Parkinbot, I have been looking at this problem of generalized extrusion,
in a context slightly removed from OpenSCAD. I've been messing around with
functional representation (F-Rep). My idea is that OpenSCAD would be more
powerful if the geometry engine could be generalized to support F-Rep, in
addition to the current mesh representation.

F-Rep allows you to provide an exact representation for any shape that can
be described by a mathematical function. And it turns out to be quite easy
to define powerful new geometrical primitives with not very much code. So
much easier than mesh algorithms. There are a bunch of OpenSCAD-like tools
that implement this already, so it's trendy, and there are open source
implementations to look at.

Even with F-Rep, it's still cheaper and more convenient to implement
linear_extrude and rotate_extrude with the same interface as in OpenSCAD,
where the shape being extruded is required to be 2D. With this restriction,
the code is simple and fast. I've got another variant (not tested) called
perimeter_extrude, which sweeps one 2D shape along the perimeter of another
2D shape. The code looks simple and fast, but I dunno if it will work in
all cases yet.

I am investigating the more general problem of sweeping a 3D shape through
space along a parameterized curve. One paper I found describes a general
solution to this problem, allowing the shape being swept to continuously
vary according to the curve parameter. Self intersections are handled. It's
totally general, but the code is complex and slow. I haven't actually tried
coding it.

I've found another research paper that describes a different solution,
where you achieve the sweep by constructing a higher dimensional shape and
then project that down to 3D. I'm not finished reading the paper.

Anyway, my answer to your comment is that there are engineering tradeoffs
where the more general algorithms may be much slower than the specialized
ones, so there is room for both.

There are definitely some annoying bugs where the geometric operations fail
to report bad arguments, and produce unexpected results instead, like what
you mentioned. Those bugs should be fixed.

I am undecided about the status of 2D shapes in my F-Rep geometry system:
should they have a different type than 3D shapes? Should they be 3D objects
that are distinguished by having a bounding box of height 0 that confines
them to the x-y plane? We do need to have identifiable 2D objects, so that
you can create a 2D object, preview it, export it to DXF.

I refuse to call translate() a linear transformation. It's technically
wrong, and it creates too much confusion if, like me, you are trying to
learn enough computational geometry to make full use of OpenSCAD, including
the linear algebra parts. I don't care about pop-culture misunderstandings
of what "non-linear" means, it's more important for me to not be confused
about the math.
Post by Parkinbot
Doug, you are right in the sense of strict terminology. But also with respect
to the title of the thread I rather prefer the term non-linear
transformation instead of 'non-affine' transformation. The notion is
commonly used and understood to characterize functions that do not just
introduce a new cartesian coordinate system.
Neverless when we talk about 'non xxx' operations in CAD we have objects in
mind that maybe approximated by one (or many) shapes and a sequence of
affine transformations. You also mention the implementational difference
between 2D and 3D-shapes - which in my eyes is a strong restriction OpenSCAD
really should get rid of. Why shouldn't a 2D shape be allowed to live in 3D?
Therefore linear_extrude() is again a good candidate to see where
expectation and implementation clash and OpenSCAD's sematics gets unexpected
for newcomers.
linear_extrude(height = 10)
rotate([40, 0, 0]) // is applied but result is implicitly truncated to
xy
translate([10, 10, 20]) // z-shift is ignored
circle(10);
linear_extrude(height = 10)
sphere(10); // not projected, emits warning, but only on first F5
It was also mentioned by others, that rotate_extrude() does unexpectedly an
implicit rotation (and even a 'strange' z-shift, when an y-offset is used).
rotate_extrude()
translate([10, 20, 0]) // effects into a z-translate
circle(9); // implicit x-rotate
At least an axis argument like "x", "y", "z" defaulting to "z" would here be
helpful.
So, for what reason are linear_extrude() and rotate_extrude() restricted to
2D shapes being placed at z=0 at all? Why can't they also operate over 2D
objects living in 3D space or even 3D objects being placed anywhere? See
this example (which can't be fully implemented with current language means,
<http://forum.openscad.org/file/n16670/linear3D.png>
linear_extrude3D()
myobj();
module linear_extrude3D(h = 10)
{
children([0]);
linear_extrude(height = h) projection() children([0]);
translate([0, 0, h]) children([0]);
}
module myobj()
difference()
{
sphere(10);
cylinder(r = 6, h = 21, center = true);
}
xxx_extrude() in my eyes are the mightiest features in OpenSCAD, but still
far away from what is possible - with current language means.
--
http://forum.openscad.org/Non-Linear-Transformations-tp14539p16670.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
_______________________________________________
OpenSCAD mailing list
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Parkinbot
2016-03-23 00:36:04 UTC
Permalink
Post by doug moen
Even with F-Rep, it's still cheaper and more convenient to implement
linear_extrude and rotate_extrude with the same interface as in OpenSCAD,
where the shape being extruded is required to be 2D. With this
restriction,
the code is simple and fast.
I've done some work on sweep() and spline interpolation on the basis of
OpenSCAD functions. Out of this background I don't see any significant
computational difference between extruding a 2D shape living in 2D or 3D.
Neither in allowing for directional vectors instead of [0,0,1].
Of course implementing linear_extrude() to operate over 3D shapes is more
sophisticated, but don't forget what is gained. It could replace hull() and
get rid of its convexity restriction. If it is done as proposed additional
costs will be limited. One could also live with twists and scales not being
applied to the objects halfs at the ends.
Post by doug moen
I've got another variant (not tested) called
perimeter_extrude, which sweeps one 2D shape along the perimeter of another
2D shape. The code looks simple and fast, but I dunno if it will work in
all cases yet.
I'am afraid you will have to deal with self intersections as soon as
linearity is lost.
Post by doug moen
I am investigating the more general problem of sweeping a 3D shape through
space along a parameterized curve. One paper I found describes a general
solution to this problem, allowing the shape being swept to continuously
vary according to the curve parameter. Self intersections are handled. It's
totally general, but the code is complex and slow. I haven't actually tried
coding it.
My approach for sweeps with fixed (or locally only smoothly morphing) shapes
is to evaluate the slope and rotation axes and calculate possible
intersections for extreme values analytically for each slice. Whenever an
intersection is found, the operation will be split and resulting shapes
finally combined with union(). The less pathologic a sweep is formulated the
faster the code.

- Rudolf -



--
View this message in context: http://forum.openscad.org/Non-Linear-Transformations-tp14539p16673.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
doug moen
2016-03-23 01:50:18 UTC
Permalink
Implementing linear_extrude() to operate over 3D shapes is more
sophisticated, but don't forget what is gained. It could replace hull() and
get rid of its convexity restriction. If it is done as proposed additional
costs will be limited. One could also live with twists and scales not being
applied to the objects halfs at the ends.
Okay, but linear_extrude() 3dshape is, except for the end caps, the same as
linear_extrude() projection() 3dshape. Little is gained except for some
convenience. But now I agree that it's not a burden to implement.

Consider this:

module linear_extrude3(h)
{
children();
linear_extrude(h) projection() children();
translate([0,0,h]) children();
}

linear_extrude3(10)
{
cube(8,center=true);
for(i=[0:90:270]) {
rotate([0,0,i]) translate([4,0,0]) sphere(2);
}
}

My comment about twist is that most of the F-Rep solid modelling systems
have a separate twist() operator that applies to any shape. It's only a
couple lines of code, so it's easy to implement, and more general than a
twist that can only be applied to the result of linear_extrude. This would
be an example of one of those functional transforms that Trygon was
promoting in the original post.
Parkinbot
2016-03-23 11:46:50 UTC
Permalink
Yes, a separate twist operator allowing for an axis argument defaulted to [0,
0, 1] would gain a lot. But I am afraid it is not so easy to implement,
because it requests a decomposition of the operands into slices.
Post by doug moen
Okay, but linear_extrude() 3dshape is, except for the end caps, the same
as linear_extrude() projection() 3dshape. Little is gained except for some
convenience.
To have the endcaps is of course the salt in the soup. After all the shapes
need to be split, twisted and scaled. I tried to add a twist, which does not
twist the endcaps in lack of the twist operator. It has already CSG shadows
(F6 works fine). But no way to add a scale, because it is not expressible in
OpenSCAD.
Btw the code shows just another linear_extrude() bug. The twist parameter
rotates with wrong sign.

<Loading Image...>
Post by doug moen
module linear_extrude3(h, twist = 0)
{
rotate([0, 0, -twist]) cap(h, true) children();
linear_extrude(h, twist = twist) projection() children();
cap(h, scale, false) children();
}
module cap(h, upper = true)
{
difference()
{
translate([0,0,upper?h:0]) children();
linear_extrude(h) projection() children();
}
}
linear_extrude3(30, 60, [1,.5])
{
translate([10, 10, 0])
{
cube(8,center=true);
for(i=[0:90:270]) {
rotate([0,0,i]) translate([4,0,0]) sphere(2);
}
}
}
--
View this message in context: http://forum.openscad.org/Non-Linear-Transformations-tp14539p16678.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
doug moen
2016-03-23 12:59:58 UTC
Permalink
Nice. I now see that the end caps need to be twisted in order for this to
work correctly with a twist parameter. A twist() operator would be needed.

In order to correctly scale the end caps, we need a projective
transformation, an extension discussed in this thread.

Interesting. The 'scale' parameter actually applies a projective
transformation to the output of linear extrude. If we supported these
transformations directly, the 'scale' parameter wouldn't be needed.

Doug.
Post by Parkinbot
Yes, a separate twist operator allowing for an axis argument defaulted to [0,
0, 1] would gain a lot. But I am afraid it is not so easy to implement,
because it requests a decomposition of the operands into slices.
Post by doug moen
Okay, but linear_extrude() 3dshape is, except for the end caps, the same
as linear_extrude() projection() 3dshape. Little is gained except for
some
Post by doug moen
convenience.
To have the endcaps is of course the salt in the soup. After all the shapes
need to be split, twisted and scaled. I tried to add a twist, which does not
twist the endcaps in lack of the twist operator. It has already CSG shadows
(F6 works fine). But no way to add a scale, because it is not expressible in
OpenSCAD.
Btw the code shows just another linear_extrude() bug. The twist parameter
rotates with wrong sign.
<http://forum.openscad.org/file/n16678/lin3.png>
Post by doug moen
module linear_extrude3(h, twist = 0)
{
rotate([0, 0, -twist]) cap(h, true) children();
linear_extrude(h, twist = twist) projection() children();
cap(h, scale, false) children();
}
module cap(h, upper = true)
{
difference()
{
translate([0,0,upper?h:0]) children();
linear_extrude(h) projection() children();
}
}
linear_extrude3(30, 60, [1,.5])
{
translate([10, 10, 0])
{
cube(8,center=true);
for(i=[0:90:270]) {
rotate([0,0,i]) translate([4,0,0]) sphere(2);
}
}
}
--
http://forum.openscad.org/Non-Linear-Transformations-tp14539p16678.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
_______________________________________________
OpenSCAD mailing list
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Carsten Arnholm
2016-03-22 17:51:49 UTC
Permalink
Post by Parkinbot
Post by Parkinbot
From the other side, also rotate_extrude() could be enriched to allow for a
height argument (definition of screws) or a given height path (scews with
nonlinear slopes).
Perhaps, in rotate_extrude, a pitch parameter combined with an ability
to specify many revolutions in the angle parameter would be enough to
define threads.

Carsten Arnholm
Carsten Arnholm
2016-03-23 14:46:29 UTC
Permalink
Post by Carsten Arnholm
Post by Parkinbot
Post by Parkinbot
From the other side, also rotate_extrude() could be enriched to allow for a
height argument (definition of screws) or a given height path (scews with
nonlinear slopes).
Perhaps, in rotate_extrude, a pitch parameter combined with an ability
to specify many revolutions in the angle parameter would be enough to
define threads.
As an experiment, I have tried this approach in my latest implementation
of rotate_extrude in Angelscript CSG. It might provide some inspiration
for OpenSCAD:

Loading Image...
Loading Image...

The complete source code generating the above is
http://arnholm.org/software/as_csg/ISO_thread.as
(Note this is based on an experimental version)

All 3d booleans are performed using carve (0.25 sec). Tesselation for
STL also done with carve.

To view the result in 3d using OpenSCAD:
http://arnholm.org/software/as_csg/ISO_thread.csg

In general the approach taken is to iteratively transform the 2d profile
into its proper 3d location and use the transformed profile to build the
3d mesh geometry and topology.

Carsten Arnholm
Parkinbot
2016-03-23 22:21:43 UTC
Permalink
nice! If you have access to the points everything is possible.

I imagine a syntax similiar to linear_extrude()
rotate_extrude(angle, height, scale)
The problem is of course how to manage self intersection. So with respect to
implementation it might be easyier to restrict the angle to the range of
-360:360 degrees, while height is your pitch offset. If you want more
windings you can define this with your 2D-shape. Have a look at my quickly
done pure OpenSCAD implementation (lib stuff should be clear from previous
posts).

<Loading Image...>
use
<shortcuts.scad>
// translate -> Tx, ...
use
<skin.scad>
// skin()
use
<naca_sweep.scad>
// define affine ops Tx_ ...
Tx(30) rotate_extrude() Toothbar();
T(10, -30) Toothbar();
linear_extrude3(angle = 600, height = PI); // full screw
Tx(-20)linear_extrude3(angle = -180, height = PI); // half screw
module linear_extrude3(angle = 360, height = 0)
skin(gen_dat(height, angle)); // we cheat here
module Toothbar(z= 10)
Tx(5) Rz(90) Tx(-(PI/2)+tan(20)) polygon(points = TB(z));
function TB(n=2) =
concat([[0, 2]], [for (i=[0:n-1], j=[0:3])
let(t = [ [0, 1], [2*tan(20), -1], [PI/2, -1], [2*tan(20)+PI/2, 1]])
[t[j][0]+i*PI, t[j][1]]], [[2*tan(20)+PI/2+(n-1)*PI, 2]]);
function gen_dat(height = 0, angle = 360, steps = 100) =
let(ang = angle%360)
let(bar = R_(180, -90, 0, Ty_(-5, vec3D(TB(10)))))
[for (i=[0:steps]) Tz_(i*height/steps, Rz_(i*ang/steps, bar))];
--
View this message in context: http://forum.openscad.org/Non-Linear-Transformations-tp14539p16695.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
Carsten Arnholm
2016-03-24 00:13:00 UTC
Permalink
Post by Parkinbot
The problem is of course how to manage self intersection.
I found it can work to make the single thread 2d profile a tiny bit
narrower than the pitch. The effect is that there is no self
intersection, but instead a continuous near miss. The gap is later
filled by the internal cylinder that is unioned with the spiraling
thread body, to make a threaded rod.
Post by Parkinbot
So with respect to
implementation it might be easyier to restrict the angle to the range of
-360:360 degrees, while height is your pitch offset. If you want more
windings you can define this with your 2D-shape.
Perhaps easier to implement, but maybe also somewhat harder to use? I
tried a few cases and managed 69 windings before things started to
become unstable. That's 69*360 degrees... admittedly it also depends on
mesh resolution how far you can go.

Carsten Arnholm
Parkinbot
2016-03-24 00:40:08 UTC
Permalink
Post by Carsten Arnholm
I found it can work to make the single thread 2d profile a tiny bit
narrower than the pitch. The effect is that there is no self
intersection, but instead a continuous near miss. The gap is later
filled by the internal cylinder that is unioned with the spiraling
thread body, to make a threaded rod.
To be honest, to me this looks more like a hack, and not like a general
solution. Why should things get unstable with increasing windings? Memory?
When I tried a 1000 'windings' CSG rendering was done in 58s.

I hope to see this or a similar solution in OpenSCAD soon, as it is really
easy to update. Maybe I should write a feature request ...



--
View this message in context: http://forum.openscad.org/Non-Linear-Transformations-tp14539p16701.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
Carsten Arnholm
2016-03-24 09:08:30 UTC
Permalink
Post by Parkinbot
Post by Carsten Arnholm
I found it can work to make the single thread 2d profile a tiny bit
narrower than the pitch. The effect is that there is no self
intersection, but instead a continuous near miss. The gap is later
filled by the internal cylinder that is unioned with the spiraling
thread body, to make a threaded rod.
To be honest, to me this looks more like a hack, and not like a general
solution.
I am not too worried about labels when things actually work in practice,
like in this case.
Post by Parkinbot
Why should things get unstable with increasing windings? Memory?
When I tried a 1000 'windings' CSG rendering was done in 58s.
If you take fixed precision integer coordinates and multiply with ever
larger factors (that is what happens when you increase the number of
windings to large numbers), you will eventually have numerical issues
since the relative tolerances are not that big. My approach was a little
simplistic since it was an experiment, but it actually worked better
than I had thought. On the timing, it was done in about .2 seconds in my
case, much less than it took to write the output files.
Post by Parkinbot
I hope to see this or a similar solution in OpenSCAD soon, as it is really
easy to update. Maybe I should write a feature request ...
Threads are much used, so probably, yes.

Carsten Arnholm

Loading...