Last active
March 21, 2017 13:06
-
-
Save nophead/b7844a2d8f1d7f1082678a1d606c961c to your computer and use it in GitHub Desktop.
Demo of corner orbit paths for laser engraving without stopping
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
paths = [ // a house | |
[[-50, 0], [-50, 80], [0, 120], [50, 80], [50, 0], [8, 0], [8, 30], [-8, 30], [-8, 0],[-50, 0]], | |
[[-40, 50], [-40, 70], [-20, 70], [-20, 50], [-40, 50]], | |
[[ 20, 10], [ 20, 30], [ 40, 30], [ 40, 10], [ 20, 10]], | |
[[ 20, 50], [ 20, 70], [ 40, 70], [ 40, 50], [ 20, 50]], | |
[[-40, 10], [-40, 30], [-20, 30], [-20, 10], [-40, 10]], | |
]; | |
home = [-150, 150]; // where to start from | |
r = 3; // orbit radius = v^2 / a. | |
for(i = [0 : 1 : len(paths) - 1]) { | |
path = paths[i]; | |
last = i ? paths[i - 1][len(paths[i - 1]) - 1] : home; | |
if(len(path) > 1) { | |
// | |
// Do the lead in travel from the last point. | |
// Ends in an arc to end up traveling in the right direction | |
// for the first cut. | |
// | |
v0 = path[0] - last; | |
v1 = path[1] - path[0]; | |
a0 = atan2(v0.y, v0.x); // angle of travel | |
a1 = atan2(v1.y, v1.x); // angle of first cut | |
a = angle_between(v0, v1); // the angle between decides which side to arc on | |
c = path[0] + rotate(v1, 90 * sign(a)) * r / norm(v1); // center of arc | |
h = c - last; // hypotenuse of rht | |
a2 = atan2(-h.y, h.x); // angle of hypotenuse | |
a3 = acos(r / norm(h)); // angle of rht | |
color("grey", 0.5) { | |
if(a > 0) { | |
theta = 180 - a2 + a3; | |
translate(c) | |
arc(r, theta, a1 + 270); | |
line(last, c + rotate([r, 0], theta)); | |
} | |
if(a < 0) { | |
theta = 360 - a2 + a3; | |
translate(c) | |
arc(r, a1 + 90, theta); | |
line(last, c + rotate([r, 0], theta)); | |
} | |
if(a == 0) | |
line(last, path[0]); | |
} | |
// | |
// Do the cuts | |
// | |
for(j = [0 : 1 : len(path) - 2]) { | |
// | |
// Each cut is joined by two arcs which are connected with a | |
// tangent. | |
// | |
p0 = path[j]; | |
p1 = path[j + 1]; | |
if(j < len(path) - 2) color("grey", 0.5) { | |
p2 = path[j + 2]; | |
v0 = p1 - p0; | |
v1 = p2 - p1; | |
a0 = atan2(v0.y, v0.x); | |
a1 = atan2(v1.y, v1.x); | |
c1 = p1 + rotate(v0, -90) * r / norm(v0); // arc centres | |
c2 = p1 + rotate(v1, -90) * r / norm(v1); | |
cl = c2 - c1; // line between centres | |
theta = atan2(cl.y, cl.x) + 90;// angle of perpenicular to tangent | |
offset = rotate([r, 0], theta);// offset of tangent from centre | |
line(c1 + offset, c2 + offset);// draw the tangent | |
translate(c1) | |
arc(r, theta, a0 + 90); // first arc | |
translate(c2) // second arc | |
arc(r, a1 + 90, theta); | |
} | |
color("red") line(p0, p1); // cut line | |
} | |
} | |
} | |
// | |
// Utilities | |
// | |
function norm_angle(a) = a > 180 ? a - 360 : a < -180 ? a + 360 : a; | |
function angle_between(v1, v2) = norm_angle(atan2(v2.y, v2.x) - atan2(v1.y, v1.x)); | |
function rotate(v1, a) = v1 * [[cos(a), sin(a)], [-sin(a), cos(a)]]; | |
// | |
// Line drawing utilities | |
// | |
line_width = .5; | |
$fs = 0.1; | |
$fa = 1; | |
module line(p1, p2) | |
hull() | |
for(p = [p1, p2]) | |
translate(p) | |
circle(d = line_width); | |
module sector(r, a1, a2) { | |
R = r * sqrt(2) + 1; | |
if(a2 > a1) | |
intersection() { | |
circle(r); | |
polygon(concat([[0,0]], | |
[for(i = [0:4]) let(a = ((4 - i) * a1 + i * a2)/ 4) | |
[R * cos(a), R * sin(a)] | |
])); | |
} | |
else echo(a1, a2); | |
} | |
module arc(r, a1, a2) | |
difference() { | |
sector(r + line_width / 2, a1, a2 > a1 ? a2 : a2 + 360); | |
circle(r - line_width / 2); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment