

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_64w64mingw32.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_64w64mingw32.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


There is probably something wrong with arches2. Try unioning it with a unit cube. 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_64w64mingw32.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_64w64mingw32.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


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? There is probably something wrong with arches2. Try unioning it with a unit cube.
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_64w64mingw32.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_64w64mingw32.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


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. 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?
There is probably something wrong with arches2. Try unioning it with a unit cube.
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_64w64mingw32.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_64w64mingw32.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


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? 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.
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?
There is probably something wrong with arches2. Try unioning it with a unit cube.
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_64w64mingw32.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_64w64mingw32.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


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 zfighting in preview.
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?
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.
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?
There is probably something wrong with arches2. Try unioning it with a unit cube.
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_64w64mingw32.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_64w64mingw32.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


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


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 <listcomprehension/skin.scad>; use <nSpline/splines.scad>; use <scadutils/transformations.scad> use <scadutils/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(((radiusthickness)*sin(angle))/((radiusthickness)*cos(angle)));
function partitionNum(pn,points) = (pn < (points2)/4) ? 0 : //OUTER RIGHT (pn < (points2)/4 + 1) ? 1 : //OUTER TOP (pn < (points2)/2 + 1) ? 2: //OUTER LEFT (pn < (3*(points2))/4 + 1) ? 3: //INNER LEFT (pn < (3*(points2))/4 + 2) ? 4: //INNER TOP 5; // INNER RIGHT
function subPointNum(points, pointNum, partition) = [pointNum, 1, //doesn't matter ((points2)/2)  pointNum, pointNum  points/2, 1, //doesn't matter ((points1)  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 ((points1)  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)  (radiusthickness)*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 = (points2)/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)  (radiusthickness)*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 = (points2)/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:(pointCnt1)]) [archX(radius, thickness, angle, i, pointCnt), archY(radius, thickness, angle, i, pointCnt)] ]; //use this with a nocap 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:(pointCnt1)]) [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*(points4)/(8*lowerphi4*apexangle) : lowerphi*(points2)/(8*lowerphi4*apexangle))),
// Actual number of points in the upper arc uppertemp = echoit2("uppertemp ",round((capwidth > 0.0) ? (lowerphiapexangle)*(points4)/(8*lowerphi4*apexangle) : (lowerphiapexangle)*(points2)/(8*lowerphi4*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:lowerpoints1]) [ w0 + (lowerradius + thickness) * cos(i * lowerphi / lowerpoints), h0 + (lowerradius + thickness) * sin(i * lowerphi / lowerpoints) ] ]), // Upper Right Outer arc uro = echoit3("uro ",[ for (i = [upperpoints1: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:upperpoints1]) [ 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 lowerpoints1 from "lowerpoints" llo = echoit3("llo ",[ for (i = [lowerpoints1: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:lowerpoints1]) [ w0  lowerradius * cos(i * lowerphi / lowerpoints), h0 + lowerradius * sin(i * lowerphi / lowerpoints) ] ], // Upper Left Inner arc uli = (solid) ? [] : [ for (i = [upperpoints1: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:upperpoints1]) [ w6  (upperradius + thickness) * cos(innertheta + i * innerphi / upperpoints), h6  (upperradius + thickness) * sin(innertheta + i * innerphi / upperpoints) ] ], // Lower Right Inner arc lri = (solid) ? [] : [ for (i = [lowerpoints1: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*(points4)/(8*lowerphi4*apexangle) : lowerphi*(points2)/(8*lowerphi4*apexangle)),
// Actual number of points in the upper arc uppertemp = round((capwidth > 0.0) ? (lowerphiapexangle)*(points4)/(8*lowerphi4*apexangle) : (lowerphiapexangle)*(points2)/(8*lowerphi4*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:lowerpoints1]) [ w0 + (lowerradius + thickness) * cos(i * lowerphi / lowerpoints), 0, h0 + (lowerradius + thickness) * sin(i * lowerphi / lowerpoints) ] ], // Upper Right Outer arc uro = [ for (i = [upperpoints1: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:upperpoints1]) [ 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((i30)*6))),verticies,thickness,solid) : (i < 91) ? waveOut(echoit4("<91",(i60)*6),verticies,thickness,solid) : waveIn(echoit4("last",180((i90)*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)); */
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


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.
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 <listcomprehension/skin.scad>; use <nSpline/splines.scad>; use <scadutils/transformations.scad> use <scadutils/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(((radiusthickness)*sin(angle))/((radiusthickness)*cos(angle)));
function partitionNum(pn,points) = (pn < (points2)/4) ? 0 : //OUTER RIGHT (pn < (points2)/4 + 1) ? 1 : //OUTER TOP (pn < (points2)/2 + 1) ? 2: //OUTER LEFT (pn < (3*(points2))/4 + 1) ? 3: //INNER LEFT (pn < (3*(points2))/4 + 2) ? 4: //INNER TOP 5; // INNER RIGHT
function subPointNum(points, pointNum, partition) = [pointNum, 1, //doesn't matter ((points2)/2)  pointNum, pointNum  points/2, 1, //doesn't matter ((points1)  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 ((points1)  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)  (radiusthickness)*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 = (points2)/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)  (radiusthickness)*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 = (points2)/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:(pointCnt1)]) [archX(radius, thickness, angle, i, pointCnt), archY(radius, thickness, angle, i, pointCnt)] ]; //use this with a nocap 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:(pointCnt1)]) [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*(points4)/(8*lowerphi4*apexangle) : lowerphi*(points2)/(8*lowerphi4*apexangle))),
// Actual number of points in the upper arc uppertemp = echoit2("uppertemp ",round((capwidth > 0.0) ? (lowerphiapexangle)*(points4)/(8*lowerphi4*apexangle) : (lowerphiapexangle)*(points2)/(8*lowerphi4*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:lowerpoints1]) [ w0 + (lowerradius + thickness) * cos(i * lowerphi / lowerpoints), h0 + (lowerradius + thickness) * sin(i * lowerphi / lowerpoints) ] ]), // Upper Right Outer arc uro = echoit3("uro ",[ for (i = [upperpoints1: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:upperpoints1]) [ 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 lowerpoints1 from "lowerpoints" llo = echoit3("llo ",[ for (i = [lowerpoints1: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:lowerpoints1]) [ w0  lowerradius * cos(i * lowerphi / lowerpoints), h0 + lowerradius * sin(i * lowerphi / lowerpoints) ] ], // Upper Left Inner arc uli = (solid) ? [] : [ for (i = [upperpoints1: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:upperpoints1]) [ w6  (upperradius + thickness) * cos(innertheta + i * innerphi / upperpoints), h6  (upperradius + thickness) * sin(innertheta + i * innerphi / upperpoints) ] ], // Lower Right Inner arc lri = (solid) ? [] : [ for (i = [lowerpoints1: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*(points4)/(8*lowerphi4*apexangle) : lowerphi*(points2)/(8*lowerphi4*apexangle)),
// Actual number of points in the upper arc uppertemp = round((capwidth > 0.0) ? (lowerphiapexangle)*(points4)/(8*lowerphi4*apexangle) : (lowerphiapexangle)*(points2)/(8*lowerphi4*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:lowerpoints1]) [ w0 + (lowerradius + thickness) * cos(i * lowerphi / lowerpoints), 0, h0 + (lowerradius + thickness) * sin(i * lowerphi / lowerpoints) ] ], // Upper Right Outer arc uro = [ for (i = [upperpoints1: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:upperpoints1]) [ 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((i30)*6))),verticies,thickness,solid) : (i < 91) ? waveOut(echoit4("<91",(i60)*6),verticies,thickness,solid) : waveIn(echoit4("last",180((i90)*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)); */
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


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?
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.
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?
There is probably something wrong with arches2. Try unioning it with a unit cube.
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_64w64mingw32.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_64w64mingw32.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


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. 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?
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.
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?
There is probably something wrong with arches2. Try unioning it with a unit cube.
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_64w64mingw32.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_64w64mingw32.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


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(0180)). The coordinates of an inbetween slice are the coordinates of the starting slice multiplied by sin(angle) and added to the ending slice which is multiplied by (1sin(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:
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.
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?
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.
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?
There is probably something wrong with arches2. Try unioning it with a unit cube.
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_64w64mingw32.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_64w64mingw32.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
_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org


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(0180)). The
coordinates of an inbetween slice are the coordinates of the starting
slice multiplied by sin(angle) and added to the ending slice which is
multiplied by (1sin(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 isuntil you
know for sure rather than just guessingit's hard to speculate about how
to solve it. Are you sure that your procedure produces a valid polyhedron,
without selfintersections? I'm not sure I understand exactly how roundoff
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 roundoff
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

