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 |
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:
_______________________________________________ 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? On Sat, Jun 8, 2019 at 12:20 PM nop head <[hidden email]> wrote:
_______________________________________________ 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. On Sat, 8 Jun 2019 at 17:38, Dan Shriver <[hidden email]> wrote:
_______________________________________________ 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? On Sat, Jun 8, 2019 at 12:54 PM nop head <[hidden email]> wrote:
_______________________________________________ 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 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:
_______________________________________________ OpenSCAD mailing list [hidden email] http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org |
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 |
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 _______________________________________________ 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. On Sat, 8 Jun 2019 at 18:53, Dan Shriver <[hidden email]> wrote:
_______________________________________________ OpenSCAD mailing list [hidden email] http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org |
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? On Sat, Jun 8, 2019 at 12:54 PM nop head <[hidden email]> wrote:
_______________________________________________ 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. On Mon, 10 Jun 2019 at 18:50, Dan Shriver <[hidden email]> wrote:
_______________________________________________ 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(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: On Mon, Jun 10, 2019 at 2:06 PM nop head <[hidden email]> wrote:
_______________________________________________ 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(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 |
Free forum by Nabble | Edit this page |