discuss@lists.openscad.org

OpenSCAD general discussion Mailing-list

View all threads

Re: parametric

JW
Joe Weinpert
Mon, Oct 28, 2024 9:34 PM

I don't have an algorithm at all.  I was looking for one, though :-)

Look at the sample pictures I sent as just being stl objects.  What would I
need to do to create them in OpenSCAD?  How do you create odd shaped
"blobs" and patterns and put them together?

Joe Weinpert
skidrowacademy.com

On Mon, Oct 28, 2024 at 5:20 PM Adrian Mariano avm4@cornell.edu wrote:

Appears that you sent this message just to me, not the list.

Do you have an algorithm that generates these parametric structures?
Because there are two separate issues here.  One is how do you produce
those patterns AT ALL.  And the second one is how do you do it in
OpenSCAD.  It would be advantageous to have a solid answer to the first
question before pondering the second one.  Or you at least need some idea
of a possible algorithm.  An algorithm for this is not immediately obvious
to me.  The problem of "how to do this in BOSL2" depends on what that
algorithm looks like, and a lot of it might not be  BOSL2 specific but
really just how to generate a pattern that looks like that.

On Sat, Oct 26, 2024 at 12:53 PM Joe Weinpert joe.weinpert@gmail.com
wrote:

Here are a couple of samples.  Parametric styles vary immensely.  It
would be nice to have a tool that can be used to create different forms.

[image: 2024-10-26_12-46-24.jpg]
[image: 2024-10-26_12-48-31.jpg]

Joe Weinpert
skidrowacademy.com

On Sat, Oct 26, 2024 at 12:40 PM Adrian Mariano avm4@cornell.edu wrote:

You need to define your goal better. I have no clue what a parametric
wall carving might be. What form?  What parameters?

On Sat, Oct 26, 2024 at 12:23 Joe Weinpert via Discuss <
discuss@lists.openscad.org> wrote:

I would like to use OpenSCAD and the BOSL library to design parametric
wood wall carving STL files.

Has anyone done this yet?

Where should I start looking?  BOSL has nearly 900 functions.

Would there be any examples of what to use?  Examples, I have found,
are the best way to learn something.

Joe Weinpert
skidrowacademy.com


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org

I don't have an algorithm at all. I was looking for one, though :-) Look at the sample pictures I sent as just being stl objects. What would I need to do to create them in OpenSCAD? How do you create odd shaped "blobs" and patterns and put them together? Joe Weinpert skidrowacademy.com On Mon, Oct 28, 2024 at 5:20 PM Adrian Mariano <avm4@cornell.edu> wrote: > Appears that you sent this message just to me, not the list. > > Do you have an algorithm that generates these parametric structures? > Because there are two separate issues here. One is how do you produce > those patterns AT ALL. And the second one is how do you do it in > OpenSCAD. It would be advantageous to have a solid answer to the first > question before pondering the second one. Or you at least need some idea > of a possible algorithm. An algorithm for this is not immediately obvious > to me. The problem of "how to do this in BOSL2" depends on what that > algorithm looks like, and a lot of it might not be BOSL2 specific but > really just how to generate a pattern that looks like that. > > On Sat, Oct 26, 2024 at 12:53 PM Joe Weinpert <joe.weinpert@gmail.com> > wrote: > >> Here are a couple of samples. Parametric styles vary immensely. It >> would be nice to have a tool that can be used to create different forms. >> >> [image: 2024-10-26_12-46-24.jpg] >> [image: 2024-10-26_12-48-31.jpg] >> >> Joe Weinpert >> skidrowacademy.com >> >> >> >> On Sat, Oct 26, 2024 at 12:40 PM Adrian Mariano <avm4@cornell.edu> wrote: >> >>> You need to define your goal better. I have no clue what a parametric >>> wall carving might be. What form? What parameters? >>> >>> On Sat, Oct 26, 2024 at 12:23 Joe Weinpert via Discuss < >>> discuss@lists.openscad.org> wrote: >>> >>>> I would like to use OpenSCAD and the BOSL library to design parametric >>>> wood wall carving STL files. >>>> >>>> Has anyone done this yet? >>>> >>>> Where should I start looking? BOSL has nearly 900 functions. >>>> >>>> Would there be any examples of what to use? Examples, I have found, >>>> are the best way to learn something. >>>> >>>> Joe Weinpert >>>> skidrowacademy.com >>>> >>>> _______________________________________________ >>>> OpenSCAD mailing list >>>> To unsubscribe send an email to discuss-leave@lists.openscad.org >>>> >>>
JB
Jordan Brown
Mon, Oct 28, 2024 9:55 PM

On 10/28/2024 2:34 PM, Joe Weinpert via Discuss wrote:

I don't have an algorithm at all.  I was looking for one, though :-)

Look at the sample pictures I sent as just being stl objects.  What
would I need to do to create them in OpenSCAD?  How do you create odd
shaped "blobs" and patterns and put them together?

polyhedron(), and math to come up with the desired shape.

Here's something I did to come up with a water wave pattern.  It's not
great but it illustrates the idea.  The bulk is the sfc() module, which
is like surface() but takes its input in the form of an array. 
surface() really should do that, but doesn't and I haven't gotten around
to making it happen.  I was never very happy with the relationship
between the resolution of the array and the size presented, so that may
be more complex than it needs to be.

For something like you describe, you need the sfc() module and a module
that produces the right height-map for your pattern.

$fa = 1;
$fs = 0.5;

waterX = 600;
waterY = 600;
waterStep = 5;
waveLengthX = 60;
waveLengthY = 50;
waveAmpX = 2;
waveAmpY = 1;
waveH = waveAmpX + waveAmpY;
baseH = waveH + 0.5;

function wave(x,y) = waveAmpXsin(360x/waveLengthX) + waveAmpYsin(360y/waveLengthY);

module water() {
water = [
let(nx = floor(waterX/waterStep))
let(xStep = waterX/nx)
let(ny = floor(waterY/waterStep))
let(yStep = waterY/ny)
for (ix = [0:nx]) [
for (iy=[0:ny])
wave(ixxStep, iyyStep)
]
];
translate([-waterX/4,-waterY/4,waveH])
sfc(water, [waterX, waterY, baseH]);
}

module sfc(a, sz) {
function dataIndex(x, y) = dataBase + x*ny + y;
nx = len(a);
ny = len(a[0]);
corners = 0;
dataBase = corners + 4;

pts = [
    [0,    0,    -sz.z],
    [nx-1, 0,    -sz.z],
    [nx-1, ny-1, -sz.z],
    [0,    ny-1, -sz.z],
    for (x = [0:nx-1])
        for (y = [0:ny-1])
            [ x, y, a[x][y] ]
];
faces = [
    [ corners+0, corners+1, corners+2 ],
    [ corners+0, corners+2, corners+3 ],
    [
        each for (x=[0:nx-1]) dataIndex(x,0),
        corners+1,
        corners+0,
    ],
    [
        each for (y=[0:ny-1]) dataIndex(nx-1,y),
        corners+2,
        corners+1,
    ],
    [
        each for (x=[nx-1:-1:0]) dataIndex(x,ny-1),
        corners+3,
        corners+2,
    ],
    [
        each for (y=[ny-1:-1:0]) dataIndex(0,y),
        corners+0,
        corners+3,
    ],
    each for (x=[0:nx-2], y=[0:ny-2]) [
        [ dataIndex(x+1, y), dataIndex(x, y), dataIndex(x, y+1) ],
        [ dataIndex(x+1, y+1), dataIndex(x+1, y), dataIndex(x, y+1) ],
    ],
];
scale([sz.x/(nx-1),sz.y/(ny-1),1])
    polyhedron(pts, faces, convexity=ceil(max(waterX/waveLengthX, waterY/waveLengthY)));

}

water();

