discuss@lists.openscad.org

OpenSCAD general discussion Mailing-list

View all threads

Polyhedron tube with irregular sides -- is it possible ?

NH
nop head
Mon, Dec 17, 2018 3:42 PM

So possibly self intersecting is fine as long as vertices don't coincide.
The topology is prerved through triangle soup when the vertices are all
unique.

On Mon, 17 Dec 2018 at 15:39, Parkinbot rudolf@digitaldocument.de wrote:

I can export it to STL and import it again without any problems.

--
Sent from: http://forum.openscad.org/


OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

So possibly self intersecting is fine as long as vertices don't coincide. The topology is prerved through triangle soup when the vertices are all unique. On Mon, 17 Dec 2018 at 15:39, Parkinbot <rudolf@digitaldocument.de> wrote: > I can export it to STL and import it again without any problems. > > > > -- > Sent from: http://forum.openscad.org/ > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
P
Parkinbot
Mon, Dec 17, 2018 3:43 PM

it is even getting wierder and wierder:

http://forum.openscad.org/file/t887/sweep.png

--
Sent from: http://forum.openscad.org/

it is even getting wierder and wierder: <http://forum.openscad.org/file/t887/sweep.png> -- Sent from: http://forum.openscad.org/
RP
Ronaldo Persiano
Mon, Dec 17, 2018 4:25 PM

Does it allow boolean operations???

Parkinbot rudolf@digitaldocument.de wrote:

it is even getting wierder and wierder:

Does it allow boolean operations??? Parkinbot <rudolf@digitaldocument.de> wrote: > it is even getting wierder and wierder: >
P
Parkinbot
Mon, Dec 17, 2018 4:33 PM

Ronaldo wrote

Does it allow boolean operations???

Yes, otherwise F10 wouldn't display a tesselation. Look at the code:

use <Naca_sweep.scad>
sweep([circle(), Tx_(3, circle(phi = 180))]);
function circle(r = 10, N=100, z=3, phi=0) =
[for(i=[0:N-1])  [rsin(360/Ni), rcos(360/Ni), zcos(360/Ni*2+phi)]];
cube(1);

--
Sent from: http://forum.openscad.org/

Ronaldo wrote > Does it allow boolean operations??? Yes, otherwise F10 wouldn't display a tesselation. Look at the code: use <Naca_sweep.scad> sweep([circle(), Tx_(3, circle(phi = 180))]); function circle(r = 10, N=100, z=3, phi=0) = [for(i=[0:N-1]) [r*sin(360/N*i), r*cos(360/N*i), z*cos(360/N*i*2+phi)]]; cube(1); -- Sent from: http://forum.openscad.org/
RP
Ronaldo Persiano
Tue, Dec 18, 2018 3:44 PM

Yes, I have observed before that a non-manifold polyhedron may be rendered.
The union of the cube with your shape renders without error unless the cube
intersect some self intersection areas of the shape. Try your example with
cube(16), for instance. You will get a CGAL error. And even when the cube
contains all your shape a CGAL error is issued. A strange shape (that
resembles to be a difference) results without error with cube(6).

Yes, I have observed before that a non-manifold polyhedron may be rendered. The union of the cube with your shape renders without error unless the cube intersect some self intersection areas of the shape. Try your example with cube(16), for instance. You will get a CGAL error. And even when the cube contains all your shape a CGAL error is issued. A strange shape (that resembles to be a difference) results without error with cube(6). > >
RP
Ronaldo Persiano
Mon, Jan 7, 2019 2:09 PM

Em seg, 10 de dez de 2018 às 20:07, Parkinbot rudolf@digitaldocument.de
escreveu:

A triangulation like earcut with holes will be cumbersome to implement in
OpenSCAD. However a fast and viable solution for implementing the
multi-hole
sweep is to use a vectorized lazy union sweep for the holes and difference
the result from the sweep of the outer polygon. For export one will have to
use a Boolean operation to do a CGAL check anyway.

Parkinbot,

The earcut method works fine with polygons with holes expressed as a unique
polygonal by bridging the holes and outer polygon by two-way bridges fully
inside the polygon interior. We just need to relax the ear test by
restricting it to the candidate ear interior. I have tested it with my
implementation of the ear method and it worked like a charm.

