mirror of
https://github.com/revarbat/BOSL2.git
synced 2025-01-16 13:50:23 +01:00
Added vnf_bend_around_y_axis().
This commit is contained in:
parent
a5fb810738
commit
32e0f26fd8
141
geometry.scad
141
geometry.scad
@ -1454,5 +1454,146 @@ function polygon_normal(poly) =
|
||||
) unit(n);
|
||||
|
||||
|
||||
function _split_polygon_at_x(poly, x) =
|
||||
let(
|
||||
xs = subindex(poly,0)
|
||||
) (min(xs) >= x || max(xs) <= x)? [poly] :
|
||||
let(
|
||||
poly2 = [
|
||||
for (p = pair_wrap(poly)) each [
|
||||
p[0],
|
||||
if(
|
||||
(p[0].x < x && p[1].x > x) ||
|
||||
(p[1].x < x && p[0].x > x)
|
||||
) let(
|
||||
u = (x - p[0].x) / (p[1].x - p[0].x)
|
||||
) [
|
||||
x, // Important for later exact match tests
|
||||
u*(p[1].y-p[0].y)+p[0].y,
|
||||
u*(p[1].z-p[0].z)+p[0].z,
|
||||
]
|
||||
]
|
||||
],
|
||||
out1 = [for (p = poly2) if(p.x <= x) p],
|
||||
out2 = [for (p = poly2) if(p.x >= x) p],
|
||||
out = [
|
||||
if (len(out1)>=3) out1,
|
||||
if (len(out2)>=3) out2,
|
||||
]
|
||||
) out;
|
||||
|
||||
|
||||
function _split_polygon_at_y(poly, y) =
|
||||
let(
|
||||
ys = subindex(poly,1)
|
||||
) (min(ys) >= y || max(ys) <= y)? [poly] :
|
||||
let(
|
||||
poly2 = [
|
||||
for (p = pair_wrap(poly)) each [
|
||||
p[0],
|
||||
if(
|
||||
(p[0].y < y && p[1].y > y) ||
|
||||
(p[1].y < y && p[0].y > y)
|
||||
) let(
|
||||
u = (y - p[0].y) / (p[1].y - p[0].y)
|
||||
) [
|
||||
u*(p[1].x-p[0].x)+p[0].x,
|
||||
y, // Important for later exact match tests
|
||||
u*(p[1].z-p[0].z)+p[0].z,
|
||||
]
|
||||
]
|
||||
],
|
||||
out1 = [for (p = poly2) if(p.y <= y) p],
|
||||
out2 = [for (p = poly2) if(p.y >= y) p],
|
||||
out = [
|
||||
if (len(out1)>=3) out1,
|
||||
if (len(out2)>=3) out2,
|
||||
]
|
||||
) out;
|
||||
|
||||
|
||||
function _split_polygon_at_z(poly, z) =
|
||||
let(
|
||||
zs = subindex(poly,1)
|
||||
) (min(zs) >= z || max(zs) <= z)? [poly] :
|
||||
let(
|
||||
poly2 = [
|
||||
for (p = pair_wrap(poly)) each [
|
||||
p[0],
|
||||
if(
|
||||
(p[0].z < z && p[1].z > z) ||
|
||||
(p[1].z < z && p[0].z > z)
|
||||
) let(
|
||||
u = (z - p[0].z) / (p[1].z - p[0].z)
|
||||
) [
|
||||
u*(p[1].x-p[0].x)+p[0].x,
|
||||
u*(p[1].y-p[0].y)+p[0].y,
|
||||
z, // Important for later exact match tests
|
||||
]
|
||||
]
|
||||
],
|
||||
out1 = [for (p = poly2) if(p.z <= z) p],
|
||||
out2 = [for (p = poly2) if(p.z >= z) p],
|
||||
out = [
|
||||
if (len(out1)>=3) out1,
|
||||
if (len(out2)>=3) out2,
|
||||
]
|
||||
) out;
|
||||
|
||||
|
||||
// Function: split_polygons_at_each_x()
|
||||
// Usage:
|
||||
// splitpolys = split_polygons_at_each_x(polys, xs);
|
||||
// Description:
|
||||
// Given a list of 3D polygons, splits all of them wherever they cross any X value given in `xs`.
|
||||
// Arguments:
|
||||
// polys = A list of 3D polygons to split.
|
||||
// xs = A list of scalar X values to split at.
|
||||
function split_polygons_at_each_x(polys, xs, _i=0) =
|
||||
_i>=len(xs)? polys :
|
||||
split_polygons_at_each_x(
|
||||
[
|
||||
for (poly = polys)
|
||||
each _split_polygon_at_x(poly, xs[_i])
|
||||
], xs, _i=_i+1
|
||||
);
|
||||
|
||||
|
||||
// Function: split_polygons_at_each_y()
|
||||
// Usage:
|
||||
// splitpolys = split_polygons_at_each_y(polys, ys);
|
||||
// Description:
|
||||
// Given a list of 3D polygons, splits all of them wherever they cross any Y value given in `ys`.
|
||||
// Arguments:
|
||||
// polys = A list of 3D polygons to split.
|
||||
// ys = A list of scalar Y values to split at.
|
||||
function split_polygons_at_each_y(polys, ys, _i=0) =
|
||||
_i>=len(ys)? polys :
|
||||
split_polygons_at_each_y(
|
||||
[
|
||||
for (poly = polys)
|
||||
each _split_polygon_at_y(poly, ys[_i])
|
||||
], ys, _i=_i+1
|
||||
);
|
||||
|
||||
|
||||
// Function: split_polygons_at_each_z()
|
||||
// Usage:
|
||||
// splitpolys = split_polygons_at_each_z(polys, zs);
|
||||
// Description:
|
||||
// Given a list of 3D polygons, splits all of them wherever they cross any Z value given in `zs`.
|
||||
// Arguments:
|
||||
// polys = A list of 3D polygons to split.
|
||||
// zs = A list of scalar Z values to split at.
|
||||
function split_polygons_at_each_z(polys, zs, _i=0) =
|
||||
_i>=len(zs)? polys :
|
||||
split_polygons_at_each_z(
|
||||
[
|
||||
for (poly = polys)
|
||||
each _split_polygon_at_z(poly, zs[_i])
|
||||
], zs, _i=_i+1
|
||||
);
|
||||
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
@ -8,7 +8,7 @@
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
BOSL_VERSION = [2,0,300];
|
||||
BOSL_VERSION = [2,0,301];
|
||||
|
||||
|
||||
// Section: BOSL Library Version Functions
|
||||
|
81
vnf.scad
81
vnf.scad
@ -397,6 +397,87 @@ function vnf_centroid(vnf) =
|
||||
) val[1]/val[0]/8;
|
||||
|
||||
|
||||
function _triangulate_planar_convex_polygons(polys) =
|
||||
polys==[]? [] :
|
||||
let(
|
||||
tris = [for (poly=polys) if (len(poly)==3) poly],
|
||||
bigs = [for (poly=polys) if (len(poly)>3) poly],
|
||||
newtris = [for (poly=bigs) select(poly,-2,0)],
|
||||
newbigs = [for (poly=bigs) select(poly,0,-2)],
|
||||
newtris2 = _triangulate_planar_convex_polygons(newbigs),
|
||||
outtris = concat(tris, newtris, newtris2)
|
||||
) outtris;
|
||||
|
||||
|
||||
// Function: vnf_bend_around_y_axis()
|
||||
// Usage:
|
||||
// bentvnf = vnf_bend_around_y_axis(vnf);
|
||||
// Description:
|
||||
// Given a VNF that is entirely above, or entirely below the Z=0 plane, bends the VNF around the
|
||||
// Y axis, splitting up faces as necessary. Returns the bent VNF. Will error out if the VNF
|
||||
// straddles the Z=0 plane, or if the bent VNF would wrap more than completely around. The 1:1
|
||||
// radius is where the curved length of the bent VNF matches the length of the original VNF. If the
|
||||
// `r` or `d` arguments are given, then they will specify the 1:1 radius or diameter. If they are
|
||||
// not given, then the 1:1 radius will be defined by the distance of the furthest vertex in the
|
||||
// original VNF from the Z=0 plane. You can adjust the granularity of the bend using the standard
|
||||
// `$fa`, `$fs`, and `$fn` variables.
|
||||
// Arguments:
|
||||
// vnf = The original VNF to bend.
|
||||
// r = If given, the radius where the size of the original shape is the same as in the original.
|
||||
// d = If given, the diameter where the size of the original shape is the same as in the original.
|
||||
// Example(3D):
|
||||
// vnf0 = cube([100,40,10], center=true);
|
||||
// vnf1 = up(35, p=vnf0);
|
||||
// vnf2 = down(50, p=vnf0);
|
||||
// bent1 = vnf_bend_around_y_axis(vnf1);
|
||||
// bent2 = vnf_bend_around_y_axis(vnf2);
|
||||
// vnf_polyhedron([bent1,bent2]);
|
||||
// Example(3D):
|
||||
// vnf0 = linear_sweep(star(n=5,step=2,d=100), height=10);
|
||||
// vnf1 = up(35, p=vnf0);
|
||||
// vnf2 = down(50, p=vnf0);
|
||||
// bent1 = vnf_bend_around_y_axis(vnf1);
|
||||
// bent2 = vnf_bend_around_y_axis(vnf2);
|
||||
// vnf_polyhedron([bent1,bent2]);
|
||||
// Example(3D):
|
||||
// rgn = union(rect([100,20],center=true), rect([20,100],center=true));
|
||||
// vnf0 = linear_sweep(zrot(45,p=rgn), height=10);
|
||||
// vnf1 = up(35, p=vnf0);
|
||||
// vnf2 = down(50, p=vnf0);
|
||||
// bent1 = vnf_bend_around_y_axis(vnf1);
|
||||
// bent2 = vnf_bend_around_y_axis(vnf2);
|
||||
// vnf_polyhedron([bent1,bent2]);
|
||||
function vnf_bend_around_y_axis(vnf,r,d) =
|
||||
let(
|
||||
vnf = vnf_triangulate(vnf),
|
||||
verts = vnf[0],
|
||||
bounds = pointlist_bounds(verts),
|
||||
bmin = bounds[0],
|
||||
bmax = bounds[1],
|
||||
r = get_radius(r=r,d=d,dflt=max(abs(bmax.z), abs(bmin.z))),
|
||||
width = bmax.x - bmin.x
|
||||
)
|
||||
assert(bmin.z > 0 || bmax.z < 0, "Entire shape MUST be completely above or below z=0.")
|
||||
assert(width <= 2*PI*r, "Shape would wrap more than completely around the cylinder.")
|
||||
let(
|
||||
min_ang = 180 * bmin.x / (PI * r),
|
||||
max_ang = 180 * bmax.x / (PI * r),
|
||||
ang_span = max_ang-min_ang,
|
||||
steps = ceil(segs(r) * ang_span/360),
|
||||
step = width / steps,
|
||||
bend_at = [for(i = [1:1:steps-1]) i*step+bmin.x],
|
||||
facepolys = [for (face=vnf[1]) select(verts,face)],
|
||||
splits = split_polygons_at_each_x(facepolys, bend_at),
|
||||
newtris = _triangulate_planar_convex_polygons(splits),
|
||||
bent_faces = [
|
||||
for (tri = newtris) [
|
||||
for (p = tri) let(
|
||||
a = 180*p.x/(r*PI) * sign(bmax.z)
|
||||
) [p.z*sin(a), p.y, p.z*cos(a)]
|
||||
]
|
||||
]
|
||||
) vnf_add_faces(faces=bent_faces);
|
||||
|
||||
|
||||
// Function&Module: vnf_validate()
|
||||
// Usage: As Function
|
||||
|
Loading…
x
Reference in New Issue
Block a user