On 10/28/2024 2:34 PM, Joe Weinpert via Discuss wrote: > > I don't have an algorithm at all.  I was looking for one, though :-) > > Look at the sample pictures I sent as just being stl objects.  What > would I need to do to create them in OpenSCAD?  How do you create odd > shaped "blobs" and patterns and put them together? > polyhedron(), and math to come up with the desired shape. Here's something I did to come up with a water wave pattern.  It's not great but it illustrates the idea.  The bulk is the sfc() module, which is like surface() but takes its input in the form of an array.  surface() really should do that, but doesn't and I haven't gotten around to making it happen.  I was never very happy with the relationship between the resolution of the array and the size presented, so that may be more complex than it needs to be. For something like you describe, you need the sfc() module and a module that produces the right height-map for your pattern. $fa = 1; $fs = 0.5; waterX = 600; waterY = 600; waterStep = 5; waveLengthX = 60; waveLengthY = 50; waveAmpX = 2; waveAmpY = 1; waveH = waveAmpX + waveAmpY; baseH = waveH + 0.5; function wave(x,y) = waveAmpX*sin(360*x/waveLengthX) + waveAmpY*sin(360*y/waveLengthY); module water() { water = [ let(nx = floor(waterX/waterStep)) let(xStep = waterX/nx) let(ny = floor(waterY/waterStep)) let(yStep = waterY/ny) for (ix = [0:nx]) [ for (iy=[0:ny]) wave(ix*xStep, iy*yStep) ] ]; translate([-waterX/4,-waterY/4,waveH]) sfc(water, [waterX, waterY, baseH]); } module sfc(a, sz) { function dataIndex(x, y) = dataBase + x*ny + y; nx = len(a); ny = len(a[0]); corners = 0; dataBase = corners + 4; pts = [ [0, 0, -sz.z], [nx-1, 0, -sz.z], [nx-1, ny-1, -sz.z], [0, ny-1, -sz.z], for (x = [0:nx-1]) for (y = [0:ny-1]) [ x, y, a[x][y] ] ]; faces = [ [ corners+0, corners+1, corners+2 ], [ corners+0, corners+2, corners+3 ], [ each for (x=[0:nx-1]) dataIndex(x,0), corners+1, corners+0, ], [ each for (y=[0:ny-1]) dataIndex(nx-1,y), corners+2, corners+1, ], [ each for (x=[nx-1:-1:0]) dataIndex(x,ny-1), corners+3, corners+2, ], [ each for (y=[ny-1:-1:0]) dataIndex(0,y), corners+0, corners+3, ], each for (x=[0:nx-2], y=[0:ny-2]) [ [ dataIndex(x+1, y), dataIndex(x, y), dataIndex(x, y+1) ], [ dataIndex(x+1, y+1), dataIndex(x+1, y), dataIndex(x, y+1) ], ], ]; scale([sz.x/(nx-1),sz.y/(ny-1),1]) polyhedron(pts, faces, convexity=ceil(max(waterX/waveLengthX, waterY/waveLengthY))); } water();
JB
Jordan Brown
Mon, Oct 28, 2024 10:26 PM

And of course that prompted me to review that program, simplify it a
bit, and replace the wave function with one that's in some ways more
interesting.

But note that the shape of the model is entirely controlled by the
wave() function and its inputs.

Note:  sfc() has a bunch of square cells to draw a surface from.  That
requires deciding which diagonal to use to split the squares into two
triangles.  It happens that it chooses the lower-right/upper-left
diagonal, but either is equally correct.  In other patterns I've found
that this uniform triangulation can produce undesirable visual
artifacts, so in some other variations on this module I've chosen which
to use at random.  The difference is in how the final "each for" is built.

And of course, BOSL2 has this in its heightfield() module: 
https://github.com/BelfrySCAD/BOSL2/wiki/shapes3d.scad#functionmodule-heightfield

waterSize = [120, 120];
waveLength = 20;
waveH = 2;
baseH = waveH + 0.5;

water(waterSize);

function wave(x, y) = sin(360*norm([x,y] - waterSize/2)/waveLength) * waveH;

module water(size) {
water = [
for (ix = [0:size.x]) [
for (iy=[0:size.y])
wave(ix, iy)
]
];
sfc(water, baseH);
}

module sfc(a, base, convexity=10) {
function dataIndex(x, y) = dataBase + x*ny + y;
nx = len(a);
ny = len(a[0]);
corners = 0;
dataBase = corners + 4;

pts = [
    [0,    0,    -base],
    [nx-1, 0,    -base],
    [nx-1, ny-1, -base],
    [0,    ny-1, -base],
    for (x = [0:nx-1])
        for (y = [0:ny-1])
            [ x, y, a[x][y] ]
];
faces = [
    [ corners+0, corners+1, corners+2 ],
    [ corners+0, corners+2, corners+3 ],
    [
        each for (x=[0:nx-1]) dataIndex(x,0),
        corners+1,
        corners+0,
    ],
    [
        each for (y=[0:ny-1]) dataIndex(nx-1,y),
        corners+2,
        corners+1,
    ],
    [
        each for (x=[nx-1:-1:0]) dataIndex(x,ny-1),
        corners+3,
        corners+2,
    ],
    [
        each for (y=[ny-1:-1:0]) dataIndex(0,y),
        corners+0,
        corners+3,
    ],
    each for (x=[0:nx-2], y=[0:ny-2]) [
        [ dataIndex(x+1, y), dataIndex(x, y), dataIndex(x, y+1) ],
        [ dataIndex(x+1, y+1), dataIndex(x+1, y), dataIndex(x, y+1) ],
    ],
];
polyhedron(pts, faces, convexity=convexity);

}

And of course that prompted me to review that program, simplify it a bit, and replace the wave function with one that's in some ways more interesting. But note that the shape of the model is entirely controlled by the wave() function and its inputs. Note:  sfc() has a bunch of square cells to draw a surface from.  That requires deciding which diagonal to use to split the squares into two triangles.  It happens that it chooses the lower-right/upper-left diagonal, but either is equally correct.  In other patterns I've found that this uniform triangulation can produce undesirable visual artifacts, so in some other variations on this module I've chosen which to use at random.  The difference is in how the final "each for" is built. And of course, BOSL2 has this in its heightfield() module:  https://github.com/BelfrySCAD/BOSL2/wiki/shapes3d.scad#functionmodule-heightfield waterSize = [120, 120]; waveLength = 20; waveH = 2; baseH = waveH + 0.5; water(waterSize); function wave(x, y) = sin(360*norm([x,y] - waterSize/2)/waveLength) * waveH; module water(size) { water = [ for (ix = [0:size.x]) [ for (iy=[0:size.y]) wave(ix, iy) ] ]; sfc(water, baseH); } module sfc(a, base, convexity=10) { function dataIndex(x, y) = dataBase + x*ny + y; nx = len(a); ny = len(a[0]); corners = 0; dataBase = corners + 4; pts = [ [0, 0, -base], [nx-1, 0, -base], [nx-1, ny-1, -base], [0, ny-1, -base], for (x = [0:nx-1]) for (y = [0:ny-1]) [ x, y, a[x][y] ] ]; faces = [ [ corners+0, corners+1, corners+2 ], [ corners+0, corners+2, corners+3 ], [ each for (x=[0:nx-1]) dataIndex(x,0), corners+1, corners+0, ], [ each for (y=[0:ny-1]) dataIndex(nx-1,y), corners+2, corners+1, ], [ each for (x=[nx-1:-1:0]) dataIndex(x,ny-1), corners+3, corners+2, ], [ each for (y=[ny-1:-1:0]) dataIndex(0,y), corners+0, corners+3, ], each for (x=[0:nx-2], y=[0:ny-2]) [ [ dataIndex(x+1, y), dataIndex(x, y), dataIndex(x, y+1) ], [ dataIndex(x+1, y+1), dataIndex(x+1, y), dataIndex(x, y+1) ], ], ]; polyhedron(pts, faces, convexity=convexity); }
JD
John David
Mon, Oct 28, 2024 10:35 PM

@Joe, that is SO CooL!  Thanks for the examples.  Hmmm... I'll have to make
some time to work on a dream project -- it really came to me in a dream,
and it is one of about 6 blacksmithing projects that I hope to make before
I put my hammers to rest.  But to REALLY give it a go, I need to find
someone to help me translate the poem that came to me in the dream into
Japanese, and then work with my best friend to render that with dry-brush
calligraphy, then execute the calligraphy in steel (which plunges into the
background stone, which ripples like waves in water)... Aaahhhh <sigh>  I
still dream ;-)

On Mon, Oct 28, 2024 at 6:27 PM Jordan Brown via Discuss <
discuss@lists.openscad.org> wrote:

And of course that prompted me to review that program, simplify it a bit,
and replace the wave function with one that's in some ways more interesting.

But note that the shape of the model is entirely controlled by the wave()
function and its inputs.

Note:  sfc() has a bunch of square cells to draw a surface from.  That
requires deciding which diagonal to use to split the squares into two
triangles.  It happens that it chooses the lower-right/upper-left diagonal,
but either is equally correct.  In other patterns I've found that this
uniform triangulation can produce undesirable visual artifacts, so in some
other variations on this module I've chosen which to use at random.  The
difference is in how the final "each for" is built.

And of course, BOSL2 has this in its heightfield() module:
https://github.com/BelfrySCAD/BOSL2/wiki/shapes3d.scad#functionmodule-heightfield

waterSize = [120, 120];
waveLength = 20;
waveH = 2;
baseH = waveH + 0.5;

water(waterSize);

function wave(x, y) = sin(360*norm([x,y] - waterSize/2)/waveLength) * waveH;

module water(size) {
water = [
for (ix = [0:size.x]) [
for (iy=[0:size.y])
wave(ix, iy)
]
];
sfc(water, baseH);
}

module sfc(a, base, convexity=10) {
function dataIndex(x, y) = dataBase + x*ny + y;
nx = len(a);
ny = len(a[0]);
corners = 0;
dataBase = corners + 4;

 pts = [
     [0,    0,    -base],
     [nx-1, 0,    -base],
     [nx-1, ny-1, -base],
     [0,    ny-1, -base],
     for (x = [0:nx-1])
         for (y = [0:ny-1])
             [ x, y, a[x][y] ]
 ];
 faces = [
     [ corners+0, corners+1, corners+2 ],
     [ corners+0, corners+2, corners+3 ],
     [
         each for (x=[0:nx-1]) dataIndex(x,0),
         corners+1,
         corners+0,
     ],
     [
         each for (y=[0:ny-1]) dataIndex(nx-1,y),
         corners+2,
         corners+1,
     ],
     [
         each for (x=[nx-1:-1:0]) dataIndex(x,ny-1),
         corners+3,
         corners+2,
     ],
     [
         each for (y=[ny-1:-1:0]) dataIndex(0,y),
         corners+0,
         corners+3,
     ],
     each for (x=[0:nx-2], y=[0:ny-2]) [
         [ dataIndex(x+1, y), dataIndex(x, y), dataIndex(x, y+1) ],
         [ dataIndex(x+1, y+1), dataIndex(x+1, y), dataIndex(x, y+1) ],
     ],
 ];
 polyhedron(pts, faces, convexity=convexity);

}


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org

@Joe, that is SO CooL! Thanks for the examples. Hmmm... I'll have to make some time to work on a dream project -- it really came to me in a dream, and it is one of about 6 blacksmithing projects that I hope to make before I put my hammers to rest. But to REALLY give it a go, I need to find someone to help me translate the poem that came to me in the dream into Japanese, and then work with my best friend to render that with dry-brush calligraphy, then execute the calligraphy in steel (which plunges into the background stone, which ripples like waves in water)... Aaahhhh <sigh> I still dream ;-) On Mon, Oct 28, 2024 at 6:27 PM Jordan Brown via Discuss < discuss@lists.openscad.org> wrote: > And of course that prompted me to review that program, simplify it a bit, > and replace the wave function with one that's in some ways more interesting. > > But note that the shape of the model is entirely controlled by the wave() > function and its inputs. > > Note: sfc() has a bunch of square cells to draw a surface from. That > requires deciding which diagonal to use to split the squares into two > triangles. It happens that it chooses the lower-right/upper-left diagonal, > but either is equally correct. In other patterns I've found that this > uniform triangulation can produce undesirable visual artifacts, so in some > other variations on this module I've chosen which to use at random. The > difference is in how the final "each for" is built. > > And of course, BOSL2 has this in its heightfield() module: > https://github.com/BelfrySCAD/BOSL2/wiki/shapes3d.scad#functionmodule-heightfield > > > waterSize = [120, 120]; > waveLength = 20; > waveH = 2; > baseH = waveH + 0.5; > > water(waterSize); > > function wave(x, y) = sin(360*norm([x,y] - waterSize/2)/waveLength) * waveH; > > module water(size) { > water = [ > for (ix = [0:size.x]) [ > for (iy=[0:size.y]) > wave(ix, iy) > ] > ]; > sfc(water, baseH); > } > > module sfc(a, base, convexity=10) { > function dataIndex(x, y) = dataBase + x*ny + y; > nx = len(a); > ny = len(a[0]); > corners = 0; > dataBase = corners + 4; > > pts = [ > [0, 0, -base], > [nx-1, 0, -base], > [nx-1, ny-1, -base], > [0, ny-1, -base], > for (x = [0:nx-1]) > for (y = [0:ny-1]) > [ x, y, a[x][y] ] > ]; > faces = [ > [ corners+0, corners+1, corners+2 ], > [ corners+0, corners+2, corners+3 ], > [ > each for (x=[0:nx-1]) dataIndex(x,0), > corners+1, > corners+0, > ], > [ > each for (y=[0:ny-1]) dataIndex(nx-1,y), > corners+2, > corners+1, > ], > [ > each for (x=[nx-1:-1:0]) dataIndex(x,ny-1), > corners+3, > corners+2, > ], > [ > each for (y=[ny-1:-1:0]) dataIndex(0,y), > corners+0, > corners+3, > ], > each for (x=[0:nx-2], y=[0:ny-2]) [ > [ dataIndex(x+1, y), dataIndex(x, y), dataIndex(x, y+1) ], > [ dataIndex(x+1, y+1), dataIndex(x+1, y), dataIndex(x, y+1) ], > ], > ]; > polyhedron(pts, faces, convexity=convexity); > } > > > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email to discuss-leave@lists.openscad.org >
JB
Jordan Brown
Mon, Oct 28, 2024 10:37 PM

Meant to include an image...

Meant to include an image...
AM
Adrian Mariano
Mon, Oct 28, 2024 11:06 PM

I don't think the waves problem gives much insight into the general
parametric problem that was posed.  Producing that general parametric
pattern as a function over the xy plane seems like it might be difficult.
I suppose there might be some cool generative method that used an iterative
process to produce a functional shape like that.

When I looked at it I thought maybe you could generate a set of paths for
each ridge (or cut, if you like).  I thought maybe this could be turned
into a texture, but that's hard.  So that leads to something like this
(where you might be able to get away regular path_sweep if there are more
gentle curves---it would be faster).  But I have no clue how you generate
the path list.

include<BOSL2/std.scad>
cuboid([10,10,1],anchor=TOP+LEFT);
cycles=3;
path = [for(t=[0:10:360cycles])  [10t/360/cycles,
(1+t/(360*cycles)/.5)*sin(t)]];
profile = [for(theta=[-180:36:180]) [theta/180/3, (1+cos(theta))/7]];
path_sweep2d(profile, path);

[image: image.png]

On Mon, Oct 28, 2024 at 5:56 PM Jordan Brown openscad@jordan.maileater.net
wrote:

On 10/28/2024 2:34 PM, Joe Weinpert via Discuss wrote:

I don't have an algorithm at all.  I was looking for one, though :-)

Look at the sample pictures I sent as just being stl objects.  What would
I need to do to create them in OpenSCAD?  How do you create odd shaped
"blobs" and patterns and put them together?

polyhedron(), and math to come up with the desired shape.

Here's something I did to come up with a water wave pattern.  It's not
great but it illustrates the idea.  The bulk is the sfc() module, which is
like surface() but takes its input in the form of an array.  surface()
really should do that, but doesn't and I haven't gotten around to making it
happen.  I was never very happy with the relationship between the
resolution of the array and the size presented, so that may be more complex
than it needs to be.

For something like you describe, you need the sfc() module and a module
that produces the right height-map for your pattern.

$fa = 1;
$fs = 0.5;

waterX = 600;
waterY = 600;
waterStep = 5;
waveLengthX = 60;
waveLengthY = 50;
waveAmpX = 2;
waveAmpY = 1;
waveH = waveAmpX + waveAmpY;
baseH = waveH + 0.5;

function wave(x,y) = waveAmpXsin(360x/waveLengthX) + waveAmpYsin(360y/waveLengthY);

module water() {
water = [
let(nx = floor(waterX/waterStep))
let(xStep = waterX/nx)
let(ny = floor(waterY/waterStep))
let(yStep = waterY/ny)
for (ix = [0:nx]) [
for (iy=[0:ny])
wave(ixxStep, iyyStep)
]
];
translate([-waterX/4,-waterY/4,waveH])
sfc(water, [waterX, waterY, baseH]);
}

module sfc(a, sz) {
function dataIndex(x, y) = dataBase + x*ny + y;
nx = len(a);
ny = len(a[0]);
corners = 0;
dataBase = corners + 4;

 pts = [
     [0,    0,    -sz.z],
     [nx-1, 0,    -sz.z],
     [nx-1, ny-1, -sz.z],
     [0,    ny-1, -sz.z],
     for (x = [0:nx-1])
         for (y = [0:ny-1])
             [ x, y, a[x][y] ]
 ];
 faces = [
     [ corners+0, corners+1, corners+2 ],
     [ corners+0, corners+2, corners+3 ],
     [
         each for (x=[0:nx-1]) dataIndex(x,0),
         corners+1,
         corners+0,
     ],
     [
         each for (y=[0:ny-1]) dataIndex(nx-1,y),
         corners+2,
         corners+1,
     ],
     [
         each for (x=[nx-1:-1:0]) dataIndex(x,ny-1),
         corners+3,
         corners+2,
     ],
     [
         each for (y=[ny-1:-1:0]) dataIndex(0,y),
         corners+0,
         corners+3,
     ],
     each for (x=[0:nx-2], y=[0:ny-2]) [
         [ dataIndex(x+1, y), dataIndex(x, y), dataIndex(x, y+1) ],
         [ dataIndex(x+1, y+1), dataIndex(x+1, y), dataIndex(x, y+1) ],
     ],
 ];
 scale([sz.x/(nx-1),sz.y/(ny-1),1])
     polyhedron(pts, faces, convexity=ceil(max(waterX/waveLengthX, waterY/waveLengthY)));

}

water();

I don't think the waves problem gives much insight into the general parametric problem that was posed. Producing that general parametric pattern as a function over the xy plane seems like it might be difficult. I suppose there might be some cool generative method that used an iterative process to produce a functional shape like that. When I looked at it I thought maybe you could generate a set of paths for each ridge (or cut, if you like). I thought maybe this could be turned into a texture, but that's hard. So that leads to something like this (where you might be able to get away regular path_sweep if there are more gentle curves---it would be faster). But I have no clue how you generate the path list. include<BOSL2/std.scad> cuboid([10,10,1],anchor=TOP+LEFT); cycles=3; path = [for(t=[0:10:360*cycles]) [10*t/360/cycles, (1+t/(360*cycles)/.5)*sin(t)]]; profile = [for(theta=[-180:36:180]) [theta/180/3, (1+cos(theta))/7]]; path_sweep2d(profile, path); [image: image.png] On Mon, Oct 28, 2024 at 5:56 PM Jordan Brown <openscad@jordan.maileater.net> wrote: > On 10/28/2024 2:34 PM, Joe Weinpert via Discuss wrote: > > > I don't have an algorithm at all. I was looking for one, though :-) > > Look at the sample pictures I sent as just being stl objects. What would > I need to do to create them in OpenSCAD? How do you create odd shaped > "blobs" and patterns and put them together? > > > polyhedron(), and math to come up with the desired shape. > > Here's something I did to come up with a water wave pattern. It's not > great but it illustrates the idea. The bulk is the sfc() module, which is > like surface() but takes its input in the form of an array. surface() > really should do that, but doesn't and I haven't gotten around to making it > happen. I was never very happy with the relationship between the > resolution of the array and the size presented, so that may be more complex > than it needs to be. > > For something like you describe, you need the sfc() module and a module > that produces the right height-map for your pattern. > > $fa = 1; > $fs = 0.5; > > waterX = 600; > waterY = 600; > waterStep = 5; > waveLengthX = 60; > waveLengthY = 50; > waveAmpX = 2; > waveAmpY = 1; > waveH = waveAmpX + waveAmpY; > baseH = waveH + 0.5; > > function wave(x,y) = waveAmpX*sin(360*x/waveLengthX) + waveAmpY*sin(360*y/waveLengthY); > > module water() { > water = [ > let(nx = floor(waterX/waterStep)) > let(xStep = waterX/nx) > let(ny = floor(waterY/waterStep)) > let(yStep = waterY/ny) > for (ix = [0:nx]) [ > for (iy=[0:ny]) > wave(ix*xStep, iy*yStep) > ] > ]; > translate([-waterX/4,-waterY/4,waveH]) > sfc(water, [waterX, waterY, baseH]); > } > > module sfc(a, sz) { > function dataIndex(x, y) = dataBase + x*ny + y; > nx = len(a); > ny = len(a[0]); > corners = 0; > dataBase = corners + 4; > > pts = [ > [0, 0, -sz.z], > [nx-1, 0, -sz.z], > [nx-1, ny-1, -sz.z], > [0, ny-1, -sz.z], > for (x = [0:nx-1]) > for (y = [0:ny-1]) > [ x, y, a[x][y] ] > ]; > faces = [ > [ corners+0, corners+1, corners+2 ], > [ corners+0, corners+2, corners+3 ], > [ > each for (x=[0:nx-1]) dataIndex(x,0), > corners+1, > corners+0, > ], > [ > each for (y=[0:ny-1]) dataIndex(nx-1,y), > corners+2, > corners+1, > ], > [ > each for (x=[nx-1:-1:0]) dataIndex(x,ny-1), > corners+3, > corners+2, > ], > [ > each for (y=[ny-1:-1:0]) dataIndex(0,y), > corners+0, > corners+3, > ], > each for (x=[0:nx-2], y=[0:ny-2]) [ > [ dataIndex(x+1, y), dataIndex(x, y), dataIndex(x, y+1) ], > [ dataIndex(x+1, y+1), dataIndex(x+1, y), dataIndex(x, y+1) ], > ], > ]; > scale([sz.x/(nx-1),sz.y/(ny-1),1]) > polyhedron(pts, faces, convexity=ceil(max(waterX/waveLengthX, waterY/waveLengthY))); > } > > water(); > > >
JB
Jordan Brown
Tue, Oct 29, 2024 4:27 AM

On 10/28/2024 4:06 PM, Adrian Mariano wrote:

I don't think the waves problem gives much insight into the general
parametric problem that was posed.

There are really two distinct problems:

  • Given a function of X and Y that tells you the height, produce a
    model.  We've got that - either your heightfield() or my sfc().
  • What function produces the shape that the OP wants?

I'm not quite as pessimistic as you are.  Remember that the "function"
doesn't need to be a mathematical function per se; it can have things
like lookup() in it.

But figuring it out won't be trivial.

Come to think of it, the easiest answer might be to draw the desired
pattern (with shading) in Paint or the equivalent, and then bring it in
with surface().

