Skip to content

Instantly share code, notes, and snippets.

@nophead
Last active March 21, 2017 13:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nophead/b7844a2d8f1d7f1082678a1d606c961c to your computer and use it in GitHub Desktop.
Save nophead/b7844a2d8f1d7f1082678a1d606c961c to your computer and use it in GitHub Desktop.
Demo of corner orbit paths for laser engraving without stopping
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