mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2025-01-01 09:49:45 +00:00
move half-space stuff to partitions.scad
This commit is contained in:
parent
edde34ff76
commit
50191bf5fd
2 changed files with 342 additions and 341 deletions
338
mutators.scad
338
mutators.scad
|
@ -8,9 +8,8 @@
|
||||||
// FileFootnotes: STD=Included in std.scad
|
// FileFootnotes: STD=Included in std.scad
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
// Section: Volume Division Mutators
|
// Section: Bounding Box
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Module: bounding_box()
|
// Module: bounding_box()
|
||||||
|
@ -96,341 +95,6 @@ module bounding_box(excess=0, planar=false) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Function&Module: half_of()
|
|
||||||
//
|
|
||||||
// Usage: as module
|
|
||||||
// half_of(v, [cp], [s], [planar]) ...
|
|
||||||
// Usage: as function
|
|
||||||
// result = half_of(p,v,[cp]);
|
|
||||||
//
|
|
||||||
// Description:
|
|
||||||
// Slices an object at a cut plane, and masks away everything that is on one side. The v parameter is either a plane specification or
|
|
||||||
// a normal vector. The s parameter is needed for the module
|
|
||||||
// version to control the size of the masking cube. If s is too large then the preview display will flip around and display the
|
|
||||||
// wrong half, but if it is too small it won't fully mask your model.
|
|
||||||
// When called as a function, you must supply a vnf, path or region in p. If planar is set to true for the module version the operation
|
|
||||||
// is performed in 2D and UP and DOWN are treated as equivalent to BACK and FWD respectively.
|
|
||||||
//
|
|
||||||
// Arguments:
|
|
||||||
// p = path, region or VNF to slice. (Function version)
|
|
||||||
// v = Normal of plane to slice at. Keeps everything on the side the normal points to. Default: [0,0,1] (UP)
|
|
||||||
// cp = If given as a scalar, moves the cut plane along the normal by the given amount. If given as a point, specifies a point on the cut plane. Default: [0,0,0]
|
|
||||||
// s = Mask size to use. Use a number larger than twice your object's largest axis. If you make this too large, OpenSCAD's preview rendering may display the wrong half. (Module version) Default: 100
|
|
||||||
// planar = If true, perform a 2D operation. When planar, a `v` of `UP` or `DOWN` becomes equivalent of `BACK` and `FWD` respectively. (Module version). Default: false.
|
|
||||||
//
|
|
||||||
// Examples:
|
|
||||||
// half_of(DOWN+BACK, cp=[0,-10,0]) cylinder(h=40, r1=10, r2=0, center=false);
|
|
||||||
// half_of(DOWN+LEFT, s=200) sphere(d=150);
|
|
||||||
// Example(2D):
|
|
||||||
// half_of([1,1], planar=true) circle(d=50);
|
|
||||||
module half_of(v=UP, cp, s=100, planar=false)
|
|
||||||
{
|
|
||||||
cp = is_vector(v,4)? assert(cp==undef, "Don't use cp with plane definition.") plane_normal(v) * v[3] :
|
|
||||||
is_vector(cp)? cp :
|
|
||||||
is_num(cp)? cp*unit(v) :
|
|
||||||
[0,0,0];
|
|
||||||
v = is_vector(v,4)? plane_normal(v) : v;
|
|
||||||
if (cp != [0,0,0]) {
|
|
||||||
translate(cp) half_of(v=v, s=s, planar=planar) translate(-cp) children();
|
|
||||||
} else if (planar) {
|
|
||||||
v = (v==UP)? BACK : (v==DOWN)? FWD : v;
|
|
||||||
ang = atan2(v.y, v.x);
|
|
||||||
difference() {
|
|
||||||
children();
|
|
||||||
rotate(ang+90) {
|
|
||||||
back(s/2) square(s, center=true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
difference() {
|
|
||||||
children();
|
|
||||||
rot(from=UP, to=-v) {
|
|
||||||
up(s/2) cube(s, center=true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function half_of(p, v=UP, cp) =
|
|
||||||
is_vnf(p) ?
|
|
||||||
assert(is_vector(v) && (len(v)==3 || len(v)==4),str("Must give 3-vector or plane specification",v))
|
|
||||||
assert(select(v,0,2)!=[0,0,0], "vector v must be nonzero")
|
|
||||||
let(
|
|
||||||
plane = is_vector(v,4) ? assert(cp==undef, "Don't use cp with plane definition.") v
|
|
||||||
: is_undef(cp) ? [each v, 0]
|
|
||||||
: is_num(cp) ? [each v, cp*(v*v)/norm(v)]
|
|
||||||
: assert(is_vector(cp,3),"Centerpoint must be a 3-vector")
|
|
||||||
[each v, cp*v]
|
|
||||||
)
|
|
||||||
vnf_halfspace(plane, p)
|
|
||||||
: is_path(p) || is_region(p) ?
|
|
||||||
let(
|
|
||||||
v = (v==UP)? BACK : (v==DOWN)? FWD : v,
|
|
||||||
cp = is_undef(cp) ? [0,0]
|
|
||||||
: is_num(cp) ? v*cp
|
|
||||||
: assert(is_vector(cp,2) || (is_vector(cp,3) && cp.z==0),"Centerpoint must be 2-vector")
|
|
||||||
cp
|
|
||||||
)
|
|
||||||
assert(is_vector(v,2) || (is_vector(v,3) && v.z==0),"Must give 2-vector")
|
|
||||||
assert(!all_zero(v), "Vector v must be nonzero")
|
|
||||||
let(
|
|
||||||
bounds = pointlist_bounds(move(-cp,p)),
|
|
||||||
L = 2*max(flatten(bounds)),
|
|
||||||
n = unit(v),
|
|
||||||
u = [-n.y,n.x],
|
|
||||||
box = [cp+u*L, cp+(v+u)*L, cp+(v-u)*L, cp-u*L]
|
|
||||||
)
|
|
||||||
intersection(box,p)
|
|
||||||
: assert(false, "Input must be a region, path or VNF");
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* This code cut 3d paths but leaves behind connecting line segments
|
|
||||||
is_path(p) ?
|
|
||||||
//assert(len(p[0]) == d, str("path must have dimension ", d))
|
|
||||||
let(z = [for(x=p) (x-cp)*v])
|
|
||||||
[ for(i=[0:len(p)-1]) each concat(z[i] >= 0 ? [p[i]] : [],
|
|
||||||
// we assume a closed path here;
|
|
||||||
// to make this correct for an open path,
|
|
||||||
// just replace this by [] when i==len(p)-1:
|
|
||||||
let(j=(i+1)%len(p))
|
|
||||||
// the remaining path may have flattened sections, but this cannot
|
|
||||||
// create self-intersection or whiskers:
|
|
||||||
z[i]*z[j] >= 0 ? [] : [(z[j]*p[i]-z[i]*p[j])/(z[j]-z[i])]) ]
|
|
||||||
:
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
// Function&Module: left_half()
|
|
||||||
//
|
|
||||||
// Usage: as module
|
|
||||||
// left_half([s], [x]) ...
|
|
||||||
// left_half(planar=true, [s], [x]) ...
|
|
||||||
// Usage: as function
|
|
||||||
// result = left_half(p, [x]);
|
|
||||||
//
|
|
||||||
// Description:
|
|
||||||
// Slices an object at a vertical Y-Z cut plane, and masks away everything that is right of it.
|
|
||||||
// The s parameter is needed for the module
|
|
||||||
// version to control the size of the masking cube. If s is too large then the preview display will flip around and display the
|
|
||||||
// wrong half, but if it is too small it won't fully mask your model.
|
|
||||||
//
|
|
||||||
// Arguments:
|
|
||||||
// p = VNF, region or path to slice (function version)
|
|
||||||
// s = Mask size to use. Use a number larger than twice your object's largest axis. If you make this too large, OpenSCAD's preview rendering may display the wrong half. (Module version) Default: 100
|
|
||||||
// x = The X coordinate of the cut-plane. Default: 0
|
|
||||||
// planar = If true, perform a 2D operation. (Module version) Default: false.
|
|
||||||
// Examples:
|
|
||||||
// left_half() sphere(r=20);
|
|
||||||
// left_half(x=-8) sphere(r=20);
|
|
||||||
// Example(2D):
|
|
||||||
// left_half(planar=true) circle(r=20);
|
|
||||||
module left_half(s=100, x=0, planar=false)
|
|
||||||
{
|
|
||||||
dir = LEFT;
|
|
||||||
difference() {
|
|
||||||
children();
|
|
||||||
translate([x,0,0]-dir*s/2) {
|
|
||||||
if (planar) {
|
|
||||||
square(s, center=true);
|
|
||||||
} else {
|
|
||||||
cube(s, center=true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function left_half(p,x=0) = half_of(p, LEFT, [x,0,0]);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Function&Module: right_half()
|
|
||||||
//
|
|
||||||
// Usage: as module
|
|
||||||
// right_half([s], [x]) ...
|
|
||||||
// right_half(planar=true, [s], [x]) ...
|
|
||||||
// Usage: as function
|
|
||||||
// result = right_half(p, [x]);
|
|
||||||
//
|
|
||||||
// Description:
|
|
||||||
// Slices an object at a vertical Y-Z cut plane, and masks away everything that is left of it.
|
|
||||||
// The s parameter is needed for the module
|
|
||||||
// version to control the size of the masking cube. If s is too large then the preview display will flip around and display the
|
|
||||||
// wrong half, but if it is too small it won't fully mask your model.
|
|
||||||
// Arguments:
|
|
||||||
// p = VNF, region or path to slice (function version)
|
|
||||||
// s = Mask size to use. Use a number larger than twice your object's largest axis. If you make this too large, OpenSCAD's preview rendering may display the wrong half. (Module version) Default: 100
|
|
||||||
// x = The X coordinate of the cut-plane. Default: 0
|
|
||||||
// planar = If true, perform a 2D operation. (Module version) Default: false.
|
|
||||||
// Examples(FlatSpin,VPD=175):
|
|
||||||
// right_half() sphere(r=20);
|
|
||||||
// right_half(x=-5) sphere(r=20);
|
|
||||||
// Example(2D):
|
|
||||||
// right_half(planar=true) circle(r=20);
|
|
||||||
module right_half(s=100, x=0, planar=false)
|
|
||||||
{
|
|
||||||
dir = RIGHT;
|
|
||||||
difference() {
|
|
||||||
children();
|
|
||||||
translate([x,0,0]-dir*s/2) {
|
|
||||||
if (planar) {
|
|
||||||
square(s, center=true);
|
|
||||||
} else {
|
|
||||||
cube(s, center=true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function right_half(p,x=0) = half_of(p, RIGHT, [x,0,0]);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Function&Module: front_half()
|
|
||||||
//
|
|
||||||
// Usage:
|
|
||||||
// front_half([s], [y]) ...
|
|
||||||
// front_half(planar=true, [s], [y]) ...
|
|
||||||
// Usage: as function
|
|
||||||
// result = front_half(p, [y]);
|
|
||||||
//
|
|
||||||
// Description:
|
|
||||||
// Slices an object at a vertical X-Z cut plane, and masks away everything that is behind it.
|
|
||||||
// The s parameter is needed for the module
|
|
||||||
// version to control the size of the masking cube. If s is too large then the preview display will flip around and display the
|
|
||||||
// wrong half, but if it is too small it won't fully mask your model.
|
|
||||||
// Arguments:
|
|
||||||
// p = VNF, region or path to slice (function version)
|
|
||||||
// s = Mask size to use. Use a number larger than twice your object's largest axis. If you make this too large, OpenSCAD's preview rendering may display the wrong half. (Module version) Default: 100
|
|
||||||
// y = The Y coordinate of the cut-plane. Default: 0
|
|
||||||
// planar = If true, perform a 2D operation. (Module version) Default: false.
|
|
||||||
// Examples(FlatSpin,VPD=175):
|
|
||||||
// front_half() sphere(r=20);
|
|
||||||
// front_half(y=5) sphere(r=20);
|
|
||||||
// Example(2D):
|
|
||||||
// front_half(planar=true) circle(r=20);
|
|
||||||
module front_half(s=100, y=0, planar=false)
|
|
||||||
{
|
|
||||||
dir = FWD;
|
|
||||||
difference() {
|
|
||||||
children();
|
|
||||||
translate([0,y,0]-dir*s/2) {
|
|
||||||
if (planar) {
|
|
||||||
square(s, center=true);
|
|
||||||
} else {
|
|
||||||
cube(s, center=true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function front_half(p,y=0) = half_of(p, FRONT, [0,y,0]);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Function&Module: back_half()
|
|
||||||
//
|
|
||||||
// Usage:
|
|
||||||
// back_half([s], [y]) ...
|
|
||||||
// back_half(planar=true, [s], [y]) ...
|
|
||||||
// Usage: as function
|
|
||||||
// result = back_half(p, [y]);
|
|
||||||
//
|
|
||||||
// Description:
|
|
||||||
// Slices an object at a vertical X-Z cut plane, and masks away everything that is in front of it.
|
|
||||||
// The s parameter is needed for the module
|
|
||||||
// version to control the size of the masking cube. If s is too large then the preview display will flip around and display the
|
|
||||||
// wrong half, but if it is too small it won't fully mask your model.
|
|
||||||
// Arguments:
|
|
||||||
// p = VNF, region or path to slice (function version)
|
|
||||||
// s = Mask size to use. Use a number larger than twice your object's largest axis. If you make this too large, OpenSCAD's preview rendering may display the wrong half. (Module version) Default: 100
|
|
||||||
// y = The Y coordinate of the cut-plane. Default: 0
|
|
||||||
// planar = If true, perform a 2D operation. (Module version) Default: false.
|
|
||||||
// Examples:
|
|
||||||
// back_half() sphere(r=20);
|
|
||||||
// back_half(y=8) sphere(r=20);
|
|
||||||
// Example(2D):
|
|
||||||
// back_half(planar=true) circle(r=20);
|
|
||||||
module back_half(s=100, y=0, planar=false)
|
|
||||||
{
|
|
||||||
dir = BACK;
|
|
||||||
difference() {
|
|
||||||
children();
|
|
||||||
translate([0,y,0]-dir*s/2) {
|
|
||||||
if (planar) {
|
|
||||||
square(s, center=true);
|
|
||||||
} else {
|
|
||||||
cube(s, center=true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function back_half(p,y=0) = half_of(p, BACK, [0,y,0]);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Function&Module: bottom_half()
|
|
||||||
//
|
|
||||||
// Usage:
|
|
||||||
// bottom_half([s], [z]) ...
|
|
||||||
// Usage: as function
|
|
||||||
// result = bottom_half(p, [z]);
|
|
||||||
//
|
|
||||||
// Description:
|
|
||||||
// Slices an object at a horizontal X-Y cut plane, and masks away everything that is above it.
|
|
||||||
// The s parameter is needed for the module
|
|
||||||
// version to control the size of the masking cube. If s is too large then the preview display will flip around and display the
|
|
||||||
// wrong half, but if it is too small it won't fully mask your model.
|
|
||||||
// Arguments:
|
|
||||||
// p = VNF, region or path to slice (function version)
|
|
||||||
// s = Mask size to use. Use a number larger than twice your object's largest axis. If you make this too large, OpenSCAD's preview rendering may display the wrong half. (Module version) Default: 100
|
|
||||||
// z = The Z coordinate of the cut-plane. Default: 0
|
|
||||||
// Examples:
|
|
||||||
// bottom_half() sphere(r=20);
|
|
||||||
// bottom_half(z=-10) sphere(r=20);
|
|
||||||
module bottom_half(s=100, z=0)
|
|
||||||
{
|
|
||||||
dir = DOWN;
|
|
||||||
difference() {
|
|
||||||
children();
|
|
||||||
translate([0,0,z]-dir*s/2) {
|
|
||||||
cube(s, center=true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function bottom_half(p,z=0) = half_of(p,BOTTOM,[0,0,z]);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Function&Module: top_half()
|
|
||||||
//
|
|
||||||
// Usage:
|
|
||||||
// top_half([s], [z]) ...
|
|
||||||
// result = top_half(p, [z]);
|
|
||||||
//
|
|
||||||
// Description:
|
|
||||||
// Slices an object at a horizontal X-Y cut plane, and masks away everything that is below it.
|
|
||||||
// The s parameter is needed for the module
|
|
||||||
// version to control the size of the masking cube. If s is too large then the preview display will flip around and display the
|
|
||||||
// wrong half, but if it is too small it won't fully mask your model.
|
|
||||||
// Arguments:
|
|
||||||
// p = VNF, region or path to slice (function version)
|
|
||||||
// s = Mask size to use. Use a number larger than twice your object's largest axis. If you make this too large, OpenSCAD's preview rendering may display the wrong half. (Module version) Default: 100
|
|
||||||
// z = The Z coordinate of the cut-plane. Default: 0
|
|
||||||
// Examples(Spin,VPD=175):
|
|
||||||
// top_half() sphere(r=20);
|
|
||||||
// top_half(z=5) sphere(r=20);
|
|
||||||
module top_half(s=100, z=0)
|
|
||||||
{
|
|
||||||
dir = UP;
|
|
||||||
difference() {
|
|
||||||
children();
|
|
||||||
translate([0,0,z]-dir*s/2) {
|
|
||||||
cube(s, center=true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function top_half(p,z=0) = half_of(p,UP,[0,0,z]);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
// Section: Warp Mutators
|
// Section: Warp Mutators
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
345
partitions.scad
345
partitions.scad
|
@ -1,15 +1,352 @@
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
// LibFile: partitions.scad
|
// LibFile: partitions.scad
|
||||||
// Modules to help partition large objects into smaller parts that can be reassembled.
|
// Cut objects with a plane, or partition them into interlocking pieces for easy printing of large objects.
|
||||||
// Includes:
|
// Includes:
|
||||||
// include <BOSL2/std.scad>
|
// include <BOSL2/std.scad>
|
||||||
// include <BOSL2/partitions.scad>
|
|
||||||
// FileGroup: Advanced Modeling
|
// FileGroup: Advanced Modeling
|
||||||
// FileSummary: Modules to help partition large objects into smaller assembled parts.
|
// FileSummary: Cut objects with a plane or partition them into interlocking pieces.
|
||||||
|
// FileFootnotes: STD=Included in std.scad
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
// Section: Partitioning
|
// Section: Planar Cutting
|
||||||
|
|
||||||
|
// Function&Module: half_of()
|
||||||
|
//
|
||||||
|
// Usage: as module
|
||||||
|
// half_of(v, [cp], [s], [planar]) ...
|
||||||
|
// Usage: as function
|
||||||
|
// result = half_of(p,v,[cp]);
|
||||||
|
//
|
||||||
|
// Description:
|
||||||
|
// Slices an object at a cut plane, and masks away everything that is on one side. The v parameter is either a plane specification or
|
||||||
|
// a normal vector. The s parameter is needed for the module
|
||||||
|
// version to control the size of the masking cube. If s is too large then the preview display will flip around and display the
|
||||||
|
// wrong half, but if it is too small it won't fully mask your model.
|
||||||
|
// When called as a function, you must supply a vnf, path or region in p. If planar is set to true for the module version the operation
|
||||||
|
// is performed in 2D and UP and DOWN are treated as equivalent to BACK and FWD respectively.
|
||||||
|
//
|
||||||
|
// Arguments:
|
||||||
|
// p = path, region or VNF to slice. (Function version)
|
||||||
|
// v = Normal of plane to slice at. Keeps everything on the side the normal points to. Default: [0,0,1] (UP)
|
||||||
|
// cp = If given as a scalar, moves the cut plane along the normal by the given amount. If given as a point, specifies a point on the cut plane. Default: [0,0,0]
|
||||||
|
// s = Mask size to use. Use a number larger than twice your object's largest axis. If you make this too large, OpenSCAD's preview rendering may display the wrong half. (Module version) Default: 100
|
||||||
|
// planar = If true, perform a 2D operation. When planar, a `v` of `UP` or `DOWN` becomes equivalent of `BACK` and `FWD` respectively. (Module version). Default: false.
|
||||||
|
//
|
||||||
|
// Examples:
|
||||||
|
// half_of(DOWN+BACK, cp=[0,-10,0]) cylinder(h=40, r1=10, r2=0, center=false);
|
||||||
|
// half_of(DOWN+LEFT, s=200) sphere(d=150);
|
||||||
|
// Example(2D):
|
||||||
|
// half_of([1,1], planar=true) circle(d=50);
|
||||||
|
module half_of(v=UP, cp, s=100, planar=false)
|
||||||
|
{
|
||||||
|
cp = is_vector(v,4)? assert(cp==undef, "Don't use cp with plane definition.") plane_normal(v) * v[3] :
|
||||||
|
is_vector(cp)? cp :
|
||||||
|
is_num(cp)? cp*unit(v) :
|
||||||
|
[0,0,0];
|
||||||
|
v = is_vector(v,4)? plane_normal(v) : v;
|
||||||
|
if (cp != [0,0,0]) {
|
||||||
|
translate(cp) half_of(v=v, s=s, planar=planar) translate(-cp) children();
|
||||||
|
} else if (planar) {
|
||||||
|
v = (v==UP)? BACK : (v==DOWN)? FWD : v;
|
||||||
|
ang = atan2(v.y, v.x);
|
||||||
|
difference() {
|
||||||
|
children();
|
||||||
|
rotate(ang+90) {
|
||||||
|
back(s/2) square(s, center=true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
difference() {
|
||||||
|
children();
|
||||||
|
rot(from=UP, to=-v) {
|
||||||
|
up(s/2) cube(s, center=true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function half_of(p, v=UP, cp) =
|
||||||
|
is_vnf(p) ?
|
||||||
|
assert(is_vector(v) && (len(v)==3 || len(v)==4),str("Must give 3-vector or plane specification",v))
|
||||||
|
assert(select(v,0,2)!=[0,0,0], "vector v must be nonzero")
|
||||||
|
let(
|
||||||
|
plane = is_vector(v,4) ? assert(cp==undef, "Don't use cp with plane definition.") v
|
||||||
|
: is_undef(cp) ? [each v, 0]
|
||||||
|
: is_num(cp) ? [each v, cp*(v*v)/norm(v)]
|
||||||
|
: assert(is_vector(cp,3),"Centerpoint must be a 3-vector")
|
||||||
|
[each v, cp*v]
|
||||||
|
)
|
||||||
|
vnf_halfspace(plane, p)
|
||||||
|
: is_path(p) || is_region(p) ?
|
||||||
|
let(
|
||||||
|
v = (v==UP)? BACK : (v==DOWN)? FWD : v,
|
||||||
|
cp = is_undef(cp) ? [0,0]
|
||||||
|
: is_num(cp) ? v*cp
|
||||||
|
: assert(is_vector(cp,2) || (is_vector(cp,3) && cp.z==0),"Centerpoint must be 2-vector")
|
||||||
|
cp
|
||||||
|
)
|
||||||
|
assert(is_vector(v,2) || (is_vector(v,3) && v.z==0),"Must give 2-vector")
|
||||||
|
assert(!all_zero(v), "Vector v must be nonzero")
|
||||||
|
let(
|
||||||
|
bounds = pointlist_bounds(move(-cp,p)),
|
||||||
|
L = 2*max(flatten(bounds)),
|
||||||
|
n = unit(v),
|
||||||
|
u = [-n.y,n.x],
|
||||||
|
box = [cp+u*L, cp+(v+u)*L, cp+(v-u)*L, cp-u*L]
|
||||||
|
)
|
||||||
|
intersection(box,p)
|
||||||
|
: assert(false, "Input must be a region, path or VNF");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* This code cut 3d paths but leaves behind connecting line segments
|
||||||
|
is_path(p) ?
|
||||||
|
//assert(len(p[0]) == d, str("path must have dimension ", d))
|
||||||
|
let(z = [for(x=p) (x-cp)*v])
|
||||||
|
[ for(i=[0:len(p)-1]) each concat(z[i] >= 0 ? [p[i]] : [],
|
||||||
|
// we assume a closed path here;
|
||||||
|
// to make this correct for an open path,
|
||||||
|
// just replace this by [] when i==len(p)-1:
|
||||||
|
let(j=(i+1)%len(p))
|
||||||
|
// the remaining path may have flattened sections, but this cannot
|
||||||
|
// create self-intersection or whiskers:
|
||||||
|
z[i]*z[j] >= 0 ? [] : [(z[j]*p[i]-z[i]*p[j])/(z[j]-z[i])]) ]
|
||||||
|
:
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
// Function&Module: left_half()
|
||||||
|
//
|
||||||
|
// Usage: as module
|
||||||
|
// left_half([s], [x]) ...
|
||||||
|
// left_half(planar=true, [s], [x]) ...
|
||||||
|
// Usage: as function
|
||||||
|
// result = left_half(p, [x]);
|
||||||
|
//
|
||||||
|
// Description:
|
||||||
|
// Slices an object at a vertical Y-Z cut plane, and masks away everything that is right of it.
|
||||||
|
// The s parameter is needed for the module
|
||||||
|
// version to control the size of the masking cube. If s is too large then the preview display will flip around and display the
|
||||||
|
// wrong half, but if it is too small it won't fully mask your model.
|
||||||
|
//
|
||||||
|
// Arguments:
|
||||||
|
// p = VNF, region or path to slice (function version)
|
||||||
|
// s = Mask size to use. Use a number larger than twice your object's largest axis. If you make this too large, OpenSCAD's preview rendering may display the wrong half. (Module version) Default: 100
|
||||||
|
// x = The X coordinate of the cut-plane. Default: 0
|
||||||
|
// planar = If true, perform a 2D operation. (Module version) Default: false.
|
||||||
|
// Examples:
|
||||||
|
// left_half() sphere(r=20);
|
||||||
|
// left_half(x=-8) sphere(r=20);
|
||||||
|
// Example(2D):
|
||||||
|
// left_half(planar=true) circle(r=20);
|
||||||
|
module left_half(s=100, x=0, planar=false)
|
||||||
|
{
|
||||||
|
dir = LEFT;
|
||||||
|
difference() {
|
||||||
|
children();
|
||||||
|
translate([x,0,0]-dir*s/2) {
|
||||||
|
if (planar) {
|
||||||
|
square(s, center=true);
|
||||||
|
} else {
|
||||||
|
cube(s, center=true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function left_half(p,x=0) = half_of(p, LEFT, [x,0,0]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Function&Module: right_half()
|
||||||
|
//
|
||||||
|
// Usage: as module
|
||||||
|
// right_half([s], [x]) ...
|
||||||
|
// right_half(planar=true, [s], [x]) ...
|
||||||
|
// Usage: as function
|
||||||
|
// result = right_half(p, [x]);
|
||||||
|
//
|
||||||
|
// Description:
|
||||||
|
// Slices an object at a vertical Y-Z cut plane, and masks away everything that is left of it.
|
||||||
|
// The s parameter is needed for the module
|
||||||
|
// version to control the size of the masking cube. If s is too large then the preview display will flip around and display the
|
||||||
|
// wrong half, but if it is too small it won't fully mask your model.
|
||||||
|
// Arguments:
|
||||||
|
// p = VNF, region or path to slice (function version)
|
||||||
|
// s = Mask size to use. Use a number larger than twice your object's largest axis. If you make this too large, OpenSCAD's preview rendering may display the wrong half. (Module version) Default: 100
|
||||||
|
// x = The X coordinate of the cut-plane. Default: 0
|
||||||
|
// planar = If true, perform a 2D operation. (Module version) Default: false.
|
||||||
|
// Examples(FlatSpin,VPD=175):
|
||||||
|
// right_half() sphere(r=20);
|
||||||
|
// right_half(x=-5) sphere(r=20);
|
||||||
|
// Example(2D):
|
||||||
|
// right_half(planar=true) circle(r=20);
|
||||||
|
module right_half(s=100, x=0, planar=false)
|
||||||
|
{
|
||||||
|
dir = RIGHT;
|
||||||
|
difference() {
|
||||||
|
children();
|
||||||
|
translate([x,0,0]-dir*s/2) {
|
||||||
|
if (planar) {
|
||||||
|
square(s, center=true);
|
||||||
|
} else {
|
||||||
|
cube(s, center=true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function right_half(p,x=0) = half_of(p, RIGHT, [x,0,0]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Function&Module: front_half()
|
||||||
|
//
|
||||||
|
// Usage:
|
||||||
|
// front_half([s], [y]) ...
|
||||||
|
// front_half(planar=true, [s], [y]) ...
|
||||||
|
// Usage: as function
|
||||||
|
// result = front_half(p, [y]);
|
||||||
|
//
|
||||||
|
// Description:
|
||||||
|
// Slices an object at a vertical X-Z cut plane, and masks away everything that is behind it.
|
||||||
|
// The s parameter is needed for the module
|
||||||
|
// version to control the size of the masking cube. If s is too large then the preview display will flip around and display the
|
||||||
|
// wrong half, but if it is too small it won't fully mask your model.
|
||||||
|
// Arguments:
|
||||||
|
// p = VNF, region or path to slice (function version)
|
||||||
|
// s = Mask size to use. Use a number larger than twice your object's largest axis. If you make this too large, OpenSCAD's preview rendering may display the wrong half. (Module version) Default: 100
|
||||||
|
// y = The Y coordinate of the cut-plane. Default: 0
|
||||||
|
// planar = If true, perform a 2D operation. (Module version) Default: false.
|
||||||
|
// Examples(FlatSpin,VPD=175):
|
||||||
|
// front_half() sphere(r=20);
|
||||||
|
// front_half(y=5) sphere(r=20);
|
||||||
|
// Example(2D):
|
||||||
|
// front_half(planar=true) circle(r=20);
|
||||||
|
module front_half(s=100, y=0, planar=false)
|
||||||
|
{
|
||||||
|
dir = FWD;
|
||||||
|
difference() {
|
||||||
|
children();
|
||||||
|
translate([0,y,0]-dir*s/2) {
|
||||||
|
if (planar) {
|
||||||
|
square(s, center=true);
|
||||||
|
} else {
|
||||||
|
cube(s, center=true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function front_half(p,y=0) = half_of(p, FRONT, [0,y,0]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Function&Module: back_half()
|
||||||
|
//
|
||||||
|
// Usage:
|
||||||
|
// back_half([s], [y]) ...
|
||||||
|
// back_half(planar=true, [s], [y]) ...
|
||||||
|
// Usage: as function
|
||||||
|
// result = back_half(p, [y]);
|
||||||
|
//
|
||||||
|
// Description:
|
||||||
|
// Slices an object at a vertical X-Z cut plane, and masks away everything that is in front of it.
|
||||||
|
// The s parameter is needed for the module
|
||||||
|
// version to control the size of the masking cube. If s is too large then the preview display will flip around and display the
|
||||||
|
// wrong half, but if it is too small it won't fully mask your model.
|
||||||
|
// Arguments:
|
||||||
|
// p = VNF, region or path to slice (function version)
|
||||||
|
// s = Mask size to use. Use a number larger than twice your object's largest axis. If you make this too large, OpenSCAD's preview rendering may display the wrong half. (Module version) Default: 100
|
||||||
|
// y = The Y coordinate of the cut-plane. Default: 0
|
||||||
|
// planar = If true, perform a 2D operation. (Module version) Default: false.
|
||||||
|
// Examples:
|
||||||
|
// back_half() sphere(r=20);
|
||||||
|
// back_half(y=8) sphere(r=20);
|
||||||
|
// Example(2D):
|
||||||
|
// back_half(planar=true) circle(r=20);
|
||||||
|
module back_half(s=100, y=0, planar=false)
|
||||||
|
{
|
||||||
|
dir = BACK;
|
||||||
|
difference() {
|
||||||
|
children();
|
||||||
|
translate([0,y,0]-dir*s/2) {
|
||||||
|
if (planar) {
|
||||||
|
square(s, center=true);
|
||||||
|
} else {
|
||||||
|
cube(s, center=true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function back_half(p,y=0) = half_of(p, BACK, [0,y,0]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Function&Module: bottom_half()
|
||||||
|
//
|
||||||
|
// Usage:
|
||||||
|
// bottom_half([s], [z]) ...
|
||||||
|
// Usage: as function
|
||||||
|
// result = bottom_half(p, [z]);
|
||||||
|
//
|
||||||
|
// Description:
|
||||||
|
// Slices an object at a horizontal X-Y cut plane, and masks away everything that is above it.
|
||||||
|
// The s parameter is needed for the module
|
||||||
|
// version to control the size of the masking cube. If s is too large then the preview display will flip around and display the
|
||||||
|
// wrong half, but if it is too small it won't fully mask your model.
|
||||||
|
// Arguments:
|
||||||
|
// p = VNF, region or path to slice (function version)
|
||||||
|
// s = Mask size to use. Use a number larger than twice your object's largest axis. If you make this too large, OpenSCAD's preview rendering may display the wrong half. (Module version) Default: 100
|
||||||
|
// z = The Z coordinate of the cut-plane. Default: 0
|
||||||
|
// Examples:
|
||||||
|
// bottom_half() sphere(r=20);
|
||||||
|
// bottom_half(z=-10) sphere(r=20);
|
||||||
|
module bottom_half(s=100, z=0)
|
||||||
|
{
|
||||||
|
dir = DOWN;
|
||||||
|
difference() {
|
||||||
|
children();
|
||||||
|
translate([0,0,z]-dir*s/2) {
|
||||||
|
cube(s, center=true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function bottom_half(p,z=0) = half_of(p,BOTTOM,[0,0,z]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Function&Module: top_half()
|
||||||
|
//
|
||||||
|
// Usage:
|
||||||
|
// top_half([s], [z]) ...
|
||||||
|
// result = top_half(p, [z]);
|
||||||
|
//
|
||||||
|
// Description:
|
||||||
|
// Slices an object at a horizontal X-Y cut plane, and masks away everything that is below it.
|
||||||
|
// The s parameter is needed for the module
|
||||||
|
// version to control the size of the masking cube. If s is too large then the preview display will flip around and display the
|
||||||
|
// wrong half, but if it is too small it won't fully mask your model.
|
||||||
|
// Arguments:
|
||||||
|
// p = VNF, region or path to slice (function version)
|
||||||
|
// s = Mask size to use. Use a number larger than twice your object's largest axis. If you make this too large, OpenSCAD's preview rendering may display the wrong half. (Module version) Default: 100
|
||||||
|
// z = The Z coordinate of the cut-plane. Default: 0
|
||||||
|
// Examples(Spin,VPD=175):
|
||||||
|
// top_half() sphere(r=20);
|
||||||
|
// top_half(z=5) sphere(r=20);
|
||||||
|
module top_half(s=100, z=0)
|
||||||
|
{
|
||||||
|
dir = UP;
|
||||||
|
difference() {
|
||||||
|
children();
|
||||||
|
translate([0,0,z]-dir*s/2) {
|
||||||
|
cube(s, center=true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function top_half(p,z=0) = half_of(p,UP,[0,0,z]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Section: Partioning into Interlocking Pieces
|
||||||
|
|
||||||
|
|
||||||
function _partition_subpath(type) =
|
function _partition_subpath(type) =
|
||||||
|
|
Loading…
Reference in a new issue