On 10/28/2024 4:06 PM, Adrian Mariano wrote: > I don't think the waves problem gives much insight into the general > parametric problem that was posed. There are really two distinct problems: * Given a function of X and Y that tells you the height, produce a model.  We've got that - either your heightfield() or my sfc(). * What function produces the shape that the OP wants? I'm not quite as pessimistic as you are.  Remember that the "function" doesn't need to be a mathematical function per se; it can have things like lookup() in it. But figuring it out won't be trivial. Come to think of it, the easiest answer might be to draw the desired pattern (with shading) in Paint or the equivalent, and then bring it in with surface().
AM
Adrian Mariano
Tue, Oct 29, 2024 4:43 AM

I absolutely agree that there are two separate problems:  (1) define what
you're trying to model and (2) actually model it.  But I believe that
you've proposed just one approach:  write a function that produces the
desired output, then feed it to heightfield().  But that might not be the
easiest approach.

If by "parametric" he means the thing that term usually means, then he
wants something that has a bunch of knobs you turn and produces different
looking results, so "draw it in other software" doesn't qualify.

It might be the case that producing the above specified function is hard
and that it's easier to produce a list of cut or ridge lines.  Then you
can't use height field unless you can turn cut lines into a function, which
is a pain because you have to apply a point spread operation that is
perpendicular to the cutline....which is basically like doing path sweep on
the cut line but for a function.  So instead...use path_sweep().

On the other hand, there might be as I suggested, some iterative method
with parameters that produces functional outputs that look like what Joe
wants.  And if you can do it as a functional form then you can make a
texture and apply it to cylinders and other shapes as well, which seems
like it would be interesting.

On Tue, Oct 29, 2024 at 12:27 AM Jordan Brown openscad@jordan.maileater.net
wrote:

On 10/28/2024 4:06 PM, Adrian Mariano wrote:

I don't think the waves problem gives much insight into the general
parametric problem that was posed.

There are really two distinct problems:

- Given a function of X and Y that tells you the height, produce a
model.  We've got that - either your heightfield() or my sfc().
- What function produces the shape that the OP wants?

I'm not quite as pessimistic as you are.  Remember that the "function"
doesn't need to be a mathematical function per se; it can have things like
lookup() in it.

But figuring it out won't be trivial.

Come to think of it, the easiest answer might be to draw the desired
pattern (with shading) in Paint or the equivalent, and then bring it in
with surface().

I absolutely agree that there are two separate problems: (1) define what you're trying to model and (2) actually model it. But I believe that you've proposed just one approach: write a function that produces the desired output, then feed it to heightfield(). But that might not be the easiest approach. If by "parametric" he means the thing that term usually means, then he wants something that has a bunch of knobs you turn and produces different looking results, so "draw it in other software" doesn't qualify. It might be the case that producing the above specified function is hard and that it's easier to produce a list of cut or ridge lines. Then you can't use height field unless you can turn cut lines into a function, which is a pain because you have to apply a point spread operation that is perpendicular to the cutline....which is basically like doing path sweep on the cut line but for a function. So instead...use path_sweep(). On the other hand, there might be as I suggested, some iterative method with parameters that produces functional outputs that look like what Joe wants. And if you can do it as a functional form then you can make a texture and apply it to cylinders and other shapes as well, which seems like it would be interesting. On Tue, Oct 29, 2024 at 12:27 AM Jordan Brown <openscad@jordan.maileater.net> wrote: > On 10/28/2024 4:06 PM, Adrian Mariano wrote: > > I don't think the waves problem gives much insight into the general > parametric problem that was posed. > > > There are really two distinct problems: > > - Given a function of X and Y that tells you the height, produce a > model. We've got that - either your heightfield() or my sfc(). > - What function produces the shape that the OP wants? > > I'm not quite as pessimistic as you are. Remember that the "function" > doesn't need to be a mathematical function per se; it can have things like > lookup() in it. > > But figuring it out won't be trivial. > > > Come to think of it, the easiest answer might be to draw the desired > pattern (with shading) in Paint or the equivalent, and then bring it in > with surface(). > > >
RW
Rogier Wolff
Tue, Oct 29, 2024 10:11 AM

I didn't quite catch the beginning of this discussion. But maybe
interesting anyway....

Because programming an algorithm in openscad might be difficult it
might be better to just do it in python and then export to openscad
syntax.

GIVEN a set of 3D curves, find a surface that matches the
set-of-curves.

If you just randomly "do stuff" then things become a mess. What do I
mean with "matches". Well, if you give a human a point cloud or a
set-of-curves, we immediately imagine the object they belong to. How
to capture that mathematically? I'd think soap surface comes close:
Minimal area of the surface.

I think I have an algorithm that is possibly perfect, possibly
close-but-not-quite.

Between each pair of curves, for each linesegment on one find the
closest point to the linesegment on the other curve. I'm not sure if
you have to take the sum of the linesegments or the actual distance to
the line. That's a triangle of your surface. For "well behaved"
curves, this gives the optimal surface. If there are not "well
behaved" curves that give a surface with holes... I don't know.

So for Jordan's example you could pass in something like:
a=5;
for (i=[0:.3:50])
translate ([0,0,asin(i360*4/50)]) circle (r=i);

or the radials. In openscad you can create a list-of-points with a
sinewave as the Z coordinate in one go. But I haven't memorized the
syntax yet.

(Initially / forever it is NOT the task of the algorithm to figure out
which pairs of curves to use for the surface. The user will have to
pass them in in sequence).

Being able to define surfaces (2d objects in 3D), would eventually
allow users to stitch them together (like we can already with
triangles) and create 3D objects. My example above together with
cylinder-surface (top=false) would create a real 3D object.

Roger. 

On Mon, Oct 28, 2024 at 07:06:25PM -0400, Adrian Mariano via Discuss wrote:

I don't think the waves problem gives much insight into the general
parametric problem that was posed.  Producing that general parametric
pattern as a function over the xy plane seems like it might be difficult.
I suppose there might be some cool generative method that used an iterative
process to produce a functional shape like that.

When I looked at it I thought maybe you could generate a set of paths for
each ridge (or cut, if you like).  I thought maybe this could be turned
into a texture, but that's hard.  So that leads to something like this
(where you might be able to get away regular path_sweep if there are more
gentle curves---it would be faster).  But I have no clue how you generate
the path list.

include<BOSL2/std.scad>
cuboid([10,10,1],anchor=TOP+LEFT);
cycles=3;
path = [for(t=[0:10:360cycles])  [10t/360/cycles,
(1+t/(360*cycles)/.5)*sin(t)]];
profile = [for(theta=[-180:36:180]) [theta/180/3, (1+cos(theta))/7]];
path_sweep2d(profile, path);

[image: image.png]

On Mon, Oct 28, 2024 at 5:56 PM Jordan Brown openscad@jordan.maileater.net
wrote:

On 10/28/2024 2:34 PM, Joe Weinpert via Discuss wrote:

I don't have an algorithm at all.  I was looking for one, though :-)

Look at the sample pictures I sent as just being stl objects.  What would
I need to do to create them in OpenSCAD?  How do you create odd shaped
"blobs" and patterns and put them together?

polyhedron(), and math to come up with the desired shape.

Here's something I did to come up with a water wave pattern.  It's not
great but it illustrates the idea.  The bulk is the sfc() module, which is
like surface() but takes its input in the form of an array.  surface()
really should do that, but doesn't and I haven't gotten around to making it
happen.  I was never very happy with the relationship between the
resolution of the array and the size presented, so that may be more complex
than it needs to be.

For something like you describe, you need the sfc() module and a module
that produces the right height-map for your pattern.

$fa = 1;
$fs = 0.5;

waterX = 600;
waterY = 600;
waterStep = 5;
waveLengthX = 60;
waveLengthY = 50;
waveAmpX = 2;
waveAmpY = 1;
waveH = waveAmpX + waveAmpY;
baseH = waveH + 0.5;

function wave(x,y) = waveAmpXsin(360x/waveLengthX) + waveAmpYsin(360y/waveLengthY);

module water() {
water = [
let(nx = floor(waterX/waterStep))
let(xStep = waterX/nx)
let(ny = floor(waterY/waterStep))
let(yStep = waterY/ny)
for (ix = [0:nx]) [
for (iy=[0:ny])
wave(ixxStep, iyyStep)
]
];
translate([-waterX/4,-waterY/4,waveH])
sfc(water, [waterX, waterY, baseH]);
}

module sfc(a, sz) {
function dataIndex(x, y) = dataBase + x*ny + y;
nx = len(a);
ny = len(a[0]);
corners = 0;
dataBase = corners + 4;

 pts = [
     [0,    0,    -sz.z],
     [nx-1, 0,    -sz.z],
     [nx-1, ny-1, -sz.z],
     [0,    ny-1, -sz.z],
     for (x = [0:nx-1])
         for (y = [0:ny-1])
             [ x, y, a[x][y] ]
 ];
 faces = [
     [ corners+0, corners+1, corners+2 ],
     [ corners+0, corners+2, corners+3 ],
     [
         each for (x=[0:nx-1]) dataIndex(x,0),
         corners+1,
         corners+0,
     ],
     [
         each for (y=[0:ny-1]) dataIndex(nx-1,y),
         corners+2,
         corners+1,
     ],
     [
         each for (x=[nx-1:-1:0]) dataIndex(x,ny-1),
         corners+3,
         corners+2,
     ],
     [
         each for (y=[ny-1:-1:0]) dataIndex(0,y),
         corners+0,
         corners+3,
     ],
     each for (x=[0:nx-2], y=[0:ny-2]) [
         [ dataIndex(x+1, y), dataIndex(x, y), dataIndex(x, y+1) ],
         [ dataIndex(x+1, y+1), dataIndex(x+1, y), dataIndex(x, y+1) ],
     ],
 ];
 scale([sz.x/(nx-1),sz.y/(ny-1),1])
     polyhedron(pts, faces, convexity=ceil(max(waterX/waveLengthX, waterY/waveLengthY)));

}

water();


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org

--
** R.E.Wolff@BitWizard.nl ** https://www.BitWizard.nl/ ** +31-15-2049110 **
**    Delftechpark 11 2628 XJ  Delft, The Netherlands.  KVK: 27239233    **
f equals m times a. When your f is steady, and your m is going down
your a** is going up.  -- Chris Hadfield about flying up the space shuttle.
**  'a' for accelleration.

I didn't quite catch the beginning of this discussion. But maybe interesting anyway.... Because programming an algorithm in openscad might be difficult it might be better to just do it in python and then export to openscad syntax. GIVEN a set of 3D curves, find a surface that matches the set-of-curves. If you just randomly "do stuff" then things become a mess. What do I mean with "matches". Well, if you give a human a point cloud or a set-of-curves, we immediately imagine the object they belong to. How to capture that mathematically? I'd think soap surface comes close: Minimal area of the surface. I think I have an algorithm that is possibly perfect, possibly close-but-not-quite. Between each pair of curves, for each linesegment on one find the closest point to the linesegment on the other curve. I'm not sure if you have to take the sum of the linesegments or the actual distance to the line. That's a triangle of your surface. For "well behaved" curves, this gives the optimal surface. If there are not "well behaved" curves that give a surface with holes... I don't know. So for Jordan's example you could pass in something like: a=5; for (i=[0:.3:50]) translate ([0,0,a*sin(i*360*4/50)]) circle (r=i); or the radials. In openscad you can create a list-of-points with a sinewave as the Z coordinate in one go. But I haven't memorized the syntax yet. (Initially / forever it is NOT the task of the algorithm to figure out which pairs of curves to use for the surface. The user will have to pass them in in sequence). Being able to define surfaces (2d objects in 3D), would eventually allow users to stitch them together (like we can already with triangles) and create 3D objects. My example above together with cylinder-surface (top=false) would create a real 3D object. Roger. On Mon, Oct 28, 2024 at 07:06:25PM -0400, Adrian Mariano via Discuss wrote: > I don't think the waves problem gives much insight into the general > parametric problem that was posed. Producing that general parametric > pattern as a function over the xy plane seems like it might be difficult. > I suppose there might be some cool generative method that used an iterative > process to produce a functional shape like that. > > When I looked at it I thought maybe you could generate a set of paths for > each ridge (or cut, if you like). I thought maybe this could be turned > into a texture, but that's hard. So that leads to something like this > (where you might be able to get away regular path_sweep if there are more > gentle curves---it would be faster). But I have no clue how you generate > the path list. > > include<BOSL2/std.scad> > cuboid([10,10,1],anchor=TOP+LEFT); > cycles=3; > path = [for(t=[0:10:360*cycles]) [10*t/360/cycles, > (1+t/(360*cycles)/.5)*sin(t)]]; > profile = [for(theta=[-180:36:180]) [theta/180/3, (1+cos(theta))/7]]; > path_sweep2d(profile, path); > > [image: image.png] > > > On Mon, Oct 28, 2024 at 5:56 PM Jordan Brown <openscad@jordan.maileater.net> > wrote: > > > On 10/28/2024 2:34 PM, Joe Weinpert via Discuss wrote: > > > > > > I don't have an algorithm at all. I was looking for one, though :-) > > > > Look at the sample pictures I sent as just being stl objects. What would > > I need to do to create them in OpenSCAD? How do you create odd shaped > > "blobs" and patterns and put them together? > > > > > > polyhedron(), and math to come up with the desired shape. > > > > Here's something I did to come up with a water wave pattern. It's not > > great but it illustrates the idea. The bulk is the sfc() module, which is > > like surface() but takes its input in the form of an array. surface() > > really should do that, but doesn't and I haven't gotten around to making it > > happen. I was never very happy with the relationship between the > > resolution of the array and the size presented, so that may be more complex > > than it needs to be. > > > > For something like you describe, you need the sfc() module and a module > > that produces the right height-map for your pattern. > > > > $fa = 1; > > $fs = 0.5; > > > > waterX = 600; > > waterY = 600; > > waterStep = 5; > > waveLengthX = 60; > > waveLengthY = 50; > > waveAmpX = 2; > > waveAmpY = 1; > > waveH = waveAmpX + waveAmpY; > > baseH = waveH + 0.5; > > > > function wave(x,y) = waveAmpX*sin(360*x/waveLengthX) + waveAmpY*sin(360*y/waveLengthY); > > > > module water() { > > water = [ > > let(nx = floor(waterX/waterStep)) > > let(xStep = waterX/nx) > > let(ny = floor(waterY/waterStep)) > > let(yStep = waterY/ny) > > for (ix = [0:nx]) [ > > for (iy=[0:ny]) > > wave(ix*xStep, iy*yStep) > > ] > > ]; > > translate([-waterX/4,-waterY/4,waveH]) > > sfc(water, [waterX, waterY, baseH]); > > } > > > > module sfc(a, sz) { > > function dataIndex(x, y) = dataBase + x*ny + y; > > nx = len(a); > > ny = len(a[0]); > > corners = 0; > > dataBase = corners + 4; > > > > pts = [ > > [0, 0, -sz.z], > > [nx-1, 0, -sz.z], > > [nx-1, ny-1, -sz.z], > > [0, ny-1, -sz.z], > > for (x = [0:nx-1]) > > for (y = [0:ny-1]) > > [ x, y, a[x][y] ] > > ]; > > faces = [ > > [ corners+0, corners+1, corners+2 ], > > [ corners+0, corners+2, corners+3 ], > > [ > > each for (x=[0:nx-1]) dataIndex(x,0), > > corners+1, > > corners+0, > > ], > > [ > > each for (y=[0:ny-1]) dataIndex(nx-1,y), > > corners+2, > > corners+1, > > ], > > [ > > each for (x=[nx-1:-1:0]) dataIndex(x,ny-1), > > corners+3, > > corners+2, > > ], > > [ > > each for (y=[ny-1:-1:0]) dataIndex(0,y), > > corners+0, > > corners+3, > > ], > > each for (x=[0:nx-2], y=[0:ny-2]) [ > > [ dataIndex(x+1, y), dataIndex(x, y), dataIndex(x, y+1) ], > > [ dataIndex(x+1, y+1), dataIndex(x+1, y), dataIndex(x, y+1) ], > > ], > > ]; > > scale([sz.x/(nx-1),sz.y/(ny-1),1]) > > polyhedron(pts, faces, convexity=ceil(max(waterX/waveLengthX, waterY/waveLengthY))); > > } > > > > water(); > > > > > > > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email to discuss-leave@lists.openscad.org -- ** R.E.Wolff@BitWizard.nl ** https://www.BitWizard.nl/ ** +31-15-2049110 ** ** Delftechpark 11 2628 XJ Delft, The Netherlands. KVK: 27239233 ** f equals m times a. When your f is steady, and your m is going down your a** is going up. -- Chris Hadfield about flying up the space shuttle. ** 'a' for accelleration.
AM
Adrian Mariano
Tue, Oct 29, 2024 10:36 AM

Rogier, I would say the hard part of this problem is producing the set of
paths, not getting from that to the shape.  I think if you have the set of
paths you can sweep them as in my example to create the shape.

I think solving the minimal surface problem (soap bubbles) is harder than
the algorithm you propose (which I didn't entirely understand).  It's not
a local problem.  But I also don't see how minimal surfaces are relevant
to this problem.

Here are examples of the desired output that appear like they were sent
directly to me and not to the list, so I'm repeating them:

[image: image.png]
[image: image.png]

On Tue, Oct 29, 2024 at 6:11 AM Rogier Wolff R.E.Wolff@bitwizard.nl wrote:

I didn't quite catch the beginning of this discussion. But maybe
interesting anyway....

Because programming an algorithm in openscad might be difficult it
might be better to just do it in python and then export to openscad
syntax.

GIVEN a set of 3D curves, find a surface that matches the
set-of-curves.

If you just randomly "do stuff" then things become a mess. What do I
mean with "matches". Well, if you give a human a point cloud or a
set-of-curves, we immediately imagine the object they belong to. How
to capture that mathematically? I'd think soap surface comes close:
Minimal area of the surface.

I think I have an algorithm that is possibly perfect, possibly
close-but-not-quite.

Between each pair of curves, for each linesegment on one find the
closest point to the linesegment on the other curve. I'm not sure if
you have to take the sum of the linesegments or the actual distance to
the line. That's a triangle of your surface. For "well behaved"
curves, this gives the optimal surface. If there are not "well
behaved" curves that give a surface with holes... I don't know.

So for Jordan's example you could pass in something like:
a=5;
for (i=[0:.3:50])
translate ([0,0,asin(i360*4/50)]) circle (r=i);

or the radials. In openscad you can create a list-of-points with a
sinewave as the Z coordinate in one go. But I haven't memorized the
syntax yet.

(Initially / forever it is NOT the task of the algorithm to figure out
which pairs of curves to use for the surface. The user will have to
pass them in in sequence).

Being able to define surfaces (2d objects in 3D), would eventually
allow users to stitch them together (like we can already with
triangles) and create 3D objects. My example above together with
cylinder-surface (top=false) would create a real 3D object.

     Roger.

On Mon, Oct 28, 2024 at 07:06:25PM -0400, Adrian Mariano via Discuss wrote:

I don't think the waves problem gives much insight into the general
parametric problem that was posed.  Producing that general parametric
pattern as a function over the xy plane seems like it might be difficult.
I suppose there might be some cool generative method that used an

iterative

process to produce a functional shape like that.

When I looked at it I thought maybe you could generate a set of paths for
each ridge (or cut, if you like).  I thought maybe this could be turned
into a texture, but that's hard.  So that leads to something like this
(where you might be able to get away regular path_sweep if there are more
gentle curves---it would be faster).  But I have no clue how you

generate

the path list.

include<BOSL2/std.scad>
cuboid([10,10,1],anchor=TOP+LEFT);
cycles=3;
path = [for(t=[0:10:360cycles])  [10t/360/cycles,
(1+t/(360*cycles)/.5)*sin(t)]];
profile = [for(theta=[-180:36:180]) [theta/180/3, (1+cos(theta))/7]];
path_sweep2d(profile, path);

[image: image.png]

On Mon, Oct 28, 2024 at 5:56 PM Jordan Brown <

wrote:

On 10/28/2024 2:34 PM, Joe Weinpert via Discuss wrote:

I don't have an algorithm at all.  I was looking for one, though :-)

Look at the sample pictures I sent as just being stl objects.  What

would

I need to do to create them in OpenSCAD?  How do you create odd shaped
"blobs" and patterns and put them together?

polyhedron(), and math to come up with the desired shape.

Here's something I did to come up with a water wave pattern.  It's not
great but it illustrates the idea.  The bulk is the sfc() module,

which is

like surface() but takes its input in the form of an array.  surface()
really should do that, but doesn't and I haven't gotten around to

making it

happen.  I was never very happy with the relationship between the
resolution of the array and the size presented, so that may be more

complex

than it needs to be.

For something like you describe, you need the sfc() module and a module
that produces the right height-map for your pattern.

$fa = 1;
$fs = 0.5;

waterX = 600;
waterY = 600;
waterStep = 5;
waveLengthX = 60;
waveLengthY = 50;
waveAmpX = 2;
waveAmpY = 1;
waveH = waveAmpX + waveAmpY;
baseH = waveH + 0.5;

function wave(x,y) = waveAmpXsin(360x/waveLengthX) +

waveAmpYsin(360y/waveLengthY);

module water() {
water = [
let(nx = floor(waterX/waterStep))
let(xStep = waterX/nx)
let(ny = floor(waterY/waterStep))
let(yStep = waterY/ny)
for (ix = [0:nx]) [
for (iy=[0:ny])
wave(ixxStep, iyyStep)
]
];
translate([-waterX/4,-waterY/4,waveH])
sfc(water, [waterX, waterY, baseH]);
}

module sfc(a, sz) {
function dataIndex(x, y) = dataBase + x*ny + y;
nx = len(a);
ny = len(a[0]);
corners = 0;
dataBase = corners + 4;

 pts = [
     [0,    0,    -sz.z],
     [nx-1, 0,    -sz.z],
     [nx-1, ny-1, -sz.z],
     [0,    ny-1, -sz.z],
     for (x = [0:nx-1])
         for (y = [0:ny-1])
             [ x, y, a[x][y] ]
 ];
 faces = [
     [ corners+0, corners+1, corners+2 ],
     [ corners+0, corners+2, corners+3 ],
     [
         each for (x=[0:nx-1]) dataIndex(x,0),
         corners+1,
         corners+0,
     ],
     [
         each for (y=[0:ny-1]) dataIndex(nx-1,y),
         corners+2,
         corners+1,
     ],
     [
         each for (x=[nx-1:-1:0]) dataIndex(x,ny-1),
         corners+3,
         corners+2,
     ],
     [
         each for (y=[ny-1:-1:0]) dataIndex(0,y),
         corners+0,
         corners+3,
     ],
     each for (x=[0:nx-2], y=[0:ny-2]) [
         [ dataIndex(x+1, y), dataIndex(x, y), dataIndex(x, y+1) ],
         [ dataIndex(x+1, y+1), dataIndex(x+1, y), dataIndex(x,

y+1) ],

     ],
 ];
 scale([sz.x/(nx-1),sz.y/(ny-1),1])
     polyhedron(pts, faces, convexity=ceil(max(waterX/waveLengthX,

waterY/waveLengthY)));

}

water();


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org

--
** R.E.Wolff@BitWizard.nl ** https://www.BitWizard.nl/ ** +31-15-2049110
**
**    Delftechpark 11 2628 XJ  Delft, The Netherlands.  KVK: 27239233    **
f equals m times a. When your f is steady, and your m is going down
your a** is going up.  -- Chris Hadfield about flying up the space shuttle.
**  'a' for accelleration.

Rogier, I would say the hard part of this problem is producing the set of paths, not getting from that to the shape. I think if you have the set of paths you can sweep them as in my example to create the shape. I think solving the minimal surface problem (soap bubbles) is harder than the algorithm you propose (which I didn't entirely understand). It's not a local problem. But I also don't see how minimal surfaces are relevant to this problem. Here are examples of the desired output that appear like they were sent directly to me and not to the list, so I'm repeating them: [image: image.png] [image: image.png] On Tue, Oct 29, 2024 at 6:11 AM Rogier Wolff <R.E.Wolff@bitwizard.nl> wrote: > > I didn't quite catch the beginning of this discussion. But maybe > interesting anyway.... > > Because programming an algorithm in openscad might be difficult it > might be better to just do it in python and then export to openscad > syntax. > > GIVEN a set of 3D curves, find a surface that matches the > set-of-curves. > > If you just randomly "do stuff" then things become a mess. What do I > mean with "matches". Well, if you give a human a point cloud or a > set-of-curves, we immediately imagine the object they belong to. How > to capture that mathematically? I'd think soap surface comes close: > Minimal area of the surface. > > I think I have an algorithm that is possibly perfect, possibly > close-but-not-quite. > > Between each pair of curves, for each linesegment on one find the > closest point to the linesegment on the other curve. I'm not sure if > you have to take the sum of the linesegments or the actual distance to > the line. That's a triangle of your surface. For "well behaved" > curves, this gives the optimal surface. If there are not "well > behaved" curves that give a surface with holes... I don't know. > > So for Jordan's example you could pass in something like: > a=5; > for (i=[0:.3:50]) > translate ([0,0,a*sin(i*360*4/50)]) circle (r=i); > > or the radials. In openscad you can create a list-of-points with a > sinewave as the Z coordinate in one go. But I haven't memorized the > syntax yet. > > (Initially / forever it is NOT the task of the algorithm to figure out > which pairs of curves to use for the surface. The user will have to > pass them in in sequence). > > Being able to define surfaces (2d objects in 3D), would eventually > allow users to stitch them together (like we can already with > triangles) and create 3D objects. My example above together with > cylinder-surface (top=false) would create a real 3D object. > > Roger. > > > On Mon, Oct 28, 2024 at 07:06:25PM -0400, Adrian Mariano via Discuss wrote: > > I don't think the waves problem gives much insight into the general > > parametric problem that was posed. Producing that general parametric > > pattern as a function over the xy plane seems like it might be difficult. > > I suppose there might be some cool generative method that used an > iterative > > process to produce a functional shape like that. > > > > When I looked at it I thought maybe you could generate a set of paths for > > each ridge (or cut, if you like). I thought maybe this could be turned > > into a texture, but that's hard. So that leads to something like this > > (where you might be able to get away regular path_sweep if there are more > > gentle curves---it would be faster). But I have no clue how you > generate > > the path list. > > > > include<BOSL2/std.scad> > > cuboid([10,10,1],anchor=TOP+LEFT); > > cycles=3; > > path = [for(t=[0:10:360*cycles]) [10*t/360/cycles, > > (1+t/(360*cycles)/.5)*sin(t)]]; > > profile = [for(theta=[-180:36:180]) [theta/180/3, (1+cos(theta))/7]]; > > path_sweep2d(profile, path); > > > > [image: image.png] > > > > > > On Mon, Oct 28, 2024 at 5:56 PM Jordan Brown < > openscad@jordan.maileater.net> > > wrote: > > > > > On 10/28/2024 2:34 PM, Joe Weinpert via Discuss wrote: > > > > > > > > > I don't have an algorithm at all. I was looking for one, though :-) > > > > > > Look at the sample pictures I sent as just being stl objects. What > would > > > I need to do to create them in OpenSCAD? How do you create odd shaped > > > "blobs" and patterns and put them together? > > > > > > > > > polyhedron(), and math to come up with the desired shape. > > > > > > Here's something I did to come up with a water wave pattern. It's not > > > great but it illustrates the idea. The bulk is the sfc() module, > which is > > > like surface() but takes its input in the form of an array. surface() > > > really should do that, but doesn't and I haven't gotten around to > making it > > > happen. I was never very happy with the relationship between the > > > resolution of the array and the size presented, so that may be more > complex > > > than it needs to be. > > > > > > For something like you describe, you need the sfc() module and a module > > > that produces the right height-map for your pattern. > > > > > > $fa = 1; > > > $fs = 0.5; > > > > > > waterX = 600; > > > waterY = 600; > > > waterStep = 5; > > > waveLengthX = 60; > > > waveLengthY = 50; > > > waveAmpX = 2; > > > waveAmpY = 1; > > > waveH = waveAmpX + waveAmpY; > > > baseH = waveH + 0.5; > > > > > > function wave(x,y) = waveAmpX*sin(360*x/waveLengthX) + > waveAmpY*sin(360*y/waveLengthY); > > > > > > module water() { > > > water = [ > > > let(nx = floor(waterX/waterStep)) > > > let(xStep = waterX/nx) > > > let(ny = floor(waterY/waterStep)) > > > let(yStep = waterY/ny) > > > for (ix = [0:nx]) [ > > > for (iy=[0:ny]) > > > wave(ix*xStep, iy*yStep) > > > ] > > > ]; > > > translate([-waterX/4,-waterY/4,waveH]) > > > sfc(water, [waterX, waterY, baseH]); > > > } > > > > > > module sfc(a, sz) { > > > function dataIndex(x, y) = dataBase + x*ny + y; > > > nx = len(a); > > > ny = len(a[0]); > > > corners = 0; > > > dataBase = corners + 4; > > > > > > pts = [ > > > [0, 0, -sz.z], > > > [nx-1, 0, -sz.z], > > > [nx-1, ny-1, -sz.z], > > > [0, ny-1, -sz.z], > > > for (x = [0:nx-1]) > > > for (y = [0:ny-1]) > > > [ x, y, a[x][y] ] > > > ]; > > > faces = [ > > > [ corners+0, corners+1, corners+2 ], > > > [ corners+0, corners+2, corners+3 ], > > > [ > > > each for (x=[0:nx-1]) dataIndex(x,0), > > > corners+1, > > > corners+0, > > > ], > > > [ > > > each for (y=[0:ny-1]) dataIndex(nx-1,y), > > > corners+2, > > > corners+1, > > > ], > > > [ > > > each for (x=[nx-1:-1:0]) dataIndex(x,ny-1), > > > corners+3, > > > corners+2, > > > ], > > > [ > > > each for (y=[ny-1:-1:0]) dataIndex(0,y), > > > corners+0, > > > corners+3, > > > ], > > > each for (x=[0:nx-2], y=[0:ny-2]) [ > > > [ dataIndex(x+1, y), dataIndex(x, y), dataIndex(x, y+1) ], > > > [ dataIndex(x+1, y+1), dataIndex(x+1, y), dataIndex(x, > y+1) ], > > > ], > > > ]; > > > scale([sz.x/(nx-1),sz.y/(ny-1),1]) > > > polyhedron(pts, faces, convexity=ceil(max(waterX/waveLengthX, > waterY/waveLengthY))); > > > } > > > > > > water(); > > > > > > > > > > > > > > _______________________________________________ > > OpenSCAD mailing list > > To unsubscribe send an email to discuss-leave@lists.openscad.org > > > -- > ** R.E.Wolff@BitWizard.nl ** https://www.BitWizard.nl/ ** +31-15-2049110 > ** > ** Delftechpark 11 2628 XJ Delft, The Netherlands. KVK: 27239233 ** > f equals m times a. When your f is steady, and your m is going down > your a** is going up. -- Chris Hadfield about flying up the space shuttle. > ** 'a' for accelleration. >