Merge pull request #473 from revarbat/revarbat_dev

Fixes for worm_gear()
This commit is contained in:
Revar Desmera 2021-03-15 05:20:11 -07:00 committed by GitHub
commit 10a667c86b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 125 additions and 72 deletions

View file

@ -489,12 +489,19 @@ function deduplicate_indexed(list, indices, closed=false, eps=EPSILON) =
indices==[]? [] : indices==[]? [] :
assert(is_vector(indices), "Indices must be a list of numbers.") assert(is_vector(indices), "Indices must be a list of numbers.")
let( let(
ll = len(list),
l = len(indices), l = len(indices),
end = l-(closed?0:1) end = l-(closed?0:1)
) [ ) [
for (i = [0:1:l-1]) let( for (i = [0:1:l-1]) let(
a = list[indices[i]], idx1 = indices[i],
b = list[indices[(i+1)%l]], idx2 = indices[(i+1)%l],
a = assert(idx1>=0,"Bad index.")
assert(idx1<len(list),"Bad index in indices.")
list[idx1],
b = assert(idx2>=0,"Bad index.")
assert(idx2<len(list),"Bad index in indices.")
list[idx2],
eq = (a == b)? true : eq = (a == b)? true :
(a*0 != b*0) || (eps==0)? false : (a*0 != b*0) || (eps==0)? false :
is_num(a) || is_vector(a) ? approx(a, b, eps=eps) is_num(a) || is_vector(a) ? approx(a, b, eps=eps)

View file

@ -1420,7 +1420,7 @@ function worm_gear(
tp = [0,r1,0] - spherical_to_xyz(r2, 90, 90+zang), tp = [0,r1,0] - spherical_to_xyz(r2, 90, 90+zang),
zang2 = u * helical zang2 = u * helical
) [ ) [
for (i = [0:1:teeth]) each for (i = [0:1:teeth-1]) each
apply( apply(
zrot(-i*360/teeth+zang2) * zrot(-i*360/teeth+zang2) *
move(tp) * move(tp) *
@ -1435,7 +1435,7 @@ function worm_gear(
face_pts = len(tooth_profile), face_pts = len(tooth_profile),
gear_pts = face_pts * teeth, gear_pts = face_pts * teeth,
top_faces =[ top_faces =[
for (i=[0:1:teeth-1], j=[0:1:(face_pts/2)-1]) each [ for (i=[0:1:teeth-1], j=[0:1:(face_pts/2)-2]) each [
[i*face_pts+j, (i+1)*face_pts-j-1, (i+1)*face_pts-j-2], [i*face_pts+j, (i+1)*face_pts-j-1, (i+1)*face_pts-j-2],
[i*face_pts+j, (i+1)*face_pts-j-2, i*face_pts+j+1] [i*face_pts+j, (i+1)*face_pts-j-2, i*face_pts+j+1]
], ],

182
vnf.scad
View file

@ -291,26 +291,27 @@ function vnf_vertex_array(
cap1 = first_defined([cap1,caps,false]), cap1 = first_defined([cap1,caps,false]),
cap2 = first_defined([cap2,caps,false]), cap2 = first_defined([cap2,caps,false]),
colcnt = cols - (col_wrap?0:1), colcnt = cols - (col_wrap?0:1),
rowcnt = rows - (row_wrap?0:1) rowcnt = rows - (row_wrap?0:1),
verts = [
each pts,
if (style=="quincunx") (
for (r = [0:1:rowcnt-1]) (
for (c = [0:1:colcnt-1]) (
let(
i1 = ((r+0)%rows)*cols + ((c+0)%cols),
i2 = ((r+1)%rows)*cols + ((c+0)%cols),
i3 = ((r+1)%rows)*cols + ((c+1)%cols),
i4 = ((r+0)%rows)*cols + ((c+1)%cols)
) mean([pts[i1], pts[i2], pts[i3], pts[i4]])
)
)
)
]
) )
rows<=1 || cols<=1 ? vnf : rows<=1 || cols<=1 ? vnf :
vnf_merge(cleanup=true, [ vnf_merge(cleanup=true, [
vnf, [ vnf, [
concat( verts,
pts,
style!="quincunx"? [] : [
for (r = [0:1:rowcnt-1]) (
for (c = [0:1:colcnt-1]) (
let(
i1 = ((r+0)%rows)*cols + ((c+0)%cols),
i2 = ((r+1)%rows)*cols + ((c+0)%cols),
i3 = ((r+1)%rows)*cols + ((c+1)%cols),
i4 = ((r+0)%rows)*cols + ((c+1)%cols)
) mean([pts[i1], pts[i2], pts[i3], pts[i4]])
)
)
]
),
concat( concat(
[ [
for (r = [0:1:rowcnt-1]) ( for (r = [0:1:rowcnt-1]) (
@ -337,8 +338,9 @@ function vnf_vertex_array(
) fsets[test?0:1] : ( ) fsets[test?0:1] : (
[[i1,i3,i2],[i1,i4,i3]] [[i1,i3,i2],[i1,i4,i3]]
), ),
rfaces = reverse? [for (face=faces) reverse(face)] : faces rfaces = reverse? [for (face=faces) reverse(face)] : faces,
) rfaces ffaces = [for (face=rfaces) if(len(deduplicate_indexed(verts,face,closed=true))>=3) face]
) faces
) )
) )
], ],
@ -618,14 +620,15 @@ function vnf_bend(vnf,r,d,axis="Z") =
// Currently checks for these problems: // Currently checks for these problems:
// Type | Color | Code | Message // Type | Color | Code | Message
// ------- | -------- | ------------ | --------------------------------- // ------- | -------- | ------------ | ---------------------------------
// WARNING | Yellow | BIG_FACE | Face has more than 3 vertices, and may confuse CGAL // WARNING | Yellow | BIG_FACE | Face has more than 3 vertices, and may confuse CGAL.
// WARNING | Brown | NULL_FACE | Face has zero area // WARNING | Brown | NULL_FACE | Face has zero area.
// ERROR | Cyan | NONPLANAR | Face vertices are not coplanar // ERROR | Cyan | NONPLANAR | Face vertices are not coplanar.
// ERROR | Orange | OVRPOP_EDGE | Too many faces attached at edge // ERROR | Brown | DUP_FACE | Multiple instances of the same face.
// ERROR | Violet | REVERSAL | Faces reverse across edge // ERROR | Orange | MULTCONN | Multiply Connected Geometry. Too many faces attached at Edge.
// ERROR | Red | T_JUNCTION | Vertex is mid-edge on another Face // ERROR | Violet | REVERSAL | Faces reverse across edge.
// ERROR | Blue | FACE_ISECT | Faces intersect // ERROR | Red | T_JUNCTION | Vertex is mid-edge on another Face.
// ERROR | Magenta | HOLE_EDGE | Edge bounds Hole // ERROR | Blue | FACE_ISECT | Faces intersect.
// ERROR | Magenta | HOLE_EDGE | Edge bounds Hole.
// . // .
// Still to implement: // Still to implement:
// - Overlapping coplanar faces. // - Overlapping coplanar faces.
@ -649,7 +652,7 @@ function vnf_bend(vnf,r,d,axis="Z") =
// [a, b, e], [a, c, b], [a, d, c], [a, e, d], [b, c, d, e] // [a, b, e], [a, c, b], [a, d, c], [a, e, d], [b, c, d, e]
// ]); // ]);
// vnf_validate(vnf); // vnf_validate(vnf);
// Example: OVRPOP_EDGE Errors; More Than Two Faces Attached to the Same Edge. This confuses CGAL, and can lead to failed renders. // Example: MULTCONN Errors; More Than Two Faces Attached to the Same Edge. This confuses CGAL, and can lead to failed renders.
// vnf = vnf_triangulate(linear_sweep(union(square(50), square(50,anchor=BACK+RIGHT)), height=50)); // vnf = vnf_triangulate(linear_sweep(union(square(50), square(50,anchor=BACK+RIGHT)), height=50));
// vnf_validate(vnf); // vnf_validate(vnf);
// Example: REVERSAL Errors; Faces Reversed Across Edge // Example: REVERSAL Errors; Faces Reversed Across Edge
@ -700,61 +703,95 @@ function vnf_validate(vnf, show_warns=true, check_isects=false) =
for (face=faces, edge=pair(face,true)) for (face=faces, edge=pair(face,true))
edge[0]<edge[1]? edge : [edge[1],edge[0]] edge[0]<edge[1]? edge : [edge[1],edge[0]]
]), ]),
dfaces = [
for (face=faces) let(
face=deduplicate_indexed(varr,face,closed=true)
) if(len(face)>=3)
face
],
face_areas = [
for (face = faces)
len(face) < 3? 0 :
polygon_area([for (k=face) varr[k]])
],
edgecnts = unique_count(edges), edgecnts = unique_count(edges),
uniq_edges = edgecnts[0], uniq_edges = edgecnts[0],
issues = []
)
let(
big_faces = !show_warns? [] : [ big_faces = !show_warns? [] : [
for (face = faces) for (face = faces)
if (len(face) > 3) if (len(face) > 3)
_vnf_validate_err("BIG_FACE", [for (i=face) varr[i]]) _vnf_validate_err("BIG_FACE", [for (i=face) varr[i]])
], ],
null_faces = !show_warns? [] : [ null_faces = !show_warns? [] : [
for (face = faces) let( for (i = idx(faces)) let(
face = deduplicate(face,closed=true) face = faces[i],
) area = face_areas[i],
if (len(face)>=3) let( faceverts = [for (k=face) varr[k]]
faceverts = [for (k=face) varr[k]],
area = polygon_area(faceverts)
) )
if (is_num(area) && abs(area) < EPSILON) if (is_num(area) && abs(area) < EPSILON)
_vnf_validate_err("NULL_FACE", faceverts) _vnf_validate_err("NULL_FACE", faceverts)
], ],
nonplanars = unique([ issues = concat(big_faces, null_faces)
for (face = faces) let( )
faceverts = [for (k=face) varr[k]], let(
area = polygon_area(faceverts) repeated_faces = [
) for (i=idx(dfaces), j=idx(dfaces))
if (is_num(area) && abs(area) > EPSILON) if (i!=j) let(
if (!coplanar(faceverts)) face1 = dfaces[i],
_vnf_validate_err("NONPLANAR", faceverts) face2 = dfaces[j]
]), ) if (min(face1) == min(face2)) let(
overpop_edges = unique([ min1 = min_index(face1),
for (i=idx(uniq_edges)) min2 = min_index(face2)
) if (min1 == min2) let(
sface1 = list_rotate(face1,min1),
sface2 = list_rotate(face2,min2)
) if (sface1 == sface2)
_vnf_validate_err("DUP_FACE", [for (i=sface1) varr[i]])
],
issues = concat(issues, repeated_faces)
) issues? issues :
let(
multconn_edges = unique([
for (i = idx(uniq_edges))
if (edgecnts[1][i]>2) if (edgecnts[1][i]>2)
_vnf_validate_err("OVRPOP_EDGE", [for (i=uniq_edges[i]) varr[i]]) _vnf_validate_err("MULTCONN", [for (i=uniq_edges[i]) varr[i]])
]), ]),
issues = concat(issues, multconn_edges)
) issues? issues :
let(
reversals = unique([ reversals = unique([
for(i = idx(faces), j = idx(faces)) if(i != j) for(i = idx(dfaces), j = idx(dfaces)) if(i != j)
if(len(deduplicate(faces[i],closed=true))>=3)
if(len(deduplicate(faces[j],closed=true))>=3)
for(edge1 = pair(faces[i],true)) for(edge1 = pair(faces[i],true))
for(edge2 = pair(faces[j],true)) for(edge2 = pair(faces[j],true))
if(edge1 == edge2) // Valid adjacent faces will never have the same vertex ordering. if(edge1 == edge2) // Valid adjacent faces will never have the same vertex ordering.
if(_edge_not_reported(edge1, varr, overpop_edges)) if(_edge_not_reported(edge1, varr, multconn_edges))
_vnf_validate_err("REVERSAL", [for (i=edge1) varr[i]]) _vnf_validate_err("REVERSAL", [for (i=edge1) varr[i]])
]), ]),
issues = concat(issues, reversals)
) issues? issues :
let(
t_juncts = unique([ t_juncts = unique([
for (v=idx(varr), edge=uniq_edges) for (v=idx(varr), edge=uniq_edges) let(
if (v!=edge[0] && v!=edge[1]) let( ia = edge[0],
a = varr[edge[0]], ib = v,
b = varr[v], ic = edge[1]
c = varr[edge[1]]
) )
if (a != b && b != c && a != c) let( if (ia!=ib && ib!=ic && ia!=ic) let(
a = varr[ia],
b = varr[ib],
c = varr[ic]
)
if (!approx(a,b) && !approx(b,c) && !approx(a,c)) let(
pt = segment_closest_point([a,c],b) pt = segment_closest_point([a,c],b)
) )
if (pt == b) if (approx(pt,b))
_vnf_validate_err("T_JUNCTION", [b]) _vnf_validate_err("T_JUNCTION", [b])
]), ]),
issues = concat(issues, t_juncts)
) issues? issues :
let(
isect_faces = !check_isects? [] : unique([ isect_faces = !check_isects? [] : unique([
for (i = [0:1:len(faces)-2]) for (i = [0:1:len(faces)-2])
for (j = [i+1:1:len(faces)-1]) let( for (j = [i+1:1:len(faces)-1]) let(
@ -787,30 +824,39 @@ function vnf_validate(vnf, show_warns=true, check_isects=false) =
if (seg[0] != seg[1]) if (seg[0] != seg[1])
_vnf_validate_err("FACE_ISECT", seg) _vnf_validate_err("FACE_ISECT", seg)
]), ]),
issues = concat(issues, isect_faces)
) issues? issues :
let(
hole_edges = unique([ hole_edges = unique([
for (i=idx(uniq_edges)) for (i=idx(uniq_edges))
if (edgecnts[1][i]<2) if (edgecnts[1][i]<2)
if (_pts_not_reported(uniq_edges[i], varr, t_juncts)) if (_pts_not_reported(uniq_edges[i], varr, t_juncts))
if (_pts_not_reported(uniq_edges[i], varr, isect_faces)) if (_pts_not_reported(uniq_edges[i], varr, isect_faces))
_vnf_validate_err("HOLE_EDGE", [for (i=uniq_edges[i]) varr[i]]) _vnf_validate_err("HOLE_EDGE", [for (i=uniq_edges[i]) varr[i]])
]) ]),
) concat( issues = concat(issues, hole_edges)
big_faces, ) issues? issues :
null_faces, let(
nonplanars, nonplanars = unique([
overpop_edges, for (i = idx(faces)) let(
reversals, face = faces[i],
t_juncts, area = face_areas[i],
isect_faces, faceverts = [for (k=face) varr[k]]
hole_edges )
); if (is_num(area) && abs(area) > EPSILON)
if (!coplanar(faceverts))
_vnf_validate_err("NONPLANAR", faceverts)
]),
issues = concat(issues, nonplanars)
) issues;
_vnf_validate_errs = [ _vnf_validate_errs = [
["BIG_FACE", "WARNING", "cyan", "Face has more than 3 vertices, and may confuse CGAL"], ["BIG_FACE", "WARNING", "cyan", "Face has more than 3 vertices, and may confuse CGAL"],
["NULL_FACE", "WARNING", "blue", "Face has zero area."], ["NULL_FACE", "WARNING", "blue", "Face has zero area."],
["NONPLANAR", "ERROR", "yellow", "Face vertices are not coplanar"], ["NONPLANAR", "ERROR", "yellow", "Face vertices are not coplanar"],
["OVRPOP_EDGE", "ERROR", "orange", "Too many faces attached at Edge"], ["DUP_FACE", "ERROR", "brown", "Multiple instances of the same face."],
["MULTCONN", "ERROR", "orange", "Multiply Connected Geometry. Too many faces attached at Edge"],
["REVERSAL", "ERROR", "violet", "Faces Reverse Across Edge"], ["REVERSAL", "ERROR", "violet", "Faces Reverse Across Edge"],
["T_JUNCTION", "ERROR", "magenta", "Vertex is mid-edge on another Face"], ["T_JUNCTION", "ERROR", "magenta", "Vertex is mid-edge on another Face"],
["FACE_ISECT", "ERROR", "brown", "Faces intersect"], ["FACE_ISECT", "ERROR", "brown", "Faces intersect"],