openscad icon indicating copy to clipboard operation
openscad copied to clipboard

Feature request: add capacity to specify surface from calculated values

Open kortschak opened this issue 6 years ago • 6 comments

Currently the surface function will give you a surface from either a png or a dat file, but you cannot generate a function-defined set of values within openscad and use that as an input to surface.

It would be nice to be able to do this, either by leveraging the code in surface and determining whether a data(?) parameter were present and using that in place of file, warning when both exist, or alternatively calculating a set of minimal set of triangles from a set of 3R points and using that to mesh (the latter is obviously much more work).


Want to back this issue? Post a bounty on it! We accept bounties via Bountysource.

kortschak avatar Nov 02 '18 03:11 kortschak

I think that sounds a bit like "construct polyhedron/mesh from point cloud". What are the example scenarios for this?

t-paul avatar Nov 02 '18 03:11 t-paul

Yes, it's a cheaper/weaker way to achieve that.

The example scenarios I'm looking at is for constructing parts for printing where it's possible to construct with CSG operations, but would be simpler with a mesh. A recent concrete example is the Prusa redesign of the extruder where I understand the they moved from OpenSCAD to another CAD solution (details escape me sorry) because of the complexity of the shapes.

kortschak avatar Nov 02 '18 04:11 kortschak

It can be done in userland:

a = [
    [0,0,0,0,0,0],
    [0,0,2,3,4,0],
    [0,-2,3,6,5,0],
    [0.-1,-2,-3,-4,0,0],
    [0,0,0,0,0,0]
];

polyhedron_from_data(a, xscale=1, yscale=1, center=true);

module polyhedron_from_data(data, xscale=1, yscale=1, center=false) {
    stride = len(data[0]);
    for (i = [0: len(data)-1] )
        assert(len(data[i]) == stride);
    points = [for (i = [0: len(data)-1] )
        for (j = [0: len(data[i])-1] )
            [j*xscale, i*yscale, data[i][j]],
    ];
    faces = [for (i = [1: len(data)-1])
        for (j = [1: len(data[i])-1])
            [(i-1)*len(data[i])+(j-1), (i-1)*len(data[i])+j, i*len(data[i])+j, i*len(data[i])+(j-1)],
    ];
    translate([center ? -(stride-1)*xscale/2 : 0, center ? -(len(data)-1)*yscale/2 : 0, 0])
        polyhedron(points, faces);
}

kortschak avatar Nov 02 '18 09:11 kortschak

Yes, it's possible, see also my 3d-function script which produces a 2-manifold polyhedron - but it's neither obvious nor easy to generate. So there's no argument against having a simpler way for defining objects. The question is mainly what a good interface would be.

t-paul avatar Nov 02 '18 21:11 t-paul

In the first instance I'd suggest adding approximately the behaviour I have above to the surface built-in, though with the sides and base (optionally) added with a depth of min(0, min(concat(data))) which I did not include above.

kortschak avatar Nov 02 '18 23:11 kortschak

I needed exactly this - surface(array). I was surprised to find that it didn't work. (But not as surprised as OpenSCAD was to try to open a file with a name that was a toString of an array.)

ISTM that the semantics would be identical to the text-file semantics for surface().

I do wonder what surface() uses as the base height - the amount of material between the lowest value in the array and the flat bottom of the result. Perhaps that should be a parameter.

jordanbrown0 avatar Dec 13 '23 08:12 jordanbrown0