discuss@lists.openscad.org

OpenSCAD general discussion Mailing-list

View all threads

Joining half tubes

DS
Dan Shriver
Sat, Jun 8, 2019 4:12 PM

I'm trying to make a complicated shape.
A quick way to imagine it is that I have a half tube on a wishbone path.

Making half of it (just a call to arches2()) works fine.

However if I use difference and mirror I get errors.

At first I thought it was because I was trying to subtract a mirrored half
tube from a mirrored half tube causing some issues.  So I changed it so
(from the first half tube) I subtract the solid version (if a half tube
imagine a half circle being subtracted from it).

However, when I do that I still get problems:

difference() {
arches2(24); //imagine a half tube
mirror([0,0,1]) {
arches2(24,true); //imagine a half circle
}
}
mirror([0,0,1]) {
arches2(24); //adding back in the half tube mirrored
}

Compiling design (CSG Tree generation)...

Rendering Polygon Mesh using CGAL...

ERROR: CGAL error in CGAL_Nef_polyhedron3(): CGAL ERROR: assertion
violation! Expr: e_below != SHalfedge_handle() File:
/opt/mxe/usr/x86_64-w64-mingw32.static.posix/include/CGAL/Nef_3/SNC_FM_decorator.h
Line: 426

ERROR: CGAL error in CGAL_Nef_polyhedron3(): CGAL ERROR: assertion
violation! Expr: e_below != SHalfedge_handle() File:
/opt/mxe/usr/x86_64-w64-mingw32.static.posix/include/CGAL/Nef_3/SNC_FM_decorator.h
Line: 426

Geometries in cache: 11

Geometry cache size in bytes: 5770888

CGAL Polyhedrons in cache: 4

CGAL cache size in bytes: 0

Total rendering time: 0 hours, 0 minutes, 14 seconds

Rendering finished.

I'm trying to make a complicated shape. A quick way to imagine it is that I have a half tube on a wishbone path. Making half of it (just a call to arches2()) works fine. However if I use difference and mirror I get errors. At first I thought it was because I was trying to subtract a mirrored half tube from a mirrored half tube causing some issues. So I changed it so (from the first half tube) I subtract the solid version (if a half tube imagine a half circle being subtracted from it). However, when I do that I still get problems: difference() { arches2(24); //imagine a half tube mirror([0,0,1]) { arches2(24,true); //imagine a half circle } } mirror([0,0,1]) { arches2(24); //adding back in the half tube mirrored } Compiling design (CSG Tree generation)... Rendering Polygon Mesh using CGAL... ERROR: CGAL error in CGAL_Nef_polyhedron3(): CGAL ERROR: assertion violation! Expr: e_below != SHalfedge_handle() File: /opt/mxe/usr/x86_64-w64-mingw32.static.posix/include/CGAL/Nef_3/SNC_FM_decorator.h Line: 426 ERROR: CGAL error in CGAL_Nef_polyhedron3(): CGAL ERROR: assertion violation! Expr: e_below != SHalfedge_handle() File: /opt/mxe/usr/x86_64-w64-mingw32.static.posix/include/CGAL/Nef_3/SNC_FM_decorator.h Line: 426 Geometries in cache: 11 Geometry cache size in bytes: 5770888 CGAL Polyhedrons in cache: 4 CGAL cache size in bytes: 0 Total rendering time: 0 hours, 0 minutes, 14 seconds Rendering finished.
NH
nop head
Sat, Jun 8, 2019 4:19 PM

There is probably something wrong with arches2. Try unioning it with a unit
cube.

On Sat, 8 Jun 2019, 17:13 Dan Shriver, tabbydan@gmail.com wrote:

I'm trying to make a complicated shape.
A quick way to imagine it is that I have a half tube on a wishbone path.

Making half of it (just a call to arches2()) works fine.

However if I use difference and mirror I get errors.

At first I thought it was because I was trying to subtract a mirrored half
tube from a mirrored half tube causing some issues.  So I changed it so
(from the first half tube) I subtract the solid version (if a half tube
imagine a half circle being subtracted from it).

However, when I do that I still get problems:

difference() {
arches2(24); //imagine a half tube
mirror([0,0,1]) {
arches2(24,true); //imagine a half circle
}
}
mirror([0,0,1]) {
arches2(24); //adding back in the half tube mirrored
}

Compiling design (CSG Tree generation)...

Rendering Polygon Mesh using CGAL...

ERROR: CGAL error in CGAL_Nef_polyhedron3(): CGAL ERROR: assertion
violation! Expr: e_below != SHalfedge_handle() File:
/opt/mxe/usr/x86_64-w64-mingw32.static.posix/include/CGAL/Nef_3/SNC_FM_decorator.h
Line: 426

ERROR: CGAL error in CGAL_Nef_polyhedron3(): CGAL ERROR: assertion
violation! Expr: e_below != SHalfedge_handle() File:
/opt/mxe/usr/x86_64-w64-mingw32.static.posix/include/CGAL/Nef_3/SNC_FM_decorator.h
Line: 426

Geometries in cache: 11

Geometry cache size in bytes: 5770888

CGAL Polyhedrons in cache: 4

CGAL cache size in bytes: 0

Total rendering time: 0 hours, 0 minutes, 14 seconds

Rendering finished.


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

There is probably something wrong with arches2. Try unioning it with a unit cube. On Sat, 8 Jun 2019, 17:13 Dan Shriver, <tabbydan@gmail.com> wrote: > I'm trying to make a complicated shape. > A quick way to imagine it is that I have a half tube on a wishbone path. > > Making half of it (just a call to arches2()) works fine. > > However if I use difference and mirror I get errors. > > At first I thought it was because I was trying to subtract a mirrored half > tube from a mirrored half tube causing some issues. So I changed it so > (from the first half tube) I subtract the solid version (if a half tube > imagine a half circle being subtracted from it). > > However, when I do that I still get problems: > > difference() { > arches2(24); //imagine a half tube > mirror([0,0,1]) { > arches2(24,true); //imagine a half circle > } > } > mirror([0,0,1]) { > arches2(24); //adding back in the half tube mirrored > } > > Compiling design (CSG Tree generation)... > > Rendering Polygon Mesh using CGAL... > > ERROR: CGAL error in CGAL_Nef_polyhedron3(): CGAL ERROR: assertion > violation! Expr: e_below != SHalfedge_handle() File: > /opt/mxe/usr/x86_64-w64-mingw32.static.posix/include/CGAL/Nef_3/SNC_FM_decorator.h > Line: 426 > > ERROR: CGAL error in CGAL_Nef_polyhedron3(): CGAL ERROR: assertion > violation! Expr: e_below != SHalfedge_handle() File: > /opt/mxe/usr/x86_64-w64-mingw32.static.posix/include/CGAL/Nef_3/SNC_FM_decorator.h > Line: 426 > > Geometries in cache: 11 > > Geometry cache size in bytes: 5770888 > > CGAL Polyhedrons in cache: 4 > > CGAL cache size in bytes: 0 > > Total rendering time: 0 hours, 0 minutes, 14 seconds > > Rendering finished. > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
DS
Dan Shriver
Sat, Jun 8, 2019 4:37 PM

You are correct.  Union with a cube gives an error too.  But I can't tell
from the error what is wrong.

If I do half the shape it renders fine and looks correct.  How do I locate
the problem?

On Sat, Jun 8, 2019 at 12:20 PM nop head nop.head@gmail.com wrote:

There is probably something wrong with arches2. Try unioning it with a
unit cube.

On Sat, 8 Jun 2019, 17:13 Dan Shriver, tabbydan@gmail.com wrote:

I'm trying to make a complicated shape.
A quick way to imagine it is that I have a half tube on a wishbone path.

Making half of it (just a call to arches2()) works fine.

However if I use difference and mirror I get errors.

At first I thought it was because I was trying to subtract a mirrored
half tube from a mirrored half tube causing some issues.  So I changed it
so (from the first half tube) I subtract the solid version (if a half tube
imagine a half circle being subtracted from it).

However, when I do that I still get problems:

difference() {
arches2(24); //imagine a half tube
mirror([0,0,1]) {
arches2(24,true); //imagine a half circle
}
}
mirror([0,0,1]) {
arches2(24); //adding back in the half tube mirrored
}

Compiling design (CSG Tree generation)...

Rendering Polygon Mesh using CGAL...

ERROR: CGAL error in CGAL_Nef_polyhedron3(): CGAL ERROR: assertion
violation! Expr: e_below != SHalfedge_handle() File:
/opt/mxe/usr/x86_64-w64-mingw32.static.posix/include/CGAL/Nef_3/SNC_FM_decorator.h
Line: 426

ERROR: CGAL error in CGAL_Nef_polyhedron3(): CGAL ERROR: assertion
violation! Expr: e_below != SHalfedge_handle() File:
/opt/mxe/usr/x86_64-w64-mingw32.static.posix/include/CGAL/Nef_3/SNC_FM_decorator.h
Line: 426

Geometries in cache: 11

Geometry cache size in bytes: 5770888

CGAL Polyhedrons in cache: 4

CGAL cache size in bytes: 0

Total rendering time: 0 hours, 0 minutes, 14 seconds

Rendering finished.


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

