From a26e6950e6894c9bb502e6f1051ee4b8a28f19d1 Mon Sep 17 00:00:00 2001 From: Adrian Mariano Date: Sat, 13 Jan 2024 19:26:15 -0500 Subject: [PATCH 1/6] add vnf_hull() and hull_region() --- regions.scad | 35 +++++++++++++++++++++++++++++++++++ skin.scad | 4 ++-- vnf.scad | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+), 2 deletions(-) diff --git a/regions.scad b/regions.scad index 73d1f39..7f94962 100644 --- a/regions.scad +++ b/regions.scad @@ -1396,4 +1396,39 @@ module exclusive_or() { } + +// Function&Module: hull_region() +// Synopsis: Compute convex hull of region or 2d path +// SynTags: Geom, Path +// Topics: Regions, Polygons, Shapes2D +// Usage: +// path = hull_region(region); +// hull_region(region); +// Description: +// Given a path, or a region, compute the convex hull +// and return it as a path. This differs from {{hull()}} and {{hull2d_path()}} which +// return an index list into the point list. As a module invokes the native hull() on +// the specified region. +// Arguments: +// region = region or path listing points to compute the hull from. +// Example(2D, NoAxes): + data = [star(id=10,od=20,n=9), + right(30, star(id=12,od=25, n=7))]; + stroke(data); + stroke([hull_region(data)],color="red"); +function hull_region(region) = + assert(is_path(region) || is_region(region)) + let( + pts = is_region(region) ? flatten(region) + : region, + order = hull2d_path(pts) + ) + select(pts,order); + +module hull_region(region) +{ + hull()region(region); +} + + // vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap diff --git a/skin.scad b/skin.scad index 529ecd4..9599986 100644 --- a/skin.scad +++ b/skin.scad @@ -2958,13 +2958,13 @@ function associate_vertices(polygons, split, curpoly=0) = // tex_size=[10,10] // ); // Example(3D): **"dimples"** (VNF) = Round divots. Specify `$fn` to set the number of segments on the cone (will be rounded to a multiple of 4). If you use $fa and $fs then the number of segments is determined for the original VNF scale of 1x1. Giving `border=` specifies the horizontal width of the flat border region between the tile edges and the edge of the dimple. Must be nonnegative and strictly less than 0.5. Default: 0.05. -// tex = texture("dimples"); +// tex = texture("dimples", $fn=16); // linear_sweep( // rect(30), texture=tex, h=30, // tex_size=[10,10] // ); // Example(3D): **"dots"** (VNF) = Raised round bumps. Specify `$fn` to set the number of segments on the cone (will be rounded to a multiple of 4). If you use $fa and $fs then the number of segments is determined for the original VNF scale of 1x1. Giving `border=` specifies the horizontal width of the flat border region between the tile edge and the edge of the dots. Must be nonnegative and strictly less than 0.5. Default: 0.05. -// tex = texture("dots"); +// tex = texture("dots", $fn=16); // linear_sweep( // rect(30), texture=tex, h=30, // tex_size=[10,10] diff --git a/vnf.scad b/vnf.scad index c6cbc4f..9f09956 100644 --- a/vnf.scad +++ b/vnf.scad @@ -1414,6 +1414,53 @@ function vnf_bend(vnf,r,d,axis="Z") = ) [new_vert,sliced[1]]; + +// Function&Module: vnf_hull() +// Synopsis: Compute convex hull of VNF or 3d path +// Usage: +// vnf_hull = hull_vnf(vnf); +// hull_vnf(vnf,[fast]); +// Description: +// Given a VNF or a list of 3d points, compute the convex hull +// and return it as a VNF. This differs from {{hull()}} and {{hull3d_faces()}} which +// return just the face list referenced to the input point list. Note that the point +// list that is returned will contain all the points that are actually used in the input +// VNF, which may be many more points than are needed to represent the convex hull. +// This is not usually a problem, but you can run the somewhat slow {{vnf_drop_unused_points()}} +// function to fix this if necessary. +// Arguments: +// region = region or path listing points to compute the hull from. +// fast = (module only) if input is a point list (not a VNF) use a fasterer cheat that may handle more points, but could emit warnings. Ignored if input is a VNF. Default: false. +// Example(3D,Big,NoAxes): Input is a VNF +// ellipse = xscale(2, p=circle($fn=48, r=3)); +// pentagon = subdivide_path(pentagon(r=1), 20); +// vnf=path_sweep(pentagon, path3d(ellipse), +// closed=true, twist=360*2); +// vnfhull = vnf_hull(vnf); +// vnf_polyhedron(vnf); +// move([10,10]) +// vnf_polyhedron(vnfhull); +// Example(2D, NoAxes): Input is a point list +// h=helix(l=40, turns=1, r=8); +// color("red")move_copies(h) +// sphere(r=0.5,$fn=12); +// vnf_polyhedron(vnf_hull(h)); +function vnf_hull(vnf) = + assert(is_vnf(vnf) || is_path(vnf,3),"Input must be a VNF or a 3d path") + let( + pts = is_vnf(vnf) ? select(vnf[0],unique(flatten(vnf[1]))) + : vnf, + faces = hull3d_faces(pts) + ) + [pts, faces]; + +module vnf_hull(vnf, fast=false) +{ + if (is_vnf(vnf)) hull()vnf_polyhedron(vnf); + else hull_points(vnf, fast); +} + + // Section: Debugging Polyhedrons /// Internal Module: _show_vertices() From 4d2045aa95d255dafed6d9f2195c4048f10c0695 Mon Sep 17 00:00:00 2001 From: adrianVmariano Date: Sun, 14 Jan 2024 00:26:39 +0000 Subject: [PATCH 2/6] Version Bump --- version.scad | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.scad b/version.scad index f01ded2..0307d82 100644 --- a/version.scad +++ b/version.scad @@ -9,7 +9,7 @@ ////////////////////////////////////////////////////////////////////// -BOSL_VERSION = [2,0,685]; +BOSL_VERSION = [2,0,686]; // Section: BOSL Library Version Functions From 01b125f665d6126b2269d230520959a211df6513 Mon Sep 17 00:00:00 2001 From: Adrian Mariano Date: Sat, 13 Jan 2024 19:59:46 -0500 Subject: [PATCH 3/6] doc fix --- regions.scad | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/regions.scad b/regions.scad index 7f94962..7c64054 100644 --- a/regions.scad +++ b/regions.scad @@ -1412,10 +1412,10 @@ module exclusive_or() { // Arguments: // region = region or path listing points to compute the hull from. // Example(2D, NoAxes): - data = [star(id=10,od=20,n=9), - right(30, star(id=12,od=25, n=7))]; - stroke(data); - stroke([hull_region(data)],color="red"); +// data = [star(id=10,od=20,n=9), +// right(30, star(id=12,od=25, n=7))]; +// stroke(data); +// stroke([hull_region(data)],color="red"); function hull_region(region) = assert(is_path(region) || is_region(region)) let( From 2c6cba73a47ee3f4fd1086f677dd709adea84139 Mon Sep 17 00:00:00 2001 From: adrianVmariano Date: Sun, 14 Jan 2024 01:00:42 +0000 Subject: [PATCH 4/6] Version Bump --- version.scad | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.scad b/version.scad index 0307d82..d7b72c3 100644 --- a/version.scad +++ b/version.scad @@ -9,7 +9,7 @@ ////////////////////////////////////////////////////////////////////// -BOSL_VERSION = [2,0,686]; +BOSL_VERSION = [2,0,687]; // Section: BOSL Library Version Functions From f42bd57fbf37ca67d350930fe03cd5d143e5b9af Mon Sep 17 00:00:00 2001 From: Adrian Mariano Date: Sat, 13 Jan 2024 23:09:25 -0500 Subject: [PATCH 5/6] doc fixes and default tex_rot fix --- shapes3d.scad | 4 ++-- skin.scad | 47 +++++++++++++++++++++++++++++++---------------- vnf.scad | 2 +- 3 files changed, 34 insertions(+), 19 deletions(-) diff --git a/shapes3d.scad b/shapes3d.scad index d0eaf07..f6bc520 100644 --- a/shapes3d.scad +++ b/shapes3d.scad @@ -1509,7 +1509,7 @@ function cyl( teardrop=false, from_end, from_end1, from_end2, texture, tex_size=[5,5], tex_reps, tex_counts, - tex_inset=false, tex_rot=false, + tex_inset=false, tex_rot=0, tex_scale, tex_depth, tex_samples, length, height, tex_taper, style, tex_style, anchor, spin=0, orient=UP @@ -1670,7 +1670,7 @@ module cyl( teardrop=false, from_end, from_end1, from_end2, texture, tex_size=[5,5], tex_reps, tex_counts, - tex_inset=false, tex_rot=false, + tex_inset=false, tex_rot=0, tex_scale, tex_depth, tex_samples, length, height, tex_taper, style, tex_style, anchor, spin=0, orient=UP diff --git a/skin.scad b/skin.scad index 9599986..574608e 100644 --- a/skin.scad +++ b/skin.scad @@ -708,7 +708,7 @@ module linear_sweep( twist=0, scale=1, shift=[0,0], slices, maxseg, style="default", convexity, caps=true, texture, tex_size=[5,5], tex_reps, tex_counts, - tex_inset=false, tex_rot=false, + tex_inset=false, tex_rot=0, tex_depth, tex_scale, tex_samples, cp, atype="hull", h,l,length, anchor, spin=0, orient=UP @@ -761,7 +761,7 @@ function linear_sweep( slices, maxseg, style="default", caps=true, cp, atype="hull", h, texture, tex_size=[5,5], tex_reps, tex_counts, - tex_inset=false, tex_rot=false, + tex_inset=false, tex_rot=0, tex_scale, tex_depth, tex_samples, h, l, length, anchor, spin=0, orient=UP ) = @@ -961,7 +961,7 @@ function linear_sweep( function rotate_sweep( shape, angle=360, texture, tex_size=[5,5], tex_counts, tex_reps, - tex_inset=false, tex_rot=false, + tex_inset=false, tex_rot=0, tex_scale, tex_depth, tex_samples, tex_taper, shift=[0,0], closed=true, style="min_edge", cp="centroid", @@ -1022,7 +1022,7 @@ function rotate_sweep( module rotate_sweep( shape, angle=360, texture, tex_size=[5,5], tex_counts, tex_reps, - tex_inset=false, tex_rot=false, + tex_inset=false, tex_rot=0, tex_scale, tex_depth, tex_samples, tex_taper, shift=[0,0], style="min_edge", @@ -2737,7 +2737,7 @@ function associate_vertices(polygons, split, curpoly=0) = // Values in the height field should range from 0 to 1. A zero height // in the height field corresponds to the height of the surface and 1 // the highest point in the texture above the surface being textured. -// Figure(2D,Big,NoScales): Here is a 2d texture described by a "grid" that just contains a single row. Such a texture can be used to create ribbing. The texture is `[[0, 1, 1, 0]]`, and the fixture shows three repetitions of the basic texture unit. +// Figure(2D,Big,NoScales,VPT=[6.21418,0.242814,0],VPD=28.8248,VPR=[0,0,0]): Here is a 2d texture described by a "grid" that just contains a single row. Such a texture can be used to create ribbing. The texture is `[[0, 1, 1, 0]]`, and the fixture shows three repetitions of the basic texture unit. // ftex1 = [0,1,1,0,0]; // stroke( transpose([count(5),ftex1]), dots=true, dots_width=3,width=.05); // right(4)stroke( transpose([count(5),ftex1]), dots=true, width=.05,dots_color="red",color="blue",dots_width=3); @@ -2753,7 +2753,7 @@ function associate_vertices(polygons, split, curpoly=0) = // is correctly designed to span the range from 0 to 1. The `tex_depth` parameter can adjust // this dimension of a texture without changing anything else, and setting `tex_depth` negative // will invert a texture. -// Figure(2D,Big,NoScales): +// Figure(2D,Big,NoScales,VPR=[0,0,0],VPT=[6.86022,-1.91238,0],VPD=28.8248): // ftex1 = [0,1,1,0,0]; // left(0)color(.6*[1,1,1])rect([12,1],anchor=BACK+LEFT); // stroke( transpose([count(5),ftex1]), dots=true, dots_width=3,width=.05); @@ -2783,8 +2783,10 @@ function associate_vertices(polygons, split, curpoly=0) = // If you want to keep the texture the same size but make the slope // steeper you need to add more points to make the uniform grid fine enough // to represent the slope you want. This means that creating sharp edges -// can require a large number of points, resulting in longer run times. -// Figure(2D,Big,NoScales): +// can require a large number of points, resulting in longer run times. +// When using the built-in textures you can control the number of points +// using the `n=` argument to {{texture()}}. +// Figure(2D,Big,NoScales,VPT=[6.21418,0.242814,0],VPD=28.8248,VPR=[0,0,0]): // ftex2 = xscale(4/11,transpose([count(12),[0,1,1,1,1,1,1,1,1,1,0,0]])); // stroke( ftex2, dots=true, dots_width=3,width=.05); // right(4)stroke( ftex2, dots=true, width=.05,dots_color="red",color="blue",dots_width=3); @@ -2806,7 +2808,7 @@ function associate_vertices(polygons, split, curpoly=0) = // [0,0,0,0]] // ``` // and we show the 3D triangulations produced by the different styles: -// Figure(3D,Big,NoAxes,VPR=[39.2,0,13.3],VPT=[3.76242,-5.50969,4.51854],VPD=32.0275): +// Figure(3D,Big,NoAxes,VPR=[45.5,0,18.2],VPT=[2.3442,-6.25815,3.91529],VPD=35.5861): // tex = [ // [0,0,0,0,0], // [0,1,1,0,0], @@ -2815,18 +2817,20 @@ function associate_vertices(polygons, split, curpoly=0) = // [0,0,0,0,0] // ]; // hm = [for(i=[0:4]) [for(j=[0:4]) [i,-j,tex[i][j]]]]; -// types = ["quincunx", "convex", "concave","default","alt","min_edge"]; -// grid2d(spacing=5, n=[3,2]){ -// let(s = types[$row*3+$col]){ +// types = ["quincunx", "convex", "concave","min_area", "default","alt","min_edge"]; +// grid_copies(spacing=5, n=[4,2]){ +// let(s = types[$row*4+$col]){ +// if (is_def(s)){ // vnf_polyhedron(vnf_vertex_array(hm,style=s)); // if ($row==1) // back(.8)right(2)rotate($vpr)color("black")text(s,size=.5,anchor=CENTER); // else -// fwd(4.7)right(2)rotate($vpr)color("black")text(s,size=.5,anchor=CENTER); +// fwd(4.7)right(2)rotate($vpr)color("black")text(s,size=.5,anchor=CENTER); +// } // } // } // Continues: -// Note that of the six available styles, five produce a different result. There may exist some concave shape where none of the styles +// Note that of the seven available styles, five produce a different result. There may exist some concave shape where none of the styles // produce the right result everywhere on the shape. If this happens it would be another limitation of height field textures. (If you have an // example of such a texture and shape please let us know!) // Subsection: VNF Textures @@ -2859,8 +2863,19 @@ function associate_vertices(polygons, split, curpoly=0) = // caps=false); // tile = move([0,1/2,2/3],yrot(90,shape)); // vnf_polyhedron(tile); - - +// Continues: +// A VNF texture provides a flat structure. In order to apply this structure to a cylinder or other curved object, the VNF must be sliced +// and "folded" so it can follow the curve. This folding is controlled by the `tex_samples` parameter to {{cyl()}}, {{linear_sweep()}}, +// and {{rotate_sweep()}}. Note that you specify it when you **use** the texture, not when you create it. This differs from height +// fields, where the analogous parameter is the `n=` parameter of the {{texture()}} function. When `tex_samples` is too small, only the +// points given in the VNF will follow the surface, resulting in a blocky look and geometrical artifacts. +// Figure(3D,NoAxes): On the left the `tex_samples` value is small and the texture is blocky. On the right, the default value of 8 allows a reasonable fit to the cylinder. +// xdistribute(spacing=5){ +// cyl(d=10/PI, h=5, chamfer=0, +// texture=texture("bricks_vnf"), tex_samples=1, tex_reps=[6,3], tex_depth=.2); +// cyl(d=10/PI, h=5, chamfer=0, +// texture=texture("bricks_vnf"), tex_samples=8, tex_reps=[6,3], tex_depth=.2); +// } // Function: texture() // Topics: Textures, Knurling diff --git a/vnf.scad b/vnf.scad index 9f09956..628c52c 100644 --- a/vnf.scad +++ b/vnf.scad @@ -54,7 +54,7 @@ EMPTY_VNF = [[],[]]; // The standard empty VNF with no vertices or faces. // col_wrap = If true, add faces to connect the last column to the first. // row_wrap = If true, add faces to connect the last row to the first. // reverse = If true, reverse all face normals. -// style = The style of subdividing the quads into faces. Valid options are "default", "alt", "min_edge", "quincunx", "convex" and "concave". +// style = The style of subdividing the quads into faces. Valid options are "default", "alt", "min_edge", "min_area", "quincunx", "convex" and "concave". // triangulate = If true, triangulates endcaps to resolve possible CGAL issues. This can be an expensive operation if the endcaps are complex. Default: false // Example(3D): // vnf = vnf_vertex_array( From ec73853de3eb7d0d070b92282be15659d9ab8908 Mon Sep 17 00:00:00 2001 From: adrianVmariano Date: Sun, 14 Jan 2024 04:09:47 +0000 Subject: [PATCH 6/6] Version Bump --- version.scad | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.scad b/version.scad index d7b72c3..78b46aa 100644 --- a/version.scad +++ b/version.scad @@ -9,7 +9,7 @@ ////////////////////////////////////////////////////////////////////// -BOSL_VERSION = [2,0,687]; +BOSL_VERSION = [2,0,688]; // Section: BOSL Library Version Functions