A few days ago I posted a piece of code creating an ellipsoid out of individual polyhedron() faces. As doug.moen pointed out, it looked like a solid, but was just a collection of faces. Here I show what happened, and why, and how to make it a solid.
First, recall that polyhedron (points=[[0,0,0],[0,1,0],[0,1,1],[0,0,1],[1,0,0],[1,1,0],[1,1,1],[1,0,1]], faces=[[0,1,2,3],[4,5,6,7],[3,2,6,7],[1,5,6,2],[0,4,7,3],[0,1,5,4]]); creates a cube, which is a solid. Multiple calls polyhedron (points=[[0,0,0],[0,1,0],[0,1,1],[0,0,1]],faces=[[0,1,2,3]]); polyhedron (points=[[1,0,0],[1,1,0],[1,1,1],[1,0,1]],faces=[[0,1,2,3]]); polyhedron (points=[[0,0,1],[0,1,1],[1,1,1],[1,0,1]],faces=[[0,1,2,3]]); polyhedron (points=[[0,1,0],[1,1,0],[1,1,1],[0,1,1]],faces=[[0,1,2,3]]); polyhedron (points=[[0,0,0],[1,0,0],[1,0,1],[0,0,1]],faces=[[0,1,2,3]]); polyhedron (points=[[0,0,0],[0,1,0],[1,1,0],[1,0,0]],faces=[[0,1,2,3]]); create the same cube, but this one is just a collection of faces, and an intersection() cannot be made. These faces need to be welded together using hull() to make it a solid that can be intersected, as follows: difference() { MyCube(); translate([.5,.5,.5]) cylinder(h=2,d=.2,$fn=20,center=true); } module MyCube() hull() { color("red") polyhedron (points=[[0,0,0],[0,1,0],[0,1,1],[0,0,1]],faces=[[0,1,2,3]]); color("yellow") polyhedron (points=[[1,0,0],[1,1,0],[1,1,1],[1,0,1]],faces=[[0,1,2,3]]); color("green") polyhedron (points=[[0,0,1],[0,1,1],[1,1,1],[1,0,1]],faces=[[0,1,2,3]]); color("magenta") polyhedron (points=[[0,1,0],[1,1,0],[1,1,1],[0,1,1]],faces=[[0,1,2,3]]); color("pink") polyhedron (points=[[0,0,0],[1,0,0],[1,0,1],[0,0,1]],faces=[[0,1,2,3]]); color("purple") polyhedron (points=[[0,0,0],[0,1,0],[1,1,0],[1,0,0]],faces=[[0,1,2,3]]); } With hull() commented out, each face of the cube has a different colour, and behaves as a separate entity. With hull() active, all faces have the same colour, and there is only one entity, a cube. hull() does even more: it allows you to remove the last three calls to polyhedron() without affecting the cube. Since calls to polyhedron() are rather slow, using hull() actually speeds up rendering. The code for the ellipsoid has been given this optimization, and rendering times have dropped from 10 seconds on my machine to 5 seconds  always with cache flushed. This is the optimised code: a=30; b=20; c=10; //halfaxes of ellipse Step=10; difference() { h(); cylinder(h=40, d=2, center=true, $fn=20);} module h() hull() Ellipsoid(); module Ellipsoid() for (v=[Step/2:Step:180Step]) for (u=[Step/2:Step:360Step/2]) SurfaceElement(u,v); module SurfaceElement(u,v) { P0=P(uStep/2,vStep/2); // corner vector for SurfaceElement() P1=P(u+Step/2,vStep/2); // corner vector for SurfaceElement() P2=P(u+Step/2,v+Step/2); // corner vector for SurfaceElement() polyhedron (points=[P0,P1,P2], faces=[[0,1,2]]); } function P(u,v)=[a*cos(u)*sin(v),b*sin(u)*sin(v),c*cos(v)]; //point on the surface of an ellipsoid There is no need to merge all points into a single list first, as has been suggested. But I still would like to know how this is done . . . Wolf 
I like this! It seems that it could be used to generate other shapes,
since the "shape" code is all in the final function. Jon On 11/10/2015 5:55 AM, wolf wrote: > A few days ago I posted > <http://forum.openscad.org/3dhullwith2dprimitivesneededtd5845.htmlhttp://> > a piece of code creating an ellipsoid out of individual polyhedron() faces. > As doug.moen > <http://forum.openscad.org/PolyhedronandcubeNotaValid2Manifoldtd14283.html> > pointed out, it looked like a solid, but was just a collection of faces. > Here I show what happened, and why, and how to make it a solid. > > First, recall that > polyhedron > (points=[[0,0,0],[0,1,0],[0,1,1],[0,0,1],[1,0,0],[1,1,0],[1,1,1],[1,0,1]], > > faces=[[0,1,2,3],[4,5,6,7],[3,2,6,7],[1,5,6,2],[0,4,7,3],[0,1,5,4]]); > creates a cube, which is a solid. > Multiple calls > polyhedron (points=[[0,0,0],[0,1,0],[0,1,1],[0,0,1]],faces=[[0,1,2,3]]); > polyhedron (points=[[1,0,0],[1,1,0],[1,1,1],[1,0,1]],faces=[[0,1,2,3]]); > polyhedron (points=[[0,0,1],[0,1,1],[1,1,1],[1,0,1]],faces=[[0,1,2,3]]); > polyhedron (points=[[0,1,0],[1,1,0],[1,1,1],[0,1,1]],faces=[[0,1,2,3]]); > polyhedron (points=[[0,0,0],[1,0,0],[1,0,1],[0,0,1]],faces=[[0,1,2,3]]); > polyhedron (points=[[0,0,0],[0,1,0],[1,1,0],[1,0,0]],faces=[[0,1,2,3]]); > create the same cube, but this one is just a collection of faces, and an > intersection() cannot be made. > These faces need to be welded together using hull() to make it a solid that > can be intersected, as follows: > difference() > { MyCube(); > translate([.5,.5,.5]) cylinder(h=2,d=.2,$fn=20,center=true); > } > module MyCube() > hull() > { color("red") polyhedron > (points=[[0,0,0],[0,1,0],[0,1,1],[0,0,1]],faces=[[0,1,2,3]]); > color("yellow") polyhedron > (points=[[1,0,0],[1,1,0],[1,1,1],[1,0,1]],faces=[[0,1,2,3]]); > color("green") polyhedron > (points=[[0,0,1],[0,1,1],[1,1,1],[1,0,1]],faces=[[0,1,2,3]]); > color("magenta") polyhedron > (points=[[0,1,0],[1,1,0],[1,1,1],[0,1,1]],faces=[[0,1,2,3]]); > color("pink") polyhedron > (points=[[0,0,0],[1,0,0],[1,0,1],[0,0,1]],faces=[[0,1,2,3]]); > color("purple") polyhedron > (points=[[0,0,0],[0,1,0],[1,1,0],[1,0,0]],faces=[[0,1,2,3]]); > } > With hull() commented out, each face of the cube has a different colour, and > behaves as a separate entity. With hull() active, all faces have the same > colour, and there is only one entity, a cube. hull() does even more: it > allows you to remove the last three calls to polyhedron() without affecting > the cube. Since calls to polyhedron() are rather slow, using hull() actually > speeds up rendering. > The code for the ellipsoid has been given this optimization, and rendering > times have dropped from 10 seconds on my machine to 5 seconds  always with > cache flushed. > This is the optimised code: > > a=30; b=20; c=10; //halfaxes of ellipse > Step=10; > difference() { h(); cylinder(h=40, d=2, center=true, $fn=20);} > module h() > hull() Ellipsoid(); > module Ellipsoid() > for (v=[Step/2:Step:180Step]) for (u=[Step/2:Step:360Step/2]) > SurfaceElement(u,v); > module SurfaceElement(u,v) > { P0=P(uStep/2,vStep/2); // corner vector for SurfaceElement() > P1=P(u+Step/2,vStep/2); // corner vector for SurfaceElement() > P2=P(u+Step/2,v+Step/2); // corner vector for SurfaceElement() > polyhedron (points=[P0,P1,P2], faces=[[0,1,2]]); > } > function P(u,v)=[a*cos(u)*sin(v),b*sin(u)*sin(v),c*cos(v)]; //point on the > surface of an ellipsoid > > There is no need to merge all points into a single list first, as has been > suggested > <http://forum.openscad.org/3dhullwith2dprimitivesneededtd5845.html> . > But I still would like to know how this is done . . . > > Wolf > > > > > >  > View this message in context: http://forum.openscad.org/Polyhedrontp14338.html > Sent from the OpenSCAD mailing list archive at Nabble.com. > > _______________________________________________ > OpenSCAD mailing list > [hidden email] > 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/10972  Release Date: 11/09/15 > > _______________________________________________ OpenSCAD mailing list [hidden email] http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org 
This post was updated on .
In reply to this post by wolf
This is how you do it with list comprehensions to make a manifold polyhedron that doesn't need wrapping in hull.
a=30; b=20; c=10; //halfaxes of ellipse Step=10; function P(u,v)=[a*cos(u)*sin(v),b*sin(u)*sin(v),c*cos(v)]; //point on the surface of an ellipsoid function SurfaceElement(u,v) = let(hs = Step / 2) [ P(u  hs, v  hs), P(u + hs, v  hs), P(u + hs, v + hs), P(u  hs, v + hs)]; function quad(i) = let(p = i * 4) [[p, p + 1, p + 2], [p, p + 2, p + 3]]; function flatten(l) = [ for (a = l) for (b = a) b ] ; elements = flatten([let(s = Step / 2) for(v = [s : Step : 180  s]) for(u = [s : Step: 360  s]) SurfaceElement(u, v)]); faces = flatten([for(v = [0 : 180 / Step  1]) for(u = [0 : 360 / Step  1]) quad(v * 360 / Step + u) ]); difference() { polyhedron(elements, faces); cylinder(h=40, d=2, center=true, $fn=20); } 
Hmm, all the newlines got eaten but I have fixed it on the forum post. On 10 November 2015 at 12:05, nophead <[hidden email]> wrote: This is how you do it with list comprehensions to make a manifold polyhedron that doesn't need wrapping in hull. a=30; b=20; c=10; //halfaxes of ellipse Step=10; function P(u,v)=[a*cos(u)*sin(v),b*sin(u)*sin(v),c*cos(v)]; //point on the surface of an ellipsoid function SurfaceElement(u,v) = let(hs = Step / 2) [ P(u  hs, v  hs), P(u + hs, v  hs), P(u + hs, v + hs), P(u  hs, v + hs)]; function quad(i) = let(p = i * 4) [[p, p + 1, p + 2], [p, p + 2, p + 3]]; function flatten(l) = [ for (a = l) for (b = a) b ] ; elements = flatten([let(s = Step / 2) for(v = [s : Step : 180  s]) for(u = [s : Step: 360  s]) SurfaceElement(u, v)]); faces = flatten([for(v = [0 : 180 / Step  1]) for(u = [0 : 360 / Step  1]) quad(v * 360 / Step + u) ]); difference() { polyhedron(elements, faces); cylinder(h=40, d=2, center=true, $fn=20); } _______________________________________________ OpenSCAD mailing list [hidden email] http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org 
It is nice that hull() accepts a collection of nonmanifold faces. Does anyone know: would hull() also accept a collection of points as inputs?20151110 13:08 GMT+01:00 nop head <[hidden email]>:
_______________________________________________ OpenSCAD mailing list [hidden email] http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org 
In reply to this post by nophead
Dear nop head, your solution looks nice and clean... 20151110 13:08 GMT+01:00 nop head <[hidden email]>:
_______________________________________________ OpenSCAD mailing list [hidden email] http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org 
There is a grave error in my last post: Yes, on could save time calculating less points P(u,v), but this would only speed up the preview somewhat.20151110 15:56 GMT+01:00 Peter Falke <[hidden email]>:
_______________________________________________ OpenSCAD mailing list [hidden email] http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org 
In reply to this post by Peter Falke
I think that the underlying topic of discussion is: polyhedron() is difficult to use. Is there an easier way to convert a collection of vertices into a 3D object? Wolf has explored the idea of gluing a cloud of nonmanifold objects into a polyhedron using hull(). It relies on passing an invalid argument list to polyhedron(), and relying on the fact that you don't currently get an error. Worse, this technique is not general, since it can't be used to construct a nonconvex object. It's also much slower than directly constructing your object with a single call to polyhedron(). Peter Falke has suggested the idea of feeding a collection of points to hull(). I don't think there's any way to do that right now. But it's an interesting suggestion, since specifying a point cloud is easier to do than specifying a disconnected cloud of faces (as in Wolf's code), which in turn is easier than specifying a connected set of faces (ie, the arguments to polyhedron()). The raw output from a 3D scanner is a point cloud. There exists software for converting this point cloud into a polyhedral mesh. I think it would be interesting to add a point_cloud() operation to OpenSCAD, for converting a list of vertices into a manifold 3D object. The algorithm should exist somewhere as open source. It's probably slower than polyhedron(), but much easier to use. The point_cloud() primitive would give us very simple and easy to write code for generating an ellipsoid. Something like this: Step=10; point_cloud( [for (v=[0: Step: 180]) for (u=[0: Step: 360]) P(u,v) ]); function P(u,v)=[a*cos(u)*sin(v),b*sin(u)*sin(v),c*cos(v)]; On 10 November 2015 at 09:32, Peter Falke <[hidden email]> wrote:
_______________________________________________ OpenSCAD mailing list [hidden email] http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org 
There are surface reconstruction hooks in CGAL: http://doc.cgal.org/latest/Surface_reconstruction_points_3/ ...but as with many things, the devil's in the implementationdetails. Andrew. 
In reply to this post by doug.moen
Yes and a 2D version would be very useful as well. It would basically fit a curve through a list of points, although there are many ways to do that of course. Another thing I would like is a concave hull, for want of a better name. As well as shapes it has to encompass it would also have a list of shapes to avoid. It would work like difference in that the first child is all the positive shapes on the inside and the rest are negative shapes on the outside. hull() for(x = [10,10], y = [10,10], z = [0, 20]) translate([x,y, z]) sphere(2); translate([0, 0, 18])} On 10 November 2015 at 15:33, doug moen <[hidden email]> wrote:
_______________________________________________ OpenSCAD mailing list [hidden email] http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org 
In reply to this post by doug.moen
The underlying approach could be simplified into generating simple shapes. For example, the ellipsoid shape, if watched closely, is basically the same as the "chain" object described in my faces.scad tool topologically. So a point_cloud() primitive can be easily coded as such: In fact, this approach is why I made faces.scad in the first place. As seen in the link mentioned, generating a basic form of polyhedron is a simple matter of generating points and picking a shape.
$ Runsun Pan, PhD
$ libs:doctest, faces(git), offline doc(git), runscad.py(2,git), synwrite(2); $ tips:Collection of tips on github 
Administrator