You are correct. Union with a cube gives an error too. But I can't tell from the error what is wrong. If I do half the shape it renders fine and looks correct. How do I locate the problem? On Sat, Jun 8, 2019 at 12:20 PM nop head <nop.head@gmail.com> wrote: > There is probably something wrong with arches2. Try unioning it with a > unit cube. > > On Sat, 8 Jun 2019, 17:13 Dan Shriver, <tabbydan@gmail.com> wrote: > >> I'm trying to make a complicated shape. >> A quick way to imagine it is that I have a half tube on a wishbone path. >> >> Making half of it (just a call to arches2()) works fine. >> >> However if I use difference and mirror I get errors. >> >> At first I thought it was because I was trying to subtract a mirrored >> half tube from a mirrored half tube causing some issues. So I changed it >> so (from the first half tube) I subtract the solid version (if a half tube >> imagine a half circle being subtracted from it). >> >> However, when I do that I still get problems: >> >> difference() { >> arches2(24); //imagine a half tube >> mirror([0,0,1]) { >> arches2(24,true); //imagine a half circle >> } >> } >> mirror([0,0,1]) { >> arches2(24); //adding back in the half tube mirrored >> } >> >> Compiling design (CSG Tree generation)... >> >> Rendering Polygon Mesh using CGAL... >> >> ERROR: CGAL error in CGAL_Nef_polyhedron3(): CGAL ERROR: assertion >> violation! Expr: e_below != SHalfedge_handle() File: >> /opt/mxe/usr/x86_64-w64-mingw32.static.posix/include/CGAL/Nef_3/SNC_FM_decorator.h >> Line: 426 >> >> ERROR: CGAL error in CGAL_Nef_polyhedron3(): CGAL ERROR: assertion >> violation! Expr: e_below != SHalfedge_handle() File: >> /opt/mxe/usr/x86_64-w64-mingw32.static.posix/include/CGAL/Nef_3/SNC_FM_decorator.h >> Line: 426 >> >> Geometries in cache: 11 >> >> Geometry cache size in bytes: 5770888 >> >> CGAL Polyhedrons in cache: 4 >> >> CGAL cache size in bytes: 0 >> >> Total rendering time: 0 hours, 0 minutes, 14 seconds >> >> Rendering finished. >> >> _______________________________________________ >> OpenSCAD mailing list >> Discuss@lists.openscad.org >> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >> > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
NH
nop head
Sat, Jun 8, 2019 4:53 PM

These sorts of problems are usually caused by creating vertices that due to
numerical error are not exactly coincident but very nearly are. They then
get collapsed due to floating point number representation and that breaks
the topology, creating holes, self intersections or degenerate triangles.
You don't notice until you try to do 3D CSG operations and then CGAL will
barf.

Think of it like this. Suppose you intersect a square with a circle (which
is actually a polygon with sloping sides). Mathematically the intersection
of a diagonal line with a square will create points exactly on the original
lines. In practice though, without infinite precision the points will be
slightly one side or the other. If you then union or difference it with the
original circle you create unimaginably small slivers.

You need to always make sure vertices are either exactly the same or
significantly different when represented in floating point numbers. It is
OK to stack integer sized cubes with exactly coincident faces but not, for
example, 0.1 cubes because 0.1 is a recurring fraction in binary. In
general there should always be some overlap when doing CSG operations.

On Sat, 8 Jun 2019 at 17:38, Dan Shriver tabbydan@gmail.com wrote:

You are correct.  Union with a cube gives an error too.  But I can't tell
from the error what is wrong.

If I do half the shape it renders fine and looks correct.  How do I locate
the problem?

On Sat, Jun 8, 2019 at 12:20 PM nop head nop.head@gmail.com wrote:

There is probably something wrong with arches2. Try unioning it with a
unit cube.

On Sat, 8 Jun 2019, 17:13 Dan Shriver, tabbydan@gmail.com wrote:

I'm trying to make a complicated shape.
A quick way to imagine it is that I have a half tube on a wishbone path.

Making half of it (just a call to arches2()) works fine.

However if I use difference and mirror I get errors.

At first I thought it was because I was trying to subtract a mirrored
half tube from a mirrored half tube causing some issues.  So I changed it
so (from the first half tube) I subtract the solid version (if a half tube
imagine a half circle being subtracted from it).

However, when I do that I still get problems:

difference() {
arches2(24); //imagine a half tube
mirror([0,0,1]) {
arches2(24,true); //imagine a half circle
}
}
mirror([0,0,1]) {
arches2(24); //adding back in the half tube mirrored
}

Compiling design (CSG Tree generation)...

Rendering Polygon Mesh using CGAL...

ERROR: CGAL error in CGAL_Nef_polyhedron3(): CGAL ERROR: assertion
violation! Expr: e_below != SHalfedge_handle() File:
/opt/mxe/usr/x86_64-w64-mingw32.static.posix/include/CGAL/Nef_3/SNC_FM_decorator.h
Line: 426

ERROR: CGAL error in CGAL_Nef_polyhedron3(): CGAL ERROR: assertion
violation! Expr: e_below != SHalfedge_handle() File:
/opt/mxe/usr/x86_64-w64-mingw32.static.posix/include/CGAL/Nef_3/SNC_FM_decorator.h
Line: 426

Geometries in cache: 11

Geometry cache size in bytes: 5770888

CGAL Polyhedrons in cache: 4

CGAL cache size in bytes: 0

Total rendering time: 0 hours, 0 minutes, 14 seconds

Rendering finished.


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

These sorts of problems are usually caused by creating vertices that due to numerical error are not exactly coincident but very nearly are. They then get collapsed due to floating point number representation and that breaks the topology, creating holes, self intersections or degenerate triangles. You don't notice until you try to do 3D CSG operations and then CGAL will barf. Think of it like this. Suppose you intersect a square with a circle (which is actually a polygon with sloping sides). Mathematically the intersection of a diagonal line with a square will create points exactly on the original lines. In practice though, without infinite precision the points will be slightly one side or the other. If you then union or difference it with the original circle you create unimaginably small slivers. You need to always make sure vertices are either exactly the same or significantly different when represented in floating point numbers. It is OK to stack integer sized cubes with exactly coincident faces but not, for example, 0.1 cubes because 0.1 is a recurring fraction in binary. In general there should always be some overlap when doing CSG operations. On Sat, 8 Jun 2019 at 17:38, Dan Shriver <tabbydan@gmail.com> wrote: > You are correct. Union with a cube gives an error too. But I can't tell > from the error what is wrong. > > If I do half the shape it renders fine and looks correct. How do I locate > the problem? > > On Sat, Jun 8, 2019 at 12:20 PM nop head <nop.head@gmail.com> wrote: > >> There is probably something wrong with arches2. Try unioning it with a >> unit cube. >> >> On Sat, 8 Jun 2019, 17:13 Dan Shriver, <tabbydan@gmail.com> wrote: >> >>> I'm trying to make a complicated shape. >>> A quick way to imagine it is that I have a half tube on a wishbone path. >>> >>> Making half of it (just a call to arches2()) works fine. >>> >>> However if I use difference and mirror I get errors. >>> >>> At first I thought it was because I was trying to subtract a mirrored >>> half tube from a mirrored half tube causing some issues. So I changed it >>> so (from the first half tube) I subtract the solid version (if a half tube >>> imagine a half circle being subtracted from it). >>> >>> However, when I do that I still get problems: >>> >>> difference() { >>> arches2(24); //imagine a half tube >>> mirror([0,0,1]) { >>> arches2(24,true); //imagine a half circle >>> } >>> } >>> mirror([0,0,1]) { >>> arches2(24); //adding back in the half tube mirrored >>> } >>> >>> Compiling design (CSG Tree generation)... >>> >>> Rendering Polygon Mesh using CGAL... >>> >>> ERROR: CGAL error in CGAL_Nef_polyhedron3(): CGAL ERROR: assertion >>> violation! Expr: e_below != SHalfedge_handle() File: >>> /opt/mxe/usr/x86_64-w64-mingw32.static.posix/include/CGAL/Nef_3/SNC_FM_decorator.h >>> Line: 426 >>> >>> ERROR: CGAL error in CGAL_Nef_polyhedron3(): CGAL ERROR: assertion >>> violation! Expr: e_below != SHalfedge_handle() File: >>> /opt/mxe/usr/x86_64-w64-mingw32.static.posix/include/CGAL/Nef_3/SNC_FM_decorator.h >>> Line: 426 >>> >>> Geometries in cache: 11 >>> >>> Geometry cache size in bytes: 5770888 >>> >>> CGAL Polyhedrons in cache: 4 >>> >>> CGAL cache size in bytes: 0 >>> >>> Total rendering time: 0 hours, 0 minutes, 14 seconds >>> >>> Rendering finished. >>> >>> _______________________________________________ >>> OpenSCAD mailing list >>> Discuss@lists.openscad.org >>> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >>> >> _______________________________________________ >> OpenSCAD mailing list >> Discuss@lists.openscad.org >> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >> > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
DS
Dan Shriver
Sat, Jun 8, 2019 5:20 PM

Thanks, that helps, but I still need some tips for locating the problem.

I do have a lot of floating point math going on here, and I believe what
you say is the case.  The only problem is locating where the problem is.

My half tube is actually made of three arches (and it slowly morphs from
one type to the next, and then repeats the cycle at the end).

To smoothly change the arch types the coordinates of one are multiplied by
(abs(sin(i)) and added to the other one which is multiplied by (1 -
abs(sin(i))) where the value i is always somewhere between 0 and 180.

In all likelihood the "coincident vertices" occur somewhere along the
morphing.  When I check the unmorphed three arches they all seem to have
vertices that look fine (those are also floating point values).

Is it known what distance vertices need to be separated from each other?

What do you do in cases like this to fix your problems?

On Sat, Jun 8, 2019 at 12:54 PM nop head nop.head@gmail.com wrote:

These sorts of problems are usually caused by creating vertices that due
to numerical error are not exactly coincident but very nearly are. They
then get collapsed due to floating point number representation and that
breaks the topology, creating holes, self intersections or degenerate
triangles. You don't notice until you try to do 3D CSG operations and then
CGAL will barf.

Think of it like this. Suppose you intersect a square with a circle (which
is actually a polygon with sloping sides). Mathematically the intersection
of a diagonal line with a square will create points exactly on the original
lines. In practice though, without infinite precision the points will be
slightly one side or the other. If you then union or difference it with the
original circle you create unimaginably small slivers.

You need to always make sure vertices are either exactly the same or
significantly different when represented in floating point numbers. It is
OK to stack integer sized cubes with exactly coincident faces but not, for
example, 0.1 cubes because 0.1 is a recurring fraction in binary. In
general there should always be some overlap when doing CSG operations.

On Sat, 8 Jun 2019 at 17:38, Dan Shriver tabbydan@gmail.com wrote:

You are correct.  Union with a cube gives an error too.  But I can't tell
from the error what is wrong.

If I do half the shape it renders fine and looks correct.  How do I
locate the problem?

On Sat, Jun 8, 2019 at 12:20 PM nop head nop.head@gmail.com wrote:

There is probably something wrong with arches2. Try unioning it with a
unit cube.

On Sat, 8 Jun 2019, 17:13 Dan Shriver, tabbydan@gmail.com wrote:

I'm trying to make a complicated shape.
A quick way to imagine it is that I have a half tube on a wishbone path.

Making half of it (just a call to arches2()) works fine.

However if I use difference and mirror I get errors.

At first I thought it was because I was trying to subtract a mirrored
half tube from a mirrored half tube causing some issues.  So I changed it
so (from the first half tube) I subtract the solid version (if a half tube
imagine a half circle being subtracted from it).

However, when I do that I still get problems:

difference() {
arches2(24); //imagine a half tube
mirror([0,0,1]) {
arches2(24,true); //imagine a half circle
}
}
mirror([0,0,1]) {
arches2(24); //adding back in the half tube mirrored
}

Compiling design (CSG Tree generation)...

Rendering Polygon Mesh using CGAL...

ERROR: CGAL error in CGAL_Nef_polyhedron3(): CGAL ERROR: assertion
violation! Expr: e_below != SHalfedge_handle() File:
/opt/mxe/usr/x86_64-w64-mingw32.static.posix/include/CGAL/Nef_3/SNC_FM_decorator.h
Line: 426

ERROR: CGAL error in CGAL_Nef_polyhedron3(): CGAL ERROR: assertion
violation! Expr: e_below != SHalfedge_handle() File:
/opt/mxe/usr/x86_64-w64-mingw32.static.posix/include/CGAL/Nef_3/SNC_FM_decorator.h
Line: 426

Geometries in cache: 11

Geometry cache size in bytes: 5770888

CGAL Polyhedrons in cache: 4

CGAL cache size in bytes: 0

Total rendering time: 0 hours, 0 minutes, 14 seconds

Rendering finished.


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

Thanks, that helps, but I still need some tips for locating the problem. I do have a lot of floating point math going on here, and I believe what you say is the case. The only problem is locating where the problem is. My half tube is actually made of three arches (and it slowly morphs from one type to the next, and then repeats the cycle at the end). To smoothly change the arch types the coordinates of one are multiplied by (abs(sin(i)) and added to the other one which is multiplied by (1 - abs(sin(i))) where the value i is always somewhere between 0 and 180. In all likelihood the "coincident vertices" occur somewhere along the morphing. When I check the unmorphed three arches they all seem to have vertices that look fine (those are also floating point values). Is it known what distance vertices need to be separated from each other? What do you do in cases like this to fix your problems? On Sat, Jun 8, 2019 at 12:54 PM nop head <nop.head@gmail.com> wrote: > These sorts of problems are usually caused by creating vertices that due > to numerical error are not exactly coincident but very nearly are. They > then get collapsed due to floating point number representation and that > breaks the topology, creating holes, self intersections or degenerate > triangles. You don't notice until you try to do 3D CSG operations and then > CGAL will barf. > > Think of it like this. Suppose you intersect a square with a circle (which > is actually a polygon with sloping sides). Mathematically the intersection > of a diagonal line with a square will create points exactly on the original > lines. In practice though, without infinite precision the points will be > slightly one side or the other. If you then union or difference it with the > original circle you create unimaginably small slivers. > > You need to always make sure vertices are either exactly the same or > significantly different when represented in floating point numbers. It is > OK to stack integer sized cubes with exactly coincident faces but not, for > example, 0.1 cubes because 0.1 is a recurring fraction in binary. In > general there should always be some overlap when doing CSG operations. > > On Sat, 8 Jun 2019 at 17:38, Dan Shriver <tabbydan@gmail.com> wrote: > >> You are correct. Union with a cube gives an error too. But I can't tell >> from the error what is wrong. >> >> If I do half the shape it renders fine and looks correct. How do I >> locate the problem? >> >> On Sat, Jun 8, 2019 at 12:20 PM nop head <nop.head@gmail.com> wrote: >> >>> There is probably something wrong with arches2. Try unioning it with a >>> unit cube. >>> >>> On Sat, 8 Jun 2019, 17:13 Dan Shriver, <tabbydan@gmail.com> wrote: >>> >>>> I'm trying to make a complicated shape. >>>> A quick way to imagine it is that I have a half tube on a wishbone path. >>>> >>>> Making half of it (just a call to arches2()) works fine. >>>> >>>> However if I use difference and mirror I get errors. >>>> >>>> At first I thought it was because I was trying to subtract a mirrored >>>> half tube from a mirrored half tube causing some issues. So I changed it >>>> so (from the first half tube) I subtract the solid version (if a half tube >>>> imagine a half circle being subtracted from it). >>>> >>>> However, when I do that I still get problems: >>>> >>>> difference() { >>>> arches2(24); //imagine a half tube >>>> mirror([0,0,1]) { >>>> arches2(24,true); //imagine a half circle >>>> } >>>> } >>>> mirror([0,0,1]) { >>>> arches2(24); //adding back in the half tube mirrored >>>> } >>>> >>>> Compiling design (CSG Tree generation)... >>>> >>>> Rendering Polygon Mesh using CGAL... >>>> >>>> ERROR: CGAL error in CGAL_Nef_polyhedron3(): CGAL ERROR: assertion >>>> violation! Expr: e_below != SHalfedge_handle() File: >>>> /opt/mxe/usr/x86_64-w64-mingw32.static.posix/include/CGAL/Nef_3/SNC_FM_decorator.h >>>> Line: 426 >>>> >>>> ERROR: CGAL error in CGAL_Nef_polyhedron3(): CGAL ERROR: assertion >>>> violation! Expr: e_below != SHalfedge_handle() File: >>>> /opt/mxe/usr/x86_64-w64-mingw32.static.posix/include/CGAL/Nef_3/SNC_FM_decorator.h >>>> Line: 426 >>>> >>>> Geometries in cache: 11 >>>> >>>> Geometry cache size in bytes: 5770888 >>>> >>>> CGAL Polyhedrons in cache: 4 >>>> >>>> CGAL cache size in bytes: 0 >>>> >>>> Total rendering time: 0 hours, 0 minutes, 14 seconds >>>> >>>> Rendering finished. >>>> >>>> _______________________________________________ >>>> OpenSCAD mailing list >>>> Discuss@lists.openscad.org >>>> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >>>> >>> _______________________________________________ >>> OpenSCAD mailing list >>> Discuss@lists.openscad.org >>> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >>> >> _______________________________________________ >> OpenSCAD mailing list >> Discuss@lists.openscad.org >> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >> > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
NH
nop head
Sat, Jun 8, 2019 5:32 PM

I rarely get these problems due to the way I code but I did get it making a
shape where I stacked two polygons, one of which had been intersected with
rectangle at 45 degrees. I fixed it by making the second polygon slightly
smaller. I have a constant eps = 1/128 for such bodges. Since the
denominator is a power of two it is an exact number in floating point. Too
small to see but large enough to stop z-fighting in preview.

OpenSCAD snaps vertices to a grid at various points so distinct vertices
need to differ somewhat more than that
https://github.com/openscad/openscad/blob/master/src/grid.h#L19 .

On Sat, 8 Jun 2019 at 18:21, Dan Shriver tabbydan@gmail.com wrote:

Thanks, that helps, but I still need some tips for locating the problem.

I do have a lot of floating point math going on here, and I believe what
you say is the case.  The only problem is locating where the problem is.

My half tube is actually made of three arches (and it slowly morphs from
one type to the next, and then repeats the cycle at the end).

To smoothly change the arch types the coordinates of one are multiplied by
(abs(sin(i)) and added to the other one which is multiplied by (1 -
abs(sin(i))) where the value i is always somewhere between 0 and 180.

In all likelihood the "coincident vertices" occur somewhere along the
morphing.  When I check the unmorphed three arches they all seem to have
vertices that look fine (those are also floating point values).

Is it known what distance vertices need to be separated from each other?

What do you do in cases like this to fix your problems?

On Sat, Jun 8, 2019 at 12:54 PM nop head nop.head@gmail.com wrote:

These sorts of problems are usually caused by creating vertices that due
to numerical error are not exactly coincident but very nearly are. They
then get collapsed due to floating point number representation and that
breaks the topology, creating holes, self intersections or degenerate
triangles. You don't notice until you try to do 3D CSG operations and then
CGAL will barf.

Think of it like this. Suppose you intersect a square with a circle
(which is actually a polygon with sloping sides). Mathematically the
intersection of a diagonal line with a square will create points exactly on
the original lines. In practice though, without infinite precision the
points will be slightly one side or the other. If you then union or
difference it with the original circle you create unimaginably small
slivers.

You need to always make sure vertices are either exactly the same or
significantly different when represented in floating point numbers. It is
OK to stack integer sized cubes with exactly coincident faces but not, for
example, 0.1 cubes because 0.1 is a recurring fraction in binary. In
general there should always be some overlap when doing CSG operations.

On Sat, 8 Jun 2019 at 17:38, Dan Shriver tabbydan@gmail.com wrote:

You are correct.  Union with a cube gives an error too.  But I can't
tell from the error what is wrong.

If I do half the shape it renders fine and looks correct.  How do I
locate the problem?

On Sat, Jun 8, 2019 at 12:20 PM nop head nop.head@gmail.com wrote:

There is probably something wrong with arches2. Try unioning it with a
unit cube.

On Sat, 8 Jun 2019, 17:13 Dan Shriver, tabbydan@gmail.com wrote:

I'm trying to make a complicated shape.
A quick way to imagine it is that I have a half tube on a wishbone
path.

Making half of it (just a call to arches2()) works fine.

However if I use difference and mirror I get errors.

At first I thought it was because I was trying to subtract a mirrored
half tube from a mirrored half tube causing some issues.  So I changed it
so (from the first half tube) I subtract the solid version (if a half tube
imagine a half circle being subtracted from it).

However, when I do that I still get problems:

difference() {
arches2(24); //imagine a half tube
mirror([0,0,1]) {
arches2(24,true); //imagine a half circle
}
}
mirror([0,0,1]) {
arches2(24); //adding back in the half tube mirrored
}

Compiling design (CSG Tree generation)...

Rendering Polygon Mesh using CGAL...

ERROR: CGAL error in CGAL_Nef_polyhedron3(): CGAL ERROR: assertion
violation! Expr: e_below != SHalfedge_handle() File:
/opt/mxe/usr/x86_64-w64-mingw32.static.posix/include/CGAL/Nef_3/SNC_FM_decorator.h
Line: 426

ERROR: CGAL error in CGAL_Nef_polyhedron3(): CGAL ERROR: assertion
violation! Expr: e_below != SHalfedge_handle() File:
/opt/mxe/usr/x86_64-w64-mingw32.static.posix/include/CGAL/Nef_3/SNC_FM_decorator.h
Line: 426

Geometries in cache: 11

Geometry cache size in bytes: 5770888

CGAL Polyhedrons in cache: 4

CGAL cache size in bytes: 0

Total rendering time: 0 hours, 0 minutes, 14 seconds

Rendering finished.


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

I rarely get these problems due to the way I code but I did get it making a shape where I stacked two polygons, one of which had been intersected with rectangle at 45 degrees. I fixed it by making the second polygon slightly smaller. I have a constant eps = 1/128 for such bodges. Since the denominator is a power of two it is an exact number in floating point. Too small to see but large enough to stop z-fighting in preview. OpenSCAD snaps vertices to a grid at various points so distinct vertices need to differ somewhat more than that https://github.com/openscad/openscad/blob/master/src/grid.h#L19 . On Sat, 8 Jun 2019 at 18:21, Dan Shriver <tabbydan@gmail.com> wrote: > Thanks, that helps, but I still need some tips for locating the problem. > > I do have a lot of floating point math going on here, and I believe what > you say is the case. The only problem is locating where the problem is. > > My half tube is actually made of three arches (and it slowly morphs from > one type to the next, and then repeats the cycle at the end). > > To smoothly change the arch types the coordinates of one are multiplied by > (abs(sin(i)) and added to the other one which is multiplied by (1 - > abs(sin(i))) where the value i is always somewhere between 0 and 180. > > In all likelihood the "coincident vertices" occur somewhere along the > morphing. When I check the unmorphed three arches they all seem to have > vertices that look fine (those are also floating point values). > > Is it known what distance vertices need to be separated from each other? > > What do you do in cases like this to fix your problems? > > On Sat, Jun 8, 2019 at 12:54 PM nop head <nop.head@gmail.com> wrote: > >> These sorts of problems are usually caused by creating vertices that due >> to numerical error are not exactly coincident but very nearly are. They >> then get collapsed due to floating point number representation and that >> breaks the topology, creating holes, self intersections or degenerate >> triangles. You don't notice until you try to do 3D CSG operations and then >> CGAL will barf. >> >> Think of it like this. Suppose you intersect a square with a circle >> (which is actually a polygon with sloping sides). Mathematically the >> intersection of a diagonal line with a square will create points exactly on >> the original lines. In practice though, without infinite precision the >> points will be slightly one side or the other. If you then union or >> difference it with the original circle you create unimaginably small >> slivers. >> >> You need to always make sure vertices are either exactly the same or >> significantly different when represented in floating point numbers. It is >> OK to stack integer sized cubes with exactly coincident faces but not, for >> example, 0.1 cubes because 0.1 is a recurring fraction in binary. In >> general there should always be some overlap when doing CSG operations. >> >> On Sat, 8 Jun 2019 at 17:38, Dan Shriver <tabbydan@gmail.com> wrote: >> >>> You are correct. Union with a cube gives an error too. But I can't >>> tell from the error what is wrong. >>> >>> If I do half the shape it renders fine and looks correct. How do I >>> locate the problem? >>> >>> On Sat, Jun 8, 2019 at 12:20 PM nop head <nop.head@gmail.com> wrote: >>> >>>> There is probably something wrong with arches2. Try unioning it with a >>>> unit cube. >>>> >>>> On Sat, 8 Jun 2019, 17:13 Dan Shriver, <tabbydan@gmail.com> wrote: >>>> >>>>> I'm trying to make a complicated shape. >>>>> A quick way to imagine it is that I have a half tube on a wishbone >>>>> path. >>>>> >>>>> Making half of it (just a call to arches2()) works fine. >>>>> >>>>> However if I use difference and mirror I get errors. >>>>> >>>>> At first I thought it was because I was trying to subtract a mirrored >>>>> half tube from a mirrored half tube causing some issues. So I changed it >>>>> so (from the first half tube) I subtract the solid version (if a half tube >>>>> imagine a half circle being subtracted from it). >>>>> >>>>> However, when I do that I still get problems: >>>>> >>>>> difference() { >>>>> arches2(24); //imagine a half tube >>>>> mirror([0,0,1]) { >>>>> arches2(24,true); //imagine a half circle >>>>> } >>>>> } >>>>> mirror([0,0,1]) { >>>>> arches2(24); //adding back in the half tube mirrored >>>>> } >>>>> >>>>> Compiling design (CSG Tree generation)... >>>>> >>>>> Rendering Polygon Mesh using CGAL... >>>>> >>>>> ERROR: CGAL error in CGAL_Nef_polyhedron3(): CGAL ERROR: assertion >>>>> violation! Expr: e_below != SHalfedge_handle() File: >>>>> /opt/mxe/usr/x86_64-w64-mingw32.static.posix/include/CGAL/Nef_3/SNC_FM_decorator.h >>>>> Line: 426 >>>>> >>>>> ERROR: CGAL error in CGAL_Nef_polyhedron3(): CGAL ERROR: assertion >>>>> violation! Expr: e_below != SHalfedge_handle() File: >>>>> /opt/mxe/usr/x86_64-w64-mingw32.static.posix/include/CGAL/Nef_3/SNC_FM_decorator.h >>>>> Line: 426 >>>>> >>>>> Geometries in cache: 11 >>>>> >>>>> Geometry cache size in bytes: 5770888 >>>>> >>>>> CGAL Polyhedrons in cache: 4 >>>>> >>>>> CGAL cache size in bytes: 0 >>>>> >>>>> Total rendering time: 0 hours, 0 minutes, 14 seconds >>>>> >>>>> Rendering finished. >>>>> >>>>> _______________________________________________ >>>>> OpenSCAD mailing list >>>>> Discuss@lists.openscad.org >>>>> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >>>>> >>>> _______________________________________________ >>>> OpenSCAD mailing list >>>> Discuss@lists.openscad.org >>>> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >>>> >>> _______________________________________________ >>> OpenSCAD mailing list >>> Discuss@lists.openscad.org >>> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >>> >> _______________________________________________ >> OpenSCAD mailing list >> Discuss@lists.openscad.org >> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >> > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
A
adrianv
Sat, Jun 8, 2019 5:45 PM

DanS wrote

Thanks, that helps, but I still need some tips for locating the problem.

It's tough for people to guess what might be wrong if we don't know what
your code actually does.  Are you using polyhedron?  Or are you doing unions
and/or intersections of primitive geometry?  Try to simplify your code and
see if you can get the problem to go away.  That might give some insight
into where the problem lies.

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

DanS wrote > Thanks, that helps, but I still need some tips for locating the problem. It's tough for people to guess what might be wrong if we don't know what your code actually does. Are you using polyhedron? Or are you doing unions and/or intersections of primitive geometry? Try to simplify your code and see if you can get the problem to go away. That might give some insight into where the problem lies. -- Sent from: http://forum.openscad.org/
DS
Dan Shriver
Sat, Jun 8, 2019 5:53 PM

I'll post my code below a dividing line.

Basically arches2() makes half the passageway.  The number of vertices MUST
be a multiple of 8.  A "solid" parameter (defaults to false) makes a solid
version for subtraction.

I confess it isn't pretty code.


use <list-comprehension/skin.scad>;
use <nSpline/splines.scad>;
use <scad-utils/transformations.scad>
use <scad-utils/lists.scad>

function echoit(x) = echo(x) x;
//function echoit2(y,x) = echo(y,x) x; //debug version
function echoit2(y,x) =  x; //debug off
function echoit3(y,x) = x; //debug off
//function echoit4(y,x) = echo(y,x) x; //debug version
function echoit4(y,x) =  x; //debug off

//hyperbolic sinh cosh etc
function cosh(x) = (exp(x) + exp(-x))/2;
function sinh(x) = (exp(x) - exp(-x))/2;
function tanh(x) = sinh(x)/cosh(x);
function coth(x) = 1/tanh(x);

function innerAngle(radius, thickness, angle) =
atan(((radius-thickness)*sin(angle))/((radius-thickness)*cos(angle)));

function partitionNum(pn,points) =
(pn < (points-2)/4) ? 0 :        //OUTER RIGHT
(pn < (points-2)/4 + 1)  ? 1 :    //OUTER TOP
(pn < (points-2)/2 + 1) ? 2:      //OUTER LEFT
(pn < (3*(points-2))/4 + 1) ? 3:  //INNER LEFT
(pn < (3*(points-2))/4 + 2) ? 4:  //INNER TOP
5;                                // INNER RIGHT

function subPointNum(points, pointNum, partition) =
[pointNum,
1, //doesn't matter
((points-2)/2) - pointNum,
pointNum - points/2,
1, //doesn't matter
((points-1) - pointNum)]
[partition];

//one more point in the outer arcs one less in the inner
function partitionNumNc(pn,points,solid) = (solid) ? (pn < (points)/2) ? 0
:        //OUTER RIGHT
(pn == (points)/2)  ? 1 :    //OUTER TOP
2 :
(pn < (points)/4) ? 0 :        //OUTER RIGHT
(pn == (points)/4)  ? 1 :    //OUTER TOP
(pn < ((points)/2)+1) ? 2:      //OUTER LEFT
(pn < (3points)/4) ? 3:  //INNER LEFT
(pn == (3
points)/4) ? 4:  //INNER TOP
5                                // INNER RIGHT
;

function subPointNumNc(points, pointNum, partition) =
[pointNum,
1, //doesn't matter
((points)/2) - pointNum,
pointNum - (points/2+1),
1, //doesn't matter
((points-1) - pointNum)]
[partition];

function archXNc(radius, thickness, angle, pointNum, points, solid) =
let(inner = innerAngle(radius, thickness, angle),
partition = partitionNumNc(pointNum,points,solid),
subPoint = subPointNumNc(points, pointNum, partition),
steps = (pointNum < (points/2)) ? (((points)/4) - 1) : (((points)/4) -
2))
[radius * cos(angle/steps * pointNum) - radius * (cos(angle)),
0,
-(radius * cos(angle/steps * subPoint) - radius * (cos(angle))), //
PTS - 2 EXP + 1
-(((radius - thickness) * cos((angle/steps) *  subPoint)) - ((radius -
thickness)*cos(angle))), //PTS -2  EXP +1
0,
(radius - thickness) * cos((angle/steps) *  subPoint) -
(radius-thickness)*cos(angle) //PTS - 2 EXP +2
]
[partition];

function archX(radius, thickness, angle, pointNum, points) = let(inner =
innerAngle(radius, thickness, angle),
partition = partitionNum(pointNum,points),
subPoint = subPointNum(points, pointNum, partition),
steps = (points-2)/4)
[radius * cos(angle/steps * pointNum) - radius * (cos(angle)),
0,
-(radius * cos(angle/steps * subPoint) - radius * (cos(angle))), //
PTS - 2 EXP + 1
-(((radius - thickness) * cos((angle/steps) *  subPoint)) - ((radius -
thickness)*cos(angle))), //PTS -2  EXP +1
0,
(radius - thickness) * cos((angle/steps) *  subPoint) -
(radius-thickness)*cos(angle) //PTS - 2 EXP +2
]
[partition];

function archY(radius, thickness, angle, pointNum, points) = let(inner =
innerAngle(radius, thickness, angle),
partition = partitionNum(pointNum,points),
subPoint = subPointNum(points, pointNum, partition),
steps = (points-2)/4)
[radius * sin(angle/steps * pointNum),
radius * sin(angle),
(radius * sin(angle/steps * subPoint)),
(radius - thickness) * sin( angle/steps * subPoint),
(radius - thickness) * sin(angle),
(radius - thickness) * sin((angle*subPoint)/steps)
]
[partition];

function archYNc(radius, thickness, angle, pointNum, points, solid) =
let(inner = innerAngle(radius, thickness, angle),
partition = partitionNumNc(pointNum,points,solid),
subPoint = subPointNumNc(points, pointNum, partition),
steps = (pointNum < (points/2)) ? ((points)/4) - 1 : ((points)/4) - 2)
[radius * sin(angle/steps * pointNum),
radius * sin(angle),
(radius * sin(angle/steps * subPoint)),
(radius - thickness) * sin( angle/steps * subPoint),
(radius - thickness) * sin(angle),
(radius - thickness) * sin((angle*subPoint)/steps)
]
[partition];

// This function actuall works on ugly numbers 6 + 4(n) points: 10, 14, 18,
22 ...
function romanArch(radius, thickness, angle, pointCnt)
= [ for (i = [0:(pointCnt-1)]) [archX(radius, thickness, angle, i,
pointCnt), archY(radius, thickness, angle, i, pointCnt)] ];

//use this with a no-cap ogee as this works out to
//be 4n +  4 points which meshes with 8n of a no cap ogee
// 8, 12, 16, 20,....
// you will have to use ODD N values to match with
// a linear progression of 8n
// (4m)+ 4 = 8n for 1 on both sides 3m=2n; 5m = 3n etc
// This function actuall works on ugly numbers 6 + 4(n) points: 10, 14, 18,
22 ...
function romanArchNc(radius, thickness, angle, pointCnt, solid = false)
= (solid) ? [ for (i = [0:(pointCnt/2 -1)]) [archXNc(radius, thickness,
angle, i, pointCnt, solid), archYNc(radius, thickness, angle, i, pointCnt,
solid)] ] : [ for (i = [0:(pointCnt-1)]) [archXNc(radius, thickness, angle,
i, pointCnt, solid), archYNc(radius, thickness, angle, i, pointCnt, solid)]
];

//the second half is missing one point, figure it out...
//romanArch(20, 1, 70, 200);

//8n (if capwidth = 0); 8n + 2 otherwise
function ogeepoly(width, thickness, lowerradius, upperradius, points, solid
= false, capwidth = 0.0, apexangle = 45.0) =
let(
// Angle extended by the arcs
lowerphi = 180.0 - acos((0.5*(width - capwidth) - lowerradius -
thickness - upperradius * cos(0.5*apexangle)) / (lowerradius + thickness +
upperradius)),
upperphi = lowerphi - 0.5 * apexangle,
apexhalf = 0.5 * apexangle,

// Number of points per lower arc
lowerpoints = echoit2("lowerpoints ",round((capwidth > 0.0) ?

lowerphi*(points-4)/(8lowerphi-4apexangle) :
lowerphi*(points-2)/(8lowerphi-4apexangle))),

// Actual number of points in the upper arc
uppertemp = echoit2("uppertemp ",round((capwidth > 0.0) ?

(lowerphi-apexangle)(points-4)/(8lowerphi-4apexangle) :
(lowerphi-apexangle)
(points-2)/(8lowerphi-4apexangle))),
targetpoints = echoit2("targetpoints ", (apexangle > 0.0) ? points - 5
: points - 2),
upperpoints = echoit2("upperpoints ",(targetpoints - 4*(lowerpoints +
uppertemp) >= -1) ? uppertemp + 1 : uppertemp),

// Key horizontal coordinates. Note: w0=x1, w6=x2
w0 = 0.5*width - thickness - lowerradius,
w1 = 0.5*capwidth,
w2 = w0 + lowerradius * cos(lowerphi),
w3 = w0 + (lowerradius + thickness) * cos(lowerphi),
w4 = w0 + lowerradius,
w5 = w0 + lowerradius + thickness,
w6 = w0 + (lowerradius + thickness + upperradius) * cos(lowerphi),

// Key vertical coordinates. Note: y1=h0=0, y2=h6
h6 = (lowerradius + thickness + upperradius) * sin(lowerphi),
h5 = h6 - upperradius * sin(apexhalf),
h4 = h5 - 0.5*capwidth * tan(apexhalf),
h3 = h6 - (upperradius + thickness) * sqrt(1.0 - w6*w6 / ((upperradius
  • thickness) * (upperradius + thickness))),
    h2 = (lowerradius + thickness) * sin(lowerphi),
    h1 = lowerradius * sin(lowerphi),
    h0 = 0.0,
    height = (apexangle > 0.0) ? (h5 + 0.5*capwidth / tan(apexhalf)) : h5,

    // We use the same number of points for the upper inner arc,
    // even though it is a bit smaller angle.
    innertheta = acos(w6 / (upperradius + thickness)),
    innerphi = lowerphi - innertheta,

    // Lower Right Outer arc
    lro = echoit3("lro ",[ for (i = [0:lowerpoints-1]) [ w0 + (lowerradius

  • thickness) * cos(i * lowerphi / lowerpoints), h0 + (lowerradius +
    thickness) * sin(i * lowerphi / lowerpoints) ] ]),
    // Upper Right Outer arc
    uro = echoit3("uro ",[ for (i = [upperpoints-1:-1:0]) [ w6 -
    upperradius * cos(apexhalf + i * upperphi / upperpoints), h6 - upperradius

  • sin(apexhalf + i * upperphi / upperpoints) ] ]),
    // Cap
    cap = (capwidth > 0.0) ? [ [ w1, h5 ], [ 0, height ] ] : [],
    // Upper Left Outer arc
    ulo = echoit3("ulo ",[ for (i = [0:upperpoints-1]) [ -w6 + upperradius
  • cos(apexhalf + i * upperphi / upperpoints), h6 - upperradius *
    sin(apexhalf + i * upperphi / upperpoints) ] ]),
    // Lower Left Outer arc
    //incorrectly 4 pts
    //changing loop first contition to lowerpoints-1 from "lowerpoints"
    llo = echoit3("llo ",[ for (i = [lowerpoints-1:-1:0]) [ -w0 -
    (lowerradius + thickness) * cos(i * lowerphi / lowerpoints), h0 +
    (lowerradius + thickness) * sin(i * lowerphi / lowerpoints) ] ]),
    // Lower Left Inner arc
    lli = (solid) ? [] : [ for (i = [0:lowerpoints-1]) [ -w0 - lowerradius
  • cos(i * lowerphi / lowerpoints), h0 + lowerradius * sin(i * lowerphi /
    lowerpoints) ] ],
    // Upper Left Inner arc
    uli = (solid) ? [] : [ for (i = [upperpoints-1:-1:0]) [ -w6 +
    (upperradius + thickness) * cos(innertheta + i * innerphi / upperpoints),
    h6 - (upperradius + thickness) * sin(innertheta + i * innerphi /
    upperpoints) ] ],
    // Upper Right Inner arc
    uri = (solid) ? [] : [ for (i = [0:upperpoints-1]) [ w6 - (upperradius
  • thickness) * cos(innertheta + i * innerphi / upperpoints), h6 -
    (upperradius + thickness) * sin(innertheta + i * innerphi / upperpoints) ]
    ],
    // Lower Right Inner arc
    lri = (solid) ? [] : [ for (i = [lowerpoints-1:-1:0]) [ w0  +
    lowerradius * cos(i * lowerphi / lowerpoints), h0 + lowerradius * sin(i *
    lowerphi / lowerpoints) ] ]
    )
    concat(lro, uro, cap, ulo, llo, lli, uli, uri, lri);

function ogeepolyPath(width, thickness, lowerradius, upperradius, points,
capwidth = 0.0, apexangle = 45.0) =
let(
// Angle extended by the arcs
lowerphi = 180.0 - acos((0.5*(width - capwidth) - lowerradius -
thickness - upperradius * cos(0.5*apexangle)) / (lowerradius + thickness +
upperradius)),
upperphi = lowerphi - 0.5 * apexangle,
apexhalf = 0.5 * apexangle,

// Number of points per lower arc
lowerpoints = round((capwidth > 0.0) ?

lowerphi*(points-4)/(8lowerphi-4apexangle) :
lowerphi*(points-2)/(8lowerphi-4apexangle)),

// Actual number of points in the upper arc
uppertemp = round((capwidth > 0.0) ?

(lowerphi-apexangle)(points-4)/(8lowerphi-4apexangle) :
(lowerphi-apexangle)
(points-2)/(8lowerphi-4apexangle)),
targetpoints = (apexangle > 0.0) ? points - 5 : points - 2,
upperpoints = (targetpoints - 4*(lowerpoints + uppertemp) >= -1) ?
uppertemp + 1 : uppertemp,

// Key horizontal coordinates. Note: w0=x1, w6=x2
w0 = 0.5*width - thickness - lowerradius,
w1 = 0.5*capwidth,
w2 = w0 + lowerradius * cos(lowerphi),
w3 = w0 + (lowerradius + thickness) * cos(lowerphi),
w4 = w0 + lowerradius,
w5 = w0 + lowerradius + thickness,
w6 = w0 + (lowerradius + thickness + upperradius) * cos(lowerphi),

// Key vertical coordinates. Note: y1=h0=0, y2=h6
h6 = (lowerradius + thickness + upperradius) * sin(lowerphi),
h5 = h6 - upperradius * sin(apexhalf),
h4 = h5 - 0.5*capwidth * tan(apexhalf),
h3 = h6 - (upperradius + thickness) * sqrt(1.0 - w6*w6 / ((upperradius
  • thickness) * (upperradius + thickness))),
    h2 = (lowerradius + thickness) * sin(lowerphi),
    h1 = lowerradius * sin(lowerphi),
    h0 = 0.0,
    height = (apexangle > 0.0) ? (h5 + 0.5*capwidth / tan(apexhalf)) : h5,

    // We use the same number of points for the upper inner arc,
    // even though it is a bit smaller angle.
    innertheta = acos(w6 / (upperradius + thickness)),
    innerphi = lowerphi - innertheta,

    // Lower Right Outer arc
    lro = [ for (i = [0:lowerpoints-1]) [ w0 + (lowerradius + thickness) *
    cos(i * lowerphi / lowerpoints), 0, h0 + (lowerradius + thickness) * sin(i

  • lowerphi / lowerpoints) ] ],
    // Upper Right Outer arc
    uro = [ for (i = [upperpoints-1:-1:0]) [ w6 - upperradius *
    cos(apexhalf + i * upperphi / upperpoints), 0, h6 - upperradius *
    sin(apexhalf + i * upperphi / upperpoints) ] ],
    // Cap
    cap = (capwidth > 0.0) ? [ [ w1, 0, h5 ], [ 0, 0, height ] ] : [],
    // Upper Left Outer arc
    ulo = [ for (i = [0:upperpoints-1]) [ -w6 + upperradius * cos(apexhalf
  • i * upperphi / upperpoints), 0, h6 - upperradius * sin(apexhalf + i *
    upperphi / upperpoints) ] ],
    // Lower Left Outer arc
    llo = [ for (i = [lowerpoints:-1:0]) [ -w0 - (lowerradius + thickness)
  • cos(i * lowerphi / lowerpoints), 0, h0 + (lowerradius + thickness) *
    sin(i * lowerphi / lowerpoints) ] ]
    )
    concat(lro, uro, cap, ulo, llo);

function stupid(i) = (i==1) ? ogeepoly(65,3,60,60,100,1,10) : romanArch(70,
3, 62, 200);

function interpolateWave(A, B, s) = [for(i=[0:len(A)-1]) (sin(s))*A[s] +
(cos(s))*B[s] ];

//NOT WHAT I WANT BUT A COOL SHAPE WITH WRONG POLYGON COUNT
//function waveOut(i) = sin(i) * romanArch(70, 3, 62, 200) + cos(i) *
ogeepoly(65,3,60,60,100,1,10);

/*
function waveOut(i) = abs(sin(i)) * romanArch(70, 3, 62, 200) + (1 -
abs(sin(i))) * ogeepoly(65,3,60,60,200,1,10);
*/

function waveOut(i,verticies,thickness,solid) = abs(sin(i)) *
romanArchNc(65, thickness, 70, verticies,solid) + (1 - abs(sin(i))) *
ogeepoly(65,thickness,60,60,verticies,solid,0.0,0);//was 1,10 at end

function waveIn(i,verticies,thickness,solid) = abs(sin(i)) *
romanArchNc(95, thickness, 40, verticies,solid) + (1 - abs(sin(i))) *
ogeepoly(65,thickness,60,60,verticies,solid,0.0,0);//was 1,10 at end

function wave(i,verticies=200,thickness,solid) = (i < 31) ?
waveOut(echoit4("<31",(i*6)),verticies,thickness,solid) :
(i < 61) ?
waveIn(echoit4("<61",(180-((i-30)*6))),verticies,thickness,solid) :
(i < 91) ?
waveOut(echoit4("<91",(i-60)*6),verticies,thickness,solid) :

waveIn(echoit4("last",180-((i-90)*6)),verticies,thickness,solid);

module arches() {

skin([
       for (i=[0 : 180])

transform(translation([0,0,(i*0.5)]) * rotation([0,0,0]), waveOut(i))
]);

translate([0,0,90]) {
    skin([
       for (i=[0 : 180])

transform(translation([0,0,(i*0.5)]) * rotation([0,0,0]), waveIn(i))
]);
}
}

module arches2(verticies=192, thickness = 8, solid = false) {

yxzpath = ogeepolyPath(650, 3, 600, 600, 420, 1, 10);

//echo(yxzpath);
//echo("blah");
//echo(yxzpath[10]);

skin([
       for (i=[1 : 105])

transform(translation(yxzpath[i]) * rotation([0,0,0]),
wave(i,verticies,thickness,solid))
]);
}

module arches4(verticies=190) {

yxzpath = ogeepolyPath(650, 3, 600, 600, 420, 1, 10);

//echo(yxzpath);
//echo("blah");
//echo(yxzpath[10]);

skin([
       for (i=[1 : 90])

transform(translation([0,0,i*0.5]) * rotation([0,0,0]), wave(i,verticies))
]);
}

module arches3(start,end,verticies=190) {

skin([
       for (i=[start : end])

transform(translation([0,0,i*0.5]) * rotation([0,0,0]),
waveOut(i,verticies))
]);
}

//polygon test of roman arch or ogee poly
//they both look ok with the same number of verticies
//(10,14,18,22,26.... 6+4(n))
//but the verticies must not be in the same order
//or number because if you do "arches3(0,90,22);"
//there is a twist...
//pts = romanArch(65, 3, 70, 22);
//pts = ogeepoly(65,3,60,60,22,0.0,0);
//polygon(pts);

//pts = romanArchNc(65, 3, 70, 24);
//polygon(pts);

//90 goes from ogee to roman completely
//arches3(0,90,24);

//half the passageway
arches2(64,4);

//translate([0,0,750]) {cube([80,80,80], true); }

//a test of unioning half the passageway with a cube
//gets errors
/*
union () {
arches2(64);

translate([0,0,750]) {cube([80,80,80], true); }
}
*/

//making a full passageway, gets errors
/*
difference() {
arches2(24);
mirror([0,0,1]) {
arches2(24,true); //subtract a SOLID version
}
}
mirror([0,0,1]) {
arches2(24);
}
*/

//polygon(ogeepoly(65,3,60,60,200,0.0,0));

/*
polygon(ogeepoly(65,3,60,60,200,1,10));
polygon(romanArch(65, 3, 70, 200));
polygon(romanArch(95, 3, 40, 200));
*/

On Sat, Jun 8, 2019 at 1:45 PM adrianv avm4@cornell.edu wrote:

DanS wrote

Thanks, that helps, but I still need some tips for locating the problem.

It's tough for people to guess what might be wrong if we don't know what
your code actually does.  Are you using polyhedron?  Or are you doing
unions
and/or intersections of primitive geometry?  Try to simplify your code and
see if you can get the problem to go away.  That might give some insight
into where the problem lies.

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


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

I'll post my code below a dividing line. Basically arches2() makes half the passageway. The number of vertices MUST be a multiple of 8. A "solid" parameter (defaults to false) makes a solid version for subtraction. I confess it isn't pretty code. ----------- use <list-comprehension/skin.scad>; use <nSpline/splines.scad>; use <scad-utils/transformations.scad> use <scad-utils/lists.scad> function echoit(x) = echo(x) x; //function echoit2(y,x) = echo(y,x) x; //debug version function echoit2(y,x) = x; //debug off function echoit3(y,x) = x; //debug off //function echoit4(y,x) = echo(y,x) x; //debug version function echoit4(y,x) = x; //debug off //hyperbolic sinh cosh etc function cosh(x) = (exp(x) + exp(-x))/2; function sinh(x) = (exp(x) - exp(-x))/2; function tanh(x) = sinh(x)/cosh(x); function coth(x) = 1/tanh(x); function innerAngle(radius, thickness, angle) = atan(((radius-thickness)*sin(angle))/((radius-thickness)*cos(angle))); function partitionNum(pn,points) = (pn < (points-2)/4) ? 0 : //OUTER RIGHT (pn < (points-2)/4 + 1) ? 1 : //OUTER TOP (pn < (points-2)/2 + 1) ? 2: //OUTER LEFT (pn < (3*(points-2))/4 + 1) ? 3: //INNER LEFT (pn < (3*(points-2))/4 + 2) ? 4: //INNER TOP 5; // INNER RIGHT function subPointNum(points, pointNum, partition) = [pointNum, 1, //doesn't matter ((points-2)/2) - pointNum, pointNum - points/2, 1, //doesn't matter ((points-1) - pointNum)] [partition]; //one more point in the outer arcs one less in the inner function partitionNumNc(pn,points,solid) = (solid) ? (pn < (points)/2) ? 0 : //OUTER RIGHT (pn == (points)/2) ? 1 : //OUTER TOP 2 : (pn < (points)/4) ? 0 : //OUTER RIGHT (pn == (points)/4) ? 1 : //OUTER TOP (pn < ((points)/2)+1) ? 2: //OUTER LEFT (pn < (3*points)/4) ? 3: //INNER LEFT (pn == (3*points)/4) ? 4: //INNER TOP 5 // INNER RIGHT ; function subPointNumNc(points, pointNum, partition) = [pointNum, 1, //doesn't matter ((points)/2) - pointNum, pointNum - (points/2+1), 1, //doesn't matter ((points-1) - pointNum)] [partition]; function archXNc(radius, thickness, angle, pointNum, points, solid) = let(inner = innerAngle(radius, thickness, angle), partition = partitionNumNc(pointNum,points,solid), subPoint = subPointNumNc(points, pointNum, partition), steps = (pointNum < (points/2)) ? (((points)/4) - 1) : (((points)/4) - 2)) [radius * cos(angle/steps * pointNum) - radius * (cos(angle)), 0, -(radius * cos(angle/steps * subPoint) - radius * (cos(angle))), // PTS - 2 EXP + 1 -(((radius - thickness) * cos((angle/steps) * subPoint)) - ((radius - thickness)*cos(angle))), //PTS -2 EXP +1 0, (radius - thickness) * cos((angle/steps) * subPoint) - (radius-thickness)*cos(angle) //PTS - 2 EXP +2 ] [partition]; function archX(radius, thickness, angle, pointNum, points) = let(inner = innerAngle(radius, thickness, angle), partition = partitionNum(pointNum,points), subPoint = subPointNum(points, pointNum, partition), steps = (points-2)/4) [radius * cos(angle/steps * pointNum) - radius * (cos(angle)), 0, -(radius * cos(angle/steps * subPoint) - radius * (cos(angle))), // PTS - 2 EXP + 1 -(((radius - thickness) * cos((angle/steps) * subPoint)) - ((radius - thickness)*cos(angle))), //PTS -2 EXP +1 0, (radius - thickness) * cos((angle/steps) * subPoint) - (radius-thickness)*cos(angle) //PTS - 2 EXP +2 ] [partition]; function archY(radius, thickness, angle, pointNum, points) = let(inner = innerAngle(radius, thickness, angle), partition = partitionNum(pointNum,points), subPoint = subPointNum(points, pointNum, partition), steps = (points-2)/4) [radius * sin(angle/steps * pointNum), radius * sin(angle), (radius * sin(angle/steps * subPoint)), (radius - thickness) * sin( angle/steps * subPoint), (radius - thickness) * sin(angle), (radius - thickness) * sin((angle*subPoint)/steps) ] [partition]; function archYNc(radius, thickness, angle, pointNum, points, solid) = let(inner = innerAngle(radius, thickness, angle), partition = partitionNumNc(pointNum,points,solid), subPoint = subPointNumNc(points, pointNum, partition), steps = (pointNum < (points/2)) ? ((points)/4) - 1 : ((points)/4) - 2) [radius * sin(angle/steps * pointNum), radius * sin(angle), (radius * sin(angle/steps * subPoint)), (radius - thickness) * sin( angle/steps * subPoint), (radius - thickness) * sin(angle), (radius - thickness) * sin((angle*subPoint)/steps) ] [partition]; // This function actuall works on ugly numbers 6 + 4(n) points: 10, 14, 18, 22 ... function romanArch(radius, thickness, angle, pointCnt) = [ for (i = [0:(pointCnt-1)]) [archX(radius, thickness, angle, i, pointCnt), archY(radius, thickness, angle, i, pointCnt)] ]; //use this with a no-cap ogee as this works out to //be 4n + 4 points which meshes with 8n of a no cap ogee // 8, 12, 16, 20,.... // you will have to use ODD N values to match with // a linear progression of 8n // (4m)+ 4 = 8n for 1 on both sides 3m=2n; 5m = 3n etc // This function actuall works on ugly numbers 6 + 4(n) points: 10, 14, 18, 22 ... function romanArchNc(radius, thickness, angle, pointCnt, solid = false) = (solid) ? [ for (i = [0:(pointCnt/2 -1)]) [archXNc(radius, thickness, angle, i, pointCnt, solid), archYNc(radius, thickness, angle, i, pointCnt, solid)] ] : [ for (i = [0:(pointCnt-1)]) [archXNc(radius, thickness, angle, i, pointCnt, solid), archYNc(radius, thickness, angle, i, pointCnt, solid)] ]; //the second half is missing one point, figure it out... //romanArch(20, 1, 70, 200); //8n (if capwidth = 0); 8n + 2 otherwise function ogeepoly(width, thickness, lowerradius, upperradius, points, solid = false, capwidth = 0.0, apexangle = 45.0) = let( // Angle extended by the arcs lowerphi = 180.0 - acos((0.5*(width - capwidth) - lowerradius - thickness - upperradius * cos(0.5*apexangle)) / (lowerradius + thickness + upperradius)), upperphi = lowerphi - 0.5 * apexangle, apexhalf = 0.5 * apexangle, // Number of points per lower arc lowerpoints = echoit2("lowerpoints ",round((capwidth > 0.0) ? lowerphi*(points-4)/(8*lowerphi-4*apexangle) : lowerphi*(points-2)/(8*lowerphi-4*apexangle))), // Actual number of points in the upper arc uppertemp = echoit2("uppertemp ",round((capwidth > 0.0) ? (lowerphi-apexangle)*(points-4)/(8*lowerphi-4*apexangle) : (lowerphi-apexangle)*(points-2)/(8*lowerphi-4*apexangle))), targetpoints = echoit2("targetpoints ", (apexangle > 0.0) ? points - 5 : points - 2), upperpoints = echoit2("upperpoints ",(targetpoints - 4*(lowerpoints + uppertemp) >= -1) ? uppertemp + 1 : uppertemp), // Key horizontal coordinates. Note: w0=x1, w6=x2 w0 = 0.5*width - thickness - lowerradius, w1 = 0.5*capwidth, w2 = w0 + lowerradius * cos(lowerphi), w3 = w0 + (lowerradius + thickness) * cos(lowerphi), w4 = w0 + lowerradius, w5 = w0 + lowerradius + thickness, w6 = w0 + (lowerradius + thickness + upperradius) * cos(lowerphi), // Key vertical coordinates. Note: y1=h0=0, y2=h6 h6 = (lowerradius + thickness + upperradius) * sin(lowerphi), h5 = h6 - upperradius * sin(apexhalf), h4 = h5 - 0.5*capwidth * tan(apexhalf), h3 = h6 - (upperradius + thickness) * sqrt(1.0 - w6*w6 / ((upperradius + thickness) * (upperradius + thickness))), h2 = (lowerradius + thickness) * sin(lowerphi), h1 = lowerradius * sin(lowerphi), h0 = 0.0, height = (apexangle > 0.0) ? (h5 + 0.5*capwidth / tan(apexhalf)) : h5, // We use the same number of points for the upper inner arc, // even though it is a bit smaller angle. innertheta = acos(w6 / (upperradius + thickness)), innerphi = lowerphi - innertheta, // Lower Right Outer arc lro = echoit3("lro ",[ for (i = [0:lowerpoints-1]) [ w0 + (lowerradius + thickness) * cos(i * lowerphi / lowerpoints), h0 + (lowerradius + thickness) * sin(i * lowerphi / lowerpoints) ] ]), // Upper Right Outer arc uro = echoit3("uro ",[ for (i = [upperpoints-1:-1:0]) [ w6 - upperradius * cos(apexhalf + i * upperphi / upperpoints), h6 - upperradius * sin(apexhalf + i * upperphi / upperpoints) ] ]), // Cap cap = (capwidth > 0.0) ? [ [ w1, h5 ], [ 0, height ] ] : [], // Upper Left Outer arc ulo = echoit3("ulo ",[ for (i = [0:upperpoints-1]) [ -w6 + upperradius * cos(apexhalf + i * upperphi / upperpoints), h6 - upperradius * sin(apexhalf + i * upperphi / upperpoints) ] ]), // Lower Left Outer arc //incorrectly 4 pts //changing loop first contition to lowerpoints-1 from "lowerpoints" llo = echoit3("llo ",[ for (i = [lowerpoints-1:-1:0]) [ -w0 - (lowerradius + thickness) * cos(i * lowerphi / lowerpoints), h0 + (lowerradius + thickness) * sin(i * lowerphi / lowerpoints) ] ]), // Lower Left Inner arc lli = (solid) ? [] : [ for (i = [0:lowerpoints-1]) [ -w0 - lowerradius * cos(i * lowerphi / lowerpoints), h0 + lowerradius * sin(i * lowerphi / lowerpoints) ] ], // Upper Left Inner arc uli = (solid) ? [] : [ for (i = [upperpoints-1:-1:0]) [ -w6 + (upperradius + thickness) * cos(innertheta + i * innerphi / upperpoints), h6 - (upperradius + thickness) * sin(innertheta + i * innerphi / upperpoints) ] ], // Upper Right Inner arc uri = (solid) ? [] : [ for (i = [0:upperpoints-1]) [ w6 - (upperradius + thickness) * cos(innertheta + i * innerphi / upperpoints), h6 - (upperradius + thickness) * sin(innertheta + i * innerphi / upperpoints) ] ], // Lower Right Inner arc lri = (solid) ? [] : [ for (i = [lowerpoints-1:-1:0]) [ w0 + lowerradius * cos(i * lowerphi / lowerpoints), h0 + lowerradius * sin(i * lowerphi / lowerpoints) ] ] ) concat(lro, uro, cap, ulo, llo, lli, uli, uri, lri); function ogeepolyPath(width, thickness, lowerradius, upperradius, points, capwidth = 0.0, apexangle = 45.0) = let( // Angle extended by the arcs lowerphi = 180.0 - acos((0.5*(width - capwidth) - lowerradius - thickness - upperradius * cos(0.5*apexangle)) / (lowerradius + thickness + upperradius)), upperphi = lowerphi - 0.5 * apexangle, apexhalf = 0.5 * apexangle, // Number of points per lower arc lowerpoints = round((capwidth > 0.0) ? lowerphi*(points-4)/(8*lowerphi-4*apexangle) : lowerphi*(points-2)/(8*lowerphi-4*apexangle)), // Actual number of points in the upper arc uppertemp = round((capwidth > 0.0) ? (lowerphi-apexangle)*(points-4)/(8*lowerphi-4*apexangle) : (lowerphi-apexangle)*(points-2)/(8*lowerphi-4*apexangle)), targetpoints = (apexangle > 0.0) ? points - 5 : points - 2, upperpoints = (targetpoints - 4*(lowerpoints + uppertemp) >= -1) ? uppertemp + 1 : uppertemp, // Key horizontal coordinates. Note: w0=x1, w6=x2 w0 = 0.5*width - thickness - lowerradius, w1 = 0.5*capwidth, w2 = w0 + lowerradius * cos(lowerphi), w3 = w0 + (lowerradius + thickness) * cos(lowerphi), w4 = w0 + lowerradius, w5 = w0 + lowerradius + thickness, w6 = w0 + (lowerradius + thickness + upperradius) * cos(lowerphi), // Key vertical coordinates. Note: y1=h0=0, y2=h6 h6 = (lowerradius + thickness + upperradius) * sin(lowerphi), h5 = h6 - upperradius * sin(apexhalf), h4 = h5 - 0.5*capwidth * tan(apexhalf), h3 = h6 - (upperradius + thickness) * sqrt(1.0 - w6*w6 / ((upperradius + thickness) * (upperradius + thickness))), h2 = (lowerradius + thickness) * sin(lowerphi), h1 = lowerradius * sin(lowerphi), h0 = 0.0, height = (apexangle > 0.0) ? (h5 + 0.5*capwidth / tan(apexhalf)) : h5, // We use the same number of points for the upper inner arc, // even though it is a bit smaller angle. innertheta = acos(w6 / (upperradius + thickness)), innerphi = lowerphi - innertheta, // Lower Right Outer arc lro = [ for (i = [0:lowerpoints-1]) [ w0 + (lowerradius + thickness) * cos(i * lowerphi / lowerpoints), 0, h0 + (lowerradius + thickness) * sin(i * lowerphi / lowerpoints) ] ], // Upper Right Outer arc uro = [ for (i = [upperpoints-1:-1:0]) [ w6 - upperradius * cos(apexhalf + i * upperphi / upperpoints), 0, h6 - upperradius * sin(apexhalf + i * upperphi / upperpoints) ] ], // Cap cap = (capwidth > 0.0) ? [ [ w1, 0, h5 ], [ 0, 0, height ] ] : [], // Upper Left Outer arc ulo = [ for (i = [0:upperpoints-1]) [ -w6 + upperradius * cos(apexhalf + i * upperphi / upperpoints), 0, h6 - upperradius * sin(apexhalf + i * upperphi / upperpoints) ] ], // Lower Left Outer arc llo = [ for (i = [lowerpoints:-1:0]) [ -w0 - (lowerradius + thickness) * cos(i * lowerphi / lowerpoints), 0, h0 + (lowerradius + thickness) * sin(i * lowerphi / lowerpoints) ] ] ) concat(lro, uro, cap, ulo, llo); function stupid(i) = (i==1) ? ogeepoly(65,3,60,60,100,1,10) : romanArch(70, 3, 62, 200); function interpolateWave(A, B, s) = [for(i=[0:len(A)-1]) (sin(s))*A[s] + (cos(s))*B[s] ]; //NOT WHAT I WANT BUT A COOL SHAPE WITH WRONG POLYGON COUNT //function waveOut(i) = sin(i) * romanArch(70, 3, 62, 200) + cos(i) * ogeepoly(65,3,60,60,100,1,10); /* function waveOut(i) = abs(sin(i)) * romanArch(70, 3, 62, 200) + (1 - abs(sin(i))) * ogeepoly(65,3,60,60,200,1,10); */ function waveOut(i,verticies,thickness,solid) = abs(sin(i)) * romanArchNc(65, thickness, 70, verticies,solid) + (1 - abs(sin(i))) * ogeepoly(65,thickness,60,60,verticies,solid,0.0,0);//was 1,10 at end function waveIn(i,verticies,thickness,solid) = abs(sin(i)) * romanArchNc(95, thickness, 40, verticies,solid) + (1 - abs(sin(i))) * ogeepoly(65,thickness,60,60,verticies,solid,0.0,0);//was 1,10 at end function wave(i,verticies=200,thickness,solid) = (i < 31) ? waveOut(echoit4("<31",(i*6)),verticies,thickness,solid) : (i < 61) ? waveIn(echoit4("<61",(180-((i-30)*6))),verticies,thickness,solid) : (i < 91) ? waveOut(echoit4("<91",(i-60)*6),verticies,thickness,solid) : waveIn(echoit4("last",180-((i-90)*6)),verticies,thickness,solid); module arches() { skin([ for (i=[0 : 180]) transform(translation([0,0,(i*0.5)]) * rotation([0,0,0]), waveOut(i)) ]); translate([0,0,90]) { skin([ for (i=[0 : 180]) transform(translation([0,0,(i*0.5)]) * rotation([0,0,0]), waveIn(i)) ]); } } module arches2(verticies=192, thickness = 8, solid = false) { yxzpath = ogeepolyPath(650, 3, 600, 600, 420, 1, 10); //echo(yxzpath); //echo("blah"); //echo(yxzpath[10]); skin([ for (i=[1 : 105]) transform(translation(yxzpath[i]) * rotation([0,0,0]), wave(i,verticies,thickness,solid)) ]); } module arches4(verticies=190) { yxzpath = ogeepolyPath(650, 3, 600, 600, 420, 1, 10); //echo(yxzpath); //echo("blah"); //echo(yxzpath[10]); skin([ for (i=[1 : 90]) transform(translation([0,0,i*0.5]) * rotation([0,0,0]), wave(i,verticies)) ]); } module arches3(start,end,verticies=190) { skin([ for (i=[start : end]) transform(translation([0,0,i*0.5]) * rotation([0,0,0]), waveOut(i,verticies)) ]); } //polygon test of roman arch or ogee poly //they both look ok with the same number of verticies //(10,14,18,22,26.... 6+4(n)) //but the verticies must not be in the same order //or number because if you do "arches3(0,90,22);" //there is a twist... //pts = romanArch(65, 3, 70, 22); //pts = ogeepoly(65,3,60,60,22,0.0,0); //polygon(pts); //pts = romanArchNc(65, 3, 70, 24); //polygon(pts); //90 goes from ogee to roman completely //arches3(0,90,24); //half the passageway arches2(64,4); //translate([0,0,750]) {cube([80,80,80], true); } //a test of unioning half the passageway with a cube //gets errors /* union () { arches2(64); translate([0,0,750]) {cube([80,80,80], true); } } */ //making a full passageway, gets errors /* difference() { arches2(24); mirror([0,0,1]) { arches2(24,true); //subtract a SOLID version } } mirror([0,0,1]) { arches2(24); } */ //polygon(ogeepoly(65,3,60,60,200,0.0,0)); /* polygon(ogeepoly(65,3,60,60,200,1,10)); polygon(romanArch(65, 3, 70, 200)); polygon(romanArch(95, 3, 40, 200)); */ On Sat, Jun 8, 2019 at 1:45 PM adrianv <avm4@cornell.edu> wrote: > DanS wrote > > Thanks, that helps, but I still need some tips for locating the problem. > > It's tough for people to guess what might be wrong if we don't know what > your code actually does. Are you using polyhedron? Or are you doing > unions > and/or intersections of primitive geometry? Try to simplify your code and > see if you can get the problem to go away. That might give some insight > into where the problem lies. > > > > > > > -- > Sent from: http://forum.openscad.org/ > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
NH
nop head
Sat, Jun 8, 2019 6:01 PM

One way to visualise the error is to export the result as an STL and view
it with Netfabb studio or Meshlab. In Netfabb studio you can highlight
holes, intersections and degenerate triangles.

On Sat, 8 Jun 2019 at 18:53, Dan Shriver tabbydan@gmail.com wrote:

I'll post my code below a dividing line.

Basically arches2() makes half the passageway.  The number of vertices
MUST be a multiple of 8.  A "solid" parameter (defaults to false) makes a
solid version for subtraction.

I confess it isn't pretty code.


use <list-comprehension/skin.scad>;
use <nSpline/splines.scad>;
use <scad-utils/transformations.scad>
use <scad-utils/lists.scad>

function echoit(x) = echo(x) x;
//function echoit2(y,x) = echo(y,x) x; //debug version
function echoit2(y,x) =  x; //debug off
function echoit3(y,x) = x; //debug off
//function echoit4(y,x) = echo(y,x) x; //debug version
function echoit4(y,x) =  x; //debug off

//hyperbolic sinh cosh etc
function cosh(x) = (exp(x) + exp(-x))/2;
function sinh(x) = (exp(x) - exp(-x))/2;
function tanh(x) = sinh(x)/cosh(x);
function coth(x) = 1/tanh(x);

function innerAngle(radius, thickness, angle) =
atan(((radius-thickness)*sin(angle))/((radius-thickness)*cos(angle)));

function partitionNum(pn,points) =
(pn < (points-2)/4) ? 0 :        //OUTER RIGHT
(pn < (points-2)/4 + 1)  ? 1 :    //OUTER TOP
(pn < (points-2)/2 + 1) ? 2:      //OUTER LEFT
(pn < (3*(points-2))/4 + 1) ? 3:  //INNER LEFT
(pn < (3*(points-2))/4 + 2) ? 4:  //INNER TOP
5;                                // INNER RIGHT

function subPointNum(points, pointNum, partition) =
[pointNum,
1, //doesn't matter
((points-2)/2) - pointNum,
pointNum - points/2,
1, //doesn't matter
((points-1) - pointNum)]
[partition];

//one more point in the outer arcs one less in the inner
function partitionNumNc(pn,points,solid) = (solid) ? (pn < (points)/2) ? 0
:        //OUTER RIGHT
(pn == (points)/2)  ? 1 :    //OUTER TOP
2 :
(pn < (points)/4) ? 0 :        //OUTER RIGHT
(pn == (points)/4)  ? 1 :    //OUTER TOP
(pn < ((points)/2)+1) ? 2:      //OUTER LEFT
(pn < (3points)/4) ? 3:  //INNER LEFT
(pn == (3
points)/4) ? 4:  //INNER TOP
5                                // INNER RIGHT
;

function subPointNumNc(points, pointNum, partition) =
[pointNum,
1, //doesn't matter
((points)/2) - pointNum,
pointNum - (points/2+1),
1, //doesn't matter
((points-1) - pointNum)]
[partition];

function archXNc(radius, thickness, angle, pointNum, points, solid) =
let(inner = innerAngle(radius, thickness, angle),
partition = partitionNumNc(pointNum,points,solid),
subPoint = subPointNumNc(points, pointNum, partition),
steps = (pointNum < (points/2)) ? (((points)/4) - 1) : (((points)/4) -
2))
[radius * cos(angle/steps * pointNum) - radius * (cos(angle)),
0,
-(radius * cos(angle/steps * subPoint) - radius * (cos(angle))), //
PTS - 2 EXP + 1
-(((radius - thickness) * cos((angle/steps) *  subPoint)) - ((radius -
thickness)*cos(angle))), //PTS -2  EXP +1
0,
(radius - thickness) * cos((angle/steps) *  subPoint) -
(radius-thickness)*cos(angle) //PTS - 2 EXP +2
]
[partition];

function archX(radius, thickness, angle, pointNum, points) = let(inner =
innerAngle(radius, thickness, angle),
partition = partitionNum(pointNum,points),
subPoint = subPointNum(points, pointNum, partition),
steps = (points-2)/4)
[radius * cos(angle/steps * pointNum) - radius * (cos(angle)),
0,
-(radius * cos(angle/steps * subPoint) - radius * (cos(angle))), //
PTS - 2 EXP + 1
-(((radius - thickness) * cos((angle/steps) *  subPoint)) - ((radius -
thickness)*cos(angle))), //PTS -2  EXP +1
0,
(radius - thickness) * cos((angle/steps) *  subPoint) -
(radius-thickness)*cos(angle) //PTS - 2 EXP +2
]
[partition];

function archY(radius, thickness, angle, pointNum, points) = let(inner =
innerAngle(radius, thickness, angle),
partition = partitionNum(pointNum,points),
subPoint = subPointNum(points, pointNum, partition),
steps = (points-2)/4)
[radius * sin(angle/steps * pointNum),
radius * sin(angle),
(radius * sin(angle/steps * subPoint)),
(radius - thickness) * sin( angle/steps * subPoint),
(radius - thickness) * sin(angle),
(radius - thickness) * sin((angle*subPoint)/steps)
]
[partition];

function archYNc(radius, thickness, angle, pointNum, points, solid) =
let(inner = innerAngle(radius, thickness, angle),
partition = partitionNumNc(pointNum,points,solid),
subPoint = subPointNumNc(points, pointNum, partition),
steps = (pointNum < (points/2)) ? ((points)/4) - 1 : ((points)/4) - 2)
[radius * sin(angle/steps * pointNum),
radius * sin(angle),
(radius * sin(angle/steps * subPoint)),
(radius - thickness) * sin( angle/steps * subPoint),
(radius - thickness) * sin(angle),
(radius - thickness) * sin((angle*subPoint)/steps)
]
[partition];

// This function actuall works on ugly numbers 6 + 4(n) points: 10, 14,
18, 22 ...
function romanArch(radius, thickness, angle, pointCnt)
= [ for (i = [0:(pointCnt-1)]) [archX(radius, thickness, angle, i,
pointCnt), archY(radius, thickness, angle, i, pointCnt)] ];

//use this with a no-cap ogee as this works out to
//be 4n +  4 points which meshes with 8n of a no cap ogee
// 8, 12, 16, 20,....
// you will have to use ODD N values to match with
// a linear progression of 8n
// (4m)+ 4 = 8n for 1 on both sides 3m=2n; 5m = 3n etc
// This function actuall works on ugly numbers 6 + 4(n) points: 10, 14,
18, 22 ...
function romanArchNc(radius, thickness, angle, pointCnt, solid = false)
= (solid) ? [ for (i = [0:(pointCnt/2 -1)]) [archXNc(radius, thickness,
angle, i, pointCnt, solid), archYNc(radius, thickness, angle, i, pointCnt,
solid)] ] : [ for (i = [0:(pointCnt-1)]) [archXNc(radius, thickness, angle,
i, pointCnt, solid), archYNc(radius, thickness, angle, i, pointCnt, solid)]
];

//the second half is missing one point, figure it out...
//romanArch(20, 1, 70, 200);

//8n (if capwidth = 0); 8n + 2 otherwise
function ogeepoly(width, thickness, lowerradius, upperradius, points,
solid = false, capwidth = 0.0, apexangle = 45.0) =
let(
// Angle extended by the arcs
lowerphi = 180.0 - acos((0.5*(width - capwidth) - lowerradius -
thickness - upperradius * cos(0.5*apexangle)) / (lowerradius + thickness +
upperradius)),
upperphi = lowerphi - 0.5 * apexangle,
apexhalf = 0.5 * apexangle,

 // Number of points per lower arc
 lowerpoints = echoit2("lowerpoints ",round((capwidth > 0.0) ?

lowerphi*(points-4)/(8lowerphi-4apexangle) :
lowerphi*(points-2)/(8lowerphi-4apexangle))),

 // Actual number of points in the upper arc
 uppertemp = echoit2("uppertemp ",round((capwidth > 0.0) ?

(lowerphi-apexangle)(points-4)/(8lowerphi-4apexangle) :
(lowerphi-apexangle)
(points-2)/(8lowerphi-4apexangle))),
targetpoints = echoit2("targetpoints ", (apexangle > 0.0) ? points - 5
: points - 2),
upperpoints = echoit2("upperpoints ",(targetpoints - 4*(lowerpoints +
uppertemp) >= -1) ? uppertemp + 1 : uppertemp),

 // Key horizontal coordinates. Note: w0=x1, w6=x2
 w0 = 0.5*width - thickness - lowerradius,
 w1 = 0.5*capwidth,
 w2 = w0 + lowerradius * cos(lowerphi),
 w3 = w0 + (lowerradius + thickness) * cos(lowerphi),
 w4 = w0 + lowerradius,
 w5 = w0 + lowerradius + thickness,
 w6 = w0 + (lowerradius + thickness + upperradius) * cos(lowerphi),

 // Key vertical coordinates. Note: y1=h0=0, y2=h6
 h6 = (lowerradius + thickness + upperradius) * sin(lowerphi),
 h5 = h6 - upperradius * sin(apexhalf),
 h4 = h5 - 0.5*capwidth * tan(apexhalf),
 h3 = h6 - (upperradius + thickness) * sqrt(1.0 - w6*w6 / ((upperradius
  • thickness) * (upperradius + thickness))),
    h2 = (lowerradius + thickness) * sin(lowerphi),
    h1 = lowerradius * sin(lowerphi),
    h0 = 0.0,
    height = (apexangle > 0.0) ? (h5 + 0.5*capwidth / tan(apexhalf)) : h5,

    // We use the same number of points for the upper inner arc,
    // even though it is a bit smaller angle.
    innertheta = acos(w6 / (upperradius + thickness)),
    innerphi = lowerphi - innertheta,

    // Lower Right Outer arc
    lro = echoit3("lro ",[ for (i = [0:lowerpoints-1]) [ w0 + (lowerradius

  • thickness) * cos(i * lowerphi / lowerpoints), h0 + (lowerradius +
    thickness) * sin(i * lowerphi / lowerpoints) ] ]),
    // Upper Right Outer arc
    uro = echoit3("uro ",[ for (i = [upperpoints-1:-1:0]) [ w6 -
    upperradius * cos(apexhalf + i * upperphi / upperpoints), h6 - upperradius

  • sin(apexhalf + i * upperphi / upperpoints) ] ]),
    // Cap
    cap = (capwidth > 0.0) ? [ [ w1, h5 ], [ 0, height ] ] : [],
    // Upper Left Outer arc
    ulo = echoit3("ulo ",[ for (i = [0:upperpoints-1]) [ -w6 + upperradius
  • cos(apexhalf + i * upperphi / upperpoints), h6 - upperradius *
    sin(apexhalf + i * upperphi / upperpoints) ] ]),
    // Lower Left Outer arc
    //incorrectly 4 pts
    //changing loop first contition to lowerpoints-1 from "lowerpoints"
    llo = echoit3("llo ",[ for (i = [lowerpoints-1:-1:0]) [ -w0 -
    (lowerradius + thickness) * cos(i * lowerphi / lowerpoints), h0 +
    (lowerradius + thickness) * sin(i * lowerphi / lowerpoints) ] ]),
    // Lower Left Inner arc
    lli = (solid) ? [] : [ for (i = [0:lowerpoints-1]) [ -w0 - lowerradius
  • cos(i * lowerphi / lowerpoints), h0 + lowerradius * sin(i * lowerphi /
    lowerpoints) ] ],
    // Upper Left Inner arc
    uli = (solid) ? [] : [ for (i = [upperpoints-1:-1:0]) [ -w6 +
    (upperradius + thickness) * cos(innertheta + i * innerphi / upperpoints),
    h6 - (upperradius + thickness) * sin(innertheta + i * innerphi /
    upperpoints) ] ],
    // Upper Right Inner arc
    uri = (solid) ? [] : [ for (i = [0:upperpoints-1]) [ w6 - (upperradius
  • thickness) * cos(innertheta + i * innerphi / upperpoints), h6 -
    (upperradius + thickness) * sin(innertheta + i * innerphi / upperpoints) ]
    ],
    // Lower Right Inner arc
    lri = (solid) ? [] : [ for (i = [lowerpoints-1:-1:0]) [ w0  +
    lowerradius * cos(i * lowerphi / lowerpoints), h0 + lowerradius * sin(i *
    lowerphi / lowerpoints) ] ]
    )
    concat(lro, uro, cap, ulo, llo, lli, uli, uri, lri);

function ogeepolyPath(width, thickness, lowerradius, upperradius, points,
capwidth = 0.0, apexangle = 45.0) =
let(
// Angle extended by the arcs
lowerphi = 180.0 - acos((0.5*(width - capwidth) - lowerradius -
thickness - upperradius * cos(0.5*apexangle)) / (lowerradius + thickness +
upperradius)),
upperphi = lowerphi - 0.5 * apexangle,
apexhalf = 0.5 * apexangle,

 // Number of points per lower arc
 lowerpoints = round((capwidth > 0.0) ?

lowerphi*(points-4)/(8lowerphi-4apexangle) :
lowerphi*(points-2)/(8lowerphi-4apexangle)),

 // Actual number of points in the upper arc
 uppertemp = round((capwidth > 0.0) ?

(lowerphi-apexangle)(points-4)/(8lowerphi-4apexangle) :
(lowerphi-apexangle)
(points-2)/(8lowerphi-4apexangle)),
targetpoints = (apexangle > 0.0) ? points - 5 : points - 2,
upperpoints = (targetpoints - 4*(lowerpoints + uppertemp) >= -1) ?
uppertemp + 1 : uppertemp,

 // Key horizontal coordinates. Note: w0=x1, w6=x2
 w0 = 0.5*width - thickness - lowerradius,
 w1 = 0.5*capwidth,
 w2 = w0 + lowerradius * cos(lowerphi),
 w3 = w0 + (lowerradius + thickness) * cos(lowerphi),
 w4 = w0 + lowerradius,
 w5 = w0 + lowerradius + thickness,
 w6 = w0 + (lowerradius + thickness + upperradius) * cos(lowerphi),

 // Key vertical coordinates. Note: y1=h0=0, y2=h6
 h6 = (lowerradius + thickness + upperradius) * sin(lowerphi),
 h5 = h6 - upperradius * sin(apexhalf),
 h4 = h5 - 0.5*capwidth * tan(apexhalf),
 h3 = h6 - (upperradius + thickness) * sqrt(1.0 - w6*w6 / ((upperradius
  • thickness) * (upperradius + thickness))),
    h2 = (lowerradius + thickness) * sin(lowerphi),
    h1 = lowerradius * sin(lowerphi),
    h0 = 0.0,
    height = (apexangle > 0.0) ? (h5 + 0.5*capwidth / tan(apexhalf)) : h5,

    // We use the same number of points for the upper inner arc,
    // even though it is a bit smaller angle.
    innertheta = acos(w6 / (upperradius + thickness)),
    innerphi = lowerphi - innertheta,

    // Lower Right Outer arc
    lro = [ for (i = [0:lowerpoints-1]) [ w0 + (lowerradius + thickness) *
    cos(i * lowerphi / lowerpoints), 0, h0 + (lowerradius + thickness) * sin(i

  • lowerphi / lowerpoints) ] ],
    // Upper Right Outer arc
    uro = [ for (i = [upperpoints-1:-1:0]) [ w6 - upperradius *
    cos(apexhalf + i * upperphi / upperpoints), 0, h6 - upperradius *
    sin(apexhalf + i * upperphi / upperpoints) ] ],
    // Cap
    cap = (capwidth > 0.0) ? [ [ w1, 0, h5 ], [ 0, 0, height ] ] : [],
    // Upper Left Outer arc
    ulo = [ for (i = [0:upperpoints-1]) [ -w6 + upperradius * cos(apexhalf
  • i * upperphi / upperpoints), 0, h6 - upperradius * sin(apexhalf + i *
    upperphi / upperpoints) ] ],
    // Lower Left Outer arc
    llo = [ for (i = [lowerpoints:-1:0]) [ -w0 - (lowerradius + thickness)
  • cos(i * lowerphi / lowerpoints), 0, h0 + (lowerradius + thickness) *
    sin(i * lowerphi / lowerpoints) ] ]
    )
    concat(lro, uro, cap, ulo, llo);

function stupid(i) = (i==1) ? ogeepoly(65,3,60,60,100,1,10) :
romanArch(70, 3, 62, 200);

function interpolateWave(A, B, s) = [for(i=[0:len(A)-1]) (sin(s))*A[s] +
(cos(s))*B[s] ];

//NOT WHAT I WANT BUT A COOL SHAPE WITH WRONG POLYGON COUNT
//function waveOut(i) = sin(i) * romanArch(70, 3, 62, 200) + cos(i) *
ogeepoly(65,3,60,60,100,1,10);

/*
function waveOut(i) = abs(sin(i)) * romanArch(70, 3, 62, 200) + (1 -
abs(sin(i))) * ogeepoly(65,3,60,60,200,1,10);
*/

function waveOut(i,verticies,thickness,solid) = abs(sin(i)) *
romanArchNc(65, thickness, 70, verticies,solid) + (1 - abs(sin(i))) *
ogeepoly(65,thickness,60,60,verticies,solid,0.0,0);//was 1,10 at end

function waveIn(i,verticies,thickness,solid) = abs(sin(i)) *
romanArchNc(95, thickness, 40, verticies,solid) + (1 - abs(sin(i))) *
ogeepoly(65,thickness,60,60,verticies,solid,0.0,0);//was 1,10 at end

function wave(i,verticies=200,thickness,solid) = (i < 31) ?
waveOut(echoit4("<31",(i*6)),verticies,thickness,solid) :
(i < 61) ?
waveIn(echoit4("<61",(180-((i-30)*6))),verticies,thickness,solid) :
(i < 91) ?
waveOut(echoit4("<91",(i-60)*6),verticies,thickness,solid) :

waveIn(echoit4("last",180-((i-90)*6)),verticies,thickness,solid);

module arches() {

 skin([
        for (i=[0 : 180])

transform(translation([0,0,(i*0.5)]) * rotation([0,0,0]), waveOut(i))
]);

 translate([0,0,90]) {
     skin([
        for (i=[0 : 180])

transform(translation([0,0,(i*0.5)]) * rotation([0,0,0]), waveIn(i))
]);
}
}

module arches2(verticies=192, thickness = 8, solid = false) {

 yxzpath = ogeepolyPath(650, 3, 600, 600, 420, 1, 10);

 //echo(yxzpath);
 //echo("blah");
 //echo(yxzpath[10]);

 skin([
        for (i=[1 : 105])

transform(translation(yxzpath[i]) * rotation([0,0,0]),
wave(i,verticies,thickness,solid))
]);
}

module arches4(verticies=190) {

 yxzpath = ogeepolyPath(650, 3, 600, 600, 420, 1, 10);

 //echo(yxzpath);
 //echo("blah");
 //echo(yxzpath[10]);

 skin([
        for (i=[1 : 90])

transform(translation([0,0,i*0.5]) * rotation([0,0,0]), wave(i,verticies))
]);
}

module arches3(start,end,verticies=190) {

 skin([
        for (i=[start : end])

transform(translation([0,0,i*0.5]) * rotation([0,0,0]),
waveOut(i,verticies))
]);
}

//polygon test of roman arch or ogee poly
//they both look ok with the same number of verticies
//(10,14,18,22,26.... 6+4(n))
//but the verticies must not be in the same order
//or number because if you do "arches3(0,90,22);"
//there is a twist...
//pts = romanArch(65, 3, 70, 22);
//pts = ogeepoly(65,3,60,60,22,0.0,0);
//polygon(pts);

//pts = romanArchNc(65, 3, 70, 24);
//polygon(pts);

//90 goes from ogee to roman completely
//arches3(0,90,24);

//half the passageway
arches2(64,4);

//translate([0,0,750]) {cube([80,80,80], true); }

//a test of unioning half the passageway with a cube
//gets errors
/*
union () {
arches2(64);

translate([0,0,750]) {cube([80,80,80], true); }
}
*/

//making a full passageway, gets errors
/*
difference() {
arches2(24);
mirror([0,0,1]) {
arches2(24,true); //subtract a SOLID version
}
}
mirror([0,0,1]) {
arches2(24);
}
*/

//polygon(ogeepoly(65,3,60,60,200,0.0,0));

/*
polygon(ogeepoly(65,3,60,60,200,1,10));
polygon(romanArch(65, 3, 70, 200));
polygon(romanArch(95, 3, 40, 200));
*/

On Sat, Jun 8, 2019 at 1:45 PM adrianv avm4@cornell.edu wrote:

DanS wrote

Thanks, that helps, but I still need some tips for locating the problem.

It's tough for people to guess what might be wrong if we don't know what
your code actually does.  Are you using polyhedron?  Or are you doing
unions
and/or intersections of primitive geometry?  Try to simplify your code and
see if you can get the problem to go away.  That might give some insight
into where the problem lies.

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


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

One way to visualise the error is to export the result as an STL and view it with Netfabb studio or Meshlab. In Netfabb studio you can highlight holes, intersections and degenerate triangles. On Sat, 8 Jun 2019 at 18:53, Dan Shriver <tabbydan@gmail.com> wrote: > I'll post my code below a dividing line. > > Basically arches2() makes half the passageway. The number of vertices > MUST be a multiple of 8. A "solid" parameter (defaults to false) makes a > solid version for subtraction. > > I confess it isn't pretty code. > > ----------- > use <list-comprehension/skin.scad>; > use <nSpline/splines.scad>; > use <scad-utils/transformations.scad> > use <scad-utils/lists.scad> > > > function echoit(x) = echo(x) x; > //function echoit2(y,x) = echo(y,x) x; //debug version > function echoit2(y,x) = x; //debug off > function echoit3(y,x) = x; //debug off > //function echoit4(y,x) = echo(y,x) x; //debug version > function echoit4(y,x) = x; //debug off > > //hyperbolic sinh cosh etc > function cosh(x) = (exp(x) + exp(-x))/2; > function sinh(x) = (exp(x) - exp(-x))/2; > function tanh(x) = sinh(x)/cosh(x); > function coth(x) = 1/tanh(x); > > function innerAngle(radius, thickness, angle) = > atan(((radius-thickness)*sin(angle))/((radius-thickness)*cos(angle))); > > function partitionNum(pn,points) = > (pn < (points-2)/4) ? 0 : //OUTER RIGHT > (pn < (points-2)/4 + 1) ? 1 : //OUTER TOP > (pn < (points-2)/2 + 1) ? 2: //OUTER LEFT > (pn < (3*(points-2))/4 + 1) ? 3: //INNER LEFT > (pn < (3*(points-2))/4 + 2) ? 4: //INNER TOP > 5; // INNER RIGHT > > function subPointNum(points, pointNum, partition) = > [pointNum, > 1, //doesn't matter > ((points-2)/2) - pointNum, > pointNum - points/2, > 1, //doesn't matter > ((points-1) - pointNum)] > [partition]; > > > //one more point in the outer arcs one less in the inner > function partitionNumNc(pn,points,solid) = (solid) ? (pn < (points)/2) ? 0 > : //OUTER RIGHT > (pn == (points)/2) ? 1 : //OUTER TOP > 2 : > (pn < (points)/4) ? 0 : //OUTER RIGHT > (pn == (points)/4) ? 1 : //OUTER TOP > (pn < ((points)/2)+1) ? 2: //OUTER LEFT > (pn < (3*points)/4) ? 3: //INNER LEFT > (pn == (3*points)/4) ? 4: //INNER TOP > 5 // INNER RIGHT > ; > > function subPointNumNc(points, pointNum, partition) = > [pointNum, > 1, //doesn't matter > ((points)/2) - pointNum, > pointNum - (points/2+1), > 1, //doesn't matter > ((points-1) - pointNum)] > [partition]; > > > function archXNc(radius, thickness, angle, pointNum, points, solid) = > let(inner = innerAngle(radius, thickness, angle), > partition = partitionNumNc(pointNum,points,solid), > subPoint = subPointNumNc(points, pointNum, partition), > steps = (pointNum < (points/2)) ? (((points)/4) - 1) : (((points)/4) - > 2)) > [radius * cos(angle/steps * pointNum) - radius * (cos(angle)), > 0, > -(radius * cos(angle/steps * subPoint) - radius * (cos(angle))), // > PTS - 2 EXP + 1 > -(((radius - thickness) * cos((angle/steps) * subPoint)) - ((radius - > thickness)*cos(angle))), //PTS -2 EXP +1 > 0, > (radius - thickness) * cos((angle/steps) * subPoint) - > (radius-thickness)*cos(angle) //PTS - 2 EXP +2 > ] > [partition]; > > function archX(radius, thickness, angle, pointNum, points) = let(inner = > innerAngle(radius, thickness, angle), > partition = partitionNum(pointNum,points), > subPoint = subPointNum(points, pointNum, partition), > steps = (points-2)/4) > [radius * cos(angle/steps * pointNum) - radius * (cos(angle)), > 0, > -(radius * cos(angle/steps * subPoint) - radius * (cos(angle))), // > PTS - 2 EXP + 1 > -(((radius - thickness) * cos((angle/steps) * subPoint)) - ((radius - > thickness)*cos(angle))), //PTS -2 EXP +1 > 0, > (radius - thickness) * cos((angle/steps) * subPoint) - > (radius-thickness)*cos(angle) //PTS - 2 EXP +2 > ] > [partition]; > > > function archY(radius, thickness, angle, pointNum, points) = let(inner = > innerAngle(radius, thickness, angle), > partition = partitionNum(pointNum,points), > subPoint = subPointNum(points, pointNum, partition), > steps = (points-2)/4) > [radius * sin(angle/steps * pointNum), > radius * sin(angle), > (radius * sin(angle/steps * subPoint)), > (radius - thickness) * sin( angle/steps * subPoint), > (radius - thickness) * sin(angle), > (radius - thickness) * sin((angle*subPoint)/steps) > ] > [partition]; > > > function archYNc(radius, thickness, angle, pointNum, points, solid) = > let(inner = innerAngle(radius, thickness, angle), > partition = partitionNumNc(pointNum,points,solid), > subPoint = subPointNumNc(points, pointNum, partition), > steps = (pointNum < (points/2)) ? ((points)/4) - 1 : ((points)/4) - 2) > [radius * sin(angle/steps * pointNum), > radius * sin(angle), > (radius * sin(angle/steps * subPoint)), > (radius - thickness) * sin( angle/steps * subPoint), > (radius - thickness) * sin(angle), > (radius - thickness) * sin((angle*subPoint)/steps) > ] > [partition]; > > // This function actuall works on ugly numbers 6 + 4(n) points: 10, 14, > 18, 22 ... > function romanArch(radius, thickness, angle, pointCnt) > = [ for (i = [0:(pointCnt-1)]) [archX(radius, thickness, angle, i, > pointCnt), archY(radius, thickness, angle, i, pointCnt)] ]; > > //use this with a no-cap ogee as this works out to > //be 4n + 4 points which meshes with 8n of a no cap ogee > // 8, 12, 16, 20,.... > // you will have to use ODD N values to match with > // a linear progression of 8n > // (4m)+ 4 = 8n for 1 on both sides 3m=2n; 5m = 3n etc > // This function actuall works on ugly numbers 6 + 4(n) points: 10, 14, > 18, 22 ... > function romanArchNc(radius, thickness, angle, pointCnt, solid = false) > = (solid) ? [ for (i = [0:(pointCnt/2 -1)]) [archXNc(radius, thickness, > angle, i, pointCnt, solid), archYNc(radius, thickness, angle, i, pointCnt, > solid)] ] : [ for (i = [0:(pointCnt-1)]) [archXNc(radius, thickness, angle, > i, pointCnt, solid), archYNc(radius, thickness, angle, i, pointCnt, solid)] > ]; > > > > //the second half is missing one point, figure it out... > //romanArch(20, 1, 70, 200); > > > > //8n (if capwidth = 0); 8n + 2 otherwise > function ogeepoly(width, thickness, lowerradius, upperradius, points, > solid = false, capwidth = 0.0, apexangle = 45.0) = > let( > // Angle extended by the arcs > lowerphi = 180.0 - acos((0.5*(width - capwidth) - lowerradius - > thickness - upperradius * cos(0.5*apexangle)) / (lowerradius + thickness + > upperradius)), > upperphi = lowerphi - 0.5 * apexangle, > apexhalf = 0.5 * apexangle, > > // Number of points per lower arc > lowerpoints = echoit2("lowerpoints ",round((capwidth > 0.0) ? > lowerphi*(points-4)/(8*lowerphi-4*apexangle) : > lowerphi*(points-2)/(8*lowerphi-4*apexangle))), > > // Actual number of points in the upper arc > uppertemp = echoit2("uppertemp ",round((capwidth > 0.0) ? > (lowerphi-apexangle)*(points-4)/(8*lowerphi-4*apexangle) : > (lowerphi-apexangle)*(points-2)/(8*lowerphi-4*apexangle))), > targetpoints = echoit2("targetpoints ", (apexangle > 0.0) ? points - 5 > : points - 2), > upperpoints = echoit2("upperpoints ",(targetpoints - 4*(lowerpoints + > uppertemp) >= -1) ? uppertemp + 1 : uppertemp), > > // Key horizontal coordinates. Note: w0=x1, w6=x2 > w0 = 0.5*width - thickness - lowerradius, > w1 = 0.5*capwidth, > w2 = w0 + lowerradius * cos(lowerphi), > w3 = w0 + (lowerradius + thickness) * cos(lowerphi), > w4 = w0 + lowerradius, > w5 = w0 + lowerradius + thickness, > w6 = w0 + (lowerradius + thickness + upperradius) * cos(lowerphi), > > // Key vertical coordinates. Note: y1=h0=0, y2=h6 > h6 = (lowerradius + thickness + upperradius) * sin(lowerphi), > h5 = h6 - upperradius * sin(apexhalf), > h4 = h5 - 0.5*capwidth * tan(apexhalf), > h3 = h6 - (upperradius + thickness) * sqrt(1.0 - w6*w6 / ((upperradius > + thickness) * (upperradius + thickness))), > h2 = (lowerradius + thickness) * sin(lowerphi), > h1 = lowerradius * sin(lowerphi), > h0 = 0.0, > height = (apexangle > 0.0) ? (h5 + 0.5*capwidth / tan(apexhalf)) : h5, > > // We use the same number of points for the upper inner arc, > // even though it is a bit smaller angle. > innertheta = acos(w6 / (upperradius + thickness)), > innerphi = lowerphi - innertheta, > > // Lower Right Outer arc > lro = echoit3("lro ",[ for (i = [0:lowerpoints-1]) [ w0 + (lowerradius > + thickness) * cos(i * lowerphi / lowerpoints), h0 + (lowerradius + > thickness) * sin(i * lowerphi / lowerpoints) ] ]), > // Upper Right Outer arc > uro = echoit3("uro ",[ for (i = [upperpoints-1:-1:0]) [ w6 - > upperradius * cos(apexhalf + i * upperphi / upperpoints), h6 - upperradius > * sin(apexhalf + i * upperphi / upperpoints) ] ]), > // Cap > cap = (capwidth > 0.0) ? [ [ w1, h5 ], [ 0, height ] ] : [], > // Upper Left Outer arc > ulo = echoit3("ulo ",[ for (i = [0:upperpoints-1]) [ -w6 + upperradius > * cos(apexhalf + i * upperphi / upperpoints), h6 - upperradius * > sin(apexhalf + i * upperphi / upperpoints) ] ]), > // Lower Left Outer arc > //incorrectly 4 pts > //changing loop first contition to lowerpoints-1 from "lowerpoints" > llo = echoit3("llo ",[ for (i = [lowerpoints-1:-1:0]) [ -w0 - > (lowerradius + thickness) * cos(i * lowerphi / lowerpoints), h0 + > (lowerradius + thickness) * sin(i * lowerphi / lowerpoints) ] ]), > // Lower Left Inner arc > lli = (solid) ? [] : [ for (i = [0:lowerpoints-1]) [ -w0 - lowerradius > * cos(i * lowerphi / lowerpoints), h0 + lowerradius * sin(i * lowerphi / > lowerpoints) ] ], > // Upper Left Inner arc > uli = (solid) ? [] : [ for (i = [upperpoints-1:-1:0]) [ -w6 + > (upperradius + thickness) * cos(innertheta + i * innerphi / upperpoints), > h6 - (upperradius + thickness) * sin(innertheta + i * innerphi / > upperpoints) ] ], > // Upper Right Inner arc > uri = (solid) ? [] : [ for (i = [0:upperpoints-1]) [ w6 - (upperradius > + thickness) * cos(innertheta + i * innerphi / upperpoints), h6 - > (upperradius + thickness) * sin(innertheta + i * innerphi / upperpoints) ] > ], > // Lower Right Inner arc > lri = (solid) ? [] : [ for (i = [lowerpoints-1:-1:0]) [ w0 + > lowerradius * cos(i * lowerphi / lowerpoints), h0 + lowerradius * sin(i * > lowerphi / lowerpoints) ] ] > ) > concat(lro, uro, cap, ulo, llo, lli, uli, uri, lri); > > function ogeepolyPath(width, thickness, lowerradius, upperradius, points, > capwidth = 0.0, apexangle = 45.0) = > let( > // Angle extended by the arcs > lowerphi = 180.0 - acos((0.5*(width - capwidth) - lowerradius - > thickness - upperradius * cos(0.5*apexangle)) / (lowerradius + thickness + > upperradius)), > upperphi = lowerphi - 0.5 * apexangle, > apexhalf = 0.5 * apexangle, > > // Number of points per lower arc > lowerpoints = round((capwidth > 0.0) ? > lowerphi*(points-4)/(8*lowerphi-4*apexangle) : > lowerphi*(points-2)/(8*lowerphi-4*apexangle)), > > // Actual number of points in the upper arc > uppertemp = round((capwidth > 0.0) ? > (lowerphi-apexangle)*(points-4)/(8*lowerphi-4*apexangle) : > (lowerphi-apexangle)*(points-2)/(8*lowerphi-4*apexangle)), > targetpoints = (apexangle > 0.0) ? points - 5 : points - 2, > upperpoints = (targetpoints - 4*(lowerpoints + uppertemp) >= -1) ? > uppertemp + 1 : uppertemp, > > // Key horizontal coordinates. Note: w0=x1, w6=x2 > w0 = 0.5*width - thickness - lowerradius, > w1 = 0.5*capwidth, > w2 = w0 + lowerradius * cos(lowerphi), > w3 = w0 + (lowerradius + thickness) * cos(lowerphi), > w4 = w0 + lowerradius, > w5 = w0 + lowerradius + thickness, > w6 = w0 + (lowerradius + thickness + upperradius) * cos(lowerphi), > > // Key vertical coordinates. Note: y1=h0=0, y2=h6 > h6 = (lowerradius + thickness + upperradius) * sin(lowerphi), > h5 = h6 - upperradius * sin(apexhalf), > h4 = h5 - 0.5*capwidth * tan(apexhalf), > h3 = h6 - (upperradius + thickness) * sqrt(1.0 - w6*w6 / ((upperradius > + thickness) * (upperradius + thickness))), > h2 = (lowerradius + thickness) * sin(lowerphi), > h1 = lowerradius * sin(lowerphi), > h0 = 0.0, > height = (apexangle > 0.0) ? (h5 + 0.5*capwidth / tan(apexhalf)) : h5, > > // We use the same number of points for the upper inner arc, > // even though it is a bit smaller angle. > innertheta = acos(w6 / (upperradius + thickness)), > innerphi = lowerphi - innertheta, > > // Lower Right Outer arc > lro = [ for (i = [0:lowerpoints-1]) [ w0 + (lowerradius + thickness) * > cos(i * lowerphi / lowerpoints), 0, h0 + (lowerradius + thickness) * sin(i > * lowerphi / lowerpoints) ] ], > // Upper Right Outer arc > uro = [ for (i = [upperpoints-1:-1:0]) [ w6 - upperradius * > cos(apexhalf + i * upperphi / upperpoints), 0, h6 - upperradius * > sin(apexhalf + i * upperphi / upperpoints) ] ], > // Cap > cap = (capwidth > 0.0) ? [ [ w1, 0, h5 ], [ 0, 0, height ] ] : [], > // Upper Left Outer arc > ulo = [ for (i = [0:upperpoints-1]) [ -w6 + upperradius * cos(apexhalf > + i * upperphi / upperpoints), 0, h6 - upperradius * sin(apexhalf + i * > upperphi / upperpoints) ] ], > // Lower Left Outer arc > llo = [ for (i = [lowerpoints:-1:0]) [ -w0 - (lowerradius + thickness) > * cos(i * lowerphi / lowerpoints), 0, h0 + (lowerradius + thickness) * > sin(i * lowerphi / lowerpoints) ] ] > ) > concat(lro, uro, cap, ulo, llo); > > function stupid(i) = (i==1) ? ogeepoly(65,3,60,60,100,1,10) : > romanArch(70, 3, 62, 200); > > function interpolateWave(A, B, s) = [for(i=[0:len(A)-1]) (sin(s))*A[s] + > (cos(s))*B[s] ]; > > > //NOT WHAT I WANT BUT A COOL SHAPE WITH WRONG POLYGON COUNT > //function waveOut(i) = sin(i) * romanArch(70, 3, 62, 200) + cos(i) * > ogeepoly(65,3,60,60,100,1,10); > > /* > function waveOut(i) = abs(sin(i)) * romanArch(70, 3, 62, 200) + (1 - > abs(sin(i))) * ogeepoly(65,3,60,60,200,1,10); > */ > > > function waveOut(i,verticies,thickness,solid) = abs(sin(i)) * > romanArchNc(65, thickness, 70, verticies,solid) + (1 - abs(sin(i))) * > ogeepoly(65,thickness,60,60,verticies,solid,0.0,0);//was 1,10 at end > > > function waveIn(i,verticies,thickness,solid) = abs(sin(i)) * > romanArchNc(95, thickness, 40, verticies,solid) + (1 - abs(sin(i))) * > ogeepoly(65,thickness,60,60,verticies,solid,0.0,0);//was 1,10 at end > > > function wave(i,verticies=200,thickness,solid) = (i < 31) ? > waveOut(echoit4("<31",(i*6)),verticies,thickness,solid) : > (i < 61) ? > waveIn(echoit4("<61",(180-((i-30)*6))),verticies,thickness,solid) : > (i < 91) ? > waveOut(echoit4("<91",(i-60)*6),verticies,thickness,solid) : > > waveIn(echoit4("last",180-((i-90)*6)),verticies,thickness,solid); > > module arches() { > > skin([ > for (i=[0 : 180]) > transform(translation([0,0,(i*0.5)]) * rotation([0,0,0]), waveOut(i)) > ]); > > translate([0,0,90]) { > skin([ > for (i=[0 : 180]) > transform(translation([0,0,(i*0.5)]) * rotation([0,0,0]), waveIn(i)) > ]); > } > } > > > module arches2(verticies=192, thickness = 8, solid = false) { > > yxzpath = ogeepolyPath(650, 3, 600, 600, 420, 1, 10); > > //echo(yxzpath); > //echo("blah"); > //echo(yxzpath[10]); > > skin([ > for (i=[1 : 105]) > transform(translation(yxzpath[i]) * rotation([0,0,0]), > wave(i,verticies,thickness,solid)) > ]); > } > > module arches4(verticies=190) { > > yxzpath = ogeepolyPath(650, 3, 600, 600, 420, 1, 10); > > //echo(yxzpath); > //echo("blah"); > //echo(yxzpath[10]); > > skin([ > for (i=[1 : 90]) > transform(translation([0,0,i*0.5]) * rotation([0,0,0]), wave(i,verticies)) > ]); > } > > module arches3(start,end,verticies=190) { > > skin([ > for (i=[start : end]) > transform(translation([0,0,i*0.5]) * rotation([0,0,0]), > waveOut(i,verticies)) > ]); > } > > > //polygon test of roman arch or ogee poly > //they both look ok with the same number of verticies > //(10,14,18,22,26.... 6+4(n)) > //but the verticies must not be in the same order > //or number because if you do "arches3(0,90,22);" > //there is a twist... > //pts = romanArch(65, 3, 70, 22); > //pts = ogeepoly(65,3,60,60,22,0.0,0); > //polygon(pts); > > > //pts = romanArchNc(65, 3, 70, 24); > //polygon(pts); > > //90 goes from ogee to roman completely > //arches3(0,90,24); > > //half the passageway > arches2(64,4); > > //translate([0,0,750]) {cube([80,80,80], true); } > > //a test of unioning half the passageway with a cube > //gets errors > /* > union () { > arches2(64); > > translate([0,0,750]) {cube([80,80,80], true); } > } > */ > > //making a full passageway, gets errors > /* > difference() { > arches2(24); > mirror([0,0,1]) { > arches2(24,true); //subtract a SOLID version > } > } > mirror([0,0,1]) { > arches2(24); > } > */ > > //polygon(ogeepoly(65,3,60,60,200,0.0,0)); > > /* > polygon(ogeepoly(65,3,60,60,200,1,10)); > polygon(romanArch(65, 3, 70, 200)); > polygon(romanArch(95, 3, 40, 200)); > */ > > On Sat, Jun 8, 2019 at 1:45 PM adrianv <avm4@cornell.edu> wrote: > >> DanS wrote >> > Thanks, that helps, but I still need some tips for locating the problem. >> >> It's tough for people to guess what might be wrong if we don't know what >> your code actually does. Are you using polyhedron? Or are you doing >> unions >> and/or intersections of primitive geometry? Try to simplify your code and >> see if you can get the problem to go away. That might give some insight >> into where the problem lies. >> >> >> >> >> >> >> -- >> Sent from: http://forum.openscad.org/ >> >> _______________________________________________ >> OpenSCAD mailing list >> Discuss@lists.openscad.org >> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >> > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
DS
Dan Shriver
Mon, Jun 10, 2019 5:49 PM

Not to beat a dead horse....

Sounds like floating problems could be fixed with some functions that round
to an input power of 2 (2^-1),(2^-2)....(2^-n).  Is there such a function
out there?

https://www.avast.com/sig-email?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=webmail&utm_term=icon
Virus-free.
www.avast.com
https://www.avast.com/sig-email?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=webmail&utm_term=link
<#DAB4FAD8-2DD7-40BB-A1B8-4E2AA1F9FDF2>

On Sat, Jun 8, 2019 at 12:54 PM nop head nop.head@gmail.com wrote:

These sorts of problems are usually caused by creating vertices that due
to numerical error are not exactly coincident but very nearly are. They
then get collapsed due to floating point number representation and that
breaks the topology, creating holes, self intersections or degenerate
triangles. You don't notice until you try to do 3D CSG operations and then
CGAL will barf.

Think of it like this. Suppose you intersect a square with a circle (which
is actually a polygon with sloping sides). Mathematically the intersection
of a diagonal line with a square will create points exactly on the original
lines. In practice though, without infinite precision the points will be
slightly one side or the other. If you then union or difference it with the
original circle you create unimaginably small slivers.

You need to always make sure vertices are either exactly the same or
significantly different when represented in floating point numbers. It is
OK to stack integer sized cubes with exactly coincident faces but not, for
example, 0.1 cubes because 0.1 is a recurring fraction in binary. In
general there should always be some overlap when doing CSG operations.

On Sat, 8 Jun 2019 at 17:38, Dan Shriver tabbydan@gmail.com wrote:

You are correct.  Union with a cube gives an error too.  But I can't tell
from the error what is wrong.

If I do half the shape it renders fine and looks correct.  How do I
locate the problem?

On Sat, Jun 8, 2019 at 12:20 PM nop head nop.head@gmail.com wrote:

There is probably something wrong with arches2. Try unioning it with a
unit cube.

On Sat, 8 Jun 2019, 17:13 Dan Shriver, tabbydan@gmail.com wrote:

I'm trying to make a complicated shape.
A quick way to imagine it is that I have a half tube on a wishbone path.

Making half of it (just a call to arches2()) works fine.

However if I use difference and mirror I get errors.

At first I thought it was because I was trying to subtract a mirrored
half tube from a mirrored half tube causing some issues.  So I changed it
so (from the first half tube) I subtract the solid version (if a half tube
imagine a half circle being subtracted from it).

However, when I do that I still get problems:

difference() {
arches2(24); //imagine a half tube
mirror([0,0,1]) {
arches2(24,true); //imagine a half circle
}
}
mirror([0,0,1]) {
arches2(24); //adding back in the half tube mirrored
}

Compiling design (CSG Tree generation)...

Rendering Polygon Mesh using CGAL...

ERROR: CGAL error in CGAL_Nef_polyhedron3(): CGAL ERROR: assertion
violation! Expr: e_below != SHalfedge_handle() File:
/opt/mxe/usr/x86_64-w64-mingw32.static.posix/include/CGAL/Nef_3/SNC_FM_decorator.h
Line: 426

ERROR: CGAL error in CGAL_Nef_polyhedron3(): CGAL ERROR: assertion
violation! Expr: e_below != SHalfedge_handle() File:
/opt/mxe/usr/x86_64-w64-mingw32.static.posix/include/CGAL/Nef_3/SNC_FM_decorator.h
Line: 426

Geometries in cache: 11

Geometry cache size in bytes: 5770888

CGAL Polyhedrons in cache: 4

CGAL cache size in bytes: 0

Total rendering time: 0 hours, 0 minutes, 14 seconds

Rendering finished.


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

Not to beat a dead horse.... Sounds like floating problems could be fixed with some functions that round to an input power of 2 (2^-1),(2^-2)....(2^-n). Is there such a function out there? <https://www.avast.com/sig-email?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=webmail&utm_term=icon> Virus-free. www.avast.com <https://www.avast.com/sig-email?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=webmail&utm_term=link> <#DAB4FAD8-2DD7-40BB-A1B8-4E2AA1F9FDF2> On Sat, Jun 8, 2019 at 12:54 PM nop head <nop.head@gmail.com> wrote: > These sorts of problems are usually caused by creating vertices that due > to numerical error are not exactly coincident but very nearly are. They > then get collapsed due to floating point number representation and that > breaks the topology, creating holes, self intersections or degenerate > triangles. You don't notice until you try to do 3D CSG operations and then > CGAL will barf. > > Think of it like this. Suppose you intersect a square with a circle (which > is actually a polygon with sloping sides). Mathematically the intersection > of a diagonal line with a square will create points exactly on the original > lines. In practice though, without infinite precision the points will be > slightly one side or the other. If you then union or difference it with the > original circle you create unimaginably small slivers. > > You need to always make sure vertices are either exactly the same or > significantly different when represented in floating point numbers. It is > OK to stack integer sized cubes with exactly coincident faces but not, for > example, 0.1 cubes because 0.1 is a recurring fraction in binary. In > general there should always be some overlap when doing CSG operations. > > On Sat, 8 Jun 2019 at 17:38, Dan Shriver <tabbydan@gmail.com> wrote: > >> You are correct. Union with a cube gives an error too. But I can't tell >> from the error what is wrong. >> >> If I do half the shape it renders fine and looks correct. How do I >> locate the problem? >> >> On Sat, Jun 8, 2019 at 12:20 PM nop head <nop.head@gmail.com> wrote: >> >>> There is probably something wrong with arches2. Try unioning it with a >>> unit cube. >>> >>> On Sat, 8 Jun 2019, 17:13 Dan Shriver, <tabbydan@gmail.com> wrote: >>> >>>> I'm trying to make a complicated shape. >>>> A quick way to imagine it is that I have a half tube on a wishbone path. >>>> >>>> Making half of it (just a call to arches2()) works fine. >>>> >>>> However if I use difference and mirror I get errors. >>>> >>>> At first I thought it was because I was trying to subtract a mirrored >>>> half tube from a mirrored half tube causing some issues. So I changed it >>>> so (from the first half tube) I subtract the solid version (if a half tube >>>> imagine a half circle being subtracted from it). >>>> >>>> However, when I do that I still get problems: >>>> >>>> difference() { >>>> arches2(24); //imagine a half tube >>>> mirror([0,0,1]) { >>>> arches2(24,true); //imagine a half circle >>>> } >>>> } >>>> mirror([0,0,1]) { >>>> arches2(24); //adding back in the half tube mirrored >>>> } >>>> >>>> Compiling design (CSG Tree generation)... >>>> >>>> Rendering Polygon Mesh using CGAL... >>>> >>>> ERROR: CGAL error in CGAL_Nef_polyhedron3(): CGAL ERROR: assertion >>>> violation! Expr: e_below != SHalfedge_handle() File: >>>> /opt/mxe/usr/x86_64-w64-mingw32.static.posix/include/CGAL/Nef_3/SNC_FM_decorator.h >>>> Line: 426 >>>> >>>> ERROR: CGAL error in CGAL_Nef_polyhedron3(): CGAL ERROR: assertion >>>> violation! Expr: e_below != SHalfedge_handle() File: >>>> /opt/mxe/usr/x86_64-w64-mingw32.static.posix/include/CGAL/Nef_3/SNC_FM_decorator.h >>>> Line: 426 >>>> >>>> Geometries in cache: 11 >>>> >>>> Geometry cache size in bytes: 5770888 >>>> >>>> CGAL Polyhedrons in cache: 4 >>>> >>>> CGAL cache size in bytes: 0 >>>> >>>> Total rendering time: 0 hours, 0 minutes, 14 seconds >>>> >>>> Rendering finished. >>>> >>>> _______________________________________________ >>>> OpenSCAD mailing list >>>> Discuss@lists.openscad.org >>>> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >>>> >>> _______________________________________________ >>> OpenSCAD mailing list >>> Discuss@lists.openscad.org >>> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >>> >> _______________________________________________ >> OpenSCAD mailing list >> Discuss@lists.openscad.org >> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >> > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org > <https://www.avast.com/sig-email?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=webmail&utm_term=icon> Virus-free. www.avast.com <https://www.avast.com/sig-email?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=webmail&utm_term=link> <#DAB4FAD8-2DD7-40BB-A1B8-4E2AA1F9FDF2>