From 50191bf5fda8b9591151203d0135d0035206418b Mon Sep 17 00:00:00 2001 From: Adrian Mariano Date: Thu, 16 Dec 2021 22:31:49 -0500 Subject: [PATCH] move half-space stuff to partitions.scad --- mutators.scad | 338 +---------------------------------------------- partitions.scad | 345 +++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 342 insertions(+), 341 deletions(-) diff --git a/mutators.scad b/mutators.scad index c722df6..646b00c 100644 --- a/mutators.scad +++ b/mutators.scad @@ -8,9 +8,8 @@ // FileFootnotes: STD=Included in std.scad ////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////// -// Section: Volume Division Mutators +// Section: 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 ////////////////////////////////////////////////////////////////////// diff --git a/partitions.scad b/partitions.scad index 5cca96b..b6b7317 100644 --- a/partitions.scad +++ b/partitions.scad @@ -1,15 +1,352 @@ ////////////////////////////////////////////////////////////////////// // 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: // include -// include // 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) =