From c790969cebd98de53bafd5b82830bba66f144374 Mon Sep 17 00:00:00 2001 From: Garth Minette Date: Mon, 11 Jan 2021 01:57:51 -0800 Subject: [PATCH] Added reuleaux_polygon() --- shapes2d.scad | 58 ++++++++++++++++++++++++++++++++++++++++ tests/test_shapes2d.scad | 9 +++++++ version.scad | 2 +- 3 files changed, 68 insertions(+), 1 deletion(-) diff --git a/shapes2d.scad b/shapes2d.scad index 91e1ab2..baee3ff 100644 --- a/shapes2d.scad +++ b/shapes2d.scad @@ -1590,6 +1590,64 @@ module supershape(step=0.5,m1=4,m2=undef,n1,n2=undef,n3=undef,a=1,b=undef, r=und } +// Function&Module: reuleaux_polygon() +// Usage: As Module +// reuleaux_polygon(N, r|d); +// Usage: As Module +// path = reuleaux_polygon(N, r|d); +// Description: +// Creates a 2D Reuleaux Polygon; a constant width shape that is not circular. +// Arguments: +// N = Number of "sides" to the Reuleaux Polygon. Must be an odd positive number. Default: 3 +// r = Radius of the shape. Scale shape to fit in a circle of radius r. +// d = Diameter of the shape. Scale shape to fit in a circle of diameter d. +// 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` +// Extra Anchors: +// "tip0", "tip1", etc. = Each tip has an anchor, pointing outwards. +// Examples(2D): +// reuleaux_polygon(N=3, r=50); +// reuleaux_polygon(N=5, d=100); +module reuleaux_polygon(N=3, r, d, anchor=CENTER, spin=0) { + assert(N>=3 && (N%2)==1); + r = get_radius(r=r, d=d, dflt=1); + path = reuleaux_polygon(N=N, r=r); + anchors = [ + for (i = [0:1:N-1]) let( + ca = 360 - (i+0.5) * 360/N, + cp = polar_to_xy(r, ca) + ) anchorpt(str("tip",i), cp, unit(cp,BACK), 0), + ]; + attachable(anchor,spin, two_d=true, path=path, anchors=anchors) { + polygon(path); + children(); + } +} + + +function reuleaux_polygon(N=3, r, d, anchor=CENTER, spin=0) = + assert(N>=3 && (N%2)==1) + let( + r = get_radius(r=r, d=d, dflt=1), + ssegs = max(3,ceil(segs(r)/N)), + slen = norm(polar_to_xy(r,0)-polar_to_xy(r,180-180/N)), + path = [ + for (i = [0:1:N-1]) let( + ca = 180 - (i+0.5) * 360/N, + sa = ca + 180 + (90/N), + ea = ca + 180 - (90/N), + cp = polar_to_xy(r, ca) + ) each arc(N=ssegs, r=slen, cp=cp, angle=[sa,ea], endpoint=false) + ], + anchors = [ + for (i = [0:1:N-1]) let( + ca = 360 - (i+0.5) * 360/N, + cp = polar_to_xy(r, ca) + ) anchorpt(str("tip",i), cp, unit(cp,BACK), 0), + ] + ) reorient(anchor,spin, two_d=true, path=path, anchors=anchors, p=path); + + // Section: 2D Masking Shapes // Function&Module: mask2d_roundover() diff --git a/tests/test_shapes2d.scad b/tests/test_shapes2d.scad index 625b99c..c13a33d 100644 --- a/tests/test_shapes2d.scad +++ b/tests/test_shapes2d.scad @@ -142,6 +142,15 @@ module test_supershape() { test_supershape(); +module test_reuleaux_polygon() { + $fn=36; + assert_approx(reuleaux_polygon(N=3, r=50),[[50,0],[45.5443467787,-6.93313174371],[40.449833029,-13.4113329645],[34.7625954562,-19.375936069],[28.5341385645,-24.7729246878],[21.8208682239,-29.5534228563],[14.6835808504,-33.6741376427],[7.18691282348,-37.0977512159],[-0.601244870218,-39.7932588011],[-8.61036146861,-41.7362494642],[-16.7679051715,-42.909127181],[-25,-43.3012701892],[-28.7764416072,-35.9759954373],[-31.8394715604,-28.3249164997],[-34.161350586,-20.417322732],[-35.7210513879,-12.324826528],[-36.5044490743,-4.12071478641],[-36.5044490743,4.12071478641],[-35.7210513879,12.324826528],[-34.161350586,20.417322732],[-31.8394715604,28.3249164997],[-28.7764416072,35.9759954373],[-25,43.3012701892],[-16.7679051715,42.909127181],[-8.61036146861,41.7362494642],[-0.601244870218,39.7932588011],[7.18691282348,37.0977512159],[14.6835808504,33.6741376427],[21.8208682239,29.5534228563],[28.5341385645,24.7729246878],[34.7625954562,19.375936069],[40.449833029,13.4113329645],[45.5443467787,6.93313174371]]); + assert_approx(reuleaux_polygon(N=3, d=100),[[50,0],[45.5443467787,-6.93313174371],[40.449833029,-13.4113329645],[34.7625954562,-19.375936069],[28.5341385645,-24.7729246878],[21.8208682239,-29.5534228563],[14.6835808504,-33.6741376427],[7.18691282348,-37.0977512159],[-0.601244870218,-39.7932588011],[-8.61036146861,-41.7362494642],[-16.7679051715,-42.909127181],[-25,-43.3012701892],[-28.7764416072,-35.9759954373],[-31.8394715604,-28.3249164997],[-34.161350586,-20.417322732],[-35.7210513879,-12.324826528],[-36.5044490743,-4.12071478641],[-36.5044490743,4.12071478641],[-35.7210513879,12.324826528],[-34.161350586,20.417322732],[-31.8394715604,28.3249164997],[-28.7764416072,35.9759954373],[-25,43.3012701892],[-16.7679051715,42.909127181],[-8.61036146861,41.7362494642],[-0.601244870218,39.7932588011],[7.18691282348,37.0977512159],[14.6835808504,33.6741376427],[21.8208682239,29.5534228563],[28.5341385645,24.7729246878],[34.7625954562,19.375936069],[40.449833029,13.4113329645],[45.5443467787,6.93313174371]]); + assert_approx(reuleaux_polygon(N=5, d=100),[[50,0],[47.0014382812,-7.98963912753],[43.2987621605,-15.6783253167],[38.921783409,-23.0041537871],[33.9057428858,-29.9081412755],[28.2910268,-36.3347009341],[22.122841544,-42.2320898832],[15.4508497187,-47.5528258148],[6.92564483387,-47.1699584219],[-1.53092011402,-46.0244388665],[-9.85075783633,-44.1254901984],[-17.9668818917,-41.4884016357],[-25.8139460215,-38.134405465],[-33.3287702792,-34.0905060913],[-40.4508497187,-29.3892626146],[-42.7211543799,-21.1629984251],[-44.2449228251,-12.7663422159],[-45.0098865668,-4.26689892573],[-45.0098865668,4.26689892573],[-44.2449228251,12.7663422159],[-42.7211543799,21.1629984251],[-40.4508497187,29.3892626146],[-33.3287702792,34.0905060913],[-25.8139460215,38.134405465],[-17.9668818917,41.4884016357],[-9.85075783633,44.1254901984],[-1.53092011402,46.0244388665],[6.92564483387,47.1699584219],[15.4508497187,47.5528258148],[22.122841544,42.2320898832],[28.2910268,36.3347009341],[33.9057428858,29.9081412755],[38.921783409,23.0041537871],[43.2987621605,15.6783253167],[47.0014382812,7.98963912753]]); +} +test_reuleaux_polygon(); + + module test_mask2d_chamfer() { assert_approx(mask2d_chamfer(x=10),[[10,-0.01],[-0.01,-0.01],[-0.01,10],[0,10],[10,0]]); assert_approx(mask2d_chamfer(y=10),[[10,-0.01],[-0.01,-0.01],[-0.01,10],[0,10],[10,0]]); diff --git a/version.scad b/version.scad index a3333e1..014b31b 100644 --- a/version.scad +++ b/version.scad @@ -6,7 +6,7 @@ ////////////////////////////////////////////////////////////////////// -BOSL_VERSION = [2,0,522]; +BOSL_VERSION = [2,0,523]; // Section: BOSL Library Version Functions