mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2025-01-21 03:49:38 +00:00
Merge pull request #678 from adrianVmariano/master
doc fixes, vnf_halfspace bugfix
This commit is contained in:
commit
ccb154f4c2
2 changed files with 280 additions and 280 deletions
|
@ -646,14 +646,14 @@ function plane_line_intersection(plane, line, bounded=false, eps=EPSILON) =
|
||||||
// bounded = If false, the line is considered unbounded. If true, it is treated as a bounded line segment. If given as `[true, false]` or `[false, true]`, the boundedness of the points are specified individually, allowing the line to be treated as a half-bounded ray. Default: false (unbounded)
|
// bounded = If false, the line is considered unbounded. If true, it is treated as a bounded line segment. If given as `[true, false]` or `[false, true]`, the boundedness of the points are specified individually, allowing the line to be treated as a half-bounded ray. Default: false (unbounded)
|
||||||
// nonzero = set to true to use the nonzero rule for determining it points are in a polygon. See point_in_polygon. Default: false.
|
// nonzero = set to true to use the nonzero rule for determining it points are in a polygon. See point_in_polygon. Default: false.
|
||||||
// eps = Tolerance in geometric comparisons. Default: `EPSILON` (1e-9)
|
// eps = Tolerance in geometric comparisons. Default: `EPSILON` (1e-9)
|
||||||
// Example: The line intersects the 3d hexagon in a single point.
|
// Example(3D): The line intersects the 3d hexagon in a single point.
|
||||||
// hex = zrot(140,p=rot([-45,40,20],p=path3d(hexagon(r=15))));
|
// hex = zrot(140,p=rot([-45,40,20],p=path3d(hexagon(r=15))));
|
||||||
// line = [[5,0,-13],[-3,-5,13]];
|
// line = [[5,0,-13],[-3,-5,13]];
|
||||||
// isect = polygon_line_intersection(hex,line);
|
// isect = polygon_line_intersection(hex,line);
|
||||||
// stroke(hex,closed=true);
|
// stroke(hex,closed=true);
|
||||||
// stroke(line);
|
// stroke(line);
|
||||||
// color("red")move(isect)sphere(r=1);
|
// color("red")move(isect)sphere(r=1,$fn=12);
|
||||||
// Example: In 2D things are more complicated. The output is a list of intersection parts, in the simplest case a single segment.
|
// Example(2D): In 2D things are more complicated. The output is a list of intersection parts, in the simplest case a single segment.
|
||||||
// hex = hexagon(r=15);
|
// hex = hexagon(r=15);
|
||||||
// line = [[-20,10],[25,-7]];
|
// line = [[-20,10],[25,-7]];
|
||||||
// isect = polygon_line_intersection(hex,line);
|
// isect = polygon_line_intersection(hex,line);
|
||||||
|
@ -665,7 +665,7 @@ function plane_line_intersection(plane, line, bounded=false, eps=EPSILON) =
|
||||||
// move(part[0]) sphere(r=1);
|
// move(part[0]) sphere(r=1);
|
||||||
// else
|
// else
|
||||||
// stroke(part);
|
// stroke(part);
|
||||||
// Example: In 2D things are more complicated. Here the line is treated as a ray.
|
// Example(2D): Here the line is treated as a ray.
|
||||||
// hex = hexagon(r=15);
|
// hex = hexagon(r=15);
|
||||||
// line = [[0,0],[25,-7]];
|
// line = [[0,0],[25,-7]];
|
||||||
// isect = polygon_line_intersection(hex,line,RAY);
|
// isect = polygon_line_intersection(hex,line,RAY);
|
||||||
|
@ -677,7 +677,7 @@ function plane_line_intersection(plane, line, bounded=false, eps=EPSILON) =
|
||||||
// move(part[0]) circle(r=1,$fn=12);
|
// move(part[0]) circle(r=1,$fn=12);
|
||||||
// else
|
// else
|
||||||
// stroke(part);
|
// stroke(part);
|
||||||
// Example: Here the intersection is a single point, which is returned as a single point "path" on the path list.
|
// Example(2D): Here the intersection is a single point, which is returned as a single point "path" on the path list.
|
||||||
// hex = hexagon(r=15);
|
// hex = hexagon(r=15);
|
||||||
// line = [[15,-10],[15,13]];
|
// line = [[15,-10],[15,13]];
|
||||||
// isect = polygon_line_intersection(hex,line,RAY);
|
// isect = polygon_line_intersection(hex,line,RAY);
|
||||||
|
@ -689,7 +689,7 @@ function plane_line_intersection(plane, line, bounded=false, eps=EPSILON) =
|
||||||
// move(part[0]) circle(r=1,$fn=12);
|
// move(part[0]) circle(r=1,$fn=12);
|
||||||
// else
|
// else
|
||||||
// stroke(part);
|
// stroke(part);
|
||||||
// Example: Another way to get a single segment
|
// Example(2D): Another way to get a single segment
|
||||||
// hex = hexagon(r=15);
|
// hex = hexagon(r=15);
|
||||||
// line = rot(30,p=[[15,-10],[15,25]],cp=[15,0]);
|
// line = rot(30,p=[[15,-10],[15,25]],cp=[15,0]);
|
||||||
// isect = polygon_line_intersection(hex,line,RAY);
|
// isect = polygon_line_intersection(hex,line,RAY);
|
||||||
|
@ -701,7 +701,7 @@ function plane_line_intersection(plane, line, bounded=false, eps=EPSILON) =
|
||||||
// move(part[0]) circle(r=1,$fn=12);
|
// move(part[0]) circle(r=1,$fn=12);
|
||||||
// else
|
// else
|
||||||
// stroke(part);
|
// stroke(part);
|
||||||
// Example: Single segment again
|
// Example(2D): Single segment again
|
||||||
// star = star(r=15,n=8,step=2);
|
// star = star(r=15,n=8,step=2);
|
||||||
// line = [[20,-5],[-5,20]];
|
// line = [[20,-5],[-5,20]];
|
||||||
// isect = polygon_line_intersection(star,line,RAY);
|
// isect = polygon_line_intersection(star,line,RAY);
|
||||||
|
@ -713,7 +713,7 @@ function plane_line_intersection(plane, line, bounded=false, eps=EPSILON) =
|
||||||
// move(part[0]) circle(r=1,$fn=12);
|
// move(part[0]) circle(r=1,$fn=12);
|
||||||
// else
|
// else
|
||||||
// stroke(part);
|
// stroke(part);
|
||||||
// Example: Solution is two points
|
// Example(2D): Solution is two points
|
||||||
// star = star(r=15,n=8,step=3);
|
// star = star(r=15,n=8,step=3);
|
||||||
// line = rot(22.5,p=[[15,-10],[15,20]],cp=[15,0]);
|
// line = rot(22.5,p=[[15,-10],[15,20]],cp=[15,0]);
|
||||||
// isect = polygon_line_intersection(star,line,SEGMENT);
|
// isect = polygon_line_intersection(star,line,SEGMENT);
|
||||||
|
@ -725,7 +725,7 @@ function plane_line_intersection(plane, line, bounded=false, eps=EPSILON) =
|
||||||
// move(part[0]) circle(r=1,$fn=12);
|
// move(part[0]) circle(r=1,$fn=12);
|
||||||
// else
|
// else
|
||||||
// stroke(part);
|
// stroke(part);
|
||||||
// Example: Solution is list of three segments
|
// Example(2D): Solution is list of three segments
|
||||||
// star = star(r=25,ir=9,n=8);
|
// star = star(r=25,ir=9,n=8);
|
||||||
// line = [[-25,12],[25,12]];
|
// line = [[-25,12],[25,12]];
|
||||||
// isect = polygon_line_intersection(star,line);
|
// isect = polygon_line_intersection(star,line);
|
||||||
|
@ -737,7 +737,7 @@ function plane_line_intersection(plane, line, bounded=false, eps=EPSILON) =
|
||||||
// move(part[0]) circle(r=1,$fn=12);
|
// move(part[0]) circle(r=1,$fn=12);
|
||||||
// else
|
// else
|
||||||
// stroke(part);
|
// stroke(part);
|
||||||
// Example: Solution is a mixture of segments and points
|
// Example(2D): Solution is a mixture of segments and points
|
||||||
// star = star(r=25,ir=9,n=7);
|
// star = star(r=25,ir=9,n=7);
|
||||||
// line = [left(10,p=star[8]), right(50,p=star[8])];
|
// line = [left(10,p=star[8]), right(50,p=star[8])];
|
||||||
// isect = polygon_line_intersection(star,line);
|
// isect = polygon_line_intersection(star,line);
|
||||||
|
@ -1591,22 +1591,17 @@ function point_in_polygon(point, poly, nonzero=false, eps=EPSILON) =
|
||||||
// poly = Array of vertices for the polygon.
|
// poly = Array of vertices for the polygon.
|
||||||
// ind = A list indexing the vertices of the polygon in `poly`.
|
// ind = A list indexing the vertices of the polygon in `poly`.
|
||||||
// eps = A maximum tolerance in geometrical tests. Default: EPSILON
|
// eps = A maximum tolerance in geometrical tests. Default: EPSILON
|
||||||
// Example:
|
// Example(2D):
|
||||||
// poly = star(id=10, od=15,n=11);
|
// poly = star(id=10, od=15,n=11);
|
||||||
// tris = polygon_triangulate(poly);
|
// tris = polygon_triangulate(poly);
|
||||||
// polygon(poly);
|
// for(tri=tris) stroke(select(poly,tri), width=.1, closed=true);
|
||||||
// up(1)
|
// Example(3D):
|
||||||
// color("blue");
|
// include <BOSL2/polyhedra.scad>
|
||||||
// for(tri=tris) trace_path(select(poly,tri), size=.1, closed=true);
|
|
||||||
//
|
|
||||||
// Example:
|
|
||||||
// include<BOSL2/polyhedra.scad>
|
|
||||||
// vnf = regular_polyhedron_info(name="dodecahedron",side=5,info="vnf");
|
// vnf = regular_polyhedron_info(name="dodecahedron",side=5,info="vnf");
|
||||||
// %vnf_polyhedron(vnf);
|
// %vnf_polyhedron(vnf);
|
||||||
// vnf_tri = [vnf[0], [for(face=vnf[1]) each polygon_triangulate(vnf[0], face) ] ];
|
// vnf_tri = [vnf[0], [for(face=vnf[1]) each polygon_triangulate(vnf[0], face) ] ];
|
||||||
// color("blue")
|
// color("blue")
|
||||||
// vnf_wireframe(vnf_tri, d=.15);
|
// vnf_wireframe(vnf_tri, width=.15);
|
||||||
|
|
||||||
function polygon_triangulate(poly, ind, eps=EPSILON) =
|
function polygon_triangulate(poly, ind, eps=EPSILON) =
|
||||||
assert(is_path(poly), "Polygon `poly` should be a list of 2d or 3d points")
|
assert(is_path(poly), "Polygon `poly` should be a list of 2d or 3d points")
|
||||||
assert(is_undef(ind)
|
assert(is_undef(ind)
|
||||||
|
|
525
vnf.scad
525
vnf.scad
|
@ -206,35 +206,35 @@ function vnf_vertex_array(
|
||||||
// points = List of point lists for each row
|
// points = List of point lists for each row
|
||||||
// row_wrap = If true then add faces connecting the first row and last row. These rows must differ by at most 2 in length.
|
// row_wrap = If true then add faces connecting the first row and last row. These rows must differ by at most 2 in length.
|
||||||
// reverse = Set this to reverse the direction of the faces
|
// reverse = Set this to reverse the direction of the faces
|
||||||
// Example: Each row has one more point than the preceeding one.
|
// Example(3D): Each row has one more point than the preceeding one.
|
||||||
// pts = [for(y=[1:1:10]) [for(x=[0:y-1]) [x,y,y]]];
|
// pts = [for(y=[1:1:10]) [for(x=[0:y-1]) [x,y,y]]];
|
||||||
// vnf = vnf_tri_array(pts);
|
// vnf = vnf_tri_array(pts);
|
||||||
// vnf_wireframe(vnf,d=.1);
|
// vnf_wireframe(vnf,width=0.1);
|
||||||
// color("red")move_copies(flatten(pts)) sphere(r=.15,$fn=9);
|
// color("red")move_copies(flatten(pts)) sphere(r=.15,$fn=9);
|
||||||
// Example: Each row has one more point than the preceeding one.
|
// Example(3D): Each row has one more point than the preceeding one.
|
||||||
// pts = [for(y=[0:2:10]) [for(x=[-y/2:y/2]) [x,y,y]]];
|
// pts = [for(y=[0:2:10]) [for(x=[-y/2:y/2]) [x,y,y]]];
|
||||||
// vnf = vnf_tri_array(pts);
|
// vnf = vnf_tri_array(pts);
|
||||||
// vnf_wireframe(vnf,d=.1);
|
// vnf_wireframe(vnf,width=0.1);
|
||||||
// color("red")move_copies(flatten(pts)) sphere(r=.15,$fn=9);
|
// color("red")move_copies(flatten(pts)) sphere(r=.15,$fn=9);
|
||||||
// Example: Chaining two VNFs to construct a cone with one point length change between rows.
|
// Example(3D): Chaining two VNFs to construct a cone with one point length change between rows.
|
||||||
// pts1 = [for(z=[0:10]) path3d(arc(3+z,r=z/2+1, angle=[0,180]),10-z)];
|
// pts1 = [for(z=[0:10]) path3d(arc(3+z,r=z/2+1, angle=[0,180]),10-z)];
|
||||||
// pts2 = [for(z=[0:10]) path3d(arc(3+z,r=z/2+1, angle=[180,360]),10-z)];
|
// pts2 = [for(z=[0:10]) path3d(arc(3+z,r=z/2+1, angle=[180,360]),10-z)];
|
||||||
// vnf = vnf_tri_array(pts1,
|
// vnf = vnf_tri_array(pts1,
|
||||||
// vnf=vnf_tri_array(pts2));
|
// vnf=vnf_tri_array(pts2));
|
||||||
// color("green")vnf_wireframe(vnf,d=.1);
|
// color("green")vnf_wireframe(vnf,width=0.1);
|
||||||
// vnf_polyhedron(vnf);
|
// vnf_polyhedron(vnf);
|
||||||
// Example: Cone with length change two between rows
|
// Example(3D): Cone with length change two between rows
|
||||||
// pts1 = [for(z=[0:1:10]) path3d(arc(3+2*z,r=z/2+1, angle=[0,180]),10-z)];
|
// pts1 = [for(z=[0:1:10]) path3d(arc(3+2*z,r=z/2+1, angle=[0,180]),10-z)];
|
||||||
// pts2 = [for(z=[0:1:10]) path3d(arc(3+2*z,r=z/2+1, angle=[180,360]),10-z)];
|
// pts2 = [for(z=[0:1:10]) path3d(arc(3+2*z,r=z/2+1, angle=[180,360]),10-z)];
|
||||||
// vnf = vnf_tri_array(pts1,
|
// vnf = vnf_tri_array(pts1,
|
||||||
// vnf=vnf_tri_array(pts2));
|
// vnf=vnf_tri_array(pts2));
|
||||||
// color("green")vnf_wireframe(vnf,d=.1);
|
// color("green")vnf_wireframe(vnf,width=0.1);
|
||||||
// vnf_polyhedron(vnf);
|
// vnf_polyhedron(vnf);
|
||||||
// Example: Point count can change irregularly
|
// Example(3D): Point count can change irregularly
|
||||||
// lens = [10,9,7,5,6,8,8,10];
|
// lens = [10,9,7,5,6,8,8,10];
|
||||||
// pts = [for(y=idx(lens)) lerpn([-lens[y],y,y],[lens[y],y,y],lens[y])];
|
// pts = [for(y=idx(lens)) lerpn([-lens[y],y,y],[lens[y],y,y],lens[y])];
|
||||||
// vnf = vnf_tri_array(pts);
|
// vnf = vnf_tri_array(pts);
|
||||||
// vnf_wireframe(vnf,d=.1);
|
// vnf_wireframe(vnf,width=0.1);
|
||||||
// color("red")move_copies(flatten(pts)) sphere(r=.15,$fn=9);
|
// color("red")move_copies(flatten(pts)) sphere(r=.15,$fn=9);
|
||||||
function vnf_tri_array(points, row_wrap=false, reverse=false, vnf=EMPTY_VNF) =
|
function vnf_tri_array(points, row_wrap=false, reverse=false, vnf=EMPTY_VNF) =
|
||||||
let(
|
let(
|
||||||
|
@ -422,234 +422,6 @@ function vnf_triangulate(vnf) =
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Section: Turning a VNF into geometry
|
|
||||||
|
|
||||||
|
|
||||||
// Module: vnf_polyhedron()
|
|
||||||
// Usage:
|
|
||||||
// vnf_polyhedron(vnf);
|
|
||||||
// vnf_polyhedron([VNF, VNF, VNF, ...]);
|
|
||||||
// Description:
|
|
||||||
// Given a VNF structure, or a list of VNF structures, creates a polyhedron from them.
|
|
||||||
// Arguments:
|
|
||||||
// vnf = A VNF structure, or list of VNF structures.
|
|
||||||
// convexity = Max number of times a line could intersect a wall of the shape.
|
|
||||||
// extent = If true, calculate anchors by extents, rather than intersection. Default: true.
|
|
||||||
// cp = Centerpoint of VNF to use for anchoring when `extent` is false. Default: `[0, 0, 0]`
|
|
||||||
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `"origin"`
|
|
||||||
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
|
|
||||||
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
|
|
||||||
module vnf_polyhedron(vnf, convexity=2, extent=true, cp=[0,0,0], anchor="origin", spin=0, orient=UP) {
|
|
||||||
vnf = is_vnf_list(vnf)? vnf_merge(vnf) : vnf;
|
|
||||||
cp = is_def(cp) ? cp : vnf_centroid(vnf);
|
|
||||||
attachable(anchor,spin,orient, vnf=vnf, extent=extent, cp=cp) {
|
|
||||||
polyhedron(vnf[0], vnf[1], convexity=convexity);
|
|
||||||
children();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Module: vnf_wireframe()
|
|
||||||
// Usage:
|
|
||||||
// vnf_wireframe(vnf, <r|d>);
|
|
||||||
// Description:
|
|
||||||
// Given a VNF, creates a wire frame ball-and-stick model of the polyhedron with a cylinder for
|
|
||||||
// each edge and a sphere at each vertex. The width parameter specifies the width of the sticks
|
|
||||||
// that form the wire frame.
|
|
||||||
// Arguments:
|
|
||||||
// vnf = A vnf structure
|
|
||||||
// width = width of the cylinders forming the wire frame. Default: 1
|
|
||||||
// Example:
|
|
||||||
// $fn=32;
|
|
||||||
// ball = sphere(r=20, $fn=6);
|
|
||||||
// vnf_wireframe(ball,width=1);
|
|
||||||
// Example:
|
|
||||||
// include <BOSL2/polyhedra.scad>
|
|
||||||
// $fn=32;
|
|
||||||
// cube_oct = regular_polyhedron_info("vnf", name="cuboctahedron", or=20);
|
|
||||||
// vnf_wireframe(cube_oct);
|
|
||||||
// Example: The spheres at the vertex are imperfect at aligning with the cylinders, so especially at low $fn things look prety ugly. This is normal.
|
|
||||||
// include <BOSL2/polyhedra.scad>
|
|
||||||
// $fn=8;
|
|
||||||
// octahedron = regular_polyhedron_info("vnf", name="octahedron", or=20);
|
|
||||||
// vnf_wireframe(octahedron,width=5);
|
|
||||||
module vnf_wireframe(vnf, width=1)
|
|
||||||
{
|
|
||||||
vertex = vnf[0];
|
|
||||||
edges = unique([for (face=vnf[1], i=idx(face))
|
|
||||||
sort([face[i], select(face,i+1)])
|
|
||||||
]);
|
|
||||||
for (e=edges) extrude_from_to(vertex[e[0]],vertex[e[1]]) circle(d=width);
|
|
||||||
move_copies(vertex) sphere(d=width);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Section: Operations on VNFs
|
|
||||||
|
|
||||||
// Function: vnf_volume()
|
|
||||||
// Usage:
|
|
||||||
// vol = vnf_volume(vnf);
|
|
||||||
// Description:
|
|
||||||
// Returns the volume enclosed by the given manifold VNF. The VNF must describe a valid polyhedron with consistent face direction and
|
|
||||||
// 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.
|
|
||||||
|
|
||||||
// Divide the polyhedron into tetrahedra with the origin as one vertex and sum up the signed volume.
|
|
||||||
function vnf_volume(vnf) =
|
|
||||||
let(verts = vnf[0])
|
|
||||||
sum([
|
|
||||||
for(face=vnf[1], j=[1:1:len(face)-2])
|
|
||||||
cross(verts[face[j+1]], verts[face[j]]) * verts[face[0]]
|
|
||||||
])/6;
|
|
||||||
|
|
||||||
|
|
||||||
// Function: vnf_area()
|
|
||||||
// Usage:
|
|
||||||
// area = vnf_area(vnf);
|
|
||||||
// Description:
|
|
||||||
// Returns the surface area in any VNF by adding up the area of all its faces. The VNF need not be a manifold.
|
|
||||||
function vnf_area(vnf) =
|
|
||||||
let(verts=vnf[0])
|
|
||||||
sum([for(face=vnf[1]) polygon_area(select(verts,face))]);
|
|
||||||
|
|
||||||
|
|
||||||
// Function: vnf_centroid()
|
|
||||||
// Usage:
|
|
||||||
// vol = vnf_centroid(vnf);
|
|
||||||
// Description:
|
|
||||||
// Returns the centroid of the given manifold VNF. The VNF must describe a valid polyhedron with consistent face direction and
|
|
||||||
// no holes; otherwise the results are undefined.
|
|
||||||
|
|
||||||
// Divide the solid up into tetrahedra with the origin as one vertex.
|
|
||||||
// The centroid of a tetrahedron is the average of its vertices.
|
|
||||||
// The centroid of the total is the volume weighted average.
|
|
||||||
function vnf_centroid(vnf) =
|
|
||||||
assert(is_vnf(vnf) && len(vnf[0])!=0 )
|
|
||||||
let(
|
|
||||||
verts = vnf[0],
|
|
||||||
pos = sum([
|
|
||||||
for(face=vnf[1], j=[1:1:len(face)-2]) let(
|
|
||||||
v0 = verts[face[0]],
|
|
||||||
v1 = verts[face[j]],
|
|
||||||
v2 = verts[face[j+1]],
|
|
||||||
vol = cross(v2,v1)*v0
|
|
||||||
)
|
|
||||||
[ vol, (v0+v1+v2)*vol ]
|
|
||||||
])
|
|
||||||
)
|
|
||||||
assert(!approx(pos[0],0, EPSILON), "The vnf has self-intersections.")
|
|
||||||
pos[1]/pos[0]/4;
|
|
||||||
|
|
||||||
|
|
||||||
// Function: vnf_halfspace()
|
|
||||||
// Usage:
|
|
||||||
// newvnf = vnf_halfspace(plane, vnf, [closed]);
|
|
||||||
// Description:
|
|
||||||
// Returns the intersection of the vnf with a half space. The half space is defined by
|
|
||||||
// plane = [A,B,C,D], taking the side where the normal [A,B,C] points: Ax+By+Cz≥D.
|
|
||||||
// If closed is set to false then the cut face is not included in the vnf. This could
|
|
||||||
// allow further extension of the vnf by merging with other vnfs.
|
|
||||||
// Arguments:
|
|
||||||
// plane = plane defining the boundary of the half space
|
|
||||||
// vnf = vnf to cut
|
|
||||||
// closed = if false do not return include cut face(s). Default: true
|
|
||||||
// Example:
|
|
||||||
// vnf = cube(10,center=true);
|
|
||||||
// cutvnf = vnf_halfspace([-1,1,-1,0], vnf);
|
|
||||||
// vnf_polyhedron(cutvnf);
|
|
||||||
// Example: Cut face has 2 components
|
|
||||||
// vnf = path_sweep(circle(r=4, $fn=16),
|
|
||||||
// circle(r=20, $fn=64),closed=true);
|
|
||||||
// cutvnf = vnf_halfspace([-1,1,-4,0], vnf);
|
|
||||||
// vnf_polyhedron(cutvnf);
|
|
||||||
// Example: Cut face is not simply connected
|
|
||||||
// vnf = path_sweep(circle(r=4, $fn=16),
|
|
||||||
// circle(r=20, $fn=64),closed=true);
|
|
||||||
// cutvnf = vnf_halfspace([0,0.7,-4,0], vnf);
|
|
||||||
// vnf_polyhedron(cutvnf);
|
|
||||||
// Example: Cut object has multiple components
|
|
||||||
// function knot(a,b,t) = // rolling knot
|
|
||||||
// [ a * cos (3 * t) / (1 - b* sin (2 *t)),
|
|
||||||
// a * sin( 3 * t) / (1 - b* sin (2 *t)),
|
|
||||||
// 1.8 * b * cos (2 * t) /(1 - b* sin (2 *t))];
|
|
||||||
// a = 0.8; b = sqrt (1 - a * a);
|
|
||||||
// ksteps = 400;
|
|
||||||
// knot_path = [for (i=[0:ksteps-1]) 50 * knot(a,b,(i/ksteps)*360)];
|
|
||||||
// ushape = [[-10, 0],[-10, 10],[ -7, 10],[ -7, 2],[ 7, 2],[ 7, 7],[ 10, 7],[ 10, 0]];
|
|
||||||
// knot=path_sweep(ushape, knot_path, closed=true, method="incremental");
|
|
||||||
// cut_knot = vnf_halfspace([1,0,0,0], knot);
|
|
||||||
// vnf_polyhedron(cut_knot);
|
|
||||||
function vnf_halfspace(plane, vnf, closed=true) =
|
|
||||||
let(
|
|
||||||
inside = [for(x=vnf[0]) plane*[each x,-1] >= 0 ? 1 : 0],
|
|
||||||
vertexmap = [0,each cumsum(inside)],
|
|
||||||
faces_edges_vertices = _vnfcut(plane, vnf[0],vertexmap,inside, vnf[1], last(vertexmap)),
|
|
||||||
newvert = concat(bselect(vnf[0],inside), faces_edges_vertices[2])
|
|
||||||
)
|
|
||||||
closed==false ? [newvert, faces_edges_vertices[0]] :
|
|
||||||
let(
|
|
||||||
allpaths = _assemble_paths(newvert, faces_edges_vertices[1]),
|
|
||||||
newpaths = [for(p=allpaths) if (len(p)>=3) p
|
|
||||||
else assert(approx(p[0],p[1]),"Orphan edge found when assembling cut edges.")
|
|
||||||
]
|
|
||||||
)
|
|
||||||
len(newpaths)<=1 ? [newvert, concat(faces_edges_vertices[0], newpaths)]
|
|
||||||
:
|
|
||||||
let(
|
|
||||||
faceregion = project_plane(plane, newpaths),
|
|
||||||
facevnf = region_faces(faceregion,reverse=true)
|
|
||||||
)
|
|
||||||
vnf_merge([[newvert, faces_edges_vertices[0]], lift_plane(plane, facevnf)]);
|
|
||||||
|
|
||||||
|
|
||||||
function _assemble_paths(vertices, edges, paths=[],i=0) =
|
|
||||||
i==len(edges) ? paths :
|
|
||||||
norm(vertices[edges[i][0]]-vertices[edges[i][1]])<EPSILON ? echo(degen=i)_assemble_paths(vertices,edges,paths,i+1) :
|
|
||||||
let( // Find paths that connects on left side and right side of the edges (if one exists)
|
|
||||||
left = [for(j=idx(paths)) if (approx(vertices[last(paths[j])],vertices[edges[i][0]])) j],
|
|
||||||
right = [for(j=idx(paths)) if (approx(vertices[edges[i][1]],vertices[paths[j][0]])) j]
|
|
||||||
)
|
|
||||||
assert(len(left)<=1 && len(right)<=1)
|
|
||||||
let(
|
|
||||||
keep_path = list_remove(paths,concat(left,right)),
|
|
||||||
update_path = left==[] && right==[] ? edges[i]
|
|
||||||
: left==[] ? concat([edges[i][0]],paths[right[0]])
|
|
||||||
: right==[] ? concat(paths[left[0]],[edges[i][1]])
|
|
||||||
: left != right ? concat(paths[left[0]], paths[right[0]])
|
|
||||||
: paths[left[0]]
|
|
||||||
)
|
|
||||||
_assemble_paths(vertices, edges, concat(keep_path, [update_path]), i+1);
|
|
||||||
|
|
||||||
|
|
||||||
function _vnfcut(plane, vertices, vertexmap, inside, faces, vertcount, newfaces=[], newedges=[], newvertices=[], i=0) =
|
|
||||||
i==len(faces) ? [newfaces, newedges, newvertices] :
|
|
||||||
let(
|
|
||||||
pts_inside = select(inside,faces[i])
|
|
||||||
)
|
|
||||||
all(pts_inside) ? _vnfcut(plane, vertices, vertexmap, inside, faces, vertcount,
|
|
||||||
concat(newfaces, [select(vertexmap,faces[i])]), newedges, newvertices, i+1):
|
|
||||||
!any(pts_inside) ? _vnfcut(plane, vertices, vertexmap,inside, faces, vertcount, newfaces, newedges, newvertices, i+1):
|
|
||||||
let(
|
|
||||||
first = search([[1,0]],pair(pts_inside,wrap=true),0)[0],
|
|
||||||
second = search([[0,1]],pair(pts_inside,wrap=true),0)[0]
|
|
||||||
)
|
|
||||||
assert(len(first)==1 && len(second)==1, "Found concave face in VNF. Run vnf_triangulate first to ensure convex faces.")
|
|
||||||
let(
|
|
||||||
newface = [each select(vertexmap,select(faces[i],second[0]+1,first[0])),vertcount, vertcount+1],
|
|
||||||
newvert = [plane_line_intersection(plane, select(vertices,select(faces[i],first[0],first[0]+1)),eps=0),
|
|
||||||
plane_line_intersection(plane, select(vertices,select(faces[i],second[0],second[0]+1)),eps=0)]
|
|
||||||
)
|
|
||||||
true //!approx(newvert[0],newvert[1])
|
|
||||||
? _vnfcut(plane, vertices, vertexmap, inside, faces, vertcount+2,
|
|
||||||
concat(newfaces, [newface]), concat(newedges,[[vertcount+1,vertcount]]),concat(newvertices,newvert),i+1)
|
|
||||||
:len(newface)>3
|
|
||||||
? _vnfcut(plane, vertices, vertexmap, inside, faces, vertcount+1,
|
|
||||||
concat(newfaces, [list_head(newface)]), newedges,concat(newvertices,[newvert[0]]),i+1)
|
|
||||||
:
|
|
||||||
_vnfcut(plane, vertices, vertexmap, inside, faces, vertcount,newfaces, newedges, newvert, i+1);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Function: vnf_slice()
|
// Function: vnf_slice()
|
||||||
// Usage:
|
// Usage:
|
||||||
// sliced = vnf_slice(vnf, dir, cuts);
|
// sliced = vnf_slice(vnf, dir, cuts);
|
||||||
|
@ -657,8 +429,8 @@ function _vnfcut(plane, vertices, vertexmap, inside, faces, vertcount, newfaces=
|
||||||
// Slice the faces of a VNF along a specified axis direction at a given list
|
// Slice the faces of a VNF along a specified axis direction at a given list
|
||||||
// of cut points. You can use this to refine the faces of a VNF before applying
|
// of cut points. You can use this to refine the faces of a VNF before applying
|
||||||
// a nonlinear transformation to its vertex set.
|
// a nonlinear transformation to its vertex set.
|
||||||
// Example:
|
// Example(3D):
|
||||||
// include <BOSL2-fork/polyhedra.scad>
|
// include <BOSL2/polyhedra.scad>
|
||||||
// vnf = regular_polyhedron_info("vnf", "dodecahedron", side=12);
|
// vnf = regular_polyhedron_info("vnf", "dodecahedron", side=12);
|
||||||
// vnf_polyhedron(vnf);
|
// vnf_polyhedron(vnf);
|
||||||
// sliced = vnf_slice(vnf, "X", [-6,-1,10]);
|
// sliced = vnf_slice(vnf, "X", [-6,-1,10]);
|
||||||
|
@ -753,6 +525,240 @@ function _slice_3dpolygons(polys, dir, cuts) =
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Section: Turning a VNF into geometry
|
||||||
|
|
||||||
|
|
||||||
|
// Module: vnf_polyhedron()
|
||||||
|
// Usage:
|
||||||
|
// vnf_polyhedron(vnf);
|
||||||
|
// vnf_polyhedron([VNF, VNF, VNF, ...]);
|
||||||
|
// Description:
|
||||||
|
// Given a VNF structure, or a list of VNF structures, creates a polyhedron from them.
|
||||||
|
// Arguments:
|
||||||
|
// vnf = A VNF structure, or list of VNF structures.
|
||||||
|
// convexity = Max number of times a line could intersect a wall of the shape.
|
||||||
|
// extent = If true, calculate anchors by extents, rather than intersection. Default: true.
|
||||||
|
// cp = Centerpoint of VNF to use for anchoring when `extent` is false. Default: `[0, 0, 0]`
|
||||||
|
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `"origin"`
|
||||||
|
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
|
||||||
|
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
|
||||||
|
module vnf_polyhedron(vnf, convexity=2, extent=true, cp=[0,0,0], anchor="origin", spin=0, orient=UP) {
|
||||||
|
vnf = is_vnf_list(vnf)? vnf_merge(vnf) : vnf;
|
||||||
|
cp = is_def(cp) ? cp : vnf_centroid(vnf);
|
||||||
|
attachable(anchor,spin,orient, vnf=vnf, extent=extent, cp=cp) {
|
||||||
|
polyhedron(vnf[0], vnf[1], convexity=convexity);
|
||||||
|
children();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Module: vnf_wireframe()
|
||||||
|
// Usage:
|
||||||
|
// vnf_wireframe(vnf, <r|d>);
|
||||||
|
// Description:
|
||||||
|
// Given a VNF, creates a wire frame ball-and-stick model of the polyhedron with a cylinder for
|
||||||
|
// each edge and a sphere at each vertex. The width parameter specifies the width of the sticks
|
||||||
|
// that form the wire frame.
|
||||||
|
// Arguments:
|
||||||
|
// vnf = A vnf structure
|
||||||
|
// width = width of the cylinders forming the wire frame. Default: 1
|
||||||
|
// Example:
|
||||||
|
// $fn=32;
|
||||||
|
// ball = sphere(r=20, $fn=6);
|
||||||
|
// vnf_wireframe(ball,width=1);
|
||||||
|
// Example:
|
||||||
|
// include <BOSL2/polyhedra.scad>
|
||||||
|
// $fn=32;
|
||||||
|
// cube_oct = regular_polyhedron_info("vnf",
|
||||||
|
// name="cuboctahedron", or=20);
|
||||||
|
// vnf_wireframe(cube_oct);
|
||||||
|
// Example: The spheres at the vertex are imperfect at aligning with the cylinders, so especially at low $fn things look prety ugly. This is normal.
|
||||||
|
// include <BOSL2/polyhedra.scad>
|
||||||
|
// $fn=8;
|
||||||
|
// octahedron = regular_polyhedron_info("vnf",
|
||||||
|
// name="octahedron", or=20);
|
||||||
|
// vnf_wireframe(octahedron,width=5);
|
||||||
|
module vnf_wireframe(vnf, width=1)
|
||||||
|
{
|
||||||
|
vertex = vnf[0];
|
||||||
|
edges = unique([for (face=vnf[1], i=idx(face))
|
||||||
|
sort([face[i], select(face,i+1)])
|
||||||
|
]);
|
||||||
|
for (e=edges) extrude_from_to(vertex[e[0]],vertex[e[1]]) circle(d=width);
|
||||||
|
move_copies(vertex) sphere(d=width);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Section: Operations on VNFs
|
||||||
|
|
||||||
|
// Function: vnf_volume()
|
||||||
|
// Usage:
|
||||||
|
// vol = vnf_volume(vnf);
|
||||||
|
// Description:
|
||||||
|
// Returns the volume enclosed by the given manifold VNF. The VNF must describe a valid polyhedron with consistent face direction and
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// Divide the polyhedron into tetrahedra with the origin as one vertex and sum up the signed volume.
|
||||||
|
function vnf_volume(vnf) =
|
||||||
|
let(verts = vnf[0])
|
||||||
|
sum([
|
||||||
|
for(face=vnf[1], j=[1:1:len(face)-2])
|
||||||
|
cross(verts[face[j+1]], verts[face[j]]) * verts[face[0]]
|
||||||
|
])/6;
|
||||||
|
|
||||||
|
|
||||||
|
// Function: vnf_area()
|
||||||
|
// Usage:
|
||||||
|
// area = vnf_area(vnf);
|
||||||
|
// Description:
|
||||||
|
// Returns the surface area in any VNF by adding up the area of all its faces. The VNF need not be a manifold.
|
||||||
|
function vnf_area(vnf) =
|
||||||
|
let(verts=vnf[0])
|
||||||
|
sum([for(face=vnf[1]) polygon_area(select(verts,face))]);
|
||||||
|
|
||||||
|
|
||||||
|
// Function: vnf_centroid()
|
||||||
|
// Usage:
|
||||||
|
// vol = vnf_centroid(vnf);
|
||||||
|
// Description:
|
||||||
|
// Returns the centroid of the given manifold VNF. The VNF must describe a valid polyhedron with consistent face direction and
|
||||||
|
// no holes; otherwise the results are undefined.
|
||||||
|
|
||||||
|
// Divide the solid up into tetrahedra with the origin as one vertex.
|
||||||
|
// The centroid of a tetrahedron is the average of its vertices.
|
||||||
|
// The centroid of the total is the volume weighted average.
|
||||||
|
function vnf_centroid(vnf) =
|
||||||
|
assert(is_vnf(vnf) && len(vnf[0])!=0 )
|
||||||
|
let(
|
||||||
|
verts = vnf[0],
|
||||||
|
pos = sum([
|
||||||
|
for(face=vnf[1], j=[1:1:len(face)-2]) let(
|
||||||
|
v0 = verts[face[0]],
|
||||||
|
v1 = verts[face[j]],
|
||||||
|
v2 = verts[face[j+1]],
|
||||||
|
vol = cross(v2,v1)*v0
|
||||||
|
)
|
||||||
|
[ vol, (v0+v1+v2)*vol ]
|
||||||
|
])
|
||||||
|
)
|
||||||
|
assert(!approx(pos[0],0, EPSILON), "The vnf has self-intersections.")
|
||||||
|
pos[1]/pos[0]/4;
|
||||||
|
|
||||||
|
|
||||||
|
// Function: vnf_halfspace()
|
||||||
|
// Usage:
|
||||||
|
// newvnf = vnf_halfspace(plane, vnf, [closed]);
|
||||||
|
// Description:
|
||||||
|
// Returns the intersection of the vnf with a half space. The half space is defined by
|
||||||
|
// plane = [A,B,C,D], taking the side where the normal [A,B,C] points: Ax+By+Cz≥D.
|
||||||
|
// If closed is set to false then the cut face is not included in the vnf. This could
|
||||||
|
// allow further extension of the vnf by merging with other vnfs.
|
||||||
|
// Arguments:
|
||||||
|
// plane = plane defining the boundary of the half space
|
||||||
|
// vnf = vnf to cut
|
||||||
|
// closed = if false do not return include cut face(s). Default: true
|
||||||
|
// Example(3D):
|
||||||
|
// vnf = cube(10,center=true);
|
||||||
|
// cutvnf = vnf_halfspace([-1,1,-1,0], vnf);
|
||||||
|
// vnf_polyhedron(cutvnf);
|
||||||
|
// Example(3D): Cut face has 2 components
|
||||||
|
// vnf = path_sweep(circle(r=4, $fn=16),
|
||||||
|
// circle(r=20, $fn=64),closed=true);
|
||||||
|
// cutvnf = vnf_halfspace([-1,1,-4,0], vnf);
|
||||||
|
// vnf_polyhedron(cutvnf);
|
||||||
|
// Example(3D): Cut face is not simply connected
|
||||||
|
// vnf = path_sweep(circle(r=4, $fn=16),
|
||||||
|
// circle(r=20, $fn=64),closed=true);
|
||||||
|
// cutvnf = vnf_halfspace([0,0.7,-4,0], vnf);
|
||||||
|
// vnf_polyhedron(cutvnf);
|
||||||
|
// Example(3D): Cut object has multiple components
|
||||||
|
// function knot(a,b,t) = // rolling knot
|
||||||
|
// [ a * cos (3 * t) / (1 - b* sin (2 *t)),
|
||||||
|
// a * sin( 3 * t) / (1 - b* sin (2 *t)),
|
||||||
|
// 1.8 * b * cos (2 * t) /(1 - b* sin (2 *t))];
|
||||||
|
// a = 0.8; b = sqrt (1 - a * a);
|
||||||
|
// ksteps = 400;
|
||||||
|
// knot_path = [for (i=[0:ksteps-1]) 50 * knot(a,b,(i/ksteps)*360)];
|
||||||
|
// ushape = [[-10, 0],[-10, 10],[ -7, 10],[ -7, 2],[ 7, 2],[ 7, 7],[ 10, 7],[ 10, 0]];
|
||||||
|
// knot=path_sweep(ushape, knot_path, closed=true, method="incremental");
|
||||||
|
// cut_knot = vnf_halfspace([1,0,0,0], knot);
|
||||||
|
// vnf_polyhedron(cut_knot);
|
||||||
|
function vnf_halfspace(plane, vnf, closed=true) =
|
||||||
|
let(
|
||||||
|
inside = [for(x=vnf[0]) plane*[each x,-1] >= 0 ? 1 : 0],
|
||||||
|
vertexmap = [0,each cumsum(inside)],
|
||||||
|
faces_edges_vertices = _vnfcut(plane, vnf[0],vertexmap,inside, vnf[1], last(vertexmap)),
|
||||||
|
newvert = concat(bselect(vnf[0],inside), faces_edges_vertices[2])
|
||||||
|
)
|
||||||
|
closed==false ? [newvert, faces_edges_vertices[0]] :
|
||||||
|
let(
|
||||||
|
allpaths = _assemble_paths(newvert, faces_edges_vertices[1]),
|
||||||
|
newpaths = [for(p=allpaths) if (len(p)>=3) p
|
||||||
|
else assert(approx(p[0],p[1]),"Orphan edge found when assembling cut edges.")
|
||||||
|
]
|
||||||
|
)
|
||||||
|
len(newpaths)<=1 ? [newvert, concat(faces_edges_vertices[0], newpaths)]
|
||||||
|
:
|
||||||
|
let(
|
||||||
|
M = project_plane(plane),
|
||||||
|
faceregion = [for(path=newpaths) path2d(apply(M,select(newvert,path)))],
|
||||||
|
facevnf = region_faces(faceregion,transform=rot_inverse(M),reverse=true)
|
||||||
|
)
|
||||||
|
vnf_merge([[newvert, faces_edges_vertices[0]], facevnf]);
|
||||||
|
|
||||||
|
|
||||||
|
function _assemble_paths(vertices, edges, paths=[],i=0) =
|
||||||
|
i==len(edges) ? paths :
|
||||||
|
norm(vertices[edges[i][0]]-vertices[edges[i][1]])<EPSILON ? _assemble_paths(vertices,edges,paths,i+1) :
|
||||||
|
let( // Find paths that connects on left side and right side of the edges (if one exists)
|
||||||
|
left = [for(j=idx(paths)) if (approx(vertices[last(paths[j])],vertices[edges[i][0]])) j],
|
||||||
|
right = [for(j=idx(paths)) if (approx(vertices[edges[i][1]],vertices[paths[j][0]])) j]
|
||||||
|
)
|
||||||
|
assert(len(left)<=1 && len(right)<=1)
|
||||||
|
let(
|
||||||
|
keep_path = list_remove(paths,concat(left,right)),
|
||||||
|
update_path = left==[] && right==[] ? edges[i]
|
||||||
|
: left==[] ? concat([edges[i][0]],paths[right[0]])
|
||||||
|
: right==[] ? concat(paths[left[0]],[edges[i][1]])
|
||||||
|
: left != right ? concat(paths[left[0]], paths[right[0]])
|
||||||
|
: paths[left[0]]
|
||||||
|
)
|
||||||
|
_assemble_paths(vertices, edges, concat(keep_path, [update_path]), i+1);
|
||||||
|
|
||||||
|
|
||||||
|
function _vnfcut(plane, vertices, vertexmap, inside, faces, vertcount, newfaces=[], newedges=[], newvertices=[], i=0) =
|
||||||
|
i==len(faces) ? [newfaces, newedges, newvertices] :
|
||||||
|
let(
|
||||||
|
pts_inside = select(inside,faces[i])
|
||||||
|
)
|
||||||
|
all(pts_inside) ? _vnfcut(plane, vertices, vertexmap, inside, faces, vertcount,
|
||||||
|
concat(newfaces, [select(vertexmap,faces[i])]), newedges, newvertices, i+1):
|
||||||
|
!any(pts_inside) ? _vnfcut(plane, vertices, vertexmap,inside, faces, vertcount, newfaces, newedges, newvertices, i+1):
|
||||||
|
let(
|
||||||
|
first = search([[1,0]],pair(pts_inside,wrap=true),0)[0],
|
||||||
|
second = search([[0,1]],pair(pts_inside,wrap=true),0)[0]
|
||||||
|
)
|
||||||
|
assert(len(first)==1 && len(second)==1, "Found concave face in VNF. Run vnf_triangulate first to ensure convex faces.")
|
||||||
|
let(
|
||||||
|
newface = [each select(vertexmap,select(faces[i],second[0]+1,first[0])),vertcount, vertcount+1],
|
||||||
|
newvert = [plane_line_intersection(plane, select(vertices,select(faces[i],first[0],first[0]+1)),eps=0),
|
||||||
|
plane_line_intersection(plane, select(vertices,select(faces[i],second[0],second[0]+1)),eps=0)]
|
||||||
|
)
|
||||||
|
true //!approx(newvert[0],newvert[1])
|
||||||
|
? _vnfcut(plane, vertices, vertexmap, inside, faces, vertcount+2,
|
||||||
|
concat(newfaces, [newface]), concat(newedges,[[vertcount+1,vertcount]]),concat(newvertices,newvert),i+1)
|
||||||
|
:len(newface)>3
|
||||||
|
? _vnfcut(plane, vertices, vertexmap, inside, faces, vertcount+1,
|
||||||
|
concat(newfaces, [list_head(newface)]), newedges,concat(newvertices,[newvert[0]]),i+1)
|
||||||
|
:
|
||||||
|
_vnfcut(plane, vertices, vertexmap, inside, faces, vertcount,newfaces, newedges, newvert, i+1);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function _triangulate_planar_convex_polygons(polys) =
|
function _triangulate_planar_convex_polygons(polys) =
|
||||||
polys==[]? [] :
|
polys==[]? [] :
|
||||||
let(
|
let(
|
||||||
|
@ -809,7 +815,8 @@ function _triangulate_planar_convex_polygons(polys) =
|
||||||
// bent2 = vnf_bend(vnf2, axis="Y");
|
// bent2 = vnf_bend(vnf2, axis="Y");
|
||||||
// vnf_polyhedron([bent1,bent2]);
|
// vnf_polyhedron([bent1,bent2]);
|
||||||
// Example(3D):
|
// Example(3D):
|
||||||
// rgn = union(rect([100,20],center=true), rect([20,100],center=true));
|
// rgn = union(rect([100,20],center=true),
|
||||||
|
// rect([20,100],center=true));
|
||||||
// vnf0 = linear_sweep(zrot(45,p=rgn), height=10);
|
// vnf0 = linear_sweep(zrot(45,p=rgn), height=10);
|
||||||
// vnf1 = up(50, p=vnf0);
|
// vnf1 = up(50, p=vnf0);
|
||||||
// vnf2 = down(50, p=vnf0);
|
// vnf2 = down(50, p=vnf0);
|
||||||
|
@ -885,26 +892,24 @@ function vnf_bend(vnf,r,d,axis="Z") =
|
||||||
) [new_vert,sliced[1]];
|
) [new_vert,sliced[1]];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Section: Debugging Polyhedrons
|
// Section: Debugging Polyhedrons
|
||||||
|
|
||||||
// Module: _show_vertices()
|
/// Internal Module: _show_vertices()
|
||||||
// Usage:
|
/// Usage:
|
||||||
// _show_vertices(vertices, [size])
|
/// _show_vertices(vertices, [size])
|
||||||
// Description:
|
/// Description:
|
||||||
// Draws all the vertices in an array, at their 3D position, numbered by their
|
/// Draws all the vertices in an array, at their 3D position, numbered by their
|
||||||
// position in the vertex array. Also draws any children of this module with
|
/// position in the vertex array. Also draws any children of this module with
|
||||||
// transparency.
|
/// transparency.
|
||||||
// Arguments:
|
/// Arguments:
|
||||||
// vertices = Array of point vertices.
|
/// vertices = Array of point vertices.
|
||||||
// size = The size of the text used to label the vertices. Default: 1
|
/// size = The size of the text used to label the vertices. Default: 1
|
||||||
// Example:
|
/// Example:
|
||||||
// verts = [for (z=[-10,10], y=[-10,10], x=[-10,10]) [x,y,z]];
|
/// verts = [for (z=[-10,10], y=[-10,10], x=[-10,10]) [x,y,z]];
|
||||||
// faces = [[0,1,2], [1,3,2], [0,4,5], [0,5,1], [1,5,7], [1,7,3], [3,7,6], [3,6,2], [2,6,4], [2,4,0], [4,6,7], [4,7,5]];
|
/// faces = [[0,1,2], [1,3,2], [0,4,5], [0,5,1], [1,5,7], [1,7,3], [3,7,6], [3,6,2], [2,6,4], [2,4,0], [4,6,7], [4,7,5]];
|
||||||
// _show_vertices(vertices=verts, size=2) {
|
/// _show_vertices(vertices=verts, size=2) {
|
||||||
// polyhedron(points=verts, faces=faces);
|
/// polyhedron(points=verts, faces=faces);
|
||||||
// }
|
/// }
|
||||||
module _show_vertices(vertices, size=1) {
|
module _show_vertices(vertices, size=1) {
|
||||||
color("blue") {
|
color("blue") {
|
||||||
dups = vector_search(vertices, EPSILON, vertices);
|
dups = vector_search(vertices, EPSILON, vertices);
|
||||||
|
@ -924,7 +929,7 @@ module _show_vertices(vertices, size=1) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Module: _show_faces()
|
/// Internal Module: _show_faces()
|
||||||
/// Usage:
|
/// Usage:
|
||||||
/// _show_faces(vertices, faces, [size=]);
|
/// _show_faces(vertices, faces, [size=]);
|
||||||
/// Description:
|
/// Description:
|
||||||
|
|
Loading…
Reference in a new issue