mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2025-01-01 09:49:45 +00:00
Various VNF optimizations.
This commit is contained in:
parent
abf1a78290
commit
fb3475abef
2 changed files with 58 additions and 52 deletions
|
@ -8,7 +8,7 @@
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
BOSL_VERSION = [2,0,250];
|
BOSL_VERSION = [2,0,251];
|
||||||
|
|
||||||
|
|
||||||
// Section: BOSL Library Version Functions
|
// Section: BOSL Library Version Functions
|
||||||
|
|
108
vnf.scad
108
vnf.scad
|
@ -121,14 +121,14 @@ function vnf_add_face(vnf=EMPTY_VNF, pts) =
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// vnf = The VNF structure to add a face to.
|
// vnf = The VNF structure to add a face to.
|
||||||
// faces = The list of faces, where each face is given as a list of vertex points.
|
// faces = The list of faces, where each face is given as a list of vertex points.
|
||||||
function vnf_add_faces(vnf=EMPTY_VNF, faces, _i=0) =
|
function vnf_add_faces(vnf=EMPTY_VNF, faces) =
|
||||||
assert(is_vnf(vnf))
|
assert(is_vnf(vnf))
|
||||||
assert(is_list(faces))
|
assert(is_list(faces))
|
||||||
let(
|
let(
|
||||||
res = set_union(vnf[0],flatten(faces), get_indices=true),
|
res = set_union(vnf[0], flatten(faces), get_indices=true),
|
||||||
idxs = res[0],
|
idxs = res[0],
|
||||||
nverts = res[1],
|
nverts = res[1],
|
||||||
offs = cumsum([for (face=faces) len(face)]),
|
offs = cumsum([0, for (face=faces) len(face)]),
|
||||||
ifaces = [
|
ifaces = [
|
||||||
for (i=idx(faces)) [
|
for (i=idx(faces)) [
|
||||||
for (j=idx(faces[i]))
|
for (j=idx(faces[i]))
|
||||||
|
@ -163,6 +163,7 @@ function vnf_merge(vnfs=[],_i=0,_acc=EMPTY_VNF) =
|
||||||
// Takes a VNF and consolidates all duplicate vertices, and drops unreferenced vertices.
|
// Takes a VNF and consolidates all duplicate vertices, and drops unreferenced vertices.
|
||||||
function vnf_compact(vnf) =
|
function vnf_compact(vnf) =
|
||||||
let(
|
let(
|
||||||
|
vnf = is_vnf_list(vnf)? vnf_merge(vnf) : vnf,
|
||||||
verts = vnf[0],
|
verts = vnf[0],
|
||||||
faces = [
|
faces = [
|
||||||
for (face=vnf[1]) [
|
for (face=vnf[1]) [
|
||||||
|
@ -179,8 +180,9 @@ function vnf_compact(vnf) =
|
||||||
// Forces triangulation of faces in the VNF that have more than 3 vertices.
|
// Forces triangulation of faces in the VNF that have more than 3 vertices.
|
||||||
function vnf_triangulate(vnf) =
|
function vnf_triangulate(vnf) =
|
||||||
let(
|
let(
|
||||||
vnf = is_vnf_list(vnf)? vnf_merge(vnf) : vnf
|
vnf = is_vnf_list(vnf)? vnf_merge(vnf) : vnf,
|
||||||
) [vnf[0], triangulate_faces(vnf[0], vnf[1])];
|
verts = vnf[0]
|
||||||
|
) [verts, triangulate_faces(verts, vnf[1])];
|
||||||
|
|
||||||
|
|
||||||
// Function: vnf_vertex_array()
|
// Function: vnf_vertex_array()
|
||||||
|
@ -355,14 +357,15 @@ module vnf_polyhedron(vnf, convexity=2) {
|
||||||
// no holes; otherwise the results are undefined. Returns a positive volume if face direction is clockwise and a negative volume
|
// no holes; otherwise the results are undefined. Returns a positive volume if face direction is clockwise and a negative volume
|
||||||
// if face direction is counter-clockwise.
|
// if face direction is counter-clockwise.
|
||||||
function vnf_volume(vnf) =
|
function vnf_volume(vnf) =
|
||||||
let(vnf = vnf_triangulate(vnf),
|
let(
|
||||||
vert=vnf[0])
|
vnf = vnf_triangulate(vnf),
|
||||||
sum([
|
verts = vnf[0]
|
||||||
for(face_index=vnf[1]) let(
|
) sum([
|
||||||
face = select(vert, face_index),
|
for(face_index=vnf[1]) let(
|
||||||
n = cross(face[2]-face[0],face[1]-face[0])
|
face = select(verts, face_index),
|
||||||
) face[0] * n
|
n = cross(face[2]-face[0],face[1]-face[0])
|
||||||
])/6;
|
) face[0] * n
|
||||||
|
])/6;
|
||||||
|
|
||||||
|
|
||||||
// Function: vnf_centroid()
|
// Function: vnf_centroid()
|
||||||
|
@ -376,11 +379,11 @@ function vnf_volume(vnf) =
|
||||||
function vnf_centroid(vnf) =
|
function vnf_centroid(vnf) =
|
||||||
let(
|
let(
|
||||||
vnf = vnf_triangulate(vnf),
|
vnf = vnf_triangulate(vnf),
|
||||||
vert = vnf[0],
|
verts = vnf[0],
|
||||||
val=sum([
|
val=sum([
|
||||||
for(face_index=vnf[1])
|
for(face_index=vnf[1])
|
||||||
let(
|
let(
|
||||||
face = select(vert, face_index),
|
face = select(verts, face_index),
|
||||||
n = cross(face[2]-face[0],face[1]-face[0])
|
n = cross(face[2]-face[0],face[1]-face[0])
|
||||||
) [
|
) [
|
||||||
face[0] * n,
|
face[0] * n,
|
||||||
|
@ -482,44 +485,47 @@ function vnf_centroid(vnf) =
|
||||||
// ], slices=0, caps=false);
|
// ], slices=0, caps=false);
|
||||||
// vnf_validate(vnf,size=2);
|
// vnf_validate(vnf,size=2);
|
||||||
function vnf_validate(vnf, show_warns=true, check_isects=false) =
|
function vnf_validate(vnf, show_warns=true, check_isects=false) =
|
||||||
|
assert(is_path(vnf[0]))
|
||||||
let(
|
let(
|
||||||
vnf = vnf_compact(vnf),
|
vnf = vnf_compact(vnf),
|
||||||
|
varr = vnf[0],
|
||||||
|
faces = vnf[1],
|
||||||
edges = sort([
|
edges = sort([
|
||||||
for (face=vnf[1], edge=pair_wrap(face))
|
for (face=faces, edge=pair_wrap(face))
|
||||||
edge[0]<edge[1]? edge : [edge[1],edge[0]]
|
edge[0]<edge[1]? edge : [edge[1],edge[0]]
|
||||||
]),
|
]),
|
||||||
edgecnts = unique_count(edges),
|
edgecnts = unique_count(edges),
|
||||||
uniq_edges = edgecnts[0],
|
uniq_edges = edgecnts[0],
|
||||||
big_faces = !show_warns? [] : [
|
big_faces = !show_warns? [] : [
|
||||||
for (face = vnf[1])
|
for (face = faces)
|
||||||
if (len(face) > 3) [
|
if (len(face) > 3) [
|
||||||
"WARNING",
|
"WARNING",
|
||||||
"BIG_FACE",
|
"BIG_FACE",
|
||||||
"Face has more than 3 vertices, and may confuse CGAL",
|
"Face has more than 3 vertices, and may confuse CGAL",
|
||||||
[for (i=face) vnf[0][i]],
|
[for (i=face) varr[i]],
|
||||||
"yellow"
|
"yellow"
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
null_faces = !show_warns? [] : [
|
null_faces = !show_warns? [] : [
|
||||||
for (face = vnf[1]) let(
|
for (face = faces) let(
|
||||||
verts = [for (k=face) vnf[0][k]],
|
faceverts = [for (k=face) varr[k]],
|
||||||
area = abs(polygon_area(verts))
|
area = abs(polygon_area(faceverts))
|
||||||
) if (area < EPSILON) [
|
) if (area < EPSILON) [
|
||||||
"WARNING",
|
"WARNING",
|
||||||
"NULL_FACE",
|
"NULL_FACE",
|
||||||
str("Face has zero area: ",fmt_float(area,15)),
|
str("Face has zero area: ",fmt_float(area,15)),
|
||||||
verts,
|
faceverts,
|
||||||
"brown"
|
"brown"
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
nonplanars = unique([
|
nonplanars = unique([
|
||||||
for (face = vnf[1]) let(
|
for (face = faces) let(
|
||||||
verts = [for (k=face) vnf[0][k]]
|
faceverts = [for (k=face) varr[k]]
|
||||||
) if (!points_are_coplanar(verts)) [
|
) if (!points_are_coplanar(faceverts)) [
|
||||||
"ERROR",
|
"ERROR",
|
||||||
"NONPLANAR",
|
"NONPLANAR",
|
||||||
"Face vertices are not coplanar",
|
"Face vertices are not coplanar",
|
||||||
verts,
|
faceverts,
|
||||||
"cyan"
|
"cyan"
|
||||||
]
|
]
|
||||||
]),
|
]),
|
||||||
|
@ -529,30 +535,30 @@ function vnf_validate(vnf, show_warns=true, check_isects=false) =
|
||||||
"ERROR",
|
"ERROR",
|
||||||
"OVRPOP_EDGE",
|
"OVRPOP_EDGE",
|
||||||
"Too many faces attached at Edge",
|
"Too many faces attached at Edge",
|
||||||
[for (i=uniq_edges[i]) vnf[0][i]],
|
[for (i=uniq_edges[i]) varr[i]],
|
||||||
"#f70"
|
"#f70"
|
||||||
]
|
]
|
||||||
]),
|
]),
|
||||||
reversals = unique([
|
reversals = unique([
|
||||||
for(i = idx(vnf[1]), j = idx(vnf[1])) if(i != j)
|
for(i = idx(faces), j = idx(faces)) if(i != j)
|
||||||
for(edge1 = pair_wrap(vnf[1][i]))
|
for(edge1 = pair_wrap(faces[i]))
|
||||||
for(edge2 = pair_wrap(vnf[1][j]))
|
for(edge2 = pair_wrap(faces[j]))
|
||||||
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, vnf, overpop_edges))
|
if(_edge_not_reported(edge1, varr, overpop_edges))
|
||||||
[
|
[
|
||||||
"ERROR",
|
"ERROR",
|
||||||
"REVERSAL",
|
"REVERSAL",
|
||||||
"Faces Reverse Across Edge",
|
"Faces Reverse Across Edge",
|
||||||
[for (i=edge1) vnf[0][i]],
|
[for (i=edge1) varr[i]],
|
||||||
"violet"
|
"violet"
|
||||||
]
|
]
|
||||||
]),
|
]),
|
||||||
t_juncts = unique([
|
t_juncts = unique([
|
||||||
for (v=idx(vnf[0]), edge=uniq_edges)
|
for (v=idx(varr), edge=uniq_edges)
|
||||||
if (v!=edge[0] && v!=edge[1]) let(
|
if (v!=edge[0] && v!=edge[1]) let(
|
||||||
a = vnf[0][edge[0]],
|
a = varr[edge[0]],
|
||||||
b = vnf[0][v],
|
b = varr[v],
|
||||||
c = vnf[0][edge[1]],
|
c = varr[edge[1]],
|
||||||
pt = segment_closest_point([a,c],b)
|
pt = segment_closest_point([a,c],b)
|
||||||
) if (pt == b) [
|
) if (pt == b) [
|
||||||
"ERROR",
|
"ERROR",
|
||||||
|
@ -563,10 +569,10 @@ function vnf_validate(vnf, show_warns=true, check_isects=false) =
|
||||||
]
|
]
|
||||||
]),
|
]),
|
||||||
isect_faces = !check_isects? [] : unique([
|
isect_faces = !check_isects? [] : unique([
|
||||||
for (i = [0:1:len(vnf[1])-2])
|
for (i = [0:1:len(faces)-2])
|
||||||
for (j = [i+1:1:len(vnf[1])-1]) let(
|
for (j = [i+1:1:len(faces)-1]) let(
|
||||||
f1 = vnf[1][i],
|
f1 = faces[i],
|
||||||
f2 = vnf[1][j],
|
f2 = faces[j],
|
||||||
shared_edges = [
|
shared_edges = [
|
||||||
for (edge1 = pair_wrap(f1), edge2 = pair_wrap(f2)) let(
|
for (edge1 = pair_wrap(f1), edge2 = pair_wrap(f2)) let(
|
||||||
e1 = edge1[0]<edge1[1]? edge1 : [edge1[1],edge1[0]],
|
e1 = edge1[0]<edge1[1]? edge1 : [edge1[1],edge1[0]],
|
||||||
|
@ -575,18 +581,18 @@ function vnf_validate(vnf, show_warns=true, check_isects=false) =
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
if (!shared_edges) let(
|
if (!shared_edges) let(
|
||||||
plane1 = plane3pt_indexed(vnf[0], f1[0], f1[1], f1[2]),
|
plane1 = plane3pt_indexed(varr, f1[0], f1[1], f1[2]),
|
||||||
plane2 = plane3pt_indexed(vnf[0], f2[0], f2[1], f2[2]),
|
plane2 = plane3pt_indexed(varr, f2[0], f2[1], f2[2]),
|
||||||
line = plane_intersection(plane1, plane2)
|
line = plane_intersection(plane1, plane2)
|
||||||
)
|
)
|
||||||
if (!is_undef(line)) let(
|
if (!is_undef(line)) let(
|
||||||
poly1 = select(vnf[0],f1),
|
poly1 = select(varr,f1),
|
||||||
isects = polygon_line_intersection(poly1,line)
|
isects = polygon_line_intersection(poly1,line)
|
||||||
)
|
)
|
||||||
if (!is_undef(isects))
|
if (!is_undef(isects))
|
||||||
for (isect=isects)
|
for (isect=isects)
|
||||||
if (len(isect)>1) let(
|
if (len(isect)>1) let(
|
||||||
poly2 = select(vnf[0],f2),
|
poly2 = select(varr,f2),
|
||||||
isects2 = polygon_line_intersection(poly2,isect,bounded=true)
|
isects2 = polygon_line_intersection(poly2,isect,bounded=true)
|
||||||
)
|
)
|
||||||
if (!is_undef(isects2))
|
if (!is_undef(isects2))
|
||||||
|
@ -602,13 +608,13 @@ function vnf_validate(vnf, show_warns=true, check_isects=false) =
|
||||||
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], vnf, t_juncts))
|
if (_pts_not_reported(uniq_edges[i], varr, t_juncts))
|
||||||
if (_pts_not_reported(uniq_edges[i], vnf, isect_faces))
|
if (_pts_not_reported(uniq_edges[i], varr, isect_faces))
|
||||||
[
|
[
|
||||||
"ERROR",
|
"ERROR",
|
||||||
"HOLE_EDGE",
|
"HOLE_EDGE",
|
||||||
"Edge bounds Hole",
|
"Edge bounds Hole",
|
||||||
[for (i=uniq_edges[i]) vnf[0][i]],
|
[for (i=uniq_edges[i]) varr[i]],
|
||||||
"magenta"
|
"magenta"
|
||||||
]
|
]
|
||||||
])
|
])
|
||||||
|
@ -624,16 +630,16 @@ function vnf_validate(vnf, show_warns=true, check_isects=false) =
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
function _pts_not_reported(pts, vnf, reports) =
|
function _pts_not_reported(pts, varr, reports) =
|
||||||
[
|
[
|
||||||
for (i = pts, report = reports, pt = report[3])
|
for (i = pts, report = reports, pt = report[3])
|
||||||
if (vnf[0][i] == pt) 1
|
if (varr[i] == pt) 1
|
||||||
] == [];
|
] == [];
|
||||||
|
|
||||||
|
|
||||||
function _edge_not_reported(edge, vnf, reports) =
|
function _edge_not_reported(edge, varr, reports) =
|
||||||
let(
|
let(
|
||||||
edge = sort([for (i=edge) vnf[0][i]])
|
edge = sort([for (i=edge) varr[i]])
|
||||||
) [
|
) [
|
||||||
for (report = reports) let(
|
for (report = reports) let(
|
||||||
pts = sort(report[3])
|
pts = sort(report[3])
|
||||||
|
|
Loading…
Reference in a new issue