mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2024-12-29 16:29:40 +00:00
add attachments to region()
rewrite "circle" attachment to use line intersection
This commit is contained in:
parent
f605bafb0d
commit
b671a0c37d
3 changed files with 27 additions and 15 deletions
|
@ -1522,7 +1522,7 @@ function _get_cp(geom) =
|
||||||
)
|
)
|
||||||
assert(type!="other", "Invalid cp value")
|
assert(type!="other", "Invalid cp value")
|
||||||
cp=="centroid" ? centroid(geom[1])
|
cp=="centroid" ? centroid(geom[1])
|
||||||
: let(points = type=="vnf"?geom[1][0]:geom[1])
|
: let(points = type=="vnf"?geom[1][0]:flatten(force_region(geom[1])))
|
||||||
cp=="mean" ? mean(points)
|
cp=="mean" ? mean(points)
|
||||||
: cp=="box" ? mean(pointlist_bounds(points))
|
: cp=="box" ? mean(pointlist_bounds(points))
|
||||||
: assert(false,"Invalid cp specification");
|
: assert(false,"Invalid cp specification");
|
||||||
|
@ -1703,13 +1703,18 @@ function _find_anchor(anchor, geom) =
|
||||||
) [anchor, pos, vec, 0]
|
) [anchor, pos, vec, 0]
|
||||||
) : type == "circle"? ( //r
|
) : type == "circle"? ( //r
|
||||||
assert(anchor.z==0, "The Z component of an anchor for a 2D shape must be 0.")
|
assert(anchor.z==0, "The Z component of an anchor for a 2D shape must be 0.")
|
||||||
let(
|
let(
|
||||||
rr = geom[1],
|
rr = geom[1],
|
||||||
r = is_num(rr)? [rr,rr] : point2d(rr),
|
r = is_num(rr)? [rr,rr] : point2d(rr),
|
||||||
|
pos = approx(anchor.x,0) ? [sign(anchor.x)*r.x,0]
|
||||||
|
: let(
|
||||||
|
m = anchor.y/anchor.x,
|
||||||
|
px = sign(anchor.x) * sqrt(1/(1/sqr(r.x) + m*m/sqr(r.y)))
|
||||||
|
)
|
||||||
|
[px,m*px],
|
||||||
anchor = unit(point2d(anchor),[0,0]),
|
anchor = unit(point2d(anchor),[0,0]),
|
||||||
pos = point2d(cp) + v_mul(r,anchor) + point2d(offset),
|
vec = [r.y/r.x*pos.x, r.x/r.y*pos.y]
|
||||||
vec = unit(v_mul(r,anchor),[0,1])
|
) [anchor, point2d(cp+offset)+pos, vec, 0]
|
||||||
) [anchor, pos, vec, 0]
|
|
||||||
) : type == "rgn_isect"? ( //region
|
) : type == "rgn_isect"? ( //region
|
||||||
assert(anchor.z==0, "The Z component of an anchor for a 2D shape must be 0.")
|
assert(anchor.z==0, "The Z component of an anchor for a 2D shape must be 0.")
|
||||||
let(
|
let(
|
||||||
|
@ -1727,7 +1732,10 @@ function _find_anchor(anchor, geom) =
|
||||||
n2 = vector_angle(anchor,n)>90? -n : n
|
n2 = vector_angle(anchor,n)>90? -n : n
|
||||||
)
|
)
|
||||||
if(!is_undef(isect) && !approx(isect,t[0])) [norm(isect), isect, n2]
|
if(!is_undef(isect) && !approx(isect,t[0])) [norm(isect), isect, n2]
|
||||||
],
|
]
|
||||||
|
)
|
||||||
|
assert(len(isects)>0, "Anchor vector does not intersect with the shape. Attachment failed.")
|
||||||
|
let(
|
||||||
maxidx = max_index(column(isects,0)),
|
maxidx = max_index(column(isects,0)),
|
||||||
isect = isects[maxidx],
|
isect = isects[maxidx],
|
||||||
pos = point2d(cp) + isect[1],
|
pos = point2d(cp) + isect[1],
|
||||||
|
@ -1736,8 +1744,7 @@ function _find_anchor(anchor, geom) =
|
||||||
) : type == "rgn_extent"? ( //region
|
) : type == "rgn_extent"? ( //region
|
||||||
assert(anchor.z==0, "The Z component of an anchor for a 2D shape must be 0.")
|
assert(anchor.z==0, "The Z component of an anchor for a 2D shape must be 0.")
|
||||||
let(
|
let(
|
||||||
rgn_raw = geom[1],
|
rgn = force_region(geom[1]),
|
||||||
rgn = is_region(rgn_raw)? rgn_raw : [rgn_raw],
|
|
||||||
anchor = point2d(anchor),
|
anchor = point2d(anchor),
|
||||||
m = rot(from=anchor, to=RIGHT) * move(-[cp.x, cp.y, 0]),
|
m = rot(from=anchor, to=RIGHT) * move(-[cp.x, cp.y, 0]),
|
||||||
rpts = apply(m, flatten(rgn)),
|
rpts = apply(m, flatten(rgn)),
|
||||||
|
|
|
@ -703,7 +703,7 @@ function arc(N, r, angle, d, cp, points, width, thickness, start, wedge=false, l
|
||||||
module arc(N, r, angle, d, cp, points, width, thickness, start, wedge=false, anchor=CENTER, spin=0)
|
module arc(N, r, angle, d, cp, points, width, thickness, start, wedge=false, anchor=CENTER, spin=0)
|
||||||
{
|
{
|
||||||
path = arc(N=N, r=r, angle=angle, d=d, cp=cp, points=points, width=width, thickness=thickness, start=start, wedge=wedge);
|
path = arc(N=N, r=r, angle=angle, d=d, cp=cp, points=points, width=width, thickness=thickness, start=start, wedge=wedge);
|
||||||
attachable(anchor,spin, two_d=true, path=path) {
|
attachable(anchor,spin, two_d=true, path=path, extent=true) {
|
||||||
polygon(path);
|
polygon(path);
|
||||||
children();
|
children();
|
||||||
}
|
}
|
||||||
|
|
17
regions.scad
17
regions.scad
|
@ -278,13 +278,16 @@ function force_region(poly) = is_path(poly) ? [poly] : poly;
|
||||||
|
|
||||||
// Module: region()
|
// Module: region()
|
||||||
// Usage:
|
// Usage:
|
||||||
// region(r);
|
// region(r, [anchor], [spin], [cp]) { ... };
|
||||||
// Description:
|
// Description:
|
||||||
// Creates the 2D polygons described by the given region or list of polygons. This module works on
|
// Creates the 2D polygons described by the given region or list of polygons. This module works on
|
||||||
// arbitrary lists of polygons that cross each other and hence do not define a valid region. The
|
// arbitrary lists of polygons that cross each other and hence do not define a valid region. The
|
||||||
// displayed result is the exclusive-or of the polygons listed in the input.
|
// displayed result is the exclusive-or of the polygons listed in the input.
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// r = region to create as geometry
|
// r = region to create as geometry
|
||||||
|
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `"origin"`
|
||||||
|
// spin = Rotate this many degrees after anchor. See [spin](attachments.scad#spin). Default: `0`
|
||||||
|
// cp = Centerpoint for determining intersection anchors or centering the shape. Determintes the base of the anchor vector. Can be "centroid", "mean", "box" or a 2D point. Default: "centroid"
|
||||||
// Example(2D): Displaying a region
|
// Example(2D): Displaying a region
|
||||||
// region([circle(d=50), square(25,center=true)]);
|
// region([circle(d=50), square(25,center=true)]);
|
||||||
// Example(2D): Displaying a list of polygons that intersect each other, which is not a region
|
// Example(2D): Displaying a list of polygons that intersect each other, which is not a region
|
||||||
|
@ -293,16 +296,18 @@ function force_region(poly) = is_path(poly) ? [poly] : poly;
|
||||||
// [square([60,10], center=true)]
|
// [square([60,10], center=true)]
|
||||||
// );
|
// );
|
||||||
// region(rgn);
|
// region(rgn);
|
||||||
module region(r)
|
module region(r, anchor="origin", spin=0, cp="centroid")
|
||||||
{
|
{
|
||||||
no_children($children);
|
|
||||||
r = force_region(r);
|
r = force_region(r);
|
||||||
dummy=assert(is_region(r), "Input is not a region");
|
dummy=assert(is_region(r), "Input is not a region");
|
||||||
points = flatten(r);
|
points = flatten(r);
|
||||||
lengths = [for(path=r) len(path)];
|
lengths = [for(path=r) len(path)];
|
||||||
starts = [0,each cumsum(lengths)];
|
starts = [0,each cumsum(lengths)];
|
||||||
paths = [for(i=idx(r)) count(s=starts[i], n=lengths[i])];
|
paths = [for(i=idx(r)) count(s=starts[i], n=lengths[i])];
|
||||||
polygon(points=points, paths=paths);
|
attachable(anchor, spin, two_d=true, region=r, extent=false, cp=cp){
|
||||||
|
polygon(points=points, paths=paths);
|
||||||
|
children();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -583,7 +588,7 @@ function region_parts(region) =
|
||||||
|
|
||||||
// Function&Module: linear_sweep()
|
// Function&Module: linear_sweep()
|
||||||
// Usage:
|
// Usage:
|
||||||
// linear_sweep(region, height, [center], [slices], [twist], [scale], [style], [convexity]);
|
// linear_sweep(region, height, [center], [slices], [twist], [scale], [style], [convexity]) {attachments};
|
||||||
// Description:
|
// Description:
|
||||||
// If called as a module, creates a polyhedron that is the linear extrusion of the given 2D region or polygon.
|
// If called as a module, creates a polyhedron that is the linear extrusion of the given 2D region or polygon.
|
||||||
// If called as a function, returns a VNF that can be used to generate a polyhedron of the linear extrusion
|
// If called as a function, returns a VNF that can be used to generate a polyhedron of the linear extrusion
|
||||||
|
@ -630,7 +635,7 @@ function region_parts(region) =
|
||||||
// mrgn = union(rgn1,rgn2);
|
// mrgn = union(rgn1,rgn2);
|
||||||
// orgn = difference(mrgn,rgn3);
|
// orgn = difference(mrgn,rgn3);
|
||||||
// linear_sweep(orgn,height=20,convexity=16) show_anchors();
|
// linear_sweep(orgn,height=20,convexity=16) show_anchors();
|
||||||
module linear_sweep(region, height=1, center, twist=0, scale=1, slices, maxseg, style="default", convexity, anchor_isect=false, anchor, spin=0, orient=UP, cp="centroid", anchor="origin") {
|
module linear_sweep(region, height=1, center, twist=0, scale=1, slices, maxseg, style="default", convexity, anchor_isect=false, spin=0, orient=UP, cp="centroid", anchor="origin") {
|
||||||
region = force_region(region);
|
region = force_region(region);
|
||||||
dummy=assert(is_region(region),"Input is not a region");
|
dummy=assert(is_region(region),"Input is not a region");
|
||||||
anchor = center ? "zcenter" : anchor;
|
anchor = center ? "zcenter" : anchor;
|
||||||
|
|
Loading…
Reference in a new issue