mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2025-01-17 18:09:40 +00:00
commit
379678127f
7 changed files with 84 additions and 72 deletions
|
@ -269,45 +269,45 @@ Which outputs Markdown code that renders like:
|
||||||
The `Function&Module` header is used to document a function which has a related module of the same name. It should have a Description sub-block. It is recommended to also have Usage, Arguments, and Example/Examples sub-blocks. You should have Usage blocks for both calling as a function, and calling as a
|
The `Function&Module` header is used to document a function which has a related module of the same name. It should have a Description sub-block. It is recommended to also have Usage, Arguments, and Example/Examples sub-blocks. You should have Usage blocks for both calling as a function, and calling as a
|
||||||
module:
|
module:
|
||||||
|
|
||||||
// Function&Module: oval()
|
// Function&Module: ellipse()
|
||||||
// Topics: 2D Shapes, Geometry
|
// Topics: 2D Shapes, Geometry
|
||||||
// Usage: As a Module
|
// Usage: As a Module
|
||||||
// oval(rx,ry);
|
// ellipse(rx,ry);
|
||||||
// Usage: As a Function
|
// Usage: As a Function
|
||||||
// path = oval(rx,ry);
|
// path = ellipse(rx,ry);
|
||||||
// Description:
|
// Description:
|
||||||
// When called as a function, returns the perimeter path of the oval.
|
// When called as a function, returns the perimeter path of the ellipse.
|
||||||
// When called as a module, creates a 2D oval shape.
|
// When called as a module, creates a 2D ellipse shape.
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// rx = X axis radius.
|
// rx = X axis radius.
|
||||||
// ry = Y axis radius.
|
// ry = Y axis radius.
|
||||||
// Example(2D): Called as a Function
|
// Example(2D): Called as a Function
|
||||||
// path = oval(100,60);
|
// path = ellipse(100,60);
|
||||||
// polygon(path);
|
// polygon(path);
|
||||||
// Example(2D): Called as a Module
|
// Example(2D): Called as a Module
|
||||||
// oval(80,60);
|
// ellipse(80,60);
|
||||||
module oval(rx,ry) {
|
module ellipse(rx,ry) {
|
||||||
polygon(oval(rx,ry));
|
polygon(ellipse(rx,ry));
|
||||||
}
|
}
|
||||||
function oval(rx,ry) =
|
function ellipse(rx,ry) =
|
||||||
[for (a=[360:-360/$fn:0.0001]) [rx*cos(a),ry*sin(a)];
|
[for (a=[360:-360/$fn:0.0001]) [rx*cos(a),ry*sin(a)];
|
||||||
|
|
||||||
Which outputs Markdown code that renders like:
|
Which outputs Markdown code that renders like:
|
||||||
|
|
||||||
> ### Function&Module: oval()
|
> ### Function&Module: ellipse()
|
||||||
> **Topics:** 2D Shapes, Geometry
|
> **Topics:** 2D Shapes, Geometry
|
||||||
>
|
>
|
||||||
> **Usage:** As a Module
|
> **Usage:** As a Module
|
||||||
>
|
>
|
||||||
> - oval(rx,ry);
|
> - ellipse(rx,ry);
|
||||||
>
|
>
|
||||||
> **Usage:** As a Function
|
> **Usage:** As a Function
|
||||||
>
|
>
|
||||||
> - path = oval(rx,ry);
|
> - path = ellipse(rx,ry);
|
||||||
>
|
>
|
||||||
> **Description:**
|
> **Description:**
|
||||||
> When called as a function, returns the perimeter path of the oval.
|
> When called as a function, returns the perimeter path of the ellipse.
|
||||||
> When called as a module, creates a 2D oval shape.
|
> When called as a module, creates a 2D ellipse shape.
|
||||||
>
|
>
|
||||||
> **Arguments:**
|
> **Arguments:**
|
||||||
> Positional Arg | What it does
|
> Positional Arg | What it does
|
||||||
|
@ -318,7 +318,7 @@ Which outputs Markdown code that renders like:
|
||||||
> **Example:** Called as a Function
|
> **Example:** Called as a Function
|
||||||
>
|
>
|
||||||
> ```openscad
|
> ```openscad
|
||||||
> path = oval(100,60);
|
> path = ellipse(100,60);
|
||||||
> polygon(path);
|
> polygon(path);
|
||||||
> ```
|
> ```
|
||||||
> GENERATED IMAGE SHOWN HERE
|
> GENERATED IMAGE SHOWN HERE
|
||||||
|
@ -326,7 +326,7 @@ Which outputs Markdown code that renders like:
|
||||||
> **Example:** Called as a Module
|
> **Example:** Called as a Module
|
||||||
>
|
>
|
||||||
> ```openscad
|
> ```openscad
|
||||||
> oval(80,60);
|
> ellipse(80,60);
|
||||||
> ```
|
> ```
|
||||||
> GENERATED IMAGE SHOWN HERE
|
> GENERATED IMAGE SHOWN HERE
|
||||||
|
|
||||||
|
@ -385,18 +385,18 @@ Usage Block
|
||||||
The Usage block describes the various ways that the current function or module can be called, with the names of the arguments. By convention, the first few arguments that can be called positionally just have their name shown. The remaining arguments that should be passed by name, will have the name followed by an `=` (equal sign). Arguments that are optional in the given Usage context are shown in `<` and `>` angle brackets:
|
The Usage block describes the various ways that the current function or module can be called, with the names of the arguments. By convention, the first few arguments that can be called positionally just have their name shown. The remaining arguments that should be passed by name, will have the name followed by an `=` (equal sign). Arguments that are optional in the given Usage context are shown in `<` and `>` angle brackets:
|
||||||
|
|
||||||
// Usage: As a Module
|
// Usage: As a Module
|
||||||
// oval(rx, ry, <spin=>);
|
// ellipse(rx, ry, <spin=>);
|
||||||
// Usage: As a Function
|
// Usage: As a Function
|
||||||
// path = oval(rx, ry, <spin=>);
|
// path = ellipse(rx, ry, <spin=>);
|
||||||
|
|
||||||
Which outputs Markdown code that renders like:
|
Which outputs Markdown code that renders like:
|
||||||
|
|
||||||
> **Usage:** As a Module
|
> **Usage:** As a Module
|
||||||
> - oval(rx, ry, <spin=>);
|
> - ellipse(rx, ry, <spin=>);
|
||||||
>
|
>
|
||||||
> **Usage:** As a Function
|
> **Usage:** As a Function
|
||||||
>
|
>
|
||||||
> - path = oval(rx, ry, <spin=>);
|
> - path = ellipse(rx, ry, <spin=>);
|
||||||
|
|
||||||
|
|
||||||
Description Block
|
Description Block
|
||||||
|
|
|
@ -1522,7 +1522,7 @@ function _get_cp(geom) =
|
||||||
)
|
)
|
||||||
assert(type!="other", "Invalid cp value")
|
assert(type!="other", "Invalid cp value")
|
||||||
cp=="centroid" ? centroid(geom[1])
|
cp=="centroid" ? centroid(geom[1])
|
||||||
: let(points = type=="vnf"?geom[1][0]:geom[1])
|
: let(points = type=="vnf"?geom[1][0]:flatten(force_region(geom[1])))
|
||||||
cp=="mean" ? mean(points)
|
cp=="mean" ? mean(points)
|
||||||
: cp=="box" ? mean(pointlist_bounds(points))
|
: cp=="box" ? mean(pointlist_bounds(points))
|
||||||
: assert(false,"Invalid cp specification");
|
: assert(false,"Invalid cp specification");
|
||||||
|
@ -1706,10 +1706,15 @@ function _find_anchor(anchor, geom) =
|
||||||
let(
|
let(
|
||||||
rr = geom[1],
|
rr = geom[1],
|
||||||
r = is_num(rr)? [rr,rr] : point2d(rr),
|
r = is_num(rr)? [rr,rr] : point2d(rr),
|
||||||
|
pos = approx(anchor.x,0) ? [0,sign(anchor.y)*r.y]
|
||||||
|
: let(
|
||||||
|
m = anchor.y/anchor.x,
|
||||||
|
px = sign(anchor.x) * sqrt(1/(1/sqr(r.x) + m*m/sqr(r.y)))
|
||||||
|
)
|
||||||
|
[px,m*px],
|
||||||
anchor = unit(point2d(anchor),[0,0]),
|
anchor = unit(point2d(anchor),[0,0]),
|
||||||
pos = point2d(cp) + v_mul(r,anchor) + point2d(offset),
|
vec = unit([r.y/r.x*pos.x, r.x/r.y*pos.y])
|
||||||
vec = unit(v_mul(r,anchor),[0,1])
|
) [anchor, point2d(cp+offset)+pos, vec, 0]
|
||||||
) [anchor, pos, vec, 0]
|
|
||||||
) : type == "rgn_isect"? ( //region
|
) : type == "rgn_isect"? ( //region
|
||||||
assert(anchor.z==0, "The Z component of an anchor for a 2D shape must be 0.")
|
assert(anchor.z==0, "The Z component of an anchor for a 2D shape must be 0.")
|
||||||
let(
|
let(
|
||||||
|
@ -1727,7 +1732,10 @@ function _find_anchor(anchor, geom) =
|
||||||
n2 = vector_angle(anchor,n)>90? -n : n
|
n2 = vector_angle(anchor,n)>90? -n : n
|
||||||
)
|
)
|
||||||
if(!is_undef(isect) && !approx(isect,t[0])) [norm(isect), isect, n2]
|
if(!is_undef(isect) && !approx(isect,t[0])) [norm(isect), isect, n2]
|
||||||
],
|
]
|
||||||
|
)
|
||||||
|
assert(len(isects)>0, "Anchor vector does not intersect with the shape. Attachment failed.")
|
||||||
|
let(
|
||||||
maxidx = max_index(column(isects,0)),
|
maxidx = max_index(column(isects,0)),
|
||||||
isect = isects[maxidx],
|
isect = isects[maxidx],
|
||||||
pos = point2d(cp) + isect[1],
|
pos = point2d(cp) + isect[1],
|
||||||
|
@ -1736,8 +1744,7 @@ function _find_anchor(anchor, geom) =
|
||||||
) : type == "rgn_extent"? ( //region
|
) : type == "rgn_extent"? ( //region
|
||||||
assert(anchor.z==0, "The Z component of an anchor for a 2D shape must be 0.")
|
assert(anchor.z==0, "The Z component of an anchor for a 2D shape must be 0.")
|
||||||
let(
|
let(
|
||||||
rgn_raw = geom[1],
|
rgn = force_region(geom[1]),
|
||||||
rgn = is_region(rgn_raw)? rgn_raw : [rgn_raw],
|
|
||||||
anchor = point2d(anchor),
|
anchor = point2d(anchor),
|
||||||
m = rot(from=anchor, to=RIGHT) * move(-[cp.x, cp.y, 0]),
|
m = rot(from=anchor, to=RIGHT) * move(-[cp.x, cp.y, 0]),
|
||||||
rpts = apply(m, flatten(rgn)),
|
rpts = apply(m, flatten(rgn)),
|
||||||
|
|
16
beziers.scad
16
beziers.scad
|
@ -1267,7 +1267,7 @@ function bezier_patch(patch, splinesteps=16, style="default") =
|
||||||
// splinesteps = Number of segments to produce on each side. Default: 16
|
// splinesteps = Number of segments to produce on each side. Default: 16
|
||||||
// reverse = reverse direction of faces. Default: false
|
// reverse = reverse direction of faces. Default: false
|
||||||
// return_edges = if true return the points on the four edges: [left, right, top, bottom]. Default: false
|
// return_edges = if true return the points on the four edges: [left, right, top, bottom]. Default: false
|
||||||
// Example(3D): This quartic patch is degenerate at one corner, where a row of control points are equal. Processing this degenerate patch normally produces excess triangles near the degenerate point.
|
// Example(3D,NoAxes): This quartic patch is degenerate at one corner, where a row of control points are equal. Processing this degenerate patch normally produces excess triangles near the degenerate point.
|
||||||
// splinesteps=8;
|
// splinesteps=8;
|
||||||
// patch=[
|
// patch=[
|
||||||
// repeat([-12.5, 12.5, 15],5),
|
// repeat([-12.5, 12.5, 15],5),
|
||||||
|
@ -1278,7 +1278,7 @@ function bezier_patch(patch, splinesteps=16, style="default") =
|
||||||
// ];
|
// ];
|
||||||
// vnf_wireframe((bezier_patch(patch, splinesteps)),width=0.1);
|
// vnf_wireframe((bezier_patch(patch, splinesteps)),width=0.1);
|
||||||
// color("red")move_copies(flatten(patch)) sphere(r=0.3,$fn=9);
|
// color("red")move_copies(flatten(patch)) sphere(r=0.3,$fn=9);
|
||||||
// Example(3D): With bezier_patch_degenerate the degenerate point does not have excess triangles. The top half of the patch decreases the number of sampled points by 2 for each row.
|
// Example(3D,NoAxes): With bezier_patch_degenerate the degenerate point does not have excess triangles. The top half of the patch decreases the number of sampled points by 2 for each row.
|
||||||
// splinesteps=8;
|
// splinesteps=8;
|
||||||
// patch=[
|
// patch=[
|
||||||
// repeat([-12.5, 12.5, 15],5),
|
// repeat([-12.5, 12.5, 15],5),
|
||||||
|
@ -1289,7 +1289,7 @@ function bezier_patch(patch, splinesteps=16, style="default") =
|
||||||
// ];
|
// ];
|
||||||
// vnf_wireframe(bezier_patch_degenerate(patch, splinesteps),width=0.1);
|
// vnf_wireframe(bezier_patch_degenerate(patch, splinesteps),width=0.1);
|
||||||
// color("red")move_copies(flatten(patch)) sphere(r=0.3,$fn=9);
|
// color("red")move_copies(flatten(patch)) sphere(r=0.3,$fn=9);
|
||||||
// Example(3D): With splinesteps odd you get one "odd" row where the point count decreases by 1 instead of 2. You may prefer even values for splinesteps to avoid this.
|
// Example(3D,NoAxes): With splinesteps odd you get one "odd" row where the point count decreases by 1 instead of 2. You may prefer even values for splinesteps to avoid this.
|
||||||
// splinesteps=7;
|
// splinesteps=7;
|
||||||
// patch=[
|
// patch=[
|
||||||
// repeat([-12.5, 12.5, 15],5),
|
// repeat([-12.5, 12.5, 15],5),
|
||||||
|
@ -1300,7 +1300,7 @@ function bezier_patch(patch, splinesteps=16, style="default") =
|
||||||
// ];
|
// ];
|
||||||
// vnf_wireframe(bezier_patch_degenerate(patch, splinesteps),width=0.1);
|
// vnf_wireframe(bezier_patch_degenerate(patch, splinesteps),width=0.1);
|
||||||
// color("red")move_copies(flatten(patch)) sphere(r=0.3,$fn=9);
|
// color("red")move_copies(flatten(patch)) sphere(r=0.3,$fn=9);
|
||||||
// Example(3D): A more extreme degeneracy occurs when the top half of a patch is degenerate to a line. (For odd length patches the middle row must be degenerate to trigger this style.) In this case the number of points in each row decreases by 1 for every row. It doesn't matter of splinesteps is odd or even.
|
// Example(3D,NoAxes): A more extreme degeneracy occurs when the top half of a patch is degenerate to a line. (For odd length patches the middle row must be degenerate to trigger this style.) In this case the number of points in each row decreases by 1 for every row. It doesn't matter of splinesteps is odd or even.
|
||||||
// splinesteps=8;
|
// splinesteps=8;
|
||||||
// patch = [[[10, 0, 0], [10, -10.4, 0], [10, -20.8, 0], [1.876, -14.30, 0], [-6.24, -7.8, 0]],
|
// patch = [[[10, 0, 0], [10, -10.4, 0], [10, -20.8, 0], [1.876, -14.30, 0], [-6.24, -7.8, 0]],
|
||||||
// [[5, 0, 0], [5, -5.2, 0], [5, -10.4, 0], [0.938, -7.15, 0], [-3.12, -3.9, 0]],
|
// [[5, 0, 0], [5, -5.2, 0], [5, -10.4, 0], [0.938, -7.15, 0], [-3.12, -3.9, 0]],
|
||||||
|
@ -1310,7 +1310,7 @@ function bezier_patch(patch, splinesteps=16, style="default") =
|
||||||
// ];
|
// ];
|
||||||
// vnf_wireframe(bezier_patch_degenerate(patch, splinesteps),width=0.1);
|
// vnf_wireframe(bezier_patch_degenerate(patch, splinesteps),width=0.1);
|
||||||
// color("red")move_copies(flatten(patch)) sphere(r=0.3,$fn=9);
|
// color("red")move_copies(flatten(patch)) sphere(r=0.3,$fn=9);
|
||||||
// Example(3D): Here is a degenerate cubic patch.
|
// Example(3D,NoScales): Here is a degenerate cubic patch.
|
||||||
// splinesteps=8;
|
// splinesteps=8;
|
||||||
// patch = [ [ [-20,0,0], [-10,0,0],[0,10,0],[0,20,0] ],
|
// patch = [ [ [-20,0,0], [-10,0,0],[0,10,0],[0,20,0] ],
|
||||||
// [ [-20,0,10], [-10,0,10],[0,10,10],[0,20,10]],
|
// [ [-20,0,10], [-10,0,10],[0,10,10],[0,20,10]],
|
||||||
|
@ -1319,7 +1319,7 @@ function bezier_patch(patch, splinesteps=16, style="default") =
|
||||||
// ];
|
// ];
|
||||||
// color("red")move_copies(flatten(patch)) sphere(r=0.3,$fn=9);
|
// color("red")move_copies(flatten(patch)) sphere(r=0.3,$fn=9);
|
||||||
// vnf_wireframe(bezier_patch_degenerate(patch, splinesteps),width=0.1);
|
// vnf_wireframe(bezier_patch_degenerate(patch, splinesteps),width=0.1);
|
||||||
// Example(3D): A more extreme degenerate cubic patch, where two rows are equal.
|
// Example(3D,NoScales): A more extreme degenerate cubic patch, where two rows are equal.
|
||||||
// splinesteps=8;
|
// splinesteps=8;
|
||||||
// patch = [ [ [-20,0,0], [-10,0,0],[0,10,0],[0,20,0] ],
|
// patch = [ [ [-20,0,0], [-10,0,0],[0,10,0],[0,20,0] ],
|
||||||
// [ [-20,0,10], [-10,0,10],[0,10,10],[0,20,10] ],
|
// [ [-20,0,10], [-10,0,10],[0,10,10],[0,20,10] ],
|
||||||
|
@ -1328,14 +1328,14 @@ function bezier_patch(patch, splinesteps=16, style="default") =
|
||||||
// ];
|
// ];
|
||||||
// color("red")move_copies(flatten(patch)) sphere(r=0.3,$fn=9);
|
// color("red")move_copies(flatten(patch)) sphere(r=0.3,$fn=9);
|
||||||
// vnf_wireframe(bezier_patch_degenerate(patch, splinesteps),width=0.1);
|
// vnf_wireframe(bezier_patch_degenerate(patch, splinesteps),width=0.1);
|
||||||
// Example(3D): Quadratic patch degenerate at the right side:
|
// Example(3D,NoScales): Quadratic patch degenerate at the right side:
|
||||||
// splinesteps=8;
|
// splinesteps=8;
|
||||||
// patch = [[[0, -10, 0],[10, -5, 0],[20, 0, 0]],
|
// patch = [[[0, -10, 0],[10, -5, 0],[20, 0, 0]],
|
||||||
// [[0, 0, 0], [10, 0, 0], [20, 0, 0]],
|
// [[0, 0, 0], [10, 0, 0], [20, 0, 0]],
|
||||||
// [[0, 0, 10], [10, 0, 5], [20, 0, 0]]];
|
// [[0, 0, 10], [10, 0, 5], [20, 0, 0]]];
|
||||||
// vnf_wireframe(bezier_patch_degenerate(patch, splinesteps),width=0.1);
|
// vnf_wireframe(bezier_patch_degenerate(patch, splinesteps),width=0.1);
|
||||||
// color("red")move_copies(flatten(patch)) sphere(r=0.3,$fn=9);
|
// color("red")move_copies(flatten(patch)) sphere(r=0.3,$fn=9);
|
||||||
// Example(3D): Cubic patch degenerate at both ends. In this case the point count changes by 2 at every row.
|
// Example(3D,NoAxes): Cubic patch degenerate at both ends. In this case the point count changes by 2 at every row.
|
||||||
// splinesteps=8;
|
// splinesteps=8;
|
||||||
// patch = [
|
// patch = [
|
||||||
// repeat([10,-10,0],4),
|
// repeat([10,-10,0],4),
|
||||||
|
|
|
@ -703,7 +703,7 @@ function arc(N, r, angle, d, cp, points, width, thickness, start, wedge=false, l
|
||||||
module arc(N, r, angle, d, cp, points, width, thickness, start, wedge=false, anchor=CENTER, spin=0)
|
module arc(N, r, angle, d, cp, points, width, thickness, start, wedge=false, anchor=CENTER, spin=0)
|
||||||
{
|
{
|
||||||
path = arc(N=N, r=r, angle=angle, d=d, cp=cp, points=points, width=width, thickness=thickness, start=start, wedge=wedge);
|
path = arc(N=N, r=r, angle=angle, d=d, cp=cp, points=points, width=width, thickness=thickness, start=start, wedge=wedge);
|
||||||
attachable(anchor,spin, two_d=true, path=path) {
|
attachable(anchor,spin, two_d=true, path=path, extent=true) {
|
||||||
polygon(path);
|
polygon(path);
|
||||||
children();
|
children();
|
||||||
}
|
}
|
||||||
|
|
15
regions.scad
15
regions.scad
|
@ -278,13 +278,16 @@ function force_region(poly) = is_path(poly) ? [poly] : poly;
|
||||||
|
|
||||||
// Module: region()
|
// Module: region()
|
||||||
// Usage:
|
// Usage:
|
||||||
// region(r);
|
// region(r, [anchor], [spin], [cp]) { ... };
|
||||||
// Description:
|
// Description:
|
||||||
// Creates the 2D polygons described by the given region or list of polygons. This module works on
|
// Creates the 2D polygons described by the given region or list of polygons. This module works on
|
||||||
// arbitrary lists of polygons that cross each other and hence do not define a valid region. The
|
// arbitrary lists of polygons that cross each other and hence do not define a valid region. The
|
||||||
// displayed result is the exclusive-or of the polygons listed in the input.
|
// displayed result is the exclusive-or of the polygons listed in the input.
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// r = region to create as geometry
|
// r = region to create as geometry
|
||||||
|
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `"origin"`
|
||||||
|
// spin = Rotate this many degrees after anchor. See [spin](attachments.scad#spin). Default: `0`
|
||||||
|
// cp = Centerpoint for determining intersection anchors or centering the shape. Determintes the base of the anchor vector. Can be "centroid", "mean", "box" or a 2D point. Default: "centroid"
|
||||||
// Example(2D): Displaying a region
|
// Example(2D): Displaying a region
|
||||||
// region([circle(d=50), square(25,center=true)]);
|
// region([circle(d=50), square(25,center=true)]);
|
||||||
// Example(2D): Displaying a list of polygons that intersect each other, which is not a region
|
// Example(2D): Displaying a list of polygons that intersect each other, which is not a region
|
||||||
|
@ -293,16 +296,18 @@ function force_region(poly) = is_path(poly) ? [poly] : poly;
|
||||||
// [square([60,10], center=true)]
|
// [square([60,10], center=true)]
|
||||||
// );
|
// );
|
||||||
// region(rgn);
|
// region(rgn);
|
||||||
module region(r)
|
module region(r, anchor="origin", spin=0, cp="centroid")
|
||||||
{
|
{
|
||||||
no_children($children);
|
|
||||||
r = force_region(r);
|
r = force_region(r);
|
||||||
dummy=assert(is_region(r), "Input is not a region");
|
dummy=assert(is_region(r), "Input is not a region");
|
||||||
points = flatten(r);
|
points = flatten(r);
|
||||||
lengths = [for(path=r) len(path)];
|
lengths = [for(path=r) len(path)];
|
||||||
starts = [0,each cumsum(lengths)];
|
starts = [0,each cumsum(lengths)];
|
||||||
paths = [for(i=idx(r)) count(s=starts[i], n=lengths[i])];
|
paths = [for(i=idx(r)) count(s=starts[i], n=lengths[i])];
|
||||||
|
attachable(anchor, spin, two_d=true, region=r, extent=false, cp=cp){
|
||||||
polygon(points=points, paths=paths);
|
polygon(points=points, paths=paths);
|
||||||
|
children();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -583,7 +588,7 @@ function region_parts(region) =
|
||||||
|
|
||||||
// Function&Module: linear_sweep()
|
// Function&Module: linear_sweep()
|
||||||
// Usage:
|
// Usage:
|
||||||
// linear_sweep(region, height, [center], [slices], [twist], [scale], [style], [convexity]);
|
// linear_sweep(region, height, [center], [slices], [twist], [scale], [style], [convexity]) {attachments};
|
||||||
// Description:
|
// Description:
|
||||||
// If called as a module, creates a polyhedron that is the linear extrusion of the given 2D region or polygon.
|
// If called as a module, creates a polyhedron that is the linear extrusion of the given 2D region or polygon.
|
||||||
// If called as a function, returns a VNF that can be used to generate a polyhedron of the linear extrusion
|
// If called as a function, returns a VNF that can be used to generate a polyhedron of the linear extrusion
|
||||||
|
@ -630,7 +635,7 @@ function region_parts(region) =
|
||||||
// mrgn = union(rgn1,rgn2);
|
// mrgn = union(rgn1,rgn2);
|
||||||
// orgn = difference(mrgn,rgn3);
|
// orgn = difference(mrgn,rgn3);
|
||||||
// linear_sweep(orgn,height=20,convexity=16) show_anchors();
|
// linear_sweep(orgn,height=20,convexity=16) show_anchors();
|
||||||
module linear_sweep(region, height=1, center, twist=0, scale=1, slices, maxseg, style="default", convexity, anchor_isect=false, anchor, spin=0, orient=UP, cp="centroid", anchor="origin") {
|
module linear_sweep(region, height=1, center, twist=0, scale=1, slices, maxseg, style="default", convexity, anchor_isect=false, spin=0, orient=UP, cp="centroid", anchor="origin") {
|
||||||
region = force_region(region);
|
region = force_region(region);
|
||||||
dummy=assert(is_region(region),"Input is not a region");
|
dummy=assert(is_region(region),"Input is not a region");
|
||||||
anchor = center ? "zcenter" : anchor;
|
anchor = center ? "zcenter" : anchor;
|
||||||
|
|
|
@ -179,7 +179,7 @@ function rect(size=1, center, rounding=0, chamfer=0, anchor, spin=0) =
|
||||||
// circle(r|d=, ...) { attachables }
|
// circle(r|d=, ...) { attachables }
|
||||||
// Usage: As a Function
|
// Usage: As a Function
|
||||||
// path = circle(r|d=, ...);
|
// path = circle(r|d=, ...);
|
||||||
// See Also: oval()
|
// See Also: ellipse()
|
||||||
// Description:
|
// Description:
|
||||||
// When called as the builtin module, creates a 2D polygon that approximates a circle of the given size.
|
// When called as the builtin module, creates a 2D polygon that approximates a circle of the given size.
|
||||||
// When called as a function, returns a 2D list of points (path) for a polygon that approximates a circle of the given size.
|
// When called as a function, returns a 2D list of points (path) for a polygon that approximates a circle of the given size.
|
||||||
|
@ -212,41 +212,41 @@ module circle(r, d, anchor=CENTER, spin=0) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Function&Module: oval()
|
// Function&Module: ellipse()
|
||||||
// Usage: As a Module
|
// Usage: As a Module
|
||||||
// oval(r|d=, [realign=], [circum=], ...);
|
// ellipse(r|d=, [realign=], [circum=], ...);
|
||||||
// Usage: With Attachments
|
// Usage: With Attachments
|
||||||
// oval(r|d=, [realign=], [circum=], ...) { attachables }
|
// ellipse(r|d=, [realign=], [circum=], ...) { attachables }
|
||||||
// Usage: As a Function
|
// Usage: As a Function
|
||||||
// path = oval(r|d=, [realign=], [circum=], ...);
|
// path = ellipse(r|d=, [realign=], [circum=], ...);
|
||||||
// Topics: Shapes (2D), Paths (2D), Path Generators, Attachable
|
// Topics: Shapes (2D), Paths (2D), Path Generators, Attachable
|
||||||
// See Also: circle()
|
// See Also: circle()
|
||||||
// Description:
|
// Description:
|
||||||
// When called as a module, creates a 2D polygon that approximates a circle or ellipse of the given size.
|
// When called as a module, creates a 2D polygon that approximates a circle or ellipse of the given size.
|
||||||
// When called as a function, returns a 2D list of points (path) for a polygon that approximates a circle or ellipse of the given size.
|
// When called as a function, returns a 2D list of points (path) for a polygon that approximates a circle or ellipse of the given size.
|
||||||
// Note that the point list or shape is the same as the one you would get by scaling the output of {{circle()}}, but with this module your
|
// Note that the point list or shape is the same as the one you would get by scaling the output of {{circle()}}, but with this module your
|
||||||
// attachments to the oval will
|
// attachments to the ellipse will
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// r = Radius of the circle or pair of semiaxes of oval
|
// r = Radius of the circle or pair of semiaxes of ellipse
|
||||||
// ---
|
// ---
|
||||||
// d = Diameter of the circle or a pair giving the full X and Y axis lengths.
|
// d = Diameter of the circle or a pair giving the full X and Y axis lengths.
|
||||||
// realign = If true, rotates the polygon that approximates the circle/oval by half of one size.
|
// realign = If true, rotates the polygon that approximates the circle/ellipse by half of one size.
|
||||||
// circum = If true, the polygon that approximates the circle will be upsized slightly to circumscribe the theoretical circle. If false, it inscribes the theoretical circle. Default: false
|
// circum = If true, the polygon that approximates the circle will be upsized slightly to circumscribe the theoretical circle. If false, it inscribes the theoretical circle. Default: false
|
||||||
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
|
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
|
||||||
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
|
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
|
||||||
// Example(2D): By Radius
|
// Example(2D): By Radius
|
||||||
// oval(r=25);
|
// ellipse(r=25);
|
||||||
// Example(2D): By Diameter
|
// Example(2D): By Diameter
|
||||||
// oval(d=50);
|
// ellipse(d=50);
|
||||||
// Example(2D): Anchoring
|
// Example(2D): Anchoring
|
||||||
// oval(d=50, anchor=FRONT);
|
// ellipse(d=50, anchor=FRONT);
|
||||||
// Example(2D): Spin
|
// Example(2D): Spin
|
||||||
// oval(d=50, anchor=FRONT, spin=45);
|
// ellipse(d=50, anchor=FRONT, spin=45);
|
||||||
// Example(NORENDER): Called as Function
|
// Example(NORENDER): Called as Function
|
||||||
// path = oval(d=50, anchor=FRONT, spin=45);
|
// path = ellipse(d=50, anchor=FRONT, spin=45);
|
||||||
module oval(r, d, realign=false, circum=false, anchor=CENTER, spin=0) {
|
module ellipse(r, d, realign=false, circum=false, anchor=CENTER, spin=0) {
|
||||||
r = get_radius(r=r, d=d, dflt=1);
|
r = get_radius(r=r, d=d, dflt=1);
|
||||||
dummy = assert((is_finite(r) || is_vector(r,2)) && all_positive(r), "Invalid radius or diameter for oval");
|
dummy = assert((is_finite(r) || is_vector(r,2)) && all_positive(r), "Invalid radius or diameter for ellipse");
|
||||||
sides = segs(max(r));
|
sides = segs(max(r));
|
||||||
sc = circum? (1 / cos(180/sides)) : 1;
|
sc = circum? (1 / cos(180/sides)) : 1;
|
||||||
rx = default(r[0],r) * sc;
|
rx = default(r[0],r) * sc;
|
||||||
|
@ -270,7 +270,7 @@ module oval(r, d, realign=false, circum=false, anchor=CENTER, spin=0) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function oval(r, d, realign=false, circum=false, anchor=CENTER, spin=0) =
|
function ellipse(r, d, realign=false, circum=false, anchor=CENTER, spin=0) =
|
||||||
let(
|
let(
|
||||||
r = get_radius(r=r, d=d, dflt=1),
|
r = get_radius(r=r, d=d, dflt=1),
|
||||||
sides = segs(max(r)),
|
sides = segs(max(r)),
|
||||||
|
@ -290,7 +290,7 @@ function oval(r, d, realign=false, circum=false, anchor=CENTER, spin=0) =
|
||||||
// regular_ngon(n, ir=/id=, [realign=]);
|
// regular_ngon(n, ir=/id=, [realign=]);
|
||||||
// regular_ngon(n, side=, [realign=]);
|
// regular_ngon(n, side=, [realign=]);
|
||||||
// Topics: Shapes (2D), Paths (2D), Path Generators, Attachable
|
// Topics: Shapes (2D), Paths (2D), Path Generators, Attachable
|
||||||
// See Also: circle(), pentagon(), hexagon(), octagon(), oval(), star()
|
// See Also: circle(), pentagon(), hexagon(), octagon(), ellipse(), star()
|
||||||
// Description:
|
// Description:
|
||||||
// When called as a function, returns a 2D path for a regular N-sided polygon.
|
// When called as a function, returns a 2D path for a regular N-sided polygon.
|
||||||
// When called as a module, creates a 2D regular N-sided polygon.
|
// When called as a module, creates a 2D regular N-sided polygon.
|
||||||
|
@ -353,7 +353,7 @@ function regular_ngon(n=6, r, d, or, od, ir, id, side, rounding=0, realign=false
|
||||||
!is_undef(align_side)? rot(from=RIGHT, to=point2d(align_side), planar=true) * rot(180/n, planar=true) :
|
!is_undef(align_side)? rot(from=RIGHT, to=point2d(align_side), planar=true) * rot(180/n, planar=true) :
|
||||||
affine2d_identity()
|
affine2d_identity()
|
||||||
),
|
),
|
||||||
path4 = rounding==0? oval(r=r, $fn=n) : (
|
path4 = rounding==0? ellipse(r=r, $fn=n) : (
|
||||||
let(
|
let(
|
||||||
steps = floor(segs(r)/n),
|
steps = floor(segs(r)/n),
|
||||||
step = 360/n/steps,
|
step = 360/n/steps,
|
||||||
|
@ -426,7 +426,7 @@ module regular_ngon(n=6, r, d, or, od, ir, id, side, rounding=0, realign=false,
|
||||||
// pentagon(ir=|id=, [realign=]);
|
// pentagon(ir=|id=, [realign=]);
|
||||||
// pentagon(side=, [realign=]);
|
// pentagon(side=, [realign=]);
|
||||||
// Topics: Shapes (2D), Paths (2D), Path Generators, Attachable
|
// Topics: Shapes (2D), Paths (2D), Path Generators, Attachable
|
||||||
// See Also: circle(), regular_ngon(), hexagon(), octagon(), oval(), star()
|
// See Also: circle(), regular_ngon(), hexagon(), octagon(), ellipse(), star()
|
||||||
// Description:
|
// Description:
|
||||||
// When called as a function, returns a 2D path for a regular pentagon.
|
// When called as a function, returns a 2D path for a regular pentagon.
|
||||||
// When called as a module, creates a 2D regular pentagon.
|
// When called as a module, creates a 2D regular pentagon.
|
||||||
|
@ -490,7 +490,7 @@ module pentagon(r, d, or, od, ir, id, side, rounding=0, realign=false, align_tip
|
||||||
// path = hexagon(ir=/id=, ...);
|
// path = hexagon(ir=/id=, ...);
|
||||||
// path = hexagon(side=, ...);
|
// path = hexagon(side=, ...);
|
||||||
// Topics: Shapes (2D), Paths (2D), Path Generators, Attachable
|
// Topics: Shapes (2D), Paths (2D), Path Generators, Attachable
|
||||||
// See Also: circle(), regular_ngon(), pentagon(), octagon(), oval(), star()
|
// See Also: circle(), regular_ngon(), pentagon(), octagon(), ellipse(), star()
|
||||||
// Description:
|
// Description:
|
||||||
// When called as a function, returns a 2D path for a regular hexagon.
|
// When called as a function, returns a 2D path for a regular hexagon.
|
||||||
// When called as a module, creates a 2D regular hexagon.
|
// When called as a module, creates a 2D regular hexagon.
|
||||||
|
@ -554,7 +554,7 @@ module hexagon(r, d, or, od, ir, id, side, rounding=0, realign=false, align_tip,
|
||||||
// path = octagon(ir=/id=, ...);
|
// path = octagon(ir=/id=, ...);
|
||||||
// path = octagon(side=, ...);
|
// path = octagon(side=, ...);
|
||||||
// Topics: Shapes (2D), Paths (2D), Path Generators, Attachable
|
// Topics: Shapes (2D), Paths (2D), Path Generators, Attachable
|
||||||
// See Also: circle(), regular_ngon(), pentagon(), hexagon(), oval(), star()
|
// See Also: circle(), regular_ngon(), pentagon(), hexagon(), ellipse(), star()
|
||||||
// Description:
|
// Description:
|
||||||
// When called as a function, returns a 2D path for a regular octagon.
|
// When called as a function, returns a 2D path for a regular octagon.
|
||||||
// When called as a module, creates a 2D regular octagon.
|
// When called as a module, creates a 2D regular octagon.
|
||||||
|
@ -763,7 +763,7 @@ module trapezoid(h, w1, w2, angle, shift=0, chamfer=0, rounding=0, anchor=CENTER
|
||||||
// path = star(n, r/or, ir, [realign=], [align_tip=], [align_pit=], ...);
|
// path = star(n, r/or, ir, [realign=], [align_tip=], [align_pit=], ...);
|
||||||
// path = star(n, r/or, step=, ...);
|
// path = star(n, r/or, step=, ...);
|
||||||
// Topics: Shapes (2D), Paths (2D), Path Generators, Attachable
|
// Topics: Shapes (2D), Paths (2D), Path Generators, Attachable
|
||||||
// See Also: circle(), oval()
|
// See Also: circle(), ellipse()
|
||||||
// Description:
|
// Description:
|
||||||
// When called as a function, returns the path needed to create a star polygon with N points.
|
// When called as a function, returns the path needed to create a star polygon with N points.
|
||||||
// When called as a module, creates a star polygon with N points.
|
// When called as a module, creates a star polygon with N points.
|
||||||
|
@ -1020,7 +1020,7 @@ function teardrop2d(r, ang=45, cap_h, d, anchor=CENTER, spin=0) =
|
||||||
// Usage: As Function
|
// Usage: As Function
|
||||||
// path = glued_circles(r/d=, [spread=], [tangent=], ...);
|
// path = glued_circles(r/d=, [spread=], [tangent=], ...);
|
||||||
// Topics: Shapes (2D), Paths (2D), Path Generators, Attachable
|
// Topics: Shapes (2D), Paths (2D), Path Generators, Attachable
|
||||||
// See Also: circle(), oval()
|
// See Also: circle(), ellipse()
|
||||||
// Description:
|
// Description:
|
||||||
// When called as a function, returns a 2D path forming a shape of two circles joined by curved waist.
|
// When called as a function, returns a 2D path forming a shape of two circles joined by curved waist.
|
||||||
// When called as a module, creates a 2D shape of two circles joined by curved waist.
|
// When called as a module, creates a 2D shape of two circles joined by curved waist.
|
||||||
|
@ -1090,7 +1090,7 @@ function _superformula(theta,m1,m2,n1,n2=1,n3=1,a=1,b=1) =
|
||||||
// Usage: As Function
|
// Usage: As Function
|
||||||
// path = supershape(step, [m1=], [m2=], [n1=], [n2=], [n3=], [a=], [b=], <r=/d=>);
|
// path = supershape(step, [m1=], [m2=], [n1=], [n2=], [n3=], [a=], [b=], <r=/d=>);
|
||||||
// Topics: Shapes (2D), Paths (2D), Path Generators, Attachable
|
// Topics: Shapes (2D), Paths (2D), Path Generators, Attachable
|
||||||
// See Also: circle(), oval()
|
// See Also: circle(), ellipse()
|
||||||
// Description:
|
// Description:
|
||||||
// When called as a function, returns a 2D path for the outline of the [Superformula](https://en.wikipedia.org/wiki/Superformula) shape.
|
// When called as a function, returns a 2D path for the outline of the [Superformula](https://en.wikipedia.org/wiki/Superformula) shape.
|
||||||
// When called as a module, creates a 2D [Superformula](https://en.wikipedia.org/wiki/Superformula) shape.
|
// When called as a module, creates a 2D [Superformula](https://en.wikipedia.org/wiki/Superformula) shape.
|
||||||
|
|
|
@ -47,11 +47,11 @@ module test_trapezoid() {
|
||||||
test_trapezoid();
|
test_trapezoid();
|
||||||
|
|
||||||
|
|
||||||
module test_oval() {
|
module test_ellipse() {
|
||||||
assert_approx(oval(d=100,$fn=24), [[50,0],[48.2962913145,-12.9409522551],[43.3012701892,-25],[35.3553390593,-35.3553390593],[25,-43.3012701892],[12.9409522551,-48.2962913145],[0,-50],[-12.9409522551,-48.2962913145],[-25,-43.3012701892],[-35.3553390593,-35.3553390593],[-43.3012701892,-25],[-48.2962913145,-12.9409522551],[-50,0],[-48.2962913145,12.9409522551],[-43.3012701892,25],[-35.3553390593,35.3553390593],[-25,43.3012701892],[-12.9409522551,48.2962913145],[0,50],[12.9409522551,48.2962913145],[25,43.3012701892],[35.3553390593,35.3553390593],[43.3012701892,25],[48.2962913145,12.9409522551]]);
|
assert_approx(ellipse(d=100,$fn=24), [[50,0],[48.2962913145,-12.9409522551],[43.3012701892,-25],[35.3553390593,-35.3553390593],[25,-43.3012701892],[12.9409522551,-48.2962913145],[0,-50],[-12.9409522551,-48.2962913145],[-25,-43.3012701892],[-35.3553390593,-35.3553390593],[-43.3012701892,-25],[-48.2962913145,-12.9409522551],[-50,0],[-48.2962913145,12.9409522551],[-43.3012701892,25],[-35.3553390593,35.3553390593],[-25,43.3012701892],[-12.9409522551,48.2962913145],[0,50],[12.9409522551,48.2962913145],[25,43.3012701892],[35.3553390593,35.3553390593],[43.3012701892,25],[48.2962913145,12.9409522551]]);
|
||||||
assert_approx(oval(d=[100,80],$fn=24), [[50,0],[48.2962913145,-10.3527618041],[43.3012701892,-20],[35.3553390593,-28.2842712475],[25,-34.6410161514],[12.9409522551,-38.6370330516],[0,-40],[-12.9409522551,-38.6370330516],[-25,-34.6410161514],[-35.3553390593,-28.2842712475],[-43.3012701892,-20],[-48.2962913145,-10.3527618041],[-50,0],[-48.2962913145,10.3527618041],[-43.3012701892,20],[-35.3553390593,28.2842712475],[-25,34.6410161514],[-12.9409522551,38.6370330516],[0,40],[12.9409522551,38.6370330516],[25,34.6410161514],[35.3553390593,28.2842712475],[43.3012701892,20],[48.2962913145,10.3527618041]]);
|
assert_approx(ellipse(d=[100,80],$fn=24), [[50,0],[48.2962913145,-10.3527618041],[43.3012701892,-20],[35.3553390593,-28.2842712475],[25,-34.6410161514],[12.9409522551,-38.6370330516],[0,-40],[-12.9409522551,-38.6370330516],[-25,-34.6410161514],[-35.3553390593,-28.2842712475],[-43.3012701892,-20],[-48.2962913145,-10.3527618041],[-50,0],[-48.2962913145,10.3527618041],[-43.3012701892,20],[-35.3553390593,28.2842712475],[-25,34.6410161514],[-12.9409522551,38.6370330516],[0,40],[12.9409522551,38.6370330516],[25,34.6410161514],[35.3553390593,28.2842712475],[43.3012701892,20],[48.2962913145,10.3527618041]]);
|
||||||
}
|
}
|
||||||
test_oval();
|
test_ellipse();
|
||||||
|
|
||||||
|
|
||||||
module test_star() {
|
module test_star() {
|
||||||
|
|
Loading…
Reference in a new issue