Last active
July 10, 2022 22:54
-
-
Save ednisley/1d80ea1681372d4f76c5b390349f6ca6 to your computer and use it in GitHub Desktop.
Bash and GCMC source code: Laser cutter marquetry / coaster test piece generator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# Marquetry test piece | |
# Ed Nisley KE4ZNU - 2022-07-01 | |
Flags='-P 4 --pedantic' # quote to avoid leading hyphen gotcha | |
SVGFlags='-P 4 --pedantic --svg --svg-no-movelayer --svg-opacity=1.0 --svg-toolwidth=0.2' | |
# Set these to match your file layout | |
ProjPath='/mnt/bulkdata/Project Files/Laser Cutter/Marquetry/Source Code' | |
LibPath='/opt/gcmc/library' | |
ScriptPath=$ProjPath | |
Script='Marquetry Test Piece.gcmc' | |
leaves="NumLeaves=$1" | |
aspect="LeafAspect=$2" | |
fn=Marq-$1-$2.svg | |
echo Output: $fn | |
gcmc $SVGFlags -D "$leaves" -D "$aspect" \ | |
--include "$LibPath" \ | |
"$ScriptPath"/"$Script" > "$fn" | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Marquetry Laser Cuttery Test Piece | |
// Ed Nisley KE4ZNU | |
// 2022-07-01 Simplest possible mandala | |
layerstack("Frame","Leaves","Rim","Base","Center","Tool1"); // SVG layers map to LightBurn colors | |
//----- | |
// Library routines | |
include("tracepath.inc.gcmc"); | |
include("tracepath_comp.inc.gcmc"); | |
include("varcs.inc.gcmc"); | |
include("engrave.inc.gcmc"); | |
FALSE = 0; | |
TRUE = !FALSE; | |
//----- | |
// Command line parameters | |
// -D various useful tidbits | |
// add unit to speeds and depths: 2000mm / -3.00mm / etc | |
if (!isdefined("OuterDia")) { | |
OuterDia = 120.0mm; | |
} | |
if (!isdefined("CenterDia")) { | |
CenterDia = 20.0mm; | |
} | |
if (!isdefined("NumLeaves")) { | |
NumLeaves = 5; | |
} | |
if (!isdefined("Sash")) { | |
Sash = 4.0mm; | |
} | |
if (!isdefined("LeafAspect")) { | |
LeafAspect = 0.40; | |
} | |
// Leaf values | |
LeafStemAngle = 360.0deg/NumLeaves; // subtended by inner sides | |
LeafStemHA = LeafStemAngle/2; | |
LeafLength = OuterDia/2 - Sash - (Sash/2)/sin(LeafStemHA); | |
LeafWidth = LeafAspect*LeafLength; | |
L1 = (LeafWidth/2)/tan(LeafStemHA); | |
L2 = LeafLength - L1; | |
// message("Len: ",LeafLength," L1: ",L1," L2: ",L2); | |
LeafTipHA = to_deg(atan(LeafWidth/2,L2)); // subtended by outer sides | |
LeafTipAngle = 2*LeafTipHA; | |
// message("Width: ",LeafWidth); | |
// message("Tip HA: ",LeafTipHA); | |
LeafID = CenterDia + 2*Sash; | |
LeafOD = LeafID + LeafLength; | |
// message("ID: ",LeafID," OD: ",LeafOD); | |
// Find leaf and rim vertices | |
P0 = [(Sash/2) / sin(LeafStemHA),0.0mm]; | |
if (P0.x < LeafID/2) { | |
a = 1 + pow(tan(LeafStemHA),2); | |
b = -2 * tan(LeafStemHA) * (Sash/2) / cos(LeafStemHA); | |
c = pow((Sash/2) / cos(LeafStemHA),2) - pow(LeafID/2,2); | |
// message("a: ",a); | |
// message("b: ",b); | |
// message("c: ",c); | |
xp = (-b + sqrt(pow(b,2) - 4*a*c))/(2*a); | |
xn = (-b - sqrt(pow(b,2) - 4*a*c))/(2*a); | |
y = xp*tan(LeafStemHA) - (Sash/2) / cos(LeafStemHA); | |
// message("p: ",xp," n: ",xn," y: ",y); | |
P1 = [xp,y]; | |
} | |
else { | |
P1 = P0; | |
} | |
P2 = P0 + [L1,LeafWidth/2]; | |
P3 = P0 + [LeafLength,0mm]; | |
P4 = P3 + [Sash/sin(LeafTipHA),0.0mm]; | |
P5r = P4.x * sin(LeafTipHA) / sin(180deg - LeafStemHA - LeafTipHA); | |
P5 = rotate_xy([P5r,0.0mm],LeafStemHA); | |
P6 = rotate_xy(P4,LeafStemAngle); | |
t2 = pow(tan(-LeafTipHA),2); | |
a = 1 + t2; | |
b = -2 * t2 * P4.x; | |
c = t2 * pow(P4.x,2) - pow(P3.x,2); | |
xp = (-b + sqrt(pow(b,2) - 4*a*c))/(2*a); | |
xn = (-b - sqrt(pow(b,2) - 4*a*c))/(2*a); | |
y = (xp - P4.x)*tan(-LeafTipHA); | |
// message("p: ",xp," n: ",xn," y: ",y); | |
P4a = [xp,y]; | |
P6a = rotate_xy(P4a,LeafStemAngle - 2*atan(P4a.y,P4a.x)); | |
// message("P4a: ",P4a); | |
// message("P6a: ",P6a); | |
// message("P0: ",P0); | |
// message("P1: ",P1); | |
// message("P2: ",P2); | |
// message("P3: ",P3); | |
// message("P4: ",P4); | |
// message("P5: ",P5); | |
// message("P6: ",P6); | |
// Construct paths | |
LeafPoints = {P1,P2,P3,[P2.x,-P2.y],[P1.x,-P1.y]}; | |
if (P0 != P1) { | |
StemArc = varc_ccw(P1 - [P1.x,-P1.y],LeafID/2); | |
StemArc += [P1.x,-P1.y]; | |
LeafPoints += StemArc; | |
} | |
RimChord = length(P4a - P6a); | |
RimThick = OuterDia/2 - Sash - length(P5); | |
RimPoints = {P4a,P5,P6a}; | |
RimArc = varc_cw(P4a - P6a,P4a.x); | |
RimArc += P6a; | |
RimPoints += RimArc; | |
//--- Lay out the frame | |
linecolor(0xff0000); | |
layer("Frame"); | |
goto([CenterDia/2,0mm]); | |
circle_cw([0mm,0mm]); | |
repeat(NumLeaves;i) { | |
a = (i-1)*LeafStemAngle; | |
tracepath(rotate_xy(LeafPoints,a)); | |
} | |
repeat(NumLeaves;i) { | |
a = (i-1)*LeafStemAngle; | |
tracepath(rotate_xy(RimPoints,a)); | |
} | |
linecolor(0xff0000); | |
goto([OuterDia/2,0]); | |
circle_cw([0mm,0mm]); | |
//--- Lay out internal pieces for oriented cutting | |
// baseplate | |
layer("Base"); | |
relocate([OuterDia + 2*Sash,0]); | |
goto([OuterDia/2,0]); | |
circle_cw([0mm,0mm]); | |
// central circle | |
layer("Center"); | |
relocate([OuterDia/2 + Sash,-(OuterDia - CenterDia)/2]); | |
goto([CenterDia/2,0mm]); | |
circle_cw([0mm,0mm]); | |
// leaves | |
layer("Leaves"); | |
repeat(NumLeaves;i) { | |
org = [LeafWidth/2 - OuterDia/2,-(OuterDia + Sash)]; | |
relocate([(i-1)*(LeafWidth + Sash) + org.x,org.y]); | |
tracepath(rotate_xy(LeafPoints,90deg)); | |
} | |
// rim | |
layer("Rim"); | |
repeat(NumLeaves;i) { | |
org = [-Sash,-(OuterDia + 2*Sash + RimChord/2)]; | |
relocate([(i-1)*(RimThick + Sash) + org.x,org.y]); | |
tracepath(rotate_xy(RimPoints,180 - LeafStemHA)); | |
} | |
// Debugging by printf() | |
if (FALSE) { | |
layer("Tool1"); | |
linecolor(0xff1f00); | |
goto([Sash/2,0mm]); | |
circle_cw([0mm,0mm]); | |
goto(P0); | |
circle_cw([0mm,0mm]); | |
goto([0,0]); | |
move([OuterDia/2,0]); | |
goto([0,0]); | |
move(OuterDia/2 * [cos(LeafStemHA),sin(LeafStemHA)]); | |
goto(P2); | |
move_r([0,-LeafWidth/2]); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment