Joining half tubes

classic Classic list List threaded Threaded
13 messages Options
Reply | Threaded
Open this post in threaded view
|

Joining half tubes

DanS
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
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: Joining half tubes

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

On Sat, 8 Jun 2019, 17:13 Dan Shriver, <[hidden email]> 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
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: Joining half tubes

DanS
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 <[hidden email]> wrote:
There is probably something wrong with arches2. Try unioning it with a unit cube.

On Sat, 8 Jun 2019, 17:13 Dan Shriver, <[hidden email]> 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
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: Joining half tubes

nophead
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 <[hidden email]> 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 <[hidden email]> wrote:
There is probably something wrong with arches2. Try unioning it with a unit cube.

On Sat, 8 Jun 2019, 17:13 Dan Shriver, <[hidden email]> 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
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: Joining half tubes

DanS
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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> wrote:
There is probably something wrong with arches2. Try unioning it with a unit cube.

On Sat, 8 Jun 2019, 17:13 Dan Shriver, <[hidden email]> 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
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: Joining half tubes

nophead
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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> wrote:
There is probably something wrong with arches2. Try unioning it with a unit cube.

On Sat, 8 Jun 2019, 17:13 Dan Shriver, <[hidden email]> 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
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: Joining half tubes

adrianv
In reply to this post by DanS
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
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: Joining half tubes

DanS
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 <[hidden email]> 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
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: Joining half tubes

nophead
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 <[hidden email]> 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 <[hidden email]> 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
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: Joining half tubes

DanS
In reply to this post by nophead
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?

Virus-free. www.avast.com

On Sat, Jun 8, 2019 at 12:54 PM nop head <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> wrote:
There is probably something wrong with arches2. Try unioning it with a unit cube.

On Sat, 8 Jun 2019, 17:13 Dan Shriver, <[hidden email]> 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
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

Virus-free. www.avast.com

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: Joining half tubes

nophead
It's a lot more complicated than rounding numbers. Whenever you truncate the precision of the vertex coordinates you risk making vertices that were distinct no longer distinct and that breaks the topology and has to be fixed up, which isn't easy.

On Mon, 10 Jun 2019 at 18:50, Dan Shriver <[hidden email]> wrote:
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?

Virus-free. www.avast.com

On Sat, Jun 8, 2019 at 12:54 PM nop head <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> wrote:
There is probably something wrong with arches2. Try unioning it with a unit cube.

On Sat, 8 Jun 2019, 17:13 Dan Shriver, <[hidden email]> 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
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

Virus-free. www.avast.com
_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: Joining half tubes

DanS
I'm making individual polygon slices.  An arch slices is either a roman arch type slice, or an ogee arch type slice.  I have three of these "basic" type arches (a fat roman arch, an ogee arch, and a thin roman arch).  Slices between these types are interpolated via abs(sin(0-180)).  The coordinates of an in-between slice are the coordinates of the starting slice multiplied by sin(angle) and added to the ending slice which is multiplied by (1-sin(angle)).  The midpoint of the bottom of each slice lies along a curve that is half of an ogee.  At the end I use skin to make a solid out of all the slices.

I'm not "knowingly" doing any truncation- but I do imagine I get lots of horrible numbers that don't fit nicely into powers of two, and every time I do an operation on those the errors probably compound.

Can you suggest an approach to avoid my problems?

Fortunately, by itself it will render (even though it isn't a valid solid), which gives me an idea of how it looks:

image.png

Virus-free. www.avast.com

On Mon, Jun 10, 2019 at 2:06 PM nop head <[hidden email]> wrote:
It's a lot more complicated than rounding numbers. Whenever you truncate the precision of the vertex coordinates you risk making vertices that were distinct no longer distinct and that breaks the topology and has to be fixed up, which isn't easy.

On Mon, 10 Jun 2019 at 18:50, Dan Shriver <[hidden email]> wrote:
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?

Virus-free. www.avast.com

On Sat, Jun 8, 2019 at 12:54 PM nop head <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> wrote:
There is probably something wrong with arches2. Try unioning it with a unit cube.

On Sat, 8 Jun 2019, 17:13 Dan Shriver, <[hidden email]> 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
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

Virus-free. www.avast.com
_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: Joining half tubes

adrianv

I'm making individual polygon slices.  An arch slices is either a roman
arch type slice, or an ogee arch type slice.  I have three of these "basic"
type arches (a fat roman arch, an ogee arch, and a thin roman arch).
Slices between these types are interpolated via abs(sin(0-180)).  The
coordinates of an in-between slice are the coordinates of the starting
slice multiplied by sin(angle) and added to the ending slice which is
multiplied by (1-sin(angle)).  The midpoint of the bottom of each slice
lies along a curve that is half of an ogee.  At the end I use skin to make
a solid out of all the slices.


Have you tried to reduce your problem to the minimal case that causes the
problem?  I think that until you nail down what the problem is---until you
know for sure rather than just guessing---it's hard to speculate about how
to solve it.   Are you sure that your procedure produces a valid polyhedron,
without self-intersections?  I'm not sure I understand exactly how round-off
error creates problems, but it seems like the solution is to never compute a
point that is supposed to be the same a second time.  Then any round-off
would necessarily be consistent.  What happens if you build up your problem
with just two slices?  Just three lices?  When does it break?  

Once you understand exactly how it's broken you will be able to figure out
how to avoid the problem.  But again, you need to figure out what the
problem is, and the way to do that is to start cutting away parts of your
model until the problem goes away so that you can clearly identify what
addition causes the problem.   If you can post some code that demonstrates
your problem which is reasonably short and accessible then somebody may be
able to give you suggestions, but figuring out your full code is too much
work, at least for me.  




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

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org