The remaining problem is to find the two-way bridges that connect all the
borders. The bridges in the runsun example are not allowed because they
cross other polygonal edges. I have found a paper (
https://www.geometrictools.com/Documentation/TriangulationByEarClipping.pdf)
that proposes a method to find those bridges. I have implemented the method
with good results. Here are two of them:

[image: PolyHoles2.PNG]
[image: PolyHoles1.PNG]

Find attached my implementation of the bridging method.

Em seg, 10 de dez de 2018 às 20:07, Parkinbot <rudolf@digitaldocument.de> escreveu: > A triangulation like earcut with holes will be cumbersome to implement in > OpenSCAD. However a fast and viable solution for implementing the > multi-hole > sweep is to use a vectorized lazy union sweep for the holes and difference > the result from the sweep of the outer polygon. For export one will have to > use a Boolean operation to do a CGAL check anyway. > > Parkinbot, The earcut method works fine with polygons with holes expressed as a unique polygonal by bridging the holes and outer polygon by two-way bridges fully inside the polygon interior. We just need to relax the ear test by restricting it to the candidate ear interior. I have tested it with my implementation of the ear method and it worked like a charm. The remaining problem is to find the two-way bridges that connect all the borders. The bridges in the runsun example are not allowed because they cross other polygonal edges. I have found a paper ( https://www.geometrictools.com/Documentation/TriangulationByEarClipping.pdf) that proposes a method to find those bridges. I have implemented the method with good results. Here are two of them: [image: PolyHoles2.PNG] [image: PolyHoles1.PNG] Find attached my implementation of the bridging method.
P
Parkinbot
Wed, Jan 9, 2019 12:45 PM

Ronaldo,

thanks, this sounds like a progress. Although the no cross restriction will
be difficult to guarantee in general when defining such a polygon, it seems
to be a step forward to implementing a fast multi-hole sweep like for
regular grids with fancy holes as shown in the example code attached. But to
be honest, meanwhile I dislike the implicitness of this representation. When
adding a new hole to a given object one will have to alter the whole polygon
sequence. This is very clumsy and makes me prefer the solution I already
characterized:

Parkinbot wrote

However a fast and viable solution for implementing the multi-hole
sweep is to use a vectorized lazy union sweep for the holes and difference
the result from the sweep of the outer polygon. For export one will have
to
use a Boolean operation to do a CGAL check anyway.

While this approach is a bit slower, it addresses an even larger class of
problems, since the multi-holes may even leave the outer body during the
sweep - which relaxes the no-mutual-intersection rule a bit. And it is easy
to add a new hole, because you just extend the vector describing the holes.

Nevertheless, if OpenSCAD offered a built-in lazy_union() operator, we
wouldn't have to discuss such things at all.

difference()
{
cube([100, 100, 5], center = true);
forXY(10, 10, 10, 10)
linear_extrude(5.01, center = true, twist=45, slices = 20)
square(6, center= true);
}

module forX(dx = 10, N=4) for($i=[0:N-1]) translate([-((N-1)/2-$i)*dx,0, 0])
children();
module forY(dy = 10, M=4) for($i=[0:M-1]) translate([0, -((M-1)/2-$i)*dy])
children();
module forXY(dx = 10, N=4, dy = 10, M=4) forX(dx, N) forY(dy, M) children();

--
Sent from: http://forum.openscad.org/

Ronaldo, thanks, this sounds like a progress. Although the no cross restriction will be difficult to guarantee in general when defining such a polygon, it seems to be a step forward to implementing a fast multi-hole sweep like for regular grids with fancy holes as shown in the example code attached. But to be honest, meanwhile I dislike the implicitness of this representation. When adding a new hole to a given object one will have to alter the whole polygon sequence. This is very clumsy and makes me prefer the solution I already characterized: Parkinbot wrote > However a fast and viable solution for implementing the multi-hole > sweep is to use a vectorized lazy union sweep for the holes and difference > the result from the sweep of the outer polygon. For export one will have > to > use a Boolean operation to do a CGAL check anyway. While this approach is a bit slower, it addresses an even larger class of problems, since the multi-holes may even leave the outer body during the sweep - which relaxes the no-mutual-intersection rule a bit. And it is easy to add a new hole, because you just extend the vector describing the holes. Nevertheless, if OpenSCAD offered a built-in lazy_union() operator, we wouldn't have to discuss such things at all. difference() { cube([100, 100, 5], center = true); forXY(10, 10, 10, 10) linear_extrude(5.01, center = true, twist=45, slices = 20) square(6, center= true); } module forX(dx = 10, N=4) for($i=[0:N-1]) translate([-((N-1)/2-$i)*dx,0, 0]) children(); module forY(dy = 10, M=4) for($i=[0:M-1]) translate([0, -((M-1)/2-$i)*dy]) children(); module forXY(dx = 10, N=4, dy = 10, M=4) forX(dx, N) forY(dy, M) children(); -- Sent from: http://forum.openscad.org/
RP
Ronaldo Persiano
Wed, Jan 9, 2019 3:54 PM

Em qua, 9 de jan de 2019 às 12:45, Parkinbot rudolf@digitaldocument.de
escreveu:

But to
be honest, meanwhile I dislike the implicitness of this representation.
When
adding a new hole to a given object one will have to alter the whole
polygon
sequence. This is very clumsy and makes me prefer the solution I already
characterized:

I understand your point but I see a very simple and general way to overcome
it.

Suppose we have a lazyUnion operator with the following header:

module lazyUnion(<list of objects>)

where the objects in the parameter list are given in a polyhedron data
format, that is, a pair of vertex list and face list. This module is easy
to be coded by:

  1. concat in one list all vertices of all objects;
  2. displace (by a fixed amount) the indices of the face list of an object
    to agree with the new order of the concatenated vertex list;
  3. call polyhedron with the new vertex list and the concat of the updated
    face list.

Usually we think to lazy-union manifold objects but this may be generalized
to lazy-union a set of surfaces that will enclose one (or many) manifold.
Surely, we need to assure manifoldness of the result to have a proper
object for CGAL. The ground of this generalization is that OpenSCAD
aggregates multiple vertices with the same coordinates as one vertex as I
mentioned 2 years ago (
http://forum.openscad.org/Can-you-sweep-a-object-with-fingers-tp19057p19203.html
).

With that in mind, the sweep of a polygon with holes may be structured as:
a) individually sweep each polygonal border of the outer polygon and of the
holes without their caps returning the result in a polyhedron data format
(a simplification of the current sweep codes);
b) triangulate the sweep ends of polygons with holes and generate its
result in a polyhedron data format;
c) call lazyUnion with the list of the above data.

As a final touch, each function which generates polyhedron data format
should have an additional parameter to promote, when needed, the reversion
of all its faces. This parameter, with default false, may be set true when
a Thrown Together view shows an incorrect orientation of that surface.

lazyUnion thought as such has many other uses as the reference I gave above
illustrates.

When facing cases where the swept holes leak out the outer sweep, then uses
the slower boolean method.

Em qua, 9 de jan de 2019 às 12:45, Parkinbot <rudolf@digitaldocument.de> escreveu: > But to > be honest, meanwhile I dislike the implicitness of this representation. > When > adding a new hole to a given object one will have to alter the whole > polygon > sequence. This is very clumsy and makes me prefer the solution I already > characterized: > I understand your point but I see a very simple and general way to overcome it. Suppose we have a lazyUnion operator with the following header: module lazyUnion(<list of objects>) where the objects in the parameter list are given in a polyhedron data format, that is, a pair of vertex list and face list. This module is easy to be coded by: 1) concat in one list all vertices of all objects; 2) displace (by a fixed amount) the indices of the face list of an object to agree with the new order of the concatenated vertex list; 3) call polyhedron with the new vertex list and the concat of the updated face list. Usually we think to lazy-union manifold objects but this may be generalized to lazy-union a set of surfaces that will enclose one (or many) manifold. Surely, we need to assure manifoldness of the result to have a proper object for CGAL. The ground of this generalization is that OpenSCAD aggregates multiple vertices with the same coordinates as one vertex as I mentioned 2 years ago ( http://forum.openscad.org/Can-you-sweep-a-object-with-fingers-tp19057p19203.html ). With that in mind, the sweep of a polygon with holes may be structured as: a) individually sweep each polygonal border of the outer polygon and of the holes without their caps returning the result in a polyhedron data format (a simplification of the current sweep codes); b) triangulate the sweep ends of polygons with holes and generate its result in a polyhedron data format; c) call lazyUnion with the list of the above data. As a final touch, each function which generates polyhedron data format should have an additional parameter to promote, when needed, the reversion of all its faces. This parameter, with default false, may be set true when a Thrown Together view shows an incorrect orientation of that surface. lazyUnion thought as such has many other uses as the reference I gave above illustrates. When facing cases where the swept holes leak out the outer sweep, then uses the slower boolean method.
P
Parkinbot
Wed, Jan 9, 2019 5:44 PM

Ronaldo

you are right, changing the representation is a typical interface task and
can be easily done within sweep() and transparent to the user.
Collect the first and last faces of the outer manifold and the holes, find
the right polyHoles-polygon to represent it and then use earcut. The rest is
a vectorized sweep.
I haven't had time to play with your algorithm more extensively as I am
short of time being on travel until Sunday. Can you post the current version
of your earcut()? Don't find mine anymore.

I would propose the following interface to keep the "affine" state as long
as possible - and allow for the lazy union of multihole sweeps:

module sweepMH(manifolds)
{
prepdata = sweepMH(manifolds);
polyhedron(prepdata[0], prepdata[1]);
}

function sweepMH(manifolds) =
let(firstface = earcut(polyHole(manifolds)))
let(lastface = earcut(polyHole(manifolds, last=true))
...

--
Sent from: http://forum.openscad.org/

Ronaldo you are right, changing the representation is a typical interface task and can be easily done within sweep() and transparent to the user. Collect the first and last faces of the outer manifold and the holes, find the right polyHoles-polygon to represent it and then use earcut. The rest is a vectorized sweep. I haven't had time to play with your algorithm more extensively as I am short of time being on travel until Sunday. Can you post the current version of your earcut()? Don't find mine anymore. I would propose the following interface to keep the "affine" state as long as possible - and allow for the lazy union of multihole sweeps: module sweepMH(manifolds) { prepdata = sweepMH(manifolds); polyhedron(prepdata[0], prepdata[1]); } function sweepMH(manifolds) = let(firstface = earcut(polyHole(manifolds))) let(lastface = earcut(polyHole(manifolds, last=true)) ... -- Sent from: http://forum.openscad.org/
RP
Ronaldo Persiano
Thu, Jan 10, 2019 5:03 PM

Parkinbot,

Find attached my last version of the polygon triangulation. I have reviewed
it converting recursions to iterations with C-like for in order to escape
the cycles early as possible. This version of the ear method is adapted to
polygons with two-way bridges. I have also a simple polygon check but it
rejects polygons with bridges. To accept polygon with bridges in that check
requires a whole new set of cumbersome tests. I don't like my
implementation of the check that resort to quick sort to make it somewhat
more efficient but if you want to try it, let me know. Another function
that you may consider, that is included in the same file of the simple
polygon test, is the plane fitting and projection to "flatten" almost
planar 3D polygons converting it in a 2D polygon before the triangulation
is called.

Both polygon triangulation and polygon with holes bridging methods fail if
they receive a non valid input. Without a proper validity check their use
is a blind fly.

Parkinbot, Find attached my last version of the polygon triangulation. I have reviewed it converting recursions to iterations with C-like for in order to escape the cycles early as possible. This version of the ear method is adapted to polygons with two-way bridges. I have also a simple polygon check but it rejects polygons with bridges. To accept polygon with bridges in that check requires a whole new set of cumbersome tests. I don't like my implementation of the check that resort to quick sort to make it somewhat more efficient but if you want to try it, let me know. Another function that you may consider, that is included in the same file of the simple polygon test, is the plane fitting and projection to "flatten" almost planar 3D polygons converting it in a 2D polygon before the triangulation is called. Both polygon triangulation and polygon with holes bridging methods fail if they receive a non valid input. Without a proper validity check their use is a blind fly.