mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2025-01-01 09:49:45 +00:00
Added spin and anchor to various 2D shapes.
This commit is contained in:
parent
c7d0be8ba5
commit
3b0a1a3383
4 changed files with 111 additions and 68 deletions
|
@ -98,7 +98,9 @@ function scale_points(pts, v=[0,0,0], cp=[0,0,0]) = [for (pt = pts) [for (i = [0
|
||||||
// pts = List of 3D points to rotate.
|
// pts = List of 3D points to rotate.
|
||||||
// ang = Angle to rotate by.
|
// ang = Angle to rotate by.
|
||||||
// cp = 2D Centerpoint to rotate around. Default: `[0,0]`
|
// cp = 2D Centerpoint to rotate around. Default: `[0,0]`
|
||||||
function rotate_points2d(pts, ang, cp=[0,0]) = let(
|
function rotate_points2d(pts, ang, cp=[0,0]) =
|
||||||
|
approx(ang,0)? pts :
|
||||||
|
let(
|
||||||
m = affine2d_zrot(ang)
|
m = affine2d_zrot(ang)
|
||||||
) [for (pt = pts) m*point3d(pt-cp)+cp];
|
) [for (pt = pts) m*point3d(pt-cp)+cp];
|
||||||
|
|
||||||
|
@ -155,7 +157,9 @@ function rotate_points3d(pts, a=0, v=undef, cp=[0,0,0], from=undef, to=undef, re
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
m = affine3d_translate(cp) * mrot * affine3d_translate(-cp)
|
m = affine3d_translate(cp) * mrot * affine3d_translate(-cp)
|
||||||
) [for (pt = pts) point3d(m*concat(point3d(pt),[1]))];
|
) (!is_undef(from) && approx(from,to))? pts :
|
||||||
|
(a==0 || a==[0,0,0])? pts :
|
||||||
|
[for (pt = pts) point3d(m*concat(point3d(pt),[1]))];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
162
shapes2d.scad
162
shapes2d.scad
|
@ -90,6 +90,8 @@ module stroke(path, width=1, endcaps=true, close=false)
|
||||||
// r = The radius of the circle to get a slice of.
|
// r = The radius of the circle to get a slice of.
|
||||||
// d = The diameter of the circle to get a slice of.
|
// d = The diameter of the circle to get a slice of.
|
||||||
// ang = The angle of the arc of the pie slice.
|
// ang = The angle of the arc of the pie slice.
|
||||||
|
// 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`
|
||||||
// Examples(2D):
|
// Examples(2D):
|
||||||
// pie_slice2d(r=50,ang=30);
|
// pie_slice2d(r=50,ang=30);
|
||||||
// pie_slice2d(d=100,ang=45);
|
// pie_slice2d(d=100,ang=45);
|
||||||
|
@ -97,18 +99,19 @@ module stroke(path, width=1, endcaps=true, close=false)
|
||||||
// pie_slice2d(d=40,ang=240);
|
// pie_slice2d(d=40,ang=240);
|
||||||
// Example(2D): Called as Function
|
// Example(2D): Called as Function
|
||||||
// stroke(close=true, pie_slice2d(r=50,ang=30));
|
// stroke(close=true, pie_slice2d(r=50,ang=30));
|
||||||
function pie_slice2d(r=undef, d=undef, ang=30) =
|
function pie_slice2d(r=undef, d=undef, ang=30, anchor=CENTER, spin=0) =
|
||||||
let(
|
let(
|
||||||
r = get_radius(r=r, d=d, dflt=10),
|
r = get_radius(r=r, d=d, dflt=10),
|
||||||
sides = ceil(segs(r)*ang/360)
|
sides = ceil(segs(r)*ang/360),
|
||||||
) concat(
|
path = concat(
|
||||||
[[0,0]],
|
[[0,0]],
|
||||||
[for (i=[0:1:sides]) let(a=i*ang/sides) r*[cos(a),sin(a)]]
|
[for (i=[0:1:sides]) let(a=i*ang/sides) r*[cos(a),sin(a)]]
|
||||||
);
|
)
|
||||||
|
) echo(r=r, path=path, anchor=anchor, na=normalize(anchor)) rot(spin, p=move(-r*normalize(anchor), p=path));
|
||||||
|
|
||||||
|
|
||||||
module pie_slice2d(r=undef, d=undef, ang=30) {
|
module pie_slice2d(r=undef, d=undef, ang=30, anchor=CENTER, spin=0) {
|
||||||
pts = pie_slice2d(r=r, d=d, ang=ang);
|
pts = pie_slice2d(r=r, d=d, ang=ang, anchor=anchor, spin=spin);
|
||||||
polygon(pts);
|
polygon(pts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,7 +133,7 @@ module pie_slice2d(r=undef, d=undef, ang=30) {
|
||||||
// If called as a function, returns a 2D or 3D path forming an arc.
|
// If called as a function, returns a 2D or 3D path forming an arc.
|
||||||
// If called as a module, creates a 2D arc polygon or pie slice shape.
|
// If called as a module, creates a 2D arc polygon or pie slice shape.
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// N = Number of line segments to form the arc curve from.
|
// N = Number of vertices to form the arc curve from.
|
||||||
// r = Radius of the arc.
|
// r = Radius of the arc.
|
||||||
// d = Diameter of the arc.
|
// d = Diameter of the arc.
|
||||||
// angle = If a scalar, specifies the end angle in degrees. If a vector of two scalars, specifies start and end angles.
|
// angle = If a scalar, specifies the end angle in degrees. If a vector of two scalars, specifies start and end angles.
|
||||||
|
@ -141,26 +144,23 @@ module pie_slice2d(r=undef, d=undef, ang=30) {
|
||||||
// start = Start angle of arc.
|
// start = Start angle of arc.
|
||||||
// wedge = If true, include centerpoint `cp` in output to form pie slice shape.
|
// wedge = If true, include centerpoint `cp` in output to form pie slice shape.
|
||||||
// Examples(2D):
|
// Examples(2D):
|
||||||
// arc(N=8, r=30, angle=30, wedge=true);
|
// arc(N=4, r=30, angle=30, wedge=true);
|
||||||
// arc(N=8, d=60, angle=30, wedge=true);
|
// arc(N=4, d=60, angle=30, wedge=true);
|
||||||
// arc(N=12, d=60, angle=120);
|
// arc(N=8, d=60, angle=120);
|
||||||
// arc(N=12, d=60, angle=120, wedge=true);
|
// arc(N=8, d=60, angle=120, wedge=true);
|
||||||
// arc(N=12, r=30, angle=[75,135], wedge=true);
|
// arc(N=12, r=30, angle=[75,135], wedge=true);
|
||||||
// arc(N=12, r=30, start=45, angle=75, wedge=true);
|
// arc(N=12, r=30, start=45, angle=75, wedge=true);
|
||||||
// arc(N=24, width=60, thickness=20);
|
// arc(N=12, width=60, thickness=20);
|
||||||
// arc(N=12, cp=[-10,5], points=[[20,10],[0,35]], wedge=true);
|
// arc(N=12, cp=[-10,5], points=[[20,10],[0,35]], wedge=true);
|
||||||
// arc(N=12, points=[[30,-5],[20,10],[-10,20]], wedge=true);
|
// arc(N=12, points=[[30,-5],[20,10],[-10,20]], wedge=true);
|
||||||
|
// arc(N=12, points=[[5,30],[-10,-10],[30,5]], wedge=true);
|
||||||
|
// Example(2D):
|
||||||
|
// path = arc(N=12, points=[[5,30],[-10,-10],[30,5]], wedge=true);
|
||||||
|
// stroke(close=true, path);
|
||||||
// Example(FlatSpin):
|
// Example(FlatSpin):
|
||||||
// include <BOSL2/paths.scad>
|
// include <BOSL2/paths.scad>
|
||||||
// path = arc(N=12, points=[[0,30,0],[0,0,30],[30,0,0]]);
|
// path = arc(N=12, points=[[0,30,0],[0,0,30],[30,0,0]]);
|
||||||
// trace_polyline(path, showpts=true, color="cyan");
|
// trace_polyline(path, showpts=true, color="cyan");
|
||||||
module arc(N, r, angle, d, cp, points, width, thickness, start, wedge=false)
|
|
||||||
{
|
|
||||||
path = arc(N=N, r=r, angle=angle, d=d, cp=cp, points=points, width=width, thickness=thickness, start=start, wedge=wedge);
|
|
||||||
polygon(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function arc(N, r, angle, d, cp, points, width, thickness, start, wedge=false) =
|
function arc(N, r, angle, d, cp, points, width, thickness, start, wedge=false) =
|
||||||
// First try for 2d arc specified by angles
|
// First try for 2d arc specified by angles
|
||||||
is_def(width) && is_def(thickness)? (
|
is_def(width) && is_def(thickness)? (
|
||||||
|
@ -172,7 +172,7 @@ function arc(N, r, angle, d, cp, points, width, thickness, start, wedge=false) =
|
||||||
)
|
)
|
||||||
assert(parmok,"Invalid parameters in arc")
|
assert(parmok,"Invalid parameters in arc")
|
||||||
let(
|
let(
|
||||||
cp = is_def(cp) ? cp : [0,0],
|
cp = is_def(cp) ? cp : [0,0],
|
||||||
start = is_def(start)? start : is_vector(angle) ? angle[0] : 0,
|
start = is_def(start)? start : is_vector(angle) ? angle[0] : 0,
|
||||||
angle = is_vector(angle)? angle[1]-angle[0] : angle,
|
angle = is_vector(angle)? angle[1]-angle[0] : angle,
|
||||||
r = get_radius(r=r,d=d),
|
r = get_radius(r=r,d=d),
|
||||||
|
@ -222,6 +222,13 @@ function arc(N, r, angle, d, cp, points, width, thickness, start, wedge=false) =
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
module arc(N, r, angle, d, cp, points, width, thickness, start, wedge=false)
|
||||||
|
{
|
||||||
|
path = arc(N=N, r=r, angle=angle, d=d, cp=cp, points=points, width=width, thickness=thickness, start=start, wedge=wedge);
|
||||||
|
polygon(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function _normal_segment(p1,p2) =
|
function _normal_segment(p1,p2) =
|
||||||
let(center = (p1+p2)/2)
|
let(center = (p1+p2)/2)
|
||||||
[center, center + norm(p1-p2)/2 * line_normal(p1,p2)];
|
[center, center + norm(p1-p2)/2 * line_normal(p1,p2)];
|
||||||
|
@ -237,18 +244,24 @@ function _normal_segment(p1,p2) =
|
||||||
// h = The Y axis height of the trapezoid.
|
// h = The Y axis height of the trapezoid.
|
||||||
// w1 = The X axis width of the front end of the trapezoid.
|
// w1 = The X axis width of the front end of the trapezoid.
|
||||||
// w2 = The X axis width of the back end of the trapezoid.
|
// w2 = The X axis width of the back end of the trapezoid.
|
||||||
|
// 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`
|
||||||
// Examples(2D):
|
// Examples(2D):
|
||||||
// trapezoid(h=30, w1=40, w2=20);
|
// trapezoid(h=30, w1=40, w2=20);
|
||||||
// trapezoid(h=25, w1=20, w2=35);
|
// trapezoid(h=25, w1=20, w2=35);
|
||||||
// trapezoid(h=20, w1=40, w2=0);
|
// trapezoid(h=20, w1=40, w2=0);
|
||||||
// Example(2D): Called as Function
|
// Example(2D): Called as Function
|
||||||
// stroke(close=true, trapezoid(h=30, w1=40, w2=20));
|
// stroke(close=true, trapezoid(h=30, w1=40, w2=20));
|
||||||
function trapezoid(h, w1, w2) =
|
function trapezoid(h, w1, w2, anchor=CENTER, spin=0) =
|
||||||
[[-w1/2,-h/2], [-w2/2,h/2], [w2/2,h/2], [w1/2,-h/2]];
|
let(
|
||||||
|
s = anchor.y>0? [w2,h] : anchor.y<0? [w1,h] : [(w1+w2)/2,h],
|
||||||
|
path = [[-w1/2,-h/2], [-w2/2,h/2], [w2/2,h/2], [w1/2,-h/2]]
|
||||||
|
) rot(spin, p=move(-vmul(anchor,s/2), p=path));
|
||||||
|
|
||||||
|
|
||||||
module trapezoid(h, w1, w2)
|
|
||||||
polygon(trapezoid(h=h, w1=w1, w2=w2));
|
module trapezoid(h, w1, w2, anchor=CENTER, spin=0)
|
||||||
|
polygon(trapezoid(h=h, w1=w1, w2=w2, anchor=anchor, spin=spin));
|
||||||
|
|
||||||
|
|
||||||
// Function&Module: regular_ngon()
|
// Function&Module: regular_ngon()
|
||||||
|
@ -267,6 +280,8 @@ module trapezoid(h, w1, w2)
|
||||||
// id = Inside diameter, at center of sides.
|
// id = Inside diameter, at center of sides.
|
||||||
// side = Length of each side.
|
// side = Length of each side.
|
||||||
// realign = If false, a tip is aligned with the Y+ axis. If true, the midpoint of a side is aligned with the Y+ axis. Default: false
|
// realign = If false, a tip is aligned with the Y+ axis. If true, the midpoint of a side is aligned with the Y+ axis. Default: false
|
||||||
|
// 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`
|
||||||
// Example(2D): by Outer Size
|
// Example(2D): by Outer Size
|
||||||
// regular_ngon(n=5, or=30);
|
// regular_ngon(n=5, or=30);
|
||||||
// regular_ngon(n=5, od=60);
|
// regular_ngon(n=5, od=60);
|
||||||
|
@ -279,16 +294,17 @@ module trapezoid(h, w1, w2)
|
||||||
// regular_ngon(n=8, side=20, realign=true);
|
// regular_ngon(n=8, side=20, realign=true);
|
||||||
// Example(2D): Called as Function
|
// Example(2D): Called as Function
|
||||||
// stroke(close=true, regular_ngon(n=6, or=30));
|
// stroke(close=true, regular_ngon(n=6, or=30));
|
||||||
function regular_ngon(n=6, or=undef, od=undef, ir=undef, id=undef, side=undef, realign=false) =
|
function regular_ngon(n=6, or=undef, od=undef, ir=undef, id=undef, side=undef, realign=false, anchor=CENTER, spin=0) =
|
||||||
let(
|
let(
|
||||||
sc = 1/cos(180/n),
|
sc = 1/cos(180/n),
|
||||||
r = get_radius(r1=ir*sc, r=or, d1=id*sc, d=od, dflt=side/2/sin(180/n)),
|
r = get_radius(r1=ir*sc, r=or, d1=id*sc, d=od, dflt=side/2/sin(180/n)),
|
||||||
offset = 90 + (realign? (180/n) : 0)
|
offset = 90 + (realign? (180/n) : 0),
|
||||||
) [for (a=[0:360/n:360-EPSILON]) r*[cos(a+offset),sin(a+offset)]];
|
path = [for (a=[0:360/n:360-EPSILON]) r*[cos(a+offset),sin(a+offset)]]
|
||||||
|
) rot(spin, p=move(-r*normalize(anchor), p=path));
|
||||||
|
|
||||||
|
|
||||||
module regular_ngon(n=6, or=undef, od=undef, ir=undef, id=undef, side=undef, realign=false)
|
module regular_ngon(n=6, or=undef, od=undef, ir=undef, id=undef, side=undef, realign=false, anchor=CENTER, spin=0)
|
||||||
polygon(regular_ngon(n=n,or=or,od=od,ir=ir,id=id,side=side,realign=realign));
|
polygon(regular_ngon(n=n,or=or,od=od,ir=ir,id=id,side=side,realign=realign, anchor=anchor, spin=spin));
|
||||||
|
|
||||||
|
|
||||||
// Function&Module: pentagon()
|
// Function&Module: pentagon()
|
||||||
|
@ -306,6 +322,8 @@ module regular_ngon(n=6, or=undef, od=undef, ir=undef, id=undef, side=undef, rea
|
||||||
// id = Inside diameter, at center of sides.
|
// id = Inside diameter, at center of sides.
|
||||||
// side = Length of each side.
|
// side = Length of each side.
|
||||||
// realign = If false, a tip is aligned with the Y+ axis. If true, the midpoint of a side is aligned with the Y+ axis. Default: false
|
// realign = If false, a tip is aligned with the Y+ axis. If true, the midpoint of a side is aligned with the Y+ axis. Default: false
|
||||||
|
// 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`
|
||||||
// Example(2D): by Outer Size
|
// Example(2D): by Outer Size
|
||||||
// pentagon(or=30);
|
// pentagon(or=30);
|
||||||
// pentagon(od=60);
|
// pentagon(od=60);
|
||||||
|
@ -318,12 +336,12 @@ module regular_ngon(n=6, or=undef, od=undef, ir=undef, id=undef, side=undef, rea
|
||||||
// pentagon(side=20, realign=true);
|
// pentagon(side=20, realign=true);
|
||||||
// Example(2D): Called as Function
|
// Example(2D): Called as Function
|
||||||
// stroke(close=true, pentagon(or=30));
|
// stroke(close=true, pentagon(or=30));
|
||||||
function pentagon(or=undef, od=undef, ir=undef, id=undef, side=undef, realign=false) =
|
function pentagon(or=undef, od=undef, ir=undef, id=undef, side=undef, realign=false, anchor=CENTER, spin=0) =
|
||||||
regular_ngon(n=5, or=or, od=od, ir=ir, id=id, side=side, realign=realign);
|
regular_ngon(n=5, or=or, od=od, ir=ir, id=id, side=side, realign=realign, anchor=anchor, spin=spin);
|
||||||
|
|
||||||
|
|
||||||
module pentagon(or=undef, od=undef, ir=undef, id=undef, side=undef, realign=false)
|
module pentagon(or=undef, od=undef, ir=undef, id=undef, side=undef, realign=false, anchor=CENTER, spin=0)
|
||||||
polygon(pentagon(or=or, od=od, ir=ir, id=id, side=side, realign=realign));
|
polygon(pentagon(or=or, od=od, ir=ir, id=id, side=side, realign=realign, anchor=anchor, spin=spin));
|
||||||
|
|
||||||
|
|
||||||
// Function&Module: hexagon()
|
// Function&Module: hexagon()
|
||||||
|
@ -339,6 +357,8 @@ module pentagon(or=undef, od=undef, ir=undef, id=undef, side=undef, realign=fals
|
||||||
// id = Inside diameter, at center of sides.
|
// id = Inside diameter, at center of sides.
|
||||||
// side = Length of each side.
|
// side = Length of each side.
|
||||||
// realign = If false, a tip is aligned with the Y+ axis. If true, the midpoint of a side is aligned with the Y+ axis. Default: false
|
// realign = If false, a tip is aligned with the Y+ axis. If true, the midpoint of a side is aligned with the Y+ axis. Default: false
|
||||||
|
// 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`
|
||||||
// Example(2D): by Outer Size
|
// Example(2D): by Outer Size
|
||||||
// hexagon(or=30);
|
// hexagon(or=30);
|
||||||
// hexagon(od=60);
|
// hexagon(od=60);
|
||||||
|
@ -351,12 +371,12 @@ module pentagon(or=undef, od=undef, ir=undef, id=undef, side=undef, realign=fals
|
||||||
// hexagon(side=20, realign=true);
|
// hexagon(side=20, realign=true);
|
||||||
// Example(2D): Called as Function
|
// Example(2D): Called as Function
|
||||||
// stroke(close=true, hexagon(or=30));
|
// stroke(close=true, hexagon(or=30));
|
||||||
function hexagon(or=undef, od=undef, ir=undef, id=undef, side=undef, realign=false) =
|
function hexagon(or=undef, od=undef, ir=undef, id=undef, side=undef, realign=false, anchor=CENTER, spin=0) =
|
||||||
regular_ngon(n=6, or=or, od=od, ir=ir, id=id, side=side, realign=realign);
|
regular_ngon(n=6, or=or, od=od, ir=ir, id=id, side=side, realign=realign, anchor=anchor, spin=spin);
|
||||||
|
|
||||||
|
|
||||||
module hexagon(or=undef, od=undef, ir=undef, id=undef, side=undef, realign=false)
|
module hexagon(or=undef, od=undef, ir=undef, id=undef, side=undef, realign=false, anchor=CENTER, spin=0)
|
||||||
polygon(hexagon(or=or, od=od, ir=ir, id=id, side=side, realign=realign));
|
polygon(hexagon(or=or, od=od, ir=ir, id=id, side=side, realign=realign, anchor=anchor, spin=spin));
|
||||||
|
|
||||||
|
|
||||||
// Function&Module: octagon()
|
// Function&Module: octagon()
|
||||||
|
@ -372,6 +392,8 @@ module hexagon(or=undef, od=undef, ir=undef, id=undef, side=undef, realign=false
|
||||||
// id = Inside diameter, at center of sides.
|
// id = Inside diameter, at center of sides.
|
||||||
// side = Length of each side.
|
// side = Length of each side.
|
||||||
// realign = If false, a tip is aligned with the Y+ axis. If true, the midpoint of a side is aligned with the Y+ axis. Default: false
|
// realign = If false, a tip is aligned with the Y+ axis. If true, the midpoint of a side is aligned with the Y+ axis. Default: false
|
||||||
|
// 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`
|
||||||
// Example(2D): by Outer Size
|
// Example(2D): by Outer Size
|
||||||
// octagon(or=30);
|
// octagon(or=30);
|
||||||
// octagon(od=60);
|
// octagon(od=60);
|
||||||
|
@ -384,12 +406,12 @@ module hexagon(or=undef, od=undef, ir=undef, id=undef, side=undef, realign=false
|
||||||
// octagon(side=20, realign=true);
|
// octagon(side=20, realign=true);
|
||||||
// Example(2D): Called as Function
|
// Example(2D): Called as Function
|
||||||
// stroke(close=true, octagon(or=30));
|
// stroke(close=true, octagon(or=30));
|
||||||
function octagon(or=undef, od=undef, ir=undef, id=undef, side=undef, realign=false) =
|
function octagon(or=undef, od=undef, ir=undef, id=undef, side=undef, realign=false, anchor=CENTER, spin=0) =
|
||||||
regular_ngon(n=8, or=or, od=od, ir=ir, id=id, side=side, realign=realign);
|
regular_ngon(n=8, or=or, od=od, ir=ir, id=id, side=side, realign=realign, anchor=anchor, spin=spin);
|
||||||
|
|
||||||
|
|
||||||
module octagon(or=undef, od=undef, ir=undef, id=undef, side=undef, realign=false)
|
module octagon(or=undef, od=undef, ir=undef, id=undef, side=undef, realign=false, anchor=CENTER, spin=0)
|
||||||
polygon(octagon(or=or, od=od, ir=ir, id=id, side=side, realign=realign));
|
polygon(octagon(or=or, od=od, ir=ir, id=id, side=side, realign=realign, anchor=anchor, spin=spin));
|
||||||
|
|
||||||
|
|
||||||
// Function&Module: glued_circles()
|
// Function&Module: glued_circles()
|
||||||
|
@ -403,6 +425,8 @@ module octagon(or=undef, od=undef, ir=undef, id=undef, side=undef, realign=false
|
||||||
// d = The diameter of the end circles.
|
// d = The diameter of the end circles.
|
||||||
// spread = The distance between the centers of the end circles.
|
// spread = The distance between the centers of the end circles.
|
||||||
// tangent = The angle in degrees of the tangent point for the joining arcs, measured away from the Y axis.
|
// tangent = The angle in degrees of the tangent point for the joining arcs, measured away from the Y axis.
|
||||||
|
// 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`
|
||||||
// Examples(2D):
|
// Examples(2D):
|
||||||
// glued_circles(r=15, spread=40, tangent=45);
|
// glued_circles(r=15, spread=40, tangent=45);
|
||||||
// glued_circles(d=30, spread=30, tangent=30);
|
// glued_circles(d=30, spread=30, tangent=30);
|
||||||
|
@ -410,7 +434,7 @@ module octagon(or=undef, od=undef, ir=undef, id=undef, side=undef, realign=false
|
||||||
// glued_circles(d=30, spread=30, tangent=-30);
|
// glued_circles(d=30, spread=30, tangent=-30);
|
||||||
// Example(2D): Called as Function
|
// Example(2D): Called as Function
|
||||||
// stroke(close=true, glued_circles(r=15, spread=40, tangent=45));
|
// stroke(close=true, glued_circles(r=15, spread=40, tangent=45));
|
||||||
function glued_circles(r=undef, d=undef, spread=10, tangent=30) =
|
function glued_circles(r=undef, d=undef, spread=10, tangent=30, anchor=CENTER, spin=0) =
|
||||||
let(
|
let(
|
||||||
r = get_radius(r=r, d=d, dflt=10),
|
r = get_radius(r=r, d=d, dflt=10),
|
||||||
r2 = (spread/2 / sin(tangent)) - r,
|
r2 = (spread/2 / sin(tangent)) - r,
|
||||||
|
@ -425,17 +449,19 @@ function glued_circles(r=undef, d=undef, spread=10, tangent=30) =
|
||||||
ea2 = 270+tangent,
|
ea2 = 270+tangent,
|
||||||
subarc = ea2-sa2,
|
subarc = ea2-sa2,
|
||||||
arcsegs = ceil(segs(r2)*abs(subarc)/360),
|
arcsegs = ceil(segs(r2)*abs(subarc)/360),
|
||||||
arcstep = subarc / arcsegs
|
arcstep = subarc / arcsegs,
|
||||||
) concat(
|
s = [spread/2+r, r],
|
||||||
[for (i=[0:1:lobesegs]) let(a=sa1+i*lobestep) r * [cos(a),sin(a)] - cp1],
|
path = concat(
|
||||||
tangent==0? [] : [for (i=[0:1:arcsegs]) let(a=ea2-i*arcstep+180) r2 * [cos(a),sin(a)] - cp2],
|
[for (i=[0:1:lobesegs]) let(a=sa1+i*lobestep) r * [cos(a),sin(a)] - cp1],
|
||||||
[for (i=[0:1:lobesegs]) let(a=sa1+i*lobestep+180) r * [cos(a),sin(a)] + cp1],
|
tangent==0? [] : [for (i=[0:1:arcsegs]) let(a=ea2-i*arcstep+180) r2 * [cos(a),sin(a)] - cp2],
|
||||||
tangent==0? [] : [for (i=[0:1:arcsegs]) let(a=ea2-i*arcstep) r2 * [cos(a),sin(a)] + cp2]
|
[for (i=[0:1:lobesegs]) let(a=sa1+i*lobestep+180) r * [cos(a),sin(a)] + cp1],
|
||||||
);
|
tangent==0? [] : [for (i=[0:1:arcsegs]) let(a=ea2-i*arcstep) r2 * [cos(a),sin(a)] + cp2]
|
||||||
|
)
|
||||||
|
) rot(spin, p=move(-vmul(anchor,s), p=path));
|
||||||
|
|
||||||
|
|
||||||
module glued_circles(r=undef, d=undef, spread=10, tangent=30)
|
module glued_circles(r=undef, d=undef, spread=10, tangent=30, anchor=CENTER, spin=0)
|
||||||
polygon(glued_circles(r=r, d=d, spread=spread, tangent=tangent));
|
polygon(glued_circles(r=r, d=d, spread=spread, tangent=tangent, anchor=anchor, spin=spin));
|
||||||
|
|
||||||
|
|
||||||
// Function&Module: star()
|
// Function&Module: star()
|
||||||
|
@ -452,6 +478,8 @@ module glued_circles(r=undef, d=undef, spread=10, tangent=30)
|
||||||
// id = The diameter to the inner corners of the star.
|
// id = The diameter to the inner corners of the star.
|
||||||
// step = Calculates the radius of the inner star corners by virtually drawing a straight line `step` tips around the star. 2 <= step < n/2
|
// step = Calculates the radius of the inner star corners by virtually drawing a straight line `step` tips around the star. 2 <= step < n/2
|
||||||
// realign = If false, a tip is aligned with the Y+ axis. If true, an inner corner is aligned with the Y+ axis. Default: false
|
// realign = If false, a tip is aligned with the Y+ axis. If true, an inner corner is aligned with the Y+ axis. Default: false
|
||||||
|
// 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`
|
||||||
// Examples(2D):
|
// Examples(2D):
|
||||||
// star(n=5, r=50, ir=25);
|
// star(n=5, r=50, ir=25);
|
||||||
// star(n=5, r=50, step=2);
|
// star(n=5, r=50, step=2);
|
||||||
|
@ -461,7 +489,7 @@ module glued_circles(r=undef, d=undef, spread=10, tangent=30)
|
||||||
// star(n=7, r=50, step=3, realign=true);
|
// star(n=7, r=50, step=3, realign=true);
|
||||||
// Example(2D): Called as Function
|
// Example(2D): Called as Function
|
||||||
// stroke(close=true, star(n=5, r=50, ir=25));
|
// stroke(close=true, star(n=5, r=50, ir=25));
|
||||||
function star(n, r, d, ir, id, step, realign=false) =
|
function star(n, r, d, ir, id, step, realign=false, anchor=CENTER, spin=0) =
|
||||||
let(
|
let(
|
||||||
r = get_radius(r=r, d=d),
|
r = get_radius(r=r, d=d),
|
||||||
count = num_defined([ir,id,step]),
|
count = num_defined([ir,id,step]),
|
||||||
|
@ -472,13 +500,13 @@ function star(n, r, d, ir, id, step, realign=false) =
|
||||||
let(
|
let(
|
||||||
stepr = is_undef(step)? r : r*cos(180*step/n)/cos(180*(step-1)/n),
|
stepr = is_undef(step)? r : r*cos(180*step/n)/cos(180*(step-1)/n),
|
||||||
ir = get_radius(r=ir, d=id, dflt=stepr),
|
ir = get_radius(r=ir, d=id, dflt=stepr),
|
||||||
offset = 90+(realign? 180/n : 0)
|
offset = 90+(realign? 180/n : 0),
|
||||||
)
|
path = [for(i=[0:1:2*n-1]) let(theta=180*i/n+offset, radius=(i%2)?ir:r) radius*[cos(theta), sin(theta)]]
|
||||||
[for(i=[0:1:2*n-1]) let(theta=180*i/n+offset, radius=(i%2)?ir:r) radius*[cos(theta), sin(theta)]];
|
) rot(spin, p=move(-r*normalize(anchor), p=path));
|
||||||
|
|
||||||
|
|
||||||
module star(n, r, d, ir, id, step, realign=false)
|
module star(n, r, d, ir, id, step, realign=false, anchor=CENTER, spin=0)
|
||||||
polygon(star(n=n, r=r, d=d, ir=ir, id=id, step=step, realign=realign));
|
polygon(star(n=n, r=r, d=d, ir=ir, id=id, step=step, realign=realign, anchor=anchor, spin=spin));
|
||||||
|
|
||||||
|
|
||||||
function _superformula(theta,m1,m2,n1,n2=1,n3=1,a=1,b=1) =
|
function _superformula(theta,m1,m2,n1,n2=1,n3=1,a=1,b=1) =
|
||||||
|
@ -501,16 +529,24 @@ function _superformula(theta,m1,m2,n1,n2=1,n3=1,a=1,b=1) =
|
||||||
// n3 = The n3 argument for the superformula.
|
// n3 = The n3 argument for the superformula.
|
||||||
// a = The a argument for the superformula.
|
// a = The a argument for the superformula.
|
||||||
// b = The b argument for the superformula.
|
// b = The b argument for the superformula.
|
||||||
|
// 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`
|
||||||
// Example(2D):
|
// Example(2D):
|
||||||
// superformula_shape(step=0.5,scale=100,m1=16,m2=16,n1=0.5,n2=0.5,n3=16);
|
// superformula_shape(step=0.5,scale=100,m1=16,m2=16,n1=0.5,n2=0.5,n3=16);
|
||||||
// Example(2D): Called as Function
|
// Example(2D): Called as Function
|
||||||
// stroke(close=true, superformula_shape(step=0.5,scale=100,m1=16,m2=16,n1=0.5,n2=0.5,n3=16));
|
// stroke(close=true, superformula_shape(step=0.5,scale=100,m1=16,m2=16,n1=0.5,n2=0.5,n3=16));
|
||||||
function superformula_shape(step=0.5,scale=1,m1,m2,n1,n2=1,n3=1,a=1,b=1) =
|
function superformula_shape(step=0.5,scale=1,m1,m2,n1,n2=1,n3=1,a=1,b=1, anchor=CENTER, spin=0) =
|
||||||
[for (a=[0:step:360]) let(r=scale*_superformula(theta=a,m1=m1,m2=m2,n1=n1,n2=n2,n3=n3)) r*[cos(a),sin(a)]];
|
let(
|
||||||
|
steps = ceil(360/step),
|
||||||
|
step = 360/steps,
|
||||||
|
angs = [for (i = [0:steps-1]) step*i],
|
||||||
|
rads = [for (a = angs) scale*_superformula(theta=a,m1=m1,m2=m2,n1=n1,n2=n2,n3=n3)],
|
||||||
|
path = [for (i = [0:steps-1]) let(a=angs[i]) rads[i]*[cos(a), sin(a)]]
|
||||||
|
) rot(spin, p=move(-max(rads)*normalize(anchor), p=path));
|
||||||
|
|
||||||
|
|
||||||
module superformula_shape(step=0.5,scale=1,m1,m2,n1,n2=1,n3=1,a=1,b=1)
|
module superformula_shape(step=0.5,scale=1,m1,m2,n1,n2=1,n3=1,a=1,b=1, anchor=CENTER, spin=0)
|
||||||
polygon(superformula_shape(step=step,scale=scale,m1=m1,m2=m2,n1=n1,n2=n2,n3=n3,a=a,b=b));
|
polygon(superformula_shape(step=step,scale=scale,m1=m1,m2=m2,n1=n1,n2=n2,n3=n3,a=a,b=b, anchor=anchor, spin=spin));
|
||||||
|
|
||||||
|
|
||||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||||
|
|
|
@ -284,8 +284,10 @@ function rot(a=0, v=undef, cp=undef, from=undef, to=undef, reverse=false, p=unde
|
||||||
rot(a=a, v=v, cp=cp, from=from, to=to, reverse=reverse, p=[p], planar=planar)[0]
|
rot(a=a, v=v, cp=cp, from=from, to=to, reverse=reverse, p=[p], planar=planar)[0]
|
||||||
) : (
|
) : (
|
||||||
planar? (
|
planar? (
|
||||||
is_undef(from)? rotate_points2d(p, a=ang*rev, cp=cp) :
|
is_undef(from)? rotate_points2d(p, a=ang*rev, cp=cp) : (
|
||||||
rotate_points2d(p, ang=vector_angle(from,to)*sign(vector_axis(from,to)[2])*rev, cp=cp)
|
approx(from,to)? p :
|
||||||
|
rotate_points2d(p, ang=vector_angle(from,to)*sign(vector_axis(from,to)[2])*rev, cp=cp)
|
||||||
|
)
|
||||||
) : (
|
) : (
|
||||||
rotate_points3d(p, a=a, v=v, cp=(is_undef(cp)? [0,0,0] : cp), from=from, to=to, reverse=reverse)
|
rotate_points3d(p, a=a, v=v, cp=(is_undef(cp)? [0,0,0] : cp), from=from, to=to, reverse=reverse)
|
||||||
)
|
)
|
||||||
|
|
|
@ -53,9 +53,10 @@ function vabs(v) = [for (x=v) abs(x)];
|
||||||
// Function: normalize()
|
// Function: normalize()
|
||||||
// Description:
|
// Description:
|
||||||
// Returns unit length normalized version of vector v.
|
// Returns unit length normalized version of vector v.
|
||||||
|
// If passed a zero-length vector, returns the unchanged vector.
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// v = The vector to normalize.
|
// v = The vector to normalize.
|
||||||
function normalize(v) = v/norm(v);
|
function normalize(v) = v==[0,0,0]? v : v/norm(v);
|
||||||
|
|
||||||
|
|
||||||
// Function: vquant()
|
// Function: vquant()
|
||||||
|
|
Loading…
Reference in a new issue