In reply to this post by doug.moen
> On Nov 10, 2015, at 10:33 AM, doug moen <[hidden email]> wrote:
> > Peter Falke has suggested the idea of feeding a collection of points to hull(). This would be as simple as adding an optional ‘points’ parameter to hull; i.e. pass points=[…] instead of children will just hull the points. I’m uncertain if this should perhaps be a separate module, to avoid mixing group nodes and leaf nodes. > I think it would be interesting to add a point_cloud() operation to OpenSCAD, for converting a list of vertices into a manifold 3D object. The algorithm should exist somewhere as open source. This would be cool. One challenge could be that the output of such an operation is depending on which algorithm was used, which would potentially lock us into one particular library or implementation where people start to depend on specific artifacts (similar to how people are using cylinder($fn=6) to create prisms). Marius _______________________________________________ OpenSCAD mailing list [hidden email] http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org 
Administrator

In reply to this post by doug.moen
> On Nov 10, 2015, at 10:33 AM, doug moen <[hidden email]> wrote: > > I think that the underlying topic of discussion is: polyhedron() is difficult to use. Is there an easier way to convert a collection of vertices into a 3D object? Another potential operator: skin > create and orient a bunch of 2D polygons in 3D space and create a skin around the result. This is already possible in userspace, but requires building 2D shapes manually: https://github.com/openscad/listcomprehensiondemos#extrusionscad Marius _______________________________________________ OpenSCAD mailing list [hidden email] http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org 
In reply to this post by doug.moen
On 11/10/2015 04:33 PM, doug moen wrote:
> Peter Falke has suggested the idea of feeding a collection of points to hull(). > See also there: https://github.com/openscad/openscad/pull/1168 I guess that would really be a simple way to quickly create some type of models. The restriction to convex models does restrict the general usage though. Unfortunately the generalized extrusion topic did not advance a lot lately. This would also bring a very powerful tool that is much easier to use than directly generating polyhedrons. > The raw output from a 3D scanner is a point cloud. There exists software for > converting this point cloud into a polyhedral mesh. I think it would be > interesting to add a point_cloud() operation to OpenSCAD, for converting a > list of vertices into a manifold 3D object. The algorithm should exist > somewhere as open source. It's probably slower than polyhedron(), but much > easier to use. > CGAL supports that, see http://doc.cgal.org/latest/Surface_reconstruction_points_3 I guess the concern here is how much geometry is generated, similar to the issues with surface() that were discussed some days ago. Still it would probably be a nice addition to the tool set. ciao, Torsten. _______________________________________________ OpenSCAD mailing list [hidden email] http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
 Torsten

Administrator

> On Nov 10, 2015, at 13:24 PM, Torsten Paul <[hidden email]> wrote:
> > On 11/10/2015 04:33 PM, doug moen wrote: >> Peter Falke has suggested the idea of feeding a collection of points to hull(). >> > See also there: https://github.com/openscad/openscad/pull/1168 > Ah, right. The old CGAL dependency issue. I’m thinking we should stop looking at CGAL as a library, but as a collection of tools, write wrappers for each of these tools separately, and keep the library dependency decoupled from any interfaces. Marius _______________________________________________ OpenSCAD mailing list [hidden email] http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org 
This post has NOT been accepted by the mailing list yet.
In reply to this post by kintel
Actually... upon looking into Wikipedia, the convex hull of a point cloud is welldefined and not implementation/algorithm dependent. Someone might decide to write, say, Chan's algorithm (https://en.wikipedia.org/wiki/Chan%27s_algorithm) into a OpenSCAD library, with calling convention as doug suggested. On the other hand, the nonconvex solid defined by a point cloud is illposed. Consider the simple case of 9 points: [[0,0,0], [1,0,0], [1,1,0], [0,1,0], [0,1,1], [1,1,1], [1,0,1], [0,0,1], [0.5,0.5,0.5]] Which is the 8 vertices of a cube plus its center point. A polyhedron with all these vertices can be a cube minus a pyramid but which way should the concave side face? There problem is illposed. I have my imperfect solution to using polyhedron() to generate highly complex solids, I understand the desire to make it easier to use (thanks to doug's post for summarizing/clarifying the topic) but someone need to come up with a rigourously posed question before someone else could come up with a general solution. 
In reply to this post by kintel
(I'm reposting this, due to a tech issue, hope I'm not annoying anyone)
Actually... upon looking into Wikipedia, the convex hull of a point cloud is welldefined and not implementation/algorithm dependent. Someone might decide to write, say, Chan's algorithm (https://en.wikipedia.org/wiki/Chan%27s_algorithm) into a OpenSCAD library, with calling convention as doug suggested. On the other hand, the nonconvex solid defined by a point cloud is illposed. Consider the simple case of 9 points: [[0,0,0], [1,0,0], [1,1,0], [0,1,0], [0,1,1], [1,1,1], [1,0,1], [0,0,1], [0.5,0.5,0.5]] Which are the 8 vertices of a cube plus its center point. A polyhedron with all these vertices can be a cube minus a pyramid but which way should the concave side face? There problem is illposed. I have my imperfect solution to using polyhedron() to generate highly complex solids, I understand the desire to make it easier to use (thanks to doug's post for summarizing/clarifying the topic) but someone need to come up with a rigourously posed question before someone else could come up with a general solution. 
This post has NOT been accepted by the mailing list yet.
In reply to this post by wolf
if you are not sure in grammar or punctuation in your essay, http://essaycorrector.org/blog/usefultipshowtoedityouressaystepbystep will teach you hor to edit your essay step by step!

Free forum by Nabble  Edit this page 