mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2025-01-01 09:49:45 +00:00
Merge branch 'master' into revarbat_dev
This commit is contained in:
commit
4fa37a94d0
19 changed files with 161 additions and 176 deletions
|
@ -1211,8 +1211,8 @@ module tag_conv_hull(tag,keep="keep")
|
||||||
// Example: Hides part of the model.
|
// Example: Hides part of the model.
|
||||||
// hide("A")
|
// hide("A")
|
||||||
// tag("main") cube(50, anchor=CENTER, $tag="Main") {
|
// tag("main") cube(50, anchor=CENTER, $tag="Main") {
|
||||||
// tag("A")attach(LEFT, BOTTOM) cylinder(d=30, l=30);
|
// tag("A")attach(LEFT, BOTTOM) cylinder(d=30, h=30);
|
||||||
// tag("B")attach(RIGHT, BOTTOM) cylinder(d=30, l=30);
|
// tag("B")attach(RIGHT, BOTTOM) cylinder(d=30, h=30);
|
||||||
// }
|
// }
|
||||||
// Example: Use an invisible parent to position children. Note that children must be retagged because they inherit the parent tag.
|
// Example: Use an invisible parent to position children. Note that children must be retagged because they inherit the parent tag.
|
||||||
// $fn=16;
|
// $fn=16;
|
||||||
|
@ -1246,8 +1246,8 @@ module hide(tags)
|
||||||
// show_only("visible")
|
// show_only("visible")
|
||||||
// cube(50, anchor=CENTER)
|
// cube(50, anchor=CENTER)
|
||||||
// tag("visible"){
|
// tag("visible"){
|
||||||
// attach(LEFT, BOTTOM) cylinder(d=30, l=30);
|
// attach(LEFT, BOTTOM) cylinder(d=30, h=30);
|
||||||
// attach(RIGHT, BOTTOM) cylinder(d=30, l=30);
|
// attach(RIGHT, BOTTOM) cylinder(d=30, h=30);
|
||||||
// }
|
// }
|
||||||
module show_only(tags)
|
module show_only(tags)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1127,7 +1127,7 @@ module sp_neck(diam,type,wall,id,style="L",bead=false, anchor, spin, orient)
|
||||||
difference(){
|
difference(){
|
||||||
union(){
|
union(){
|
||||||
thread_helix(d=T-.01, profile=profile, pitch = INCH/tpi, turns=twist/360, taper=taperlen, anchor=TOP);
|
thread_helix(d=T-.01, profile=profile, pitch = INCH/tpi, turns=twist/360, taper=taperlen, anchor=TOP);
|
||||||
cylinder(d=T-depth*2,l=H,anchor=TOP);
|
cylinder(d=T-depth*2,h=H,anchor=TOP);
|
||||||
if (bead)
|
if (bead)
|
||||||
down(bead_shift)
|
down(bead_shift)
|
||||||
rotate_extrude()
|
rotate_extrude()
|
||||||
|
|
|
@ -194,6 +194,19 @@ function all_equal(vec,eps=0) =
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Function: are_ends_equal()
|
||||||
|
// Usage:
|
||||||
|
// are_ends_equal(list, [eps]);
|
||||||
|
// Description:
|
||||||
|
// Returns true if the first and last points in the given list are equal to within epsilon.
|
||||||
|
// Arguments:
|
||||||
|
// list = list to check
|
||||||
|
// eps = Tolerance for approximate equality. Default: `EPSILON` (1e-9)
|
||||||
|
function are_ends_equal(list, eps=EPSILON) =
|
||||||
|
assert(is_list(list) && len(list)>0, "Must give a nonempty list")
|
||||||
|
approx(list[0], list[len(list)-1], eps=eps);
|
||||||
|
|
||||||
|
|
||||||
// Function: is_increasing()
|
// Function: is_increasing()
|
||||||
// Usage:
|
// Usage:
|
||||||
// bool = is_increasing(list, [strict]);
|
// bool = is_increasing(list, [strict]);
|
||||||
|
|
|
@ -442,6 +442,7 @@ function is_coplanar(points, eps=EPSILON) =
|
||||||
// Function: plane3pt()
|
// Function: plane3pt()
|
||||||
// Usage:
|
// Usage:
|
||||||
// plane = plane3pt(p1, p2, p3);
|
// plane = plane3pt(p1, p2, p3);
|
||||||
|
// plane = plane3pt([p1, p2, p3]);
|
||||||
// Topics: Geometry, Planes
|
// Topics: Geometry, Planes
|
||||||
// Description:
|
// Description:
|
||||||
// Generates the normalized cartesian equation of a plane from three 3d points.
|
// Generates the normalized cartesian equation of a plane from three 3d points.
|
||||||
|
|
|
@ -266,7 +266,7 @@ module rounding_corner_mask(r, d, style="octa", excess=0.1, anchor=CENTER, spin=
|
||||||
translate(-excess*[1,1,1])
|
translate(-excess*[1,1,1])
|
||||||
cube(size=r+excess, center=false);
|
cube(size=r+excess, center=false);
|
||||||
translate([r,r,r])
|
translate([r,r,r])
|
||||||
sphere(r=r, style=style);
|
spheroid(r=r, style=style);
|
||||||
}
|
}
|
||||||
children();
|
children();
|
||||||
}
|
}
|
||||||
|
|
|
@ -143,7 +143,7 @@ _hose_waist = [1.7698, 1.8251, 3.95998];
|
||||||
// right(25)modular_hose(1/2,"segment");
|
// right(25)modular_hose(1/2,"segment");
|
||||||
// right(60)modular_hose(3/4,"segment");
|
// right(60)modular_hose(3/4,"segment");
|
||||||
// Example: A mount point for modular hose
|
// Example: A mount point for modular hose
|
||||||
// cylinder(l=10, r=20)
|
// cylinder(h=10, r=20)
|
||||||
// attach(TOP) modular_hose(1/2, "ball", waist_len=15);
|
// attach(TOP) modular_hose(1/2, "ball", waist_len=15);
|
||||||
// Example: Mounting plate for something at the end of the hose
|
// Example: Mounting plate for something at the end of the hose
|
||||||
// cuboid([50,50,5])
|
// cuboid([50,50,5])
|
||||||
|
|
16
paths.scad
16
paths.scad
|
@ -87,21 +87,13 @@ function force_path(path, name="path") =
|
||||||
: path;
|
: path;
|
||||||
|
|
||||||
|
|
||||||
// Function: is_closed_path()
|
|
||||||
// Usage:
|
|
||||||
// is_closed_path(path, [eps]);
|
|
||||||
// Description:
|
|
||||||
// Returns true if the first and last points in the given path are coincident.
|
|
||||||
function is_closed_path(path, eps=EPSILON) = approx(path[0], path[len(path)-1], eps=eps);
|
|
||||||
|
|
||||||
|
|
||||||
// Function: close_path()
|
// Function: close_path()
|
||||||
// Usage:
|
// Usage:
|
||||||
// close_path(path);
|
// close_path(path);
|
||||||
// Description:
|
// Description:
|
||||||
// If a path's last point does not coincide with its first point, closes the path so it does.
|
// If a path's last point does not coincide with its first point, closes the path so it does.
|
||||||
function close_path(path, eps=EPSILON) =
|
function close_path(path, eps=EPSILON) =
|
||||||
is_closed_path(path,eps=eps)? path : concat(path,[path[0]]);
|
are_ends_equal(path,eps=eps)? path : concat(path,[path[0]]);
|
||||||
|
|
||||||
|
|
||||||
// Function: cleanup_path()
|
// Function: cleanup_path()
|
||||||
|
@ -110,7 +102,7 @@ function close_path(path, eps=EPSILON) =
|
||||||
// Description:
|
// Description:
|
||||||
// If a path's last point coincides with its first point, deletes the last point in the path.
|
// If a path's last point coincides with its first point, deletes the last point in the path.
|
||||||
function cleanup_path(path, eps=EPSILON) =
|
function cleanup_path(path, eps=EPSILON) =
|
||||||
is_closed_path(path,eps=eps)? [for (i=[0:1:len(path)-2]) path[i]] : path;
|
are_ends_equal(path,eps=eps)? [for (i=[0:1:len(path)-2]) path[i]] : path;
|
||||||
|
|
||||||
|
|
||||||
/// Internal Function: _path_select()
|
/// Internal Function: _path_select()
|
||||||
|
@ -1096,7 +1088,7 @@ function _assemble_a_path_from_fragments(fragments, rightmost=true, startfrag=0,
|
||||||
let(
|
let(
|
||||||
path = fragments[startfrag],
|
path = fragments[startfrag],
|
||||||
newfrags = [for (i=idx(fragments)) if (i!=startfrag) fragments[i]]
|
newfrags = [for (i=idx(fragments)) if (i!=startfrag) fragments[i]]
|
||||||
) is_closed_path(path, eps=eps)? (
|
) are_ends_equal(path, eps=eps)? (
|
||||||
// starting fragment is already closed
|
// starting fragment is already closed
|
||||||
[path, newfrags]
|
[path, newfrags]
|
||||||
) : let(
|
) : let(
|
||||||
|
@ -1109,7 +1101,7 @@ function _assemble_a_path_from_fragments(fragments, rightmost=true, startfrag=0,
|
||||||
// No remaining fragments connect! INCOMPLETE PATH!
|
// No remaining fragments connect! INCOMPLETE PATH!
|
||||||
// Treat it as complete.
|
// Treat it as complete.
|
||||||
[path, remainder]
|
[path, remainder]
|
||||||
) : is_closed_path(foundfrag, eps=eps)? (
|
) : are_ends_equal(foundfrag, eps=eps)? (
|
||||||
// Found fragment is already closed
|
// Found fragment is already closed
|
||||||
[foundfrag, concat([path], remainder)]
|
[foundfrag, concat([path], remainder)]
|
||||||
) : let(
|
) : let(
|
||||||
|
|
|
@ -2924,7 +2924,7 @@ Access to the derivative smoothing parameter?
|
||||||
// ellipse = ellipse([17,10],$fn=164);
|
// ellipse = ellipse([17,10],$fn=164);
|
||||||
// join_prism(ellipse,base="sphere",base_r=30, length=18,
|
// join_prism(ellipse,base="sphere",base_r=30, length=18,
|
||||||
// fillet=18, n=25, overlap=1);
|
// fillet=18, n=25, overlap=1);
|
||||||
// sphere(r=30,circum=true, $fn=96);
|
// spheroid(r=30,circum=true, $fn=96);
|
||||||
// Example(3D,NoScales): This example shows a failed rounding attempt where the result is self-intersecting. Using the `debug=true` option makes it possible to view the result to understand what went wrong. Note that the concave corners have a crease where the fillet crosses itself. The error message will advise you to decrease the size of the fillet. You can also fix the problem by making your concave curves shallower.
|
// Example(3D,NoScales): This example shows a failed rounding attempt where the result is self-intersecting. Using the `debug=true` option makes it possible to view the result to understand what went wrong. Note that the concave corners have a crease where the fillet crosses itself. The error message will advise you to decrease the size of the fillet. You can also fix the problem by making your concave curves shallower.
|
||||||
// flower = [for(theta=lerpn(0,360,180,endpoint=false))
|
// flower = [for(theta=lerpn(0,360,180,endpoint=false))
|
||||||
// (15+2.5*sin(6*theta))*[cos(theta),sin(theta)]];
|
// (15+2.5*sin(6*theta))*[cos(theta),sin(theta)]];
|
||||||
|
@ -2934,19 +2934,19 @@ Access to the derivative smoothing parameter?
|
||||||
// sq = rect(15);
|
// sq = rect(15);
|
||||||
// join_prism(sq, base="sphere", base_r=25,
|
// join_prism(sq, base="sphere", base_r=25,
|
||||||
// length=18, fillet=4, n=12);
|
// length=18, fillet=4, n=12);
|
||||||
// sphere(r=25, circum=true, $fn=96);
|
// spheroid(r=25, circum=true, $fn=96);
|
||||||
// Example(3D,NoScales): To fix the problem, you must subdivide the polygon that defines the prism. But note that the join_prism method works poorly at sharp corners.
|
// Example(3D,NoScales): To fix the problem, you must subdivide the polygon that defines the prism. But note that the join_prism method works poorly at sharp corners.
|
||||||
// sq = subdivide_path(rect(15),n=64);
|
// sq = subdivide_path(rect(15),n=64);
|
||||||
// join_prism(sq, base="sphere", base_r=25,
|
// join_prism(sq, base="sphere", base_r=25,
|
||||||
// length=18, fillet=4, n=12);
|
// length=18, fillet=4, n=12);
|
||||||
// sphere(r=25, circum=true,$fn=96);
|
// spheroid(r=25, circum=true,$fn=96);
|
||||||
// Example(3D,NoScales): In the previous example, a small rounding of the prism corners produces a nicer result.
|
// Example(3D,NoScales): In the previous example, a small rounding of the prism corners produces a nicer result.
|
||||||
// sq = subdivide_path(
|
// sq = subdivide_path(
|
||||||
// round_corners(rect(15),cut=.5,$fn=32),
|
// round_corners(rect(15),cut=.5,$fn=32),
|
||||||
// n=128);
|
// n=128);
|
||||||
// join_prism(sq, base="sphere", base_r=25,
|
// join_prism(sq, base="sphere", base_r=25,
|
||||||
// length=18, fillet=4, n=12);
|
// length=18, fillet=4, n=12);
|
||||||
// sphere(r=25, circum=true,$fn=96);
|
// spheroid(r=25, circum=true,$fn=96);
|
||||||
// Example(3D,NoScales): The final option for specifying the base is to use an arbitrary prism, specified by a polygon. Note that the base prism is oriented to the RIGHT, so the attached prism remains Z oriented.
|
// Example(3D,NoScales): The final option for specifying the base is to use an arbitrary prism, specified by a polygon. Note that the base prism is oriented to the RIGHT, so the attached prism remains Z oriented.
|
||||||
// ellipse = ellipse([17,10],$fn=164);
|
// ellipse = ellipse([17,10],$fn=164);
|
||||||
// join_prism(zrot(90,ellipse), base=2*ellipse, length=19,
|
// join_prism(zrot(90,ellipse), base=2*ellipse, length=19,
|
||||||
|
@ -3032,7 +3032,7 @@ Access to the derivative smoothing parameter?
|
||||||
// base_T = xrot(5)*yrot(-12);
|
// base_T = xrot(5)*yrot(-12);
|
||||||
// join_prism(flower,base="cylinder",base_r=25, fillet=4, n=12,
|
// join_prism(flower,base="cylinder",base_r=25, fillet=4, n=12,
|
||||||
// aux="sphere",aux_r=35,base_T=base_T, aux_T=aux_T);
|
// aux="sphere",aux_r=35,base_T=base_T, aux_T=aux_T);
|
||||||
// multmatrix(aux_T)sphere(35,circum=true);
|
// multmatrix(aux_T)spheroid(35,circum=true);
|
||||||
// multmatrix(base_T)xcyl(l=75,r=25,circum=true);
|
// multmatrix(base_T)xcyl(l=75,r=25,circum=true);
|
||||||
// Example(3D,NoScales,VPR=[84,0,21],VPT=[13.6,-1,46.8],VPD=446): Here we translate the sphere to the right and the prism goes with it
|
// Example(3D,NoScales,VPR=[84,0,21],VPT=[13.6,-1,46.8],VPD=446): Here we translate the sphere to the right and the prism goes with it
|
||||||
// flower = [for(theta=lerpn(0,360,180,endpoint=false))
|
// flower = [for(theta=lerpn(0,360,180,endpoint=false))
|
||||||
|
@ -3040,7 +3040,7 @@ Access to the derivative smoothing parameter?
|
||||||
// aux_T = right(40)*up(85);
|
// aux_T = right(40)*up(85);
|
||||||
// join_prism(flower,base="cylinder",base_r=25, n=12,
|
// join_prism(flower,base="cylinder",base_r=25, n=12,
|
||||||
// aux="sphere",aux_r=35, aux_T=aux_T, fillet=4);
|
// aux="sphere",aux_r=35, aux_T=aux_T, fillet=4);
|
||||||
// multmatrix(aux_T)sphere(35,circum=true);
|
// multmatrix(aux_T)spheroid(35,circum=true);
|
||||||
// xcyl(l=75,r=25,circum=true);
|
// xcyl(l=75,r=25,circum=true);
|
||||||
// Example(3D,NoScales,VPR=[84,0,21],VPT=[13.6,-1,46.8],VPD=446): This is the previous example with the prism_end_T transformation used to shift the far end of the prism away from the sphere center. Note that prism_end_T can be any transformation, but it just acts on the location of the prism endpoint to shift the direction the prism points.
|
// Example(3D,NoScales,VPR=[84,0,21],VPT=[13.6,-1,46.8],VPD=446): This is the previous example with the prism_end_T transformation used to shift the far end of the prism away from the sphere center. Note that prism_end_T can be any transformation, but it just acts on the location of the prism endpoint to shift the direction the prism points.
|
||||||
// flower = [for(theta=lerpn(0,360,180,endpoint=false))
|
// flower = [for(theta=lerpn(0,360,180,endpoint=false))
|
||||||
|
@ -3049,7 +3049,7 @@ Access to the derivative smoothing parameter?
|
||||||
// join_prism(flower,base="cylinder",base_r=25,
|
// join_prism(flower,base="cylinder",base_r=25,
|
||||||
// prism_end_T=left(4), fillet=3, n=12,
|
// prism_end_T=left(4), fillet=3, n=12,
|
||||||
// aux="sphere",aux_r=35, aux_T=aux_T);
|
// aux="sphere",aux_r=35, aux_T=aux_T);
|
||||||
// multmatrix(aux_T)sphere(35,circum=true);
|
// multmatrix(aux_T)spheroid(35,circum=true);
|
||||||
// xcyl(l=75,r=25,circum=true);
|
// xcyl(l=75,r=25,circum=true);
|
||||||
// Example(3D,NoScales,VPR=[96.9,0,157.5],VPT=[-7.77616,-2.272,37.9424],VPD=366.527): Here the base is a cylinder but the auxilary object is a generic prism, and the joiner prism has a scale factor.
|
// Example(3D,NoScales,VPR=[96.9,0,157.5],VPT=[-7.77616,-2.272,37.9424],VPD=366.527): Here the base is a cylinder but the auxilary object is a generic prism, and the joiner prism has a scale factor.
|
||||||
// flower = [for(theta=lerpn(0,360,180,endpoint=false))
|
// flower = [for(theta=lerpn(0,360,180,endpoint=false))
|
||||||
|
|
|
@ -1211,7 +1211,7 @@ module jittered_poly(path, dist=1/512) {
|
||||||
//
|
//
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// r = radius of circular part of teardrop. (Default: 1)
|
// r = radius of circular part of teardrop. (Default: 1)
|
||||||
// ang = angle of hat walls from the Y axis. (Default: 45 degrees)
|
// ang = angle of hat walls from the Y axis (half the angle of the peak). (Default: 45 degrees)
|
||||||
// cap_h = if given, height above center where the shape will be truncated.
|
// cap_h = if given, height above center where the shape will be truncated.
|
||||||
// ---
|
// ---
|
||||||
// d = diameter of circular portion of bottom. (Use instead of r)
|
// d = diameter of circular portion of bottom. (Use instead of r)
|
||||||
|
|
124
shapes3d.scad
124
shapes3d.scad
|
@ -27,8 +27,8 @@ use <builtins.scad>
|
||||||
// vnf = cube(size, ...);
|
// vnf = cube(size, ...);
|
||||||
// See Also: cuboid(), prismoid()
|
// See Also: cuboid(), prismoid()
|
||||||
// Description:
|
// Description:
|
||||||
// Creates a 3D cubic object with support for anchoring and attachments.
|
// Creates a 3D cubic object.
|
||||||
// This can be used as a drop-in replacement for the built-in `cube()` module.
|
// This module extends the built-in cube()` module by providing support for attachments and a function form.
|
||||||
// When called as a function, returns a [VNF](vnf.scad) for a cube.
|
// When called as a function, returns a [VNF](vnf.scad) for a cube.
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// size = The size of the cube.
|
// size = The size of the cube.
|
||||||
|
@ -1063,7 +1063,7 @@ function wedge(size=[1,1,1], center, anchor, spin=0, orient=UP) =
|
||||||
|
|
||||||
// Function&Module: cylinder()
|
// Function&Module: cylinder()
|
||||||
// Topics: Shapes (3D), Attachable, VNF Generators
|
// Topics: Shapes (3D), Attachable, VNF Generators
|
||||||
// Usage: As Module (as in Native OpenSCAD)
|
// Usage: As Module (as in native OpenSCAD)
|
||||||
// cylinder(h, r=/d=, [center=]);
|
// cylinder(h, r=/d=, [center=]);
|
||||||
// cylinder(h, r1/d1=, r2/d2=, [center=]);
|
// cylinder(h, r1/d1=, r2/d2=, [center=]);
|
||||||
// Usage: With BOSL2 anchoring and attachment extensions
|
// Usage: With BOSL2 anchoring and attachment extensions
|
||||||
|
@ -1074,14 +1074,14 @@ function wedge(size=[1,1,1], center, anchor, spin=0, orient=UP) =
|
||||||
// vnf = cylinder(h, r1/d1=, r2/d2=, ...);
|
// vnf = cylinder(h, r1/d1=, r2/d2=, ...);
|
||||||
// See Also: cyl()
|
// See Also: cyl()
|
||||||
// Description:
|
// Description:
|
||||||
// Creates a 3D cylinder or conic object with support for anchoring and attachments.
|
// Creates a 3D cylinder or conic object.
|
||||||
// This modules extends the built-in `cylinder()` module by adding support for attachment.
|
// This modules extends the built-in `cylinder()` module by adding support for attachment and by adding a function version.
|
||||||
// When called as a function, returns a [VNF](vnf.scad) for a cylinder.
|
// When called as a function, returns a [VNF](vnf.scad) for a cylinder.
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// l / h = The height of the cylinder.
|
// h = The height of the cylinder.
|
||||||
// r1 = The bottom radius of the cylinder. (Before orientation.)
|
// r1 = The bottom radius of the cylinder. (Before orientation.)
|
||||||
// r2 = The top radius of the cylinder. (Before orientation.)
|
// r2 = The top radius of the cylinder. (Before orientation.)
|
||||||
// center = If given, overrides `anchor`. A true value sets `anchor=CENTER`, false sets `anchor=BOTTOM`.
|
// center = If given, overrides `anchor`. A true value sets `anchor=CENTER`, false sets `anchor=BOTTOM`. Default: false
|
||||||
// ---
|
// ---
|
||||||
// d1 = The bottom diameter of the cylinder. (Before orientation.)
|
// d1 = The bottom diameter of the cylinder. (Before orientation.)
|
||||||
// d2 = The top diameter of the cylinder. (Before orientation.)
|
// d2 = The top diameter of the cylinder. (Before orientation.)
|
||||||
|
@ -1112,24 +1112,24 @@ function wedge(size=[1,1,1], center, anchor, spin=0, orient=UP) =
|
||||||
// cylinder(h=30, d1=25, d2=10) show_anchors();
|
// cylinder(h=30, d1=25, d2=10) show_anchors();
|
||||||
// }
|
// }
|
||||||
|
|
||||||
module cylinder(h, r1, r2, center, l, r, d, d1, d2, anchor, spin=0, orient=UP)
|
module cylinder(h, r1, r2, center, r, d, d1, d2, anchor, spin=0, orient=UP)
|
||||||
{
|
{
|
||||||
anchor = get_anchor(anchor, center, BOTTOM, BOTTOM);
|
anchor = get_anchor(anchor, center, BOTTOM, BOTTOM);
|
||||||
r1 = get_radius(r1=r1, r=r, d1=d1, d=d, dflt=1);
|
r1 = get_radius(r1=r1, r=r, d1=d1, d=d, dflt=1);
|
||||||
r2 = get_radius(r1=r2, r=r, d1=d2, d=d, dflt=1);
|
r2 = get_radius(r1=r2, r=r, d1=d2, d=d, dflt=1);
|
||||||
l = first_defined([h, l, 1]);
|
h = default(h,1);
|
||||||
attachable(anchor,spin,orient, r1=r1, r2=r2, l=l) {
|
attachable(anchor,spin,orient, r1=r1, r2=r2, l=h) {
|
||||||
_cylinder(h=l, r1=r1, r2=r2, center=true);
|
_cylinder(h=h, r1=r1, r2=r2, center=true);
|
||||||
children();
|
children();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function cylinder(h, r1, r2, center, l, r, d, d1, d2, anchor, spin=0, orient=UP) =
|
function cylinder(h, r1, r2, center, r, d, d1, d2, anchor, spin=0, orient=UP) =
|
||||||
let(
|
let(
|
||||||
anchor = get_anchor(anchor, center, BOTTOM, BOTTOM),
|
anchor = get_anchor(anchor, center, BOTTOM, BOTTOM),
|
||||||
r1 = get_radius(r1=r1, r=r, d1=d1, d=d, dflt=1),
|
r1 = get_radius(r1=r1, r=r, d1=d1, d=d, dflt=1),
|
||||||
r2 = get_radius(r1=r2, r=r, d1=d2, d=d, dflt=1),
|
r2 = get_radius(r1=r2, r=r, d1=d2, d=d, dflt=1),
|
||||||
l = first_defined([h, l, 1]),
|
l = default(h,1),
|
||||||
sides = segs(max(r1,r2)),
|
sides = segs(max(r1,r2)),
|
||||||
verts = [
|
verts = [
|
||||||
for (i=[0:1:sides-1]) let(a=360*(1-i/sides)) [r1*cos(a),r1*sin(a),-l/2],
|
for (i=[0:1:sides-1]) let(a=360*(1-i/sides)) [r1*cos(a),r1*sin(a),-l/2],
|
||||||
|
@ -1977,21 +1977,21 @@ function pie_slice(
|
||||||
|
|
||||||
// Function&Module: sphere()
|
// Function&Module: sphere()
|
||||||
// Topics: Shapes (3D), Attachable, VNF Generators
|
// Topics: Shapes (3D), Attachable, VNF Generators
|
||||||
// Usage: As Module
|
// Usage: As Module (native OpenSCAD)
|
||||||
// sphere(r|d=, [circum=], [style=], ...) [ATTACHMENTS];
|
// sphere(r|d=);
|
||||||
// Usage: As Function
|
// Usage: Using BOSL2 attachments extensions
|
||||||
// vnf = sphere(r|d=, [circum=], [style=], ...);
|
// sphere(r|d=, [anchor=], [spin=], [orient=]) [ATTACHMENTS];
|
||||||
|
// Usage: As Function (BOSL2 extension)
|
||||||
|
// vnf = sphere(r|d=, [anchor=], [spin=], [orient=]) [ATTACHMENTS];
|
||||||
// See Also: spheroid()
|
// See Also: spheroid()
|
||||||
// Description:
|
// Description:
|
||||||
// Creates a sphere object, with support for anchoring and attachments.
|
// Creates a sphere object.
|
||||||
// This is a drop-in replacement for the built-in `sphere()` module.
|
// This module extends the built-in `sphere()` module by providing support for BOSL2 anchoring and attachments, and a function form.
|
||||||
// When called as a function, returns a [VNF](vnf.scad) for a sphere.
|
// When called as a function, returns a [VNF](vnf.scad) for a sphere.
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// r = Radius of the sphere.
|
// r = Radius of the sphere.
|
||||||
// ---
|
// ---
|
||||||
// d = Diameter of the sphere.
|
// d = Diameter of the sphere.
|
||||||
// circum = If true, the sphere is made large enough to circumscribe the sphere of the ideal side. Otherwise inscribes. Default: false (inscribes)
|
|
||||||
// style = The style of the sphere's construction. One of "orig", "aligned", "stagger", "octa", or "icosa". Default: "orig"
|
|
||||||
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
|
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
|
||||||
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
|
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
|
||||||
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
|
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
|
||||||
|
@ -1999,16 +1999,6 @@ function pie_slice(
|
||||||
// sphere(r=50);
|
// sphere(r=50);
|
||||||
// Example: By Diameter
|
// Example: By Diameter
|
||||||
// sphere(d=100);
|
// sphere(d=100);
|
||||||
// Example: style="orig"
|
|
||||||
// sphere(d=100, style="orig", $fn=10);
|
|
||||||
// Example: style="aligned"
|
|
||||||
// sphere(d=100, style="aligned", $fn=10);
|
|
||||||
// Example: style="stagger"
|
|
||||||
// sphere(d=100, style="stagger", $fn=10);
|
|
||||||
// Example: style="icosa"
|
|
||||||
// sphere(d=100, style="icosa", $fn=10);
|
|
||||||
// // In "icosa" style, $fn is quantized
|
|
||||||
// // to the nearest multiple of 5.
|
|
||||||
// Example: Anchoring
|
// Example: Anchoring
|
||||||
// sphere(d=100, anchor=FRONT);
|
// sphere(d=100, anchor=FRONT);
|
||||||
// Example: Spin
|
// Example: Spin
|
||||||
|
@ -2017,27 +2007,17 @@ function pie_slice(
|
||||||
// sphere(d=100, anchor=FRONT, spin=45, orient=FWD);
|
// sphere(d=100, anchor=FRONT, spin=45, orient=FWD);
|
||||||
// Example: Standard Connectors
|
// Example: Standard Connectors
|
||||||
// sphere(d=50) show_anchors();
|
// sphere(d=50) show_anchors();
|
||||||
// Example: Called as Function
|
|
||||||
// vnf = sphere(d=100, style="icosa");
|
|
||||||
// vnf_polyhedron(vnf);
|
|
||||||
|
|
||||||
module sphere(r, d, circum=false, style="orig", anchor=CENTER, spin=0, orient=UP) {
|
module sphere(r, d, anchor=CENTER, spin=0, orient=UP) {
|
||||||
r = get_radius(r=r, d=d, dflt=1);
|
r = get_radius(r=r, d=d, dflt=1);
|
||||||
if (!circum && style=="orig" && is_num(r)) {
|
attachable(anchor,spin,orient, r=r) {
|
||||||
attachable(anchor,spin,orient, r=r) {
|
|
||||||
_sphere(r=r);
|
_sphere(r=r);
|
||||||
children();
|
children();
|
||||||
}
|
|
||||||
} else {
|
|
||||||
spheroid(
|
|
||||||
r=r, circum=circum, style=style,
|
|
||||||
anchor=anchor, spin=spin, orient=orient
|
|
||||||
) children();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function sphere(r, d, circum=false, style="orig", anchor=CENTER, spin=0, orient=UP) =
|
function sphere(r, d, anchor=CENTER, spin=0, orient=UP) =
|
||||||
spheroid(r=r, d=d, circum=circum, style=style, anchor=anchor, spin=spin, orient=orient);
|
spheroid(r=r, d=d, style="orig", anchor=anchor, spin=spin, orient=orient);
|
||||||
|
|
||||||
|
|
||||||
// Function&Module: spheroid()
|
// Function&Module: spheroid()
|
||||||
|
@ -2920,7 +2900,8 @@ function _cut_interp(pathcut, path, data) =
|
||||||
// top = direction or list of directions pointing toward the top of the text
|
// top = direction or list of directions pointing toward the top of the text
|
||||||
// reverse = reverse the letters if true. Not allowed for 2D path. Default: false
|
// reverse = reverse the letters if true. Not allowed for 2D path. Default: false
|
||||||
// textmetrics = if set to true and lettersize is not given then use the experimental textmetrics feature. You must be running a dev snapshot that includes this feature and have the feature turned on in your preferences. Default: false
|
// textmetrics = if set to true and lettersize is not given then use the experimental textmetrics feature. You must be running a dev snapshot that includes this feature and have the feature turned on in your preferences. Default: false
|
||||||
// kern = scalar or array giving size adjustments for each letter. Default: 0
|
// valign = align text to the path using "top", "bottom", "center" or "baseline". You can also adjust position with a numerical offset as in "top-5" or "bottom+2". This only works with textmetrics enabled. You can give a simple numerical offset, which will be relative to the baseline and works even without textmetrics. Default: "baseline"
|
||||||
|
// kern = scalar or array giving spacing adjusments between each letter. If it's an array it should have one less entry than the text string. Default: 0
|
||||||
// Example(3D,NoScales): The examples use Courier, a monospaced font. The width is 1/1.2 times the specified size for this font. This text could wrap around a cylinder.
|
// Example(3D,NoScales): The examples use Courier, a monospaced font. The width is 1/1.2 times the specified size for this font. This text could wrap around a cylinder.
|
||||||
// path = path3d(arc(100, r=25, angle=[245, 370]));
|
// path = path3d(arc(100, r=25, angle=[245, 370]));
|
||||||
// color("red")stroke(path, width=.3);
|
// color("red")stroke(path, width=.3);
|
||||||
|
@ -2980,10 +2961,10 @@ function _cut_interp(pathcut, path, data) =
|
||||||
// Example(3D,NoScales): The kern parameter lets you adjust the letter spacing either with a uniform value for each letter, or with an array to make adjustments throughout the text. Here we show a case where adding some extra space gives a better look in a tight circle. When textmetrics are off, `lettersize` can do this job, but with textmetrics, you'll need to use `kern` to make adjustments relative to the text metric sizes.
|
// Example(3D,NoScales): The kern parameter lets you adjust the letter spacing either with a uniform value for each letter, or with an array to make adjustments throughout the text. Here we show a case where adding some extra space gives a better look in a tight circle. When textmetrics are off, `lettersize` can do this job, but with textmetrics, you'll need to use `kern` to make adjustments relative to the text metric sizes.
|
||||||
// path = path3d(arc(100, r=12, angle=[150, 450]));
|
// path = path3d(arc(100, r=12, angle=[150, 450]));
|
||||||
// color("red")stroke(path, width=.3);
|
// color("red")stroke(path, width=.3);
|
||||||
// kern = [1,1.2,1,1,.3,-.2,1,0,.8,1,1.1,1];
|
// kern = [1,1.2,1,1,.3,-.2,1,0,.8,1,1.1];
|
||||||
// path_text(path, "Example text", font="Courier", size=5, lettersize = 5/1.2, kern=kern, normal=UP);
|
// path_text(path, "Example text", font="Courier", size=5, lettersize = 5/1.2, kern=kern, normal=UP);
|
||||||
|
|
||||||
module path_text(path, text, font, size, thickness, lettersize, offset=0, reverse=false, normal, top, center=false, textmetrics=false, kern=0, height,h)
|
module path_text(path, text, font, size, thickness, lettersize, offset=0, reverse=false, normal, top, center=false, textmetrics=false, kern=0, height,h, valign="baseline")
|
||||||
{
|
{
|
||||||
no_children($children);
|
no_children($children);
|
||||||
dummy2=assert(is_path(path,[2,3]),"Must supply a 2d or 3d path")
|
dummy2=assert(is_path(path,[2,3]),"Must supply a 2d or 3d path")
|
||||||
|
@ -3008,27 +2989,45 @@ module path_text(path, text, font, size, thickness, lettersize, offset=0, revers
|
||||||
: is_def(top) ? top
|
: is_def(top) ? top
|
||||||
: undef;
|
: undef;
|
||||||
|
|
||||||
kern = force_list(kern, len(text));
|
kern = force_list(kern, len(text)-1);
|
||||||
dummy3 = assert(is_list(kern) && len(kern)==len(text), "kern must be a scalar or list whose length is len(text)");
|
dummy3 = assert(is_list(kern) && len(kern)==len(text)-1, "kern must be a scalar or list whose length is len(text)-1");
|
||||||
|
|
||||||
lsize = kern + (
|
lsize = is_def(lettersize) ? force_list(lettersize, len(text))
|
||||||
is_def(lettersize) ? force_list(lettersize, len(text))
|
|
||||||
: textmetrics ? [for(letter=text) let(t=textmetrics(letter, font=font, size=size)) t.advance[0]]
|
: textmetrics ? [for(letter=text) let(t=textmetrics(letter, font=font, size=size)) t.advance[0]]
|
||||||
: assert(false, "textmetrics disabled: Must specify letter size")
|
: assert(false, "textmetrics disabled: Must specify letter size");
|
||||||
);
|
lcenter = convolve(lsize,[1,1]/2)+[0,each kern,0] ;
|
||||||
textlength = sum(lsize);
|
textlength = sum(lsize)+sum(kern);
|
||||||
|
|
||||||
|
ascent = !textmetrics ? undef
|
||||||
|
: textmetrics(text, font=font, size=size).ascent;
|
||||||
|
descent = !textmetrics ? undef
|
||||||
|
: textmetrics(text, font=font, size=size).descent;
|
||||||
|
|
||||||
|
vadjustment = is_num(valign) ? -valign
|
||||||
|
: !textmetrics ? assert(valign=="baseline","valign requires textmetrics support") 0
|
||||||
|
: let(
|
||||||
|
table = [
|
||||||
|
["baseline", 0],
|
||||||
|
["top", -ascent],
|
||||||
|
["bottom", descent],
|
||||||
|
["center", (descent-ascent)/2]
|
||||||
|
],
|
||||||
|
match = [for(i=idx(table)) if (starts_with(valign,table[i][0])) i]
|
||||||
|
)
|
||||||
|
assert(len(match)==1, "Invalid valign value")
|
||||||
|
table[match[0]][1] - parse_num(substr(valign,len(table[match[0]][0])));
|
||||||
|
|
||||||
dummy1 = assert(textlength<=path_length(path),"Path is too short for the text");
|
dummy1 = assert(textlength<=path_length(path),"Path is too short for the text");
|
||||||
|
|
||||||
start = center ? (path_length(path) - textlength)/2 : 0;
|
start = center ? (path_length(path) - textlength)/2 : 0;
|
||||||
|
|
||||||
pts = path_cut_points(path, add_scalar([0, each cumsum(lsize)],start+lsize[0]/2), direction=true);
|
pts = path_cut_points(path, add_scalar([ each cumsum(lcenter)],start+0*lsize[0]/2), direction=true);
|
||||||
|
|
||||||
|
|
||||||
usernorm = is_def(normal);
|
usernorm = is_def(normal);
|
||||||
usetop = is_def(top);
|
usetop = is_def(top);
|
||||||
|
|
||||||
normpts = is_undef(normal) ? (reverse?1:-1)*column(pts,3) : _cut_interp(pts,path, normal);
|
normpts = is_undef(normal) ? (reverse?1:-1)*column(pts,3) : _cut_interp(pts,path, normal);
|
||||||
toppts = is_undef(top) ? undef : _cut_interp(pts,path,top);
|
toppts = is_undef(top) ? undef : _cut_interp(pts,path,top);
|
||||||
|
|
||||||
for (i = idx(text)) {
|
for (i = idx(text)) {
|
||||||
tangent = pts[i][2];
|
tangent = pts[i][2];
|
||||||
checks =
|
checks =
|
||||||
|
@ -3047,8 +3046,13 @@ module path_text(path, text, font, size, thickness, lettersize, offset=0, revers
|
||||||
y=usetop ? toppts[i] : undef
|
y=usetop ? toppts[i] : undef
|
||||||
) up(offset-thickness/2) {
|
) up(offset-thickness/2) {
|
||||||
linear_extrude(height=thickness)
|
linear_extrude(height=thickness)
|
||||||
left(lsize[0]/2)
|
back(vadjustment)
|
||||||
|
{
|
||||||
|
stroke([[0,0],[0,14]], width=.3, endcap2="arrow");
|
||||||
|
|
||||||
|
left(lsize[i]/2)
|
||||||
text(text[i], font=font, size=size);
|
text(text[i], font=font, size=size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
frame_map(
|
frame_map(
|
||||||
|
|
33
skin.scad
33
skin.scad
|
@ -1609,8 +1609,8 @@ module spiral_sweep(poly, h, r, turns=1, taper, center, r1, r2, d, d1, d2, taper
|
||||||
// curve = [for(theta=[0:4:359])
|
// curve = [for(theta=[0:4:359])
|
||||||
// [r*cos(theta), r*sin(theta), 10+sin(6*theta)]];
|
// [r*cos(theta), r*sin(theta), 10+sin(6*theta)]];
|
||||||
// difference(){
|
// difference(){
|
||||||
// cylinder(r=r, l=len);
|
// cylinder(r=r, h=len);
|
||||||
// down(.5)cylinder(r=r-thickness, l=len+1);
|
// down(.5)cylinder(r=r-thickness, h=len+1);
|
||||||
// path_sweep(left(.05,square([1.1,1])), curve, closed=true,
|
// path_sweep(left(.05,square([1.1,1])), curve, closed=true,
|
||||||
// method="manual", normal=UP);
|
// method="manual", normal=UP);
|
||||||
// }
|
// }
|
||||||
|
@ -3438,35 +3438,6 @@ function _textured_linear_sweep(
|
||||||
) reorient(anchor,spin,orient, vnf=final_vnf, extent=true, anchors=anchors, p=final_vnf);
|
) reorient(anchor,spin,orient, vnf=final_vnf, extent=true, anchors=anchors, p=final_vnf);
|
||||||
|
|
||||||
|
|
||||||
module _textured_linear_sweep(
|
|
||||||
path, texture, tex_size=[5,5], h,
|
|
||||||
inset=false, rot=false, tex_scale=1,
|
|
||||||
twist, scale, shift, samples, caps=true,
|
|
||||||
style="min_edge", l,
|
|
||||||
height, length, counts,
|
|
||||||
anchor=CENTER, spin=0, orient=UP,
|
|
||||||
convexity=10
|
|
||||||
) {
|
|
||||||
h = first_defined([h, l, height, length, 1]);
|
|
||||||
vnf = _textured_linear_sweep(
|
|
||||||
path, texture, h=h, caps=caps,
|
|
||||||
tex_size=tex_size, counts=counts,
|
|
||||||
inset=inset, rot=rot, tex_scale=tex_scale,
|
|
||||||
twist=twist, scale=scale, shift=shift,
|
|
||||||
samples=samples, style=style,
|
|
||||||
anchor=CENTER, spin=0, orient=UP
|
|
||||||
);
|
|
||||||
cent = centroid(path);
|
|
||||||
anchors = [
|
|
||||||
named_anchor("centroid_top", point3d(cent, h/2), UP),
|
|
||||||
named_anchor("centroid", point3d(cent), UP),
|
|
||||||
named_anchor("centroid_bot", point3d(cent,-h/2), DOWN)
|
|
||||||
];
|
|
||||||
attachable(anchor,spin,orient, vnf=vnf, extent=true, anchors=anchors) {
|
|
||||||
vnf_polyhedron(vnf, convexity=convexity);
|
|
||||||
children();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function _find_vnf_tile_edge_path(vnf, val) =
|
function _find_vnf_tile_edge_path(vnf, val) =
|
||||||
let(
|
let(
|
||||||
|
|
|
@ -121,6 +121,18 @@ module test_is_decreasing() {
|
||||||
test_is_decreasing();
|
test_is_decreasing();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
module test_are_ends_equal() {
|
||||||
|
assert(!are_ends_equal([[1,2,3],[4,5,6],[1,8,9]]));
|
||||||
|
assert(are_ends_equal([[1,2,3],[4,5,6],[1,8,9],[1,2,3]]));
|
||||||
|
assert(are_ends_equal([1,2,3,1.00004],eps=1e-2));
|
||||||
|
assert(are_ends_equal([3]));
|
||||||
|
}
|
||||||
|
test_are_ends_equal();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
module test_find_approx() {
|
module test_find_approx() {
|
||||||
assert(find_approx(1, [2,3,1.05,4,1,2,.99], eps=.1)==2);
|
assert(find_approx(1, [2,3,1.05,4,1,2,.99], eps=.1)==2);
|
||||||
assert(find_approx(1, [2,3,1.05,4,1,2,.99], all=true, eps=.1)==[2,4,6]);
|
assert(find_approx(1, [2,3,1.05,4,1,2,.99], all=true, eps=.1)==[2,4,6]);
|
||||||
|
|
|
@ -33,13 +33,6 @@ test_is_1region();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
module test_is_closed_path() {
|
|
||||||
assert(!is_closed_path([[1,2,3],[4,5,6],[1,8,9]]));
|
|
||||||
assert(is_closed_path([[1,2,3],[4,5,6],[1,8,9],[1,2,3]]));
|
|
||||||
}
|
|
||||||
test_is_closed_path();
|
|
||||||
|
|
||||||
|
|
||||||
module test_close_path() {
|
module test_close_path() {
|
||||||
assert(close_path([[1,2,3],[4,5,6],[1,8,9]]) == [[1,2,3],[4,5,6],[1,8,9],[1,2,3]]);
|
assert(close_path([[1,2,3],[4,5,6],[1,8,9]]) == [[1,2,3],[4,5,6],[1,8,9],[1,2,3]]);
|
||||||
assert(close_path([[1,2,3],[4,5,6],[1,8,9],[1,2,3]]) == [[1,2,3],[4,5,6],[1,8,9],[1,2,3]]);
|
assert(close_path([[1,2,3],[4,5,6],[1,8,9],[1,2,3]]) == [[1,2,3],[4,5,6],[1,8,9],[1,2,3]]);
|
||||||
|
|
|
@ -94,28 +94,28 @@ module test_cyl() {
|
||||||
$fn=12;
|
$fn=12;
|
||||||
shape_compare() {
|
shape_compare() {
|
||||||
cyl(r=50,l=10,circum=true,anchor=BOTTOM);
|
cyl(r=50,l=10,circum=true,anchor=BOTTOM);
|
||||||
cylinder(r=50/cos(180/12),l=10);
|
cylinder(r=50/cos(180/12),h=10);
|
||||||
}
|
}
|
||||||
shape_compare() {
|
shape_compare() {
|
||||||
cyl(r=50,l=10,circum=false,anchor=BOTTOM);
|
cyl(r=50,l=10,circum=false,anchor=BOTTOM);
|
||||||
cylinder(r=50,l=10);
|
cylinder(r=50,h=10);
|
||||||
}
|
}
|
||||||
shape_compare() {
|
shape_compare() {
|
||||||
cyl(r=50,l=10,chamfer=1,circum=true,anchor=BOTTOM);
|
cyl(r=50,l=10,chamfer=1,circum=true,anchor=BOTTOM);
|
||||||
union() {
|
union() {
|
||||||
r=50/cos(180/12);
|
r=50/cos(180/12);
|
||||||
cylinder(r1=r-1,r2=r,l=1);
|
cylinder(r1=r-1,r2=r,h=1);
|
||||||
up(1) cylinder(r=r,l=8);
|
up(1) cylinder(r=r,h=8);
|
||||||
up(9) cylinder(r1=r,r2=r-1,l=1);
|
up(9) cylinder(r1=r,r2=r-1,h=1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
shape_compare() {
|
shape_compare() {
|
||||||
cyl(r=50,l=10,chamfer=1,circum=false,anchor=BOTTOM);
|
cyl(r=50,l=10,chamfer=1,circum=false,anchor=BOTTOM);
|
||||||
union() {
|
union() {
|
||||||
r=50;
|
r=50;
|
||||||
cylinder(r1=r-1,r2=r,l=1);
|
cylinder(r1=r-1,r2=r,h=1);
|
||||||
up(1) cylinder(r=r,l=8);
|
up(1) cylinder(r=r,h=8);
|
||||||
up(9) cylinder(r1=r,r2=r-1,l=1);
|
up(9) cylinder(r1=r,r2=r-1,h=1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -686,7 +686,7 @@ module npt_threaded_rod(
|
||||||
internal=internal,
|
internal=internal,
|
||||||
higbee=true
|
higbee=true
|
||||||
);
|
);
|
||||||
if (hollow) cylinder(l=l+1, d=size*INCH, center=true);
|
if (hollow) cylinder(h=l+1, d=size*INCH, center=true);
|
||||||
}
|
}
|
||||||
children();
|
children();
|
||||||
}
|
}
|
||||||
|
@ -1270,7 +1270,7 @@ module generic_threaded_rod(
|
||||||
);
|
);
|
||||||
|
|
||||||
slope = (_r1-_r2)/l;
|
slope = (_r1-_r2)/l;
|
||||||
maxlen = 2*pitch;
|
maxlen = 5*pitch;
|
||||||
|
|
||||||
attachable(anchor,spin,orient, r1=_r1, r2=_r2, l=l) {
|
attachable(anchor,spin,orient, r1=_r1, r2=_r2, l=l) {
|
||||||
union(){
|
union(){
|
||||||
|
|
|
@ -251,7 +251,7 @@ function ang_adj_to_opp(ang,adj) = adj_ang_to_opp(adj,ang);
|
||||||
// hyp = opp_adj_to_hyp(opp,adj);
|
// hyp = opp_adj_to_hyp(opp,adj);
|
||||||
// Topics: Geometry, Trigonometry, Triangles
|
// Topics: Geometry, Trigonometry, Triangles
|
||||||
// Description:
|
// Description:
|
||||||
// Given the length of the adjacent and opposite sides of a right triangle, returns the length of thee hypotenuse.
|
// Given the length of the adjacent and opposite sides of a right triangle, returns the length of the hypotenuse.
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// adj = The length of the side of the right triangle that is adjacent to the primary angle.
|
// adj = The length of the side of the right triangle that is adjacent to the primary angle.
|
||||||
// opp = The length of the side of the right triangle that is opposite from the primary angle.
|
// opp = The length of the side of the right triangle that is opposite from the primary angle.
|
||||||
|
|
|
@ -320,7 +320,7 @@ but the cylinder's bottom is placed at the center of the cube.
|
||||||
```openscad-3D
|
```openscad-3D
|
||||||
include <BOSL2/std.scad>
|
include <BOSL2/std.scad>
|
||||||
cube(50)
|
cube(50)
|
||||||
cylinder(d=25,l=75);
|
cylinder(d=25,h=75);
|
||||||
```
|
```
|
||||||
|
|
||||||
If you explicitly anchor the child object then the anchor you choose will be aligned
|
If you explicitly anchor the child object then the anchor you choose will be aligned
|
||||||
|
@ -331,7 +331,7 @@ side of the cylinder is aligned with the center of the cube.
|
||||||
```openscad-3D
|
```openscad-3D
|
||||||
include <BOSL2/std.scad>
|
include <BOSL2/std.scad>
|
||||||
cube(50,anchor=FRONT)
|
cube(50,anchor=FRONT)
|
||||||
cylinder(d=25,l=95,anchor=RIGHT);
|
cylinder(d=25,h=95,anchor=RIGHT);
|
||||||
```
|
```
|
||||||
|
|
||||||
The `position()` module enables you to specify where on the parent to
|
The `position()` module enables you to specify where on the parent to
|
||||||
|
@ -343,7 +343,7 @@ RIGHT anchor of the cube.
|
||||||
```openscad-3D
|
```openscad-3D
|
||||||
include <BOSL2/std.scad>
|
include <BOSL2/std.scad>
|
||||||
cube(50,anchor=FRONT)
|
cube(50,anchor=FRONT)
|
||||||
position(RIGHT) cylinder(d=25,l=75,anchor=LEFT);
|
position(RIGHT) cylinder(d=25,h=75,anchor=LEFT);
|
||||||
```
|
```
|
||||||
|
|
||||||
Using this mechanism you can position objects relative to other
|
Using this mechanism you can position objects relative to other
|
||||||
|
@ -355,7 +355,7 @@ include <BOSL2/std.scad>
|
||||||
cube([50,50,30],center=true)
|
cube([50,50,30],center=true)
|
||||||
position(TOP+RIGHT) cube([25,40,10], anchor=RIGHT+BOT)
|
position(TOP+RIGHT) cube([25,40,10], anchor=RIGHT+BOT)
|
||||||
position(LEFT+FRONT+TOP) cube([12,12,8], anchor=LEFT+FRONT+BOT)
|
position(LEFT+FRONT+TOP) cube([12,12,8], anchor=LEFT+FRONT+BOT)
|
||||||
cylinder(l=10,r=3);
|
cylinder(h=10,r=3);
|
||||||
```
|
```
|
||||||
|
|
||||||
The positioning mechanism is not magical: it simply applies a
|
The positioning mechanism is not magical: it simply applies a
|
||||||
|
@ -483,14 +483,14 @@ point on the sphere.
|
||||||
```openscad-3D
|
```openscad-3D
|
||||||
include<BOSL2/std.scad>
|
include<BOSL2/std.scad>
|
||||||
sphere(40)
|
sphere(40)
|
||||||
position(RIGHT+TOP) cylinder(r=8,l=20);
|
position(RIGHT+TOP) cylinder(r=8,h=20);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
```openscad-3D
|
```openscad-3D
|
||||||
include<BOSL2/std.scad>
|
include<BOSL2/std.scad>
|
||||||
sphere(40)
|
sphere(40)
|
||||||
attach(RIGHT+TOP) cylinder(r=8,l=20);
|
attach(RIGHT+TOP) cylinder(r=8,h=20);
|
||||||
```
|
```
|
||||||
|
|
||||||
In the example above, the cylinder's center point is attached to the
|
In the example above, the cylinder's center point is attached to the
|
||||||
|
@ -572,13 +572,13 @@ case.
|
||||||
```openscad-3D
|
```openscad-3D
|
||||||
include <BOSL2/std.scad>
|
include <BOSL2/std.scad>
|
||||||
cube(50,center=true)
|
cube(50,center=true)
|
||||||
attach(RIGHT)cylinder(d1=30,d2=15,l=25);
|
attach(RIGHT)cylinder(d1=30,d2=15,h=25);
|
||||||
```
|
```
|
||||||
|
|
||||||
```openscad-3D
|
```openscad-3D
|
||||||
include <BOSL2/std.scad>
|
include <BOSL2/std.scad>
|
||||||
cube(50,center=true)
|
cube(50,center=true)
|
||||||
attach(RIGHT+TOP)cylinder(d1=30,d2=15,l=25);
|
attach(RIGHT+TOP)cylinder(d1=30,d2=15,h=25);
|
||||||
```
|
```
|
||||||
|
|
||||||
In the second example, the child object points diagonally away
|
In the second example, the child object points diagonally away
|
||||||
|
@ -593,7 +593,7 @@ think that it moves the object first, and then it gets attached.
|
||||||
```openscad-3D
|
```openscad-3D
|
||||||
include <BOSL2/std.scad>
|
include <BOSL2/std.scad>
|
||||||
cube(50,center=true)
|
cube(50,center=true)
|
||||||
attach(RIGHT)cylinder(d1=30,d2=15,l=25,anchor=FRONT);
|
attach(RIGHT)cylinder(d1=30,d2=15,h=25,anchor=FRONT);
|
||||||
```
|
```
|
||||||
|
|
||||||
In the above example we anchor the child to its FRONT and then attach
|
In the above example we anchor the child to its FRONT and then attach
|
||||||
|
@ -624,14 +624,14 @@ when doing differences.
|
||||||
include <BOSL2/std.scad>
|
include <BOSL2/std.scad>
|
||||||
cube(50,center=true)
|
cube(50,center=true)
|
||||||
attach(TOP,overlap=10)
|
attach(TOP,overlap=10)
|
||||||
cylinder(d=20,l=20);
|
cylinder(d=20,h=20);
|
||||||
```
|
```
|
||||||
|
|
||||||
```openscad-3D
|
```openscad-3D
|
||||||
include <BOSL2/std.scad>
|
include <BOSL2/std.scad>
|
||||||
cube(50,center=true)
|
cube(50,center=true)
|
||||||
attach(TOP,overlap=-20)
|
attach(TOP,overlap=-20)
|
||||||
cylinder(d=20,l=20);
|
cylinder(d=20,h=20);
|
||||||
```
|
```
|
||||||
|
|
||||||
As with `position()`, you can still apply your own translations and
|
As with `position()`, you can still apply your own translations and
|
||||||
|
@ -645,7 +645,7 @@ include <BOSL2/std.scad>
|
||||||
cube(50,center=true)
|
cube(50,center=true)
|
||||||
up(13)
|
up(13)
|
||||||
attach(RIGHT)
|
attach(RIGHT)
|
||||||
cylinder(d1=30,d2=15,l=25);
|
cylinder(d1=30,d2=15,h=25);
|
||||||
```
|
```
|
||||||
|
|
||||||
On the other hand, if you put the translation between the attach and
|
On the other hand, if you put the translation between the attach and
|
||||||
|
@ -657,7 +657,7 @@ include <BOSL2/std.scad>
|
||||||
cube(50,center=true)
|
cube(50,center=true)
|
||||||
attach(RIGHT)
|
attach(RIGHT)
|
||||||
up(13)
|
up(13)
|
||||||
cylinder(d1=30,d2=15,l=25);
|
cylinder(d1=30,d2=15,h=25);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
@ -676,25 +676,25 @@ attaching with those anchors.
|
||||||
```openscad-3D
|
```openscad-3D
|
||||||
include <BOSL2/std.scad>
|
include <BOSL2/std.scad>
|
||||||
cube(50,anchor=BOT) attach(TOP) anchor_arrow(30);
|
cube(50,anchor=BOT) attach(TOP) anchor_arrow(30);
|
||||||
right(60)cylinder(d1=30,d2=15,l=25) attach(TOP) anchor_arrow(30);
|
right(60)cylinder(d1=30,d2=15,h=25) attach(TOP) anchor_arrow(30);
|
||||||
```
|
```
|
||||||
|
|
||||||
```openscad-3D
|
```openscad-3D
|
||||||
include <BOSL2/std.scad>
|
include <BOSL2/std.scad>
|
||||||
cube(50,anchor=BOT)
|
cube(50,anchor=BOT)
|
||||||
attach(TOP,TOP) cylinder(d1=30,d2=15,l=25);
|
attach(TOP,TOP) cylinder(d1=30,d2=15,h=25);
|
||||||
```
|
```
|
||||||
|
|
||||||
```openscad-3D
|
```openscad-3D
|
||||||
include <BOSL2/std.scad>
|
include <BOSL2/std.scad>
|
||||||
cube(50,center=true) attach(RIGHT) anchor_arrow(30);
|
cube(50,center=true) attach(RIGHT) anchor_arrow(30);
|
||||||
right(80)cylinder(d1=30,d2=15,l=25) attach(LEFT) anchor_arrow(30);
|
right(80)cylinder(d1=30,d2=15,h=25) attach(LEFT) anchor_arrow(30);
|
||||||
```
|
```
|
||||||
|
|
||||||
```openscad-3D
|
```openscad-3D
|
||||||
include <BOSL2/std.scad>
|
include <BOSL2/std.scad>
|
||||||
cube(50,center=true)
|
cube(50,center=true)
|
||||||
attach(RIGHT,LEFT) cylinder(d1=30,d2=15,l=25);
|
attach(RIGHT,LEFT) cylinder(d1=30,d2=15,h=25);
|
||||||
```
|
```
|
||||||
|
|
||||||
Note that when you attach with two anchors like this, the attachment
|
Note that when you attach with two anchors like this, the attachment
|
||||||
|
@ -710,15 +710,15 @@ hidden in the middle of the objects.
|
||||||
|
|
||||||
```openscad-3D
|
```openscad-3D
|
||||||
include <BOSL2/std.scad>
|
include <BOSL2/std.scad>
|
||||||
cylinder(d1=30,d2=15,l=25) attach(CENTER) anchor_arrow(40);
|
cylinder(d1=30,d2=15,h=25) attach(CENTER) anchor_arrow(40);
|
||||||
right(40)cylinder(d1=30,d2=15,l=25) attach(CENTER) anchor_arrow(40);
|
right(40)cylinder(d1=30,d2=15,h=25) attach(CENTER) anchor_arrow(40);
|
||||||
```
|
```
|
||||||
|
|
||||||
```openscad-3D
|
```openscad-3D
|
||||||
include <BOSL2/std.scad>
|
include <BOSL2/std.scad>
|
||||||
cylinder(d1=30,d2=15,l=25)
|
cylinder(d1=30,d2=15,h=25)
|
||||||
attach(CENTER,CENTER)
|
attach(CENTER,CENTER)
|
||||||
cylinder(d1=30,d2=15,l=25);
|
cylinder(d1=30,d2=15,h=25);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
@ -729,8 +729,8 @@ You can attach or position more than one child at a time by enclosing them all i
|
||||||
```openscad-3D
|
```openscad-3D
|
||||||
include <BOSL2/std.scad>
|
include <BOSL2/std.scad>
|
||||||
cube(50, center=true) {
|
cube(50, center=true) {
|
||||||
attach(TOP) cylinder(d1=50,d2=20,l=20);
|
attach(TOP) cylinder(d1=50,d2=20,h=20);
|
||||||
position(RIGHT) cylinder(d1=50,d2=20,l=20);
|
position(RIGHT) cylinder(d1=50,d2=20,h=20);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -740,13 +740,13 @@ desired anchors as a list to the `attach()` or `position()` modules:
|
||||||
```openscad-3D
|
```openscad-3D
|
||||||
include <BOSL2/std.scad>
|
include <BOSL2/std.scad>
|
||||||
cube(50, center=true)
|
cube(50, center=true)
|
||||||
attach([RIGHT,FRONT],TOP) cylinder(d1=35,d2=20,l=25);
|
attach([RIGHT,FRONT],TOP) cylinder(d1=35,d2=20,h=25);
|
||||||
```
|
```
|
||||||
|
|
||||||
```openscad-3D
|
```openscad-3D
|
||||||
include <BOSL2/std.scad>
|
include <BOSL2/std.scad>
|
||||||
cube(50, center=true)
|
cube(50, center=true)
|
||||||
position([TOP,RIGHT,FRONT]) cylinder(d1=35,d2=20,l=25);
|
position([TOP,RIGHT,FRONT]) cylinder(d1=35,d2=20,h=25);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
@ -987,7 +987,7 @@ module round_corner(r) difference() {
|
||||||
translate(-[1,1,1])
|
translate(-[1,1,1])
|
||||||
cube(r+1);
|
cube(r+1);
|
||||||
translate([r,r,r])
|
translate([r,r,r])
|
||||||
sphere(r=r, style="aligned", $fn=quantup(segs(r),4));
|
spheroid(r=r, style="aligned", $fn=quantup(segs(r),4));
|
||||||
}
|
}
|
||||||
round_corner(r=10);
|
round_corner(r=10);
|
||||||
```
|
```
|
||||||
|
@ -1000,7 +1000,7 @@ module round_corner(r) difference() {
|
||||||
translate(-[1,1,1])
|
translate(-[1,1,1])
|
||||||
cube(r+1);
|
cube(r+1);
|
||||||
translate([r,r,r])
|
translate([r,r,r])
|
||||||
sphere(r=r, style="aligned", $fn=quantup(segs(r),4));
|
spheroid(r=r, style="aligned", $fn=quantup(segs(r),4));
|
||||||
}
|
}
|
||||||
diff()
|
diff()
|
||||||
cube([50,60,70],center=true)
|
cube([50,60,70],center=true)
|
||||||
|
@ -1017,7 +1017,7 @@ module round_corner(r) difference() {
|
||||||
translate(-[1,1,1])
|
translate(-[1,1,1])
|
||||||
cube(r+1);
|
cube(r+1);
|
||||||
translate([r,r,r])
|
translate([r,r,r])
|
||||||
sphere(r=r, style="aligned", $fn=quantup(segs(r),4));
|
spheroid(r=r, style="aligned", $fn=quantup(segs(r),4));
|
||||||
}
|
}
|
||||||
module round_edge(l,r) difference() {
|
module round_edge(l,r) difference() {
|
||||||
translate([-1,-1,-l/2])
|
translate([-1,-1,-l/2])
|
||||||
|
|
|
@ -9,7 +9,7 @@ Firstoff, include the BOSL2 library, then make a starting module that just has a
|
||||||
```openscad-3D
|
```openscad-3D
|
||||||
include <BOSL2/std.scad>
|
include <BOSL2/std.scad>
|
||||||
module tree(l=1500, sc=0.7)
|
module tree(l=1500, sc=0.7)
|
||||||
cylinder(l=l, d1=l/5, d2=l/5*sc);
|
cylinder(h=l, d1=l/5, d2=l/5*sc);
|
||||||
tree();
|
tree();
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -20,9 +20,9 @@ You can attach a branch to the top of the trunk by using `attach()` as a child o
|
||||||
```openscad-3D
|
```openscad-3D
|
||||||
include <BOSL2/std.scad>
|
include <BOSL2/std.scad>
|
||||||
module tree(l=1500, sc=0.7)
|
module tree(l=1500, sc=0.7)
|
||||||
cylinder(l=l, d1=l/5, d2=l/5*sc)
|
cylinder(h=l, d1=l/5, d2=l/5*sc)
|
||||||
attach(TOP)
|
attach(TOP)
|
||||||
yrot(30) cylinder(l=l*sc, d1=l/5*sc, d2=l/5*sc*sc);
|
yrot(30) cylinder(h=l*sc, d1=l/5*sc, d2=l/5*sc*sc);
|
||||||
tree();
|
tree();
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -33,10 +33,10 @@ Instead of attaching each branch individually, you can make multiple copies of o
|
||||||
```openscad-3D
|
```openscad-3D
|
||||||
include <BOSL2/std.scad>
|
include <BOSL2/std.scad>
|
||||||
module tree(l=1500, sc=0.7)
|
module tree(l=1500, sc=0.7)
|
||||||
cylinder(l=l, d1=l/5, d2=l/5*sc)
|
cylinder(h=l, d1=l/5, d2=l/5*sc)
|
||||||
attach(TOP)
|
attach(TOP)
|
||||||
zrot_copies(n=2) // Replicate that branch
|
zrot_copies(n=2) // Replicate that branch
|
||||||
yrot(30) cylinder(l=l*sc, d1=l/5*sc, d2=l/5*sc*sc);
|
yrot(30) cylinder(h=l*sc, d1=l/5*sc, d2=l/5*sc*sc);
|
||||||
tree();
|
tree();
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ Since branches look much like the main trunk, we can make the tree recursive. Do
|
||||||
```openscad-Med
|
```openscad-Med
|
||||||
include <BOSL2/std.scad>
|
include <BOSL2/std.scad>
|
||||||
module tree(l=1500, sc=0.7, depth=10)
|
module tree(l=1500, sc=0.7, depth=10)
|
||||||
cylinder(l=l, d1=l/5, d2=l/5*sc)
|
cylinder(h=l, d1=l/5, d2=l/5*sc)
|
||||||
attach(TOP)
|
attach(TOP)
|
||||||
if (depth>0) { // Important!
|
if (depth>0) { // Important!
|
||||||
zrot_copies(n=2)
|
zrot_copies(n=2)
|
||||||
|
@ -63,7 +63,7 @@ A flat planar tree isn't what we want, so lets bush it out a bit by rotating eac
|
||||||
```openscad-Med
|
```openscad-Med
|
||||||
include <BOSL2/std.scad>
|
include <BOSL2/std.scad>
|
||||||
module tree(l=1500, sc=0.7, depth=10)
|
module tree(l=1500, sc=0.7, depth=10)
|
||||||
cylinder(l=l, d1=l/5, d2=l/5*sc)
|
cylinder(h=l, d1=l/5, d2=l/5*sc)
|
||||||
attach(TOP)
|
attach(TOP)
|
||||||
if (depth>0) {
|
if (depth>0) {
|
||||||
zrot(90) // Bush it out
|
zrot(90) // Bush it out
|
||||||
|
@ -80,7 +80,7 @@ Let's add leaves. They look much like squashed versions of the standard teardrop
|
||||||
```openscad-Big
|
```openscad-Big
|
||||||
include <BOSL2/std.scad>
|
include <BOSL2/std.scad>
|
||||||
module tree(l=1500, sc=0.7, depth=10)
|
module tree(l=1500, sc=0.7, depth=10)
|
||||||
cylinder(l=l, d1=l/5, d2=l/5*sc)
|
cylinder(h=l, d1=l/5, d2=l/5*sc)
|
||||||
attach(TOP)
|
attach(TOP)
|
||||||
if (depth>0) {
|
if (depth>0) {
|
||||||
zrot(90)
|
zrot(90)
|
||||||
|
@ -104,7 +104,7 @@ nested `recolor()`.
|
||||||
include <BOSL2/std.scad>
|
include <BOSL2/std.scad>
|
||||||
module tree(l=1500, sc=0.7, depth=10)
|
module tree(l=1500, sc=0.7, depth=10)
|
||||||
recolor("lightgray")
|
recolor("lightgray")
|
||||||
cylinder(l=l, d1=l/5, d2=l/5*sc)
|
cylinder(h=l, d1=l/5, d2=l/5*sc)
|
||||||
attach(TOP)
|
attach(TOP)
|
||||||
if (depth>0) {
|
if (depth>0) {
|
||||||
zrot(90)
|
zrot(90)
|
||||||
|
|
5
vnf.scad
5
vnf.scad
|
@ -206,9 +206,8 @@ function vnf_vertex_array(
|
||||||
: [[i1,i3,i2],[i1,i4,i3]],
|
: [[i1,i3,i2],[i1,i4,i3]],
|
||||||
// remove degenerate faces
|
// remove degenerate faces
|
||||||
culled_faces= [for(face=faces)
|
culled_faces= [for(face=faces)
|
||||||
if (norm(verts[face[0]]-verts[face[1]])>EPSILON &&
|
if (norm(cross(verts[face[1]]-verts[face[0]],
|
||||||
norm(verts[face[1]]-verts[face[2]])>EPSILON &&
|
verts[face[2]]-verts[face[0]]))>EPSILON)
|
||||||
norm(verts[face[2]]-verts[face[0]])>EPSILON)
|
|
||||||
face
|
face
|
||||||
],
|
],
|
||||||
rfaces = reverse? [for (face=culled_faces) reverse(face)] : culled_faces
|
rfaces = reverse? [for (face=culled_faces) reverse(face)] : culled_faces
|
||||||
|
|
Loading…
Reference in a new issue