diff --git a/debug.scad b/debug.scad index 6cff32f..fab17eb 100644 --- a/debug.scad +++ b/debug.scad @@ -9,6 +9,114 @@ ////////////////////////////////////////////////////////////////////// +// Section: Debugging Paths and Polygons + +// Module: trace_polyline() +// Description: +// Renders lines between each point of a polyline path. +// Can also optionally show the individual vertex points. +// Arguments: +// pline = The array of points in the polyline. +// closed = If true, draw the segment from the last vertex to the first. Default: false +// showpts = If true, draw vertices and control points. +// N = Mark the first and every Nth vertex after in a different color and shape. +// size = Diameter of the lines drawn. +// color = Color to draw the lines (but not vertices) in. +// Example(FlatSpin): +// polyline = [for (a=[0:30:210]) 10*[cos(a), sin(a), sin(a)]]; +// trace_polyline(polyline, showpts=true, size=0.5, color="lightgreen"); +module trace_polyline(pline, closed=false, showpts=false, N=1, size=1, color="yellow") { + assert(is_path(pline),"Input pline is not a path"); + sides = segs(size/2); + pline = closed? close_path(pline) : pline; + if (showpts) { + for (i = [0:1:len(pline)-1]) { + translate(pline[i]) { + if (i%N == 0) { + color("blue") sphere(d=size*2.5, $fn=8); + } else { + color("red") { + cylinder(d=size/2, h=size*3, center=true, $fn=8); + xrot(90) cylinder(d=size/2, h=size*3, center=true, $fn=8); + yrot(90) cylinder(d=size/2, h=size*3, center=true, $fn=8); + } + } + } + } + } + if (N!=3) { + color(color) path_sweep(circle(d=size,$fn=sides), path3d(pline)); + } else { + for (i = [0:1:len(pline)-2]) { + if (N!=3 || (i%N) != 1) { + color(color) extrude_from_to(pline[i], pline[i+1]) circle(d=size, $fn=sides); + } + } + } +} + + +// Module: debug_polygon() +// Description: A drop-in replacement for `polygon()` that renders and labels the path points. +// Arguments: +// points = The array of 2D polygon vertices. +// paths = The path connections between the vertices. +// convexity = The max number of walls a ray can pass through the given polygon paths. +// Example(Big2D): +// debug_polygon( +// points=concat( +// regular_ngon(or=10, n=8), +// regular_ngon(or=8, n=8) +// ), +// paths=[ +// [for (i=[0:7]) i], +// [for (i=[15:-1:8]) i] +// ] +// ); +module debug_polygon(points, paths=undef, convexity=2, size=1) +{ + pths = is_undef(paths)? [for (i=[0:1:len(points)-1]) i] : is_num(paths[0])? [paths] : paths; + echo(points=points); + echo(paths=paths); + linear_extrude(height=0.01, convexity=convexity, center=true) { + polygon(points=points, paths=paths, convexity=convexity); + } + for (i = [0:1:len(points)-1]) { + color("red") { + up(0.2) { + translate(points[i]) { + linear_extrude(height=0.1, convexity=10, center=true) { + text(text=str(i), size=size, halign="center", valign="center"); + } + } + } + } + } + for (j = [0:1:len(paths)-1]) { + path = paths[j]; + translate(points[path[0]]) { + color("cyan") up(0.1) cylinder(d=size*1.5, h=0.01, center=false, $fn=12); + } + translate(points[path[len(path)-1]]) { + color("pink") up(0.11) cylinder(d=size*1.5, h=0.01, center=false, $fn=4); + } + for (i = [0:1:len(path)-1]) { + midpt = (points[path[i]] + points[path[(i+1)%len(path)]])/2; + color("blue") { + up(0.2) { + translate(midpt) { + linear_extrude(height=0.1, convexity=10, center=true) { + text(text=str(chr(65+j),i), size=size/2, halign="center", valign="center"); + } + } + } + } + } + } +} + + + // Section: Debugging Polyhedrons @@ -277,56 +385,63 @@ module frame_ref(s=15) { // Example(2D,Big): Metric vs Imperial // ruler(12,width=50,inch=true,labels=true,maxscale=0); // fwd(50)ruler(300,width=50,labels=true); -module ruler(length=100, width=undef, thickness=1, depth=3, labels=false, pipscale=1/3, maxscale=undef, colors=["black","white"], alpha=1.0, unit=1, inch=false, anchor=ALLNEG, spin=0, orient=UP) +module ruler(length=100, width=undef, thickness=1, depth=3, labels=false, pipscale=1/3, maxscale=undef, colors=["black","white"], alpha=1.0, unit=1, inch=false, anchor=LEFT+BACK+TOP, spin=0, orient=UP) { - inchfactor = 25.4; - assert(depth<=5, "Cannot render scales smaller than depth=5"); - assert(len(colors)==2, "colors must contain a list of exactly two colors."); - length = inch ? inchfactor * length : length; - unit = inch ? inchfactor*unit : unit; - maxscale = is_def(maxscale)? maxscale : floor(log(length/unit-EPSILON)); - scales = unit * [for(logsize = [maxscale:-1:maxscale-depth+1]) pow(10,logsize)]; - echo(scales=scales); - widthfactor = (1-pipscale) / (1-pow(pipscale,depth)); - width = default(width, scales[0]); - widths = width * widthfactor * [for(logsize = [0:-1:-depth+1]) pow(pipscale,-logsize)]; - offsets = concat([0],cumsum(widths)); - attachable(anchor,spin,orient, size=[length,width,thickness], offset=offset) { - translate([-length/2, -width/2, 0]) - for(i=[0:1:len(scales)-1]){ - count = ceil(length/scales[i]); - fontsize = 0.5*min(widths[i], scales[i]/ceil(log(count*scales[i]/unit))); - back(offsets[i]) - xspread(scales[i], n=count, sp=[0,0,0]) - union(){ - actlen = ($idx0 ? quantup(widths[i],1/1024) : widths[i]; // What is the i>0 test supposed to do here? - cube([quantup(actlen,1/1024),quantup(w,1/1024),thickness], anchor=FRONT+LEFT); - } - mark = i == 0 && $idx % 10 == 0 && $idx != 0 ? 0 : - i == 0 && $idx % 10 == 9 && $idx != count-1 ? 1 : - $idx % 10 == 4 ? 1 : - $idx % 10 == 5 ? 0 : - -1; - flip = 1-mark*2; - if (mark >= 0){ - marklength = min(widths[i]/2, scales[i]*2); - markwidth = marklength*0.4; - translate([mark*scales[i],widths[i]]) - color(colors[1-$idx%2], alpha=alpha) - linear_extrude(height=thickness+scales[i]/100, convexity=2, center=true) - polygon(scale([flip*markwidth, marklength],p=[[0,0], [1, -1], [0,-0.9]])); - } - if (labels && scales[i]/unit+EPSILON >= 1) - color(colors[($idx+1)%2], alpha=alpha) - linear_extrude(height=thickness+scales[i]/100, convexity=2, center=true) - back(scales[i]*.02) - text(text=str( $idx * scales[i] / unit), size=fontsize, halign="left", valign="baseline"); - } - } - children(); - } + inchfactor = 25.4; + assert(depth<=5, "Cannot render scales smaller than depth=5"); + assert(len(colors)==2, "colors must contain a list of exactly two colors."); + length = inch ? inchfactor * length : length; + unit = inch ? inchfactor*unit : unit; + maxscale = is_def(maxscale)? maxscale : floor(log(length/unit-EPSILON)); + scales = unit * [for(logsize = [maxscale:-1:maxscale-depth+1]) pow(10,logsize)]; + widthfactor = (1-pipscale) / (1-pow(pipscale,depth)); + width = default(width, scales[0]); + widths = width * widthfactor * [for(logsize = [0:-1:-depth+1]) pow(pipscale,-logsize)]; + offsets = concat([0],cumsum(widths)); + attachable(anchor,spin,orient, size=[length,width,thickness]) { + translate([-length/2, -width/2, 0]) + for(i=[0:1:len(scales)-1]) { + count = ceil(length/scales[i]); + fontsize = 0.5*min(widths[i], scales[i]/ceil(log(count*scales[i]/unit))); + back(offsets[i]) { + xspread(scales[i], n=count, sp=[0,0,0]) union() { + actlen = ($idx0 ? quantup(widths[i],1/1024) : widths[i]; // What is the i>0 test supposed to do here? + cube([quantup(actlen,1/1024),quantup(w,1/1024),thickness], anchor=FRONT+LEFT); + } + mark = + i == 0 && $idx % 10 == 0 && $idx != 0 ? 0 : + i == 0 && $idx % 10 == 9 && $idx != count-1 ? 1 : + $idx % 10 == 4 ? 1 : + $idx % 10 == 5 ? 0 : -1; + flip = 1-mark*2; + if (mark >= 0) { + marklength = min(widths[i]/2, scales[i]*2); + markwidth = marklength*0.4; + translate([mark*scales[i], widths[i], 0]) { + color(colors[1-$idx%2], alpha=alpha) { + linear_extrude(height=thickness+scales[i]/100, convexity=2, center=true) { + polygon(scale([flip*markwidth, marklength],p=[[0,0], [1, -1], [0,-0.9]])); + } + } + } + } + if (labels && scales[i]/unit+EPSILON >= 1) { + color(colors[($idx+1)%2], alpha=alpha) { + linear_extrude(height=thickness+scales[i]/100, convexity=2, center=true) { + back(scales[i]*.02) { + text(text=str( $idx * scales[i] / unit), size=fontsize, halign="left", valign="baseline"); + } + } + } + } + + } + } + } + children(); + } } diff --git a/paths.scad b/paths.scad index a16ab78..77746cb 100644 --- a/paths.scad +++ b/paths.scad @@ -847,110 +847,6 @@ module path_extrude(path, convexity=10, clipsize=100) { } -// Module: trace_polyline() -// Description: -// Renders lines between each point of a polyline path. -// Can also optionally show the individual vertex points. -// Arguments: -// pline = The array of points in the polyline. -// closed = If true, draw the segment from the last vertex to the first. Default: false -// showpts = If true, draw vertices and control points. -// N = Mark the first and every Nth vertex after in a different color and shape. -// size = Diameter of the lines drawn. -// color = Color to draw the lines (but not vertices) in. -// Example(FlatSpin): -// polyline = [for (a=[0:30:210]) 10*[cos(a), sin(a), sin(a)]]; -// trace_polyline(polyline, showpts=true, size=0.5, color="lightgreen"); -module trace_polyline(pline, closed=false, showpts=false, N=1, size=1, color="yellow") { - assert(is_path(pline),"Input pline is not a path"); - sides = segs(size/2); - pline = closed? close_path(pline) : pline; - if (showpts) { - for (i = [0:1:len(pline)-1]) { - translate(pline[i]) { - if (i%N == 0) { - color("blue") sphere(d=size*2.5, $fn=8); - } else { - color("red") { - cylinder(d=size/2, h=size*3, center=true, $fn=8); - xrot(90) cylinder(d=size/2, h=size*3, center=true, $fn=8); - yrot(90) cylinder(d=size/2, h=size*3, center=true, $fn=8); - } - } - } - } - } - if (N!=3) { - color(color) path_sweep(circle(d=size,$fn=sides), path3d(pline)); - } else { - for (i = [0:1:len(pline)-2]) { - if (N!=3 || (i%N) != 1) { - color(color) extrude_from_to(pline[i], pline[i+1]) circle(d=size, $fn=sides); - } - } - } -} - - -// Module: debug_polygon() -// Description: A drop-in replacement for `polygon()` that renders and labels the path points. -// Arguments: -// points = The array of 2D polygon vertices. -// paths = The path connections between the vertices. -// convexity = The max number of walls a ray can pass through the given polygon paths. -// Example(Big2D): -// debug_polygon( -// points=concat( -// regular_ngon(or=10, n=8), -// regular_ngon(or=8, n=8) -// ), -// paths=[ -// [for (i=[0:7]) i], -// [for (i=[15:-1:8]) i] -// ] -// ); -module debug_polygon(points, paths=undef, convexity=2, size=1) -{ - pths = is_undef(paths)? [for (i=[0:1:len(points)-1]) i] : is_num(paths[0])? [paths] : paths; - echo(points=points); - echo(paths=paths); - linear_extrude(height=0.01, convexity=convexity, center=true) { - polygon(points=points, paths=paths, convexity=convexity); - } - for (i = [0:1:len(points)-1]) { - color("red") { - up(0.2) { - translate(points[i]) { - linear_extrude(height=0.1, convexity=10, center=true) { - text(text=str(i), size=size, halign="center", valign="center"); - } - } - } - } - } - for (j = [0:1:len(paths)-1]) { - path = paths[j]; - translate(points[path[0]]) { - color("cyan") up(0.1) cylinder(d=size*1.5, h=0.01, center=false, $fn=12); - } - translate(points[path[len(path)-1]]) { - color("pink") up(0.11) cylinder(d=size*1.5, h=0.01, center=false, $fn=4); - } - for (i = [0:1:len(path)-1]) { - midpt = (points[path[i]] + points[path[(i+1)%len(path)]])/2; - color("blue") { - up(0.2) { - translate(midpt) { - linear_extrude(height=0.1, convexity=10, center=true) { - text(text=str(chr(65+j),i), size=size/2, halign="center", valign="center"); - } - } - } - } - } - } -} - // Module: path_spread() // // Description: diff --git a/version.scad b/version.scad index e810c87..0b2b0a5 100644 --- a/version.scad +++ b/version.scad @@ -8,7 +8,7 @@ ////////////////////////////////////////////////////////////////////// -BOSL_VERSION = [2,0,170]; +BOSL_VERSION = [2,0,171]; // Section: BOSL Library Version Functions