mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2024-12-29 16:29:40 +00:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
34ca921490
4 changed files with 169 additions and 87 deletions
|
@ -588,8 +588,7 @@ module screw(spec, head, drive, thread, drive_size,
|
|||
assert(is_finite(length) && length>0, "Must specify positive screw length")
|
||||
assert(is_finite(_shoulder_len) && _shoulder_len>=0, "Must specify a nonegative shoulder length")
|
||||
assert(is_finite(_shoulder_diam) && _shoulder_diam>=0, "Must specify nonnegative shoulder diameter")
|
||||
assert(is_undef(user_thread_len) || (is_finite(user_thread_len) && user_thread_len>=0), "Must specify nonnegative thread length")
|
||||
assert(!_teardrop || pitch==0);
|
||||
assert(is_undef(user_thread_len) || (is_finite(user_thread_len) && user_thread_len>=0), "Must specify nonnegative thread length");
|
||||
sides = max(pitch==0 ? 3 : 12, segs(nominal_diam/2));
|
||||
head_height = headless || flathead ? 0
|
||||
: counterbore==true || is_undef(counterbore) || counterbore==0 ? struct_val(spec, "head_height")
|
||||
|
@ -716,7 +715,7 @@ module screw(spec, head, drive, thread, drive_size,
|
|||
pitch = struct_val(threadspec, "pitch"),
|
||||
l=thread_len+eps_thread, left_handed=false, internal=_internal,
|
||||
bevel1=bevel1,
|
||||
bevel2=bevel2,
|
||||
bevel2=bevel2,teardrop=_teardrop,
|
||||
blunt_start=blunt_start, blunt_start1=blunt_start1, blunt_start2=blunt_start2,
|
||||
$fn=sides, anchor=TOP);
|
||||
}
|
||||
|
@ -774,7 +773,7 @@ module screw(spec, head, drive, thread, drive_size,
|
|||
// head = head type. See [screw heads](#subsection-screw-heads) Default: none
|
||||
// ---
|
||||
// thread = thread type or specification for threaded masks, true to make a threaded mask with the standard threads, or false to make an unthreaded mask. See [screw pitch](#subsection-standard-screw-pitch). Default: false
|
||||
// teardrop = if true produce teardrop hole. Only compatible with clearance holes, not threaded. Default: false
|
||||
// teardrop = if true produce teardrop hole. Default: false
|
||||
// oversize = amount to increase diameter of the screw hole (hole and countersink). A scalar or length 2 vector. Default: use computed tolerance
|
||||
// hole_oversize = amount to increase diameter of the hole. Overrides the use of tolerance and replaces any settings given in the screw specification.
|
||||
// head_oversize = amount to increase diameter of head. Overrides the user of tolerance and replaces any settings given in the screw specification.
|
||||
|
@ -852,7 +851,6 @@ module screw_hole(spec, head, thread, oversize, hole_oversize, head_oversize,
|
|||
counterbore = default(counterbore, default_counterbore);
|
||||
dummy = _validate_screw_spec(screwspec);
|
||||
threaded = thread==true || (is_finite(thread) && thread>0) || (is_undef(thread) && struct_val(screwspec,"pitch")>0);
|
||||
dummy2 = assert(!threaded || !teardrop, "Cannot make threaded teardrop holes");
|
||||
oversize = force_list(oversize,2);
|
||||
hole_oversize = first_defined([hole_oversize, oversize[0],struct_val(screwspec,"shaft_oversize")]);
|
||||
head_oversize = first_defined([head_oversize, oversize[1],struct_val(screwspec,"head_oversize")]);
|
||||
|
|
114
skin.scad
114
skin.scad
|
@ -2876,6 +2876,16 @@ function associate_vertices(polygons, split, curpoly=0) =
|
|||
// cyl(d=10/PI, h=5, chamfer=0,
|
||||
// texture=texture("bricks_vnf"), tex_samples=8, tex_reps=[6,3], tex_depth=.2);
|
||||
// }
|
||||
// Continues:
|
||||
// Note that when the VNF is sliced,
|
||||
// extra points can be introduced in the interior of faces leading to unexpected irregularities in the textures, which appear
|
||||
// as extra triangles. These artifacts can be minimized by making the VNF texture's faces as large as possible rather than using
|
||||
// a triangulated VNF, but depending on the specific VNF texture, it may be impossible to entirely eliminate them.
|
||||
// Figure(3D,Big,NoAxes,VPR=[140.9,0,345.7],VPT=[9.48289,-0.88709,5.7837],VPD=39.5401): The left shows a normal bricks_vnf texture. The right shows a texture that was first passed through {{vnf_triangulate()}}. Note the extra triangle artifacts visible across the brick faces.
|
||||
// tex = texture("bricks_vnf");
|
||||
// cyl(d=10,h=15,texture=tex, tex_reps=[4,2],tex_samples=5);
|
||||
// up(7)fwd(-3)right(15)cyl(d=10,h=15,texture=vnf_triangulate(tex), tex_reps=[4,2],tex_samples=5);
|
||||
|
||||
|
||||
// Function: texture()
|
||||
// Topics: Textures, Knurling
|
||||
|
@ -3155,10 +3165,10 @@ function texture(tex, n, border, gap, roughness, inset) =
|
|||
assert(is_undef(n), str(tex,__vnf_no_n_mesg))
|
||||
let(
|
||||
border = default(border,1/4)*2,
|
||||
gap = default(gap,1/4)
|
||||
gap = default(gap,1/4),
|
||||
f=echo(gap, border, gap+border, gap+2*border)
|
||||
)
|
||||
assert(all_nonnegative([border,gap]), "trunc_ribs_vnf texture requires gap>=0 and border>=0")
|
||||
assert(gap+border > 0, "trunc_ribs_vnf texture requires that gap+border>0")
|
||||
assert(gap+border <= 1, "trunc_ribs_vnf texture requires that gap+2*border<=1")
|
||||
[
|
||||
[
|
||||
|
@ -3166,9 +3176,9 @@ function texture(tex, n, border, gap, roughness, inset) =
|
|||
each move([0.5,0.5], p=path3d(rect([1-gap-border,1]),1)),
|
||||
each path3d(square(1)),
|
||||
], [
|
||||
[1,2,6], [1,6,5], [0,4,3], [3,4,7],
|
||||
if (gap+border < 1-EPSILON) each [[4,5,6], [4,6,7]],
|
||||
if (gap > EPSILON) each [[1,9,10], [1,10,2], [0,3,8], [3,11,8]],
|
||||
[4,7,3,0], [1,2,6,5],
|
||||
if (gap+border < 1-EPSILON) [4,5,6,7],
|
||||
if (gap > EPSILON) each [[1,9,10,2], [0,3,11,8]],
|
||||
]
|
||||
] :
|
||||
tex=="wave_ribs"?
|
||||
|
@ -3249,11 +3259,9 @@ function texture(tex, n, border, gap, roughness, inset) =
|
|||
each path3d(square(1)),
|
||||
each move([1/2,1/2,1], p=path3d(rect(1-2*border))),
|
||||
], [
|
||||
for (i=[0:3]) each [
|
||||
[i, (i+1)%4, i+4],
|
||||
[(i+1)%4, (i+1)%4+4, i+4],
|
||||
],
|
||||
[4,5,6], [4,6,7],
|
||||
for (i=[0:3])
|
||||
[i, (i+1)%4, (i+1)%4+4,i+4],
|
||||
[4,5,6,7]
|
||||
]
|
||||
] :
|
||||
tex=="hills"?
|
||||
|
@ -3300,15 +3308,9 @@ function texture(tex, n, border, gap, roughness, inset) =
|
|||
each move([0.5+gap/2, 0.5+gap/2, 0], p=path3d(square([0.5-gap/2, 0.5-gap]))),
|
||||
each move([0.5+gap/2+border/2, 0.5+gap/2+border/2, 1], p=path3d(square([0.5-gap/2-border/2, 0.5-gap-border]))),
|
||||
], [
|
||||
[ 8, 9,10], [ 8,10,11], [16,17,18], [16,18,19], [24,25,26],
|
||||
[24,26,27], [ 0, 1, 5], [ 0, 5, 4], [ 1,13, 6], [ 1, 6, 5],
|
||||
[ 6,13,12], [ 6,12,21], [ 7,21,20], [ 6,21, 7], [ 0, 4, 7],
|
||||
[ 0, 7,20], [21,12,15], [21,15,22], [ 3,23,22], [ 3,22,15],
|
||||
[ 2,15,14], [ 2, 3,15], [23,27,26], [23,26,22], [21,22,26],
|
||||
[21,26,25], [21,25,24], [21,24,20], [12,16,19], [12,19,15],
|
||||
[14,15,19], [14,19,18], [13,17,16], [13,16,12], [ 6,10, 9],
|
||||
[ 6, 9, 5], [ 5, 9, 8], [ 5, 8, 4], [ 4, 8,11], [ 4,11, 7],
|
||||
[ 7,11,10], [ 7,10, 6],
|
||||
[0,4,7,20], [4,8,11,7], [9,8,4,5], [4,0,1,5], [10,9,5,6],
|
||||
[20,7,6,13,12,21] ,[2,3,23,22,15,14], [15,19,18,14], [22,23,27,26], [16,19,15,12],[13,6,5,1],
|
||||
[26,25,21,22], [8,9,10,11],[7,11,10,6],[17,16,12,13],[22,21,12,15],[16,17,18,19],[24,25,26,27],[25,24,20,21]
|
||||
]
|
||||
] :
|
||||
tex=="checkers"?
|
||||
|
@ -3329,15 +3331,11 @@ function texture(tex, n, border, gap, roughness, inset) =
|
|||
[1,1/2,0], [1,1-border,0], [1,1,1], [1/2-border/2,1-border/2,1/2],
|
||||
[1-border/2,1-border/2,1/2], [1-border/2,1/2-border/2,1/2],
|
||||
], [
|
||||
for (i=[0:4:12]) each [[i,i+1,i+2], [i, i+2, i+3]],
|
||||
[10,13,11], [13,12,11], [2,5,4], [4,3,2],
|
||||
[0,3,10], [10,9,0], [4,7,14], [4,14,13],
|
||||
[4,13,16], [10,16,13], [10,3,16], [3,4,16],
|
||||
[7,6,17], [7,17,18], [14,19,20], [14,20,15],
|
||||
[8,11,22], [8,22,21], [12,15,24], [12,24,23],
|
||||
[7,18,26], [7,26,14], [14,26,19], [18,19,26],
|
||||
[15,20,27], [20,25,27], [24,27,25], [15,27,24],
|
||||
[11,12,28], [12,23,28], [11,28,22], [23,22,28],
|
||||
for (i=[0:4:12]) each [[i,i+1,i+2,i+3]],
|
||||
[10,16,13,12,28,11],[9,0,3,16,10], [11,28,22,21,8],
|
||||
[4,7,26,14,13,16], [7,6,17,18,26], [5,4,16,3,2],
|
||||
[19,20,27,15,14,26], [20,25,27], [19,26,18],
|
||||
[23,28,12,15,27,24], [23,22,28], [24,27,25]
|
||||
]
|
||||
] :
|
||||
tex=="cones"?
|
||||
|
@ -3352,11 +3350,13 @@ function texture(tex, n, border, gap, roughness, inset) =
|
|||
[
|
||||
each move([1/2,1/2], p=path3d(circle(d=1-2*border,$fn=n))),
|
||||
[1/2,1/2,1],
|
||||
each path3d(square(1)),
|
||||
each border>0 ? path3d(subdivide_path(square(1),refine=2,closed=true))
|
||||
: path3d(square(1))
|
||||
], [
|
||||
for (i=[0:1:n-1]) [i, (i+1)%n, n],
|
||||
for (i=[0:1:3], j=[0:1:n/4-1]) [n+1+i, (i*n/4+j+1)%n, i*n/4+j],
|
||||
if (border > 0) for (i = [0:1:3]) [i+n+1, (i+1)%4+n+1, ((i+1)*n/4)%n],
|
||||
if (border>0) for (i=[0:3]) [for(j=[(i+1)*n/4:-1:i*n/4]) j%n,
|
||||
(2*i+7)%8+n+1,(2*i)%8+n+1, (2*i+1)%8+n+1],
|
||||
if (border==0) for (i=[0:3]) [for(j=[(i+1)*n/4:-1:i*n/4]) j%n, i+n+1]
|
||||
]
|
||||
] :
|
||||
tex=="cubes"?
|
||||
|
@ -3387,10 +3387,10 @@ function texture(tex, n, border, gap, roughness, inset) =
|
|||
for (a=[0:90:359]) each move([1/2,1/2], p=zrot(-a, p=[[1/2,border,1], [border,1/2,1], [1/2,1/2,1]]))
|
||||
], [
|
||||
for (i=[0:3]) each let(j=i*3+8) [
|
||||
[i,(i+1)%4,(i+1)%4+4], [i,(i+1)%4+4,i+4],
|
||||
[j,j+1,j+2], [i, (i+3)%4, j], [(i+3)%4, j+1, j],
|
||||
[i,(i+1)%4,(i+1)%4+4,i+4],
|
||||
[j,j+1,j+2], [i, (i+3)%4,j+1, j],
|
||||
],
|
||||
[4,5,6], [4,6,7],
|
||||
[4,5,6,7],
|
||||
]
|
||||
] :
|
||||
tex=="dimples" || tex=="dots" ?
|
||||
|
@ -3408,23 +3408,25 @@ function texture(tex, n, border, gap, roughness, inset) =
|
|||
cp = [1/2, 1/2, r*sin(45)*(dots?-1:1)],
|
||||
sc = 1 / (r - abs(cp.z)),
|
||||
uverts = [
|
||||
each path3d(square(1)),
|
||||
for (p=[0:1:rows-1], t=[0:360/n:359.999])
|
||||
cp + (
|
||||
dots? spherical_to_xyz(r, -t, 45-45*p/rows) :
|
||||
spherical_to_xyz(r, -t, 135+45*p/rows)
|
||||
),
|
||||
cp + r * (dots?UP:DOWN),
|
||||
each border>0 ? path3d(subdivide_path(square(1),refine=2,closed=true))
|
||||
: path3d(square(1)),
|
||||
|
||||
],
|
||||
verts = zscale(sc, p=uverts),
|
||||
faces = [
|
||||
for (i=[0:1:3], j=[0:1:n/4-1]) [i, 4+(i*n/4+j+1)%n, 4+i*n/4+j],
|
||||
for (i=[0:1:rows-2], j=[0:1:n-1]) each [
|
||||
[4+i*n+j, 4+(i+1)*n+(j+1)%n, 4+(i+1)*n+j],
|
||||
[4+i*n+j, 4+i*n+(j+1)%n, 4+(i+1)*n+(j+1)%n],
|
||||
[i*n+j, i*n+(j+1)%n, (i+1)*n+(j+1)%n,(i+1)*n+j],
|
||||
],
|
||||
for (i=[0:1:n-1]) [4+(rows-1)*n+i, 4+(rows-1)*n+(i+1)%n, 4+rows*n],
|
||||
if (border>0) for (i=[0:3]) [i, (i+1)%4, 4+(i+1)%4*n/4]
|
||||
for (i=[0:1:n-1]) [(rows-1)*n+i, (rows-1)*n+(i+1)%n, rows*n],
|
||||
if (border>0) for (i=[0:3]) [for(j=[(i+1)*n/4:-1:i*n/4]) j%n,
|
||||
(2*i+7)%8+rows*n+1,(2*i)%8+rows*n+1, (2*i+1)%8+rows*n+1],
|
||||
if (border==0) for (i=[0:3]) [for(j=[(i+1)*n/4:-1:i*n/4]) j%n, i+rows*n+1]
|
||||
]
|
||||
) [verts, faces] :
|
||||
tex=="tri_grid"?
|
||||
|
@ -3457,13 +3459,15 @@ function texture(tex, n, border, gap, roughness, inset) =
|
|||
[adj,y6,1], [1-adj,y6,1],
|
||||
[0,1,0], [1,1,0],
|
||||
], [
|
||||
[0,2,3], [0,3,1], [2,6,3], [0,12,2], [2,12,6], [3,6,12], [3,12,1],
|
||||
[0,4,8], [0,8,12], [4,7,8], [7,11,12], [7,12,8],
|
||||
[1,12,9], [1,9,5], [5,9,10], [9,12,13], [9,13,10],
|
||||
[11,14,15], [11,15,12], [19,15,14], [19,23,12], [19,12,15],
|
||||
[12,16,13], [16,17,13], [16,20,17], [12,24,20], [12,20,16],
|
||||
[21,22,18], [21,23,24], [21,24,22], [12,23,21], [12,21,18],
|
||||
[12,18,22], [12,22,24],
|
||||
[0,2,3,1],
|
||||
[21,23,24,22],
|
||||
[2,6,3], [0,12,6,2], [1,3,6,12],
|
||||
[0,4,8,12], [4,7,8], [8,7,11,12],
|
||||
[1,12,9,5], [5,9,10], [10,9,12,13],
|
||||
[11,14,15,12], [19,15,14], [19,23,12,15],
|
||||
[16,17,13,12], [16,20,17], [12,24,20,16],
|
||||
[21,22,18], [12,23,21,18],
|
||||
[12,18,22,24],
|
||||
]
|
||||
] :
|
||||
tex=="hex_grid"?
|
||||
|
@ -3492,14 +3496,14 @@ function texture(tex, n, border, gap, roughness, inset) =
|
|||
hex[5]+[0,diag*sc,1],
|
||||
[0,1,1], [0.5-border,1,1], [0.5,1,0], [0.5+border,1,1], [1,1,1],
|
||||
], [
|
||||
for (i=[0:2:5]) let(b=6) [b+i, b+(i+1)%6, b+(i+2)%6], [6,8,10],
|
||||
for (i=[0:1:5]) each [ [i, (i+1)%6, (i+1)%6+6], [i, (i+1)%6+6, i+6] ],
|
||||
[19,13,12], [19,12,20], [17,16,15], [17,15,14],
|
||||
[21,25,26], [21,26,22], [23,28,29], [23,29,24],
|
||||
[0,12,13], [0,13,1], [1,14,15], [1,15,2],
|
||||
[3,21,22], [3,22,4], [4,23,24], [4,24,5],
|
||||
[1,13,19], [1,19,18], [1,18,17], [1,17,14],
|
||||
[4,22,26], [4,26,27], [4,27,28], [4,28,23],
|
||||
count(6,s=6),
|
||||
for (i=[0:1:5]) [i,(i+1)%6, (i+1)%6+6, i+6],
|
||||
[20,19,13,12], [17,16,15,14],
|
||||
[21,25,26,22], [23,28,29,24],
|
||||
[0,12,13,1], [1,14,15,2],
|
||||
[3,21,22,4], [4,23,24,5],
|
||||
[1,13,19,18], [1,18,17,14],
|
||||
[4,22,26,27], [4,27,28,23],
|
||||
]
|
||||
] :
|
||||
tex=="rough"?
|
||||
|
|
|
@ -9,8 +9,7 @@
|
|||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
BOSL_VERSION = [2,0,694];
|
||||
|
||||
BOSL_VERSION = [2,0,700];
|
||||
|
||||
|
||||
// Section: BOSL Library Version Functions
|
||||
|
|
131
vnf.scad
131
vnf.scad
|
@ -682,7 +682,7 @@ function vnf_faces(vnf) = vnf[1];
|
|||
// Synopsis: Reverses the faces of a VNF.
|
||||
// SynTags: VNF
|
||||
// Topics: VNF Manipulation
|
||||
// See Also: vnf_quantize(), vnf_merge_points(), vnf_drop_unused_points(), vnf_triangulate(), vnf_slice()
|
||||
// See Also: vnf_quantize(), vnf_merge_points(), vnf_drop_unused_points(), vnf_triangulate(), vnf_slice(), vnf_unify_faces()
|
||||
// Usage:
|
||||
// rvnf = vnf_reverse_faces(vnf);
|
||||
// Description:
|
||||
|
@ -712,7 +712,7 @@ function vnf_quantize(vnf,q=pow(2,-12)) =
|
|||
// Synopsis: Consolidates duplicate vertices of a VNF.
|
||||
// SynTags: VNF
|
||||
// Topics: VNF Manipulation
|
||||
// See Also: vnf_reverse_faces(), vnf_quantize(), vnf_drop_unused_points(), vnf_triangulate(), vnf_slice()
|
||||
// See Also: vnf_reverse_faces(), vnf_quantize(), vnf_drop_unused_points(), vnf_triangulate(), vnf_slice(), vnf_unify_faces()
|
||||
// Usage:
|
||||
// new_vnf = vnf_merge_points(vnf, [eps]);
|
||||
// Description:
|
||||
|
@ -748,7 +748,7 @@ function vnf_merge_points(vnf,eps=EPSILON) =
|
|||
// Synopsis: Removes unreferenced vertices from a VNF.
|
||||
// SynTags: VNF
|
||||
// Topics: VNF Manipulation
|
||||
// See Also: vnf_reverse_faces(), vnf_quantize(), vnf_merge_points(), vnf_triangulate(), vnf_slice()
|
||||
// See Also: vnf_reverse_faces(), vnf_quantize(), vnf_merge_points(), vnf_triangulate(), vnf_slice(), vnf_unify_faces()
|
||||
// Usage:
|
||||
// clean_vnf = vnf_drop_unused_points(vnf);
|
||||
// Description:
|
||||
|
@ -780,7 +780,7 @@ function _link_indicator(l,imin,imax) =
|
|||
// Synopsis: Triangulates the faces of a VNF.
|
||||
// SynTags: VNF
|
||||
// Topics: VNF Manipulation
|
||||
// See Also: vnf_reverse_faces(), vnf_quantize(), vnf_merge_points(), vnf_drop_unused_points(), vnf_slice()
|
||||
// See Also: vnf_reverse_faces(), vnf_quantize(), vnf_merge_points(), vnf_drop_unused_points(), vnf_slice(), vnf_unify_faces()
|
||||
// Usage:
|
||||
// vnf2 = vnf_triangulate(vnf);
|
||||
// Description:
|
||||
|
@ -806,6 +806,84 @@ function vnf_triangulate(vnf) =
|
|||
|
||||
|
||||
|
||||
// Function: vnf_unify_faces()
|
||||
// Synopsis: Remove triangulation from VNF, returning a copy with full faces
|
||||
// SynTags: VNF
|
||||
// Topics: VNF Manipulation
|
||||
// See Also: vnf_reverse_faces(), vnf_quantize(), vnf_merge_points(), vnf_triangulate(), vnf_slice()
|
||||
// Usage:
|
||||
// newvnf = vnf_unify_faces(vnf);
|
||||
// Description:
|
||||
// When a VNF has been triangulated, the polygons that form the true faces have been chopped up into
|
||||
// triangles. This can create problems for algorithms that operate on the VNF itself, where you might
|
||||
// want to be able to identify the true faces. This function merges together the triangles that
|
||||
// form those true faces, turning a VNF where each true face is represented by a single entry
|
||||
// in the faces list of the VNF. This function requires that the true faces have no internal vertices.
|
||||
// This will always be true for a triangulated VNF, but might fail for a VNF with some other
|
||||
// face partition. If internal vertices are present, the output will include backtracking paths from
|
||||
// the boundary to all of those vertices.
|
||||
// Arguments:
|
||||
// vnf = vnf whose faces you want to unify
|
||||
// Example(3D,Med,NoAxes): Original prism on the left is triangulated. On the right, the result of unifying the faces.
|
||||
// $fn=16;
|
||||
// poly = linear_sweep(hexagon(side=10),h=35);
|
||||
// vnf = vnf_unify_faces(poly);
|
||||
// vnf_wireframe(poly);
|
||||
// color([0,1,1,.70])vnf_polyhedron(poly);
|
||||
// right(25){
|
||||
// vnf_wireframe(vnf);
|
||||
// color([0,1,1,.70])vnf_polyhedron(vnf);
|
||||
// }
|
||||
|
||||
function vnf_unify_faces(vnf) =
|
||||
let(
|
||||
faces = vnf[1],
|
||||
edges = [for(i=idx(faces), edge=pair(faces[i],wrap=true))
|
||||
[[min(edge),max(edge)],i]],
|
||||
normals = [for(face=faces) polygon_normal(select(vnf[0],face))],
|
||||
facelist = count(faces), //[for(i=[1:1:len(faces)-1]) i],
|
||||
newfaces = _detri_combine_faces(edges,faces,normals,facelist,0)
|
||||
)
|
||||
[vnf[0],newfaces];
|
||||
|
||||
|
||||
function _detri_combine_faces(edgelist,faces,normals,facelist,curface) =
|
||||
curface==len(faces)? select(faces,facelist)
|
||||
: !in_list(curface,facelist) ? _detri_combine_faces(edgelist,faces,normals,facelist,curface+1)
|
||||
:
|
||||
let(
|
||||
thisface=faces[curface],
|
||||
neighbors = [for(i=idx(thisface))
|
||||
let(
|
||||
edgepair = search([sort(select(thisface,i,i+1))],edgelist,0)[0],
|
||||
choices = select(edgelist,edgepair),
|
||||
good_choice=[for(choice=choices)
|
||||
if (choice[1]!=curface && in_list(choice[1],facelist) && normals[choice[1]]*normals[curface]>1-EPSILON)
|
||||
choice],
|
||||
d=assert(len(good_choice)<=1)
|
||||
)
|
||||
len(good_choice)==1 ? good_choice[0][1] : -1
|
||||
],
|
||||
// Check for duplicates in the neighbor list so we don't add them twice
|
||||
dups = search([for(n=neighbors) if (n>=0) n], neighbors,0),
|
||||
goodind = column(dups,0),
|
||||
newface = [for(i=idx(thisface))
|
||||
each
|
||||
!in_list(i,goodind) ? [thisface[i]]
|
||||
:
|
||||
let(
|
||||
ind = search(select(thisface,i,i+1), faces[neighbors[i]])
|
||||
)
|
||||
select(faces[neighbors[i]],ind[0],ind[1]-1)
|
||||
],
|
||||
usedfaces = [for(n=neighbors) if (n>=0) n],
|
||||
faces = list_set(faces,curface,newface),
|
||||
facelist = list_remove_values(facelist,usedfaces)
|
||||
)
|
||||
_detri_combine_faces(edgelist,faces,normals,facelist,len(usedfaces)==0?curface+1:curface);
|
||||
|
||||
|
||||
|
||||
function _vnf_sort_vertices(vnf, idx=[2,1,0]) =
|
||||
let(
|
||||
verts = vnf[0],
|
||||
|
@ -843,7 +921,8 @@ function _vnf_sort_vertices(vnf, idx=[2,1,0]) =
|
|||
// color("red")vnf_wireframe(sliced,width=.3);
|
||||
function vnf_slice(vnf,dir,cuts) =
|
||||
let(
|
||||
cuts = [for (cut=cuts) _shift_cut_plane(vnf,dir,cut)],
|
||||
// Code below seems to be unnecessary
|
||||
//cuts = [for (cut=cuts) _shift_cut_plane(vnf,dir,cut)],
|
||||
vert = vnf[0],
|
||||
faces = [for(face=vnf[1]) select(vert,face)],
|
||||
poly_list = _slice_3dpolygons(faces, dir, cuts)
|
||||
|
@ -920,26 +999,28 @@ function _slice_3dpolygons(polys, dir, cuts) =
|
|||
)
|
||||
flatten([
|
||||
for (poly = polys)
|
||||
let( plane = plane_from_polygon(poly))
|
||||
assert(plane,"Found non-coplanar face.")
|
||||
let(
|
||||
normal = point3d(plane),
|
||||
pnormal = normal - (normal*I[dir_ind])*I[dir_ind]
|
||||
)
|
||||
approx(pnormal,[0,0,0]) ? [poly] :
|
||||
let (
|
||||
pind = max_index(v_abs(pnormal)), // project along this direction
|
||||
otherind = 3-pind-dir_ind, // keep dir_ind and this direction
|
||||
keep = [I[dir_ind], I[otherind]], // dir ind becomes the x dir
|
||||
poly2d = poly*transpose(keep), // project to 2d, putting selected direction in the X position
|
||||
poly_list = [for(p=_split_2dpolygons_at_each_x([poly2d], cuts))
|
||||
let(
|
||||
a = p*keep, // unproject, but pind dimension data is missing
|
||||
ofs = outer_product((repeat(plane[3], len(a))-a*normal)/plane[pind],I[pind])
|
||||
)
|
||||
a+ofs] // ofs computes the missing pind dimension data and adds it back in
|
||||
)
|
||||
poly_list
|
||||
if (polygon_area(poly)>EPSILON) // Discard zero area polygons
|
||||
let(
|
||||
plane = plane_from_polygon(poly,1e-4))
|
||||
assert(plane,"Found non-coplanar face.")
|
||||
let(
|
||||
normal = point3d(plane),
|
||||
pnormal = normal - (normal*I[dir_ind])*I[dir_ind]
|
||||
)
|
||||
approx(pnormal,[0,0,0]) ? [poly] // Polygons parallel to cut plane just pass through
|
||||
: let(
|
||||
pind = max_index(v_abs(pnormal)), // project along this direction
|
||||
otherind = 3-pind-dir_ind, // keep dir_ind and this direction
|
||||
keep = [I[dir_ind], I[otherind]], // dir ind becomes the x dir
|
||||
poly2d = poly*transpose(keep), // project to 2d, putting selected direction in the X position
|
||||
poly_list = [for(p=_split_2dpolygons_at_each_x([poly2d], cuts))
|
||||
let(
|
||||
a = p*keep, // unproject, but pind dimension data is missing
|
||||
ofs = outer_product((repeat(plane[3], len(a))-a*normal)/plane[pind],I[pind])
|
||||
)
|
||||
a+ofs] // ofs computes the missing pind dimension data and adds it back in
|
||||
)
|
||||
poly_list
|
||||
]);
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue