Polygone kirigami
Polygone kirigami (outter boundary uncomment at the end)
Problem from svg file when sent to laser cutter...
Log in to post a comment.
Canvas.setpenopacity(1);
const turtle = new Turtle();
let scale = 1; // min=0, max=20, step=0.1
// ============================================================
// PARAMETERS
// ============================================================
// Polygon geometry
let sides = 8; // min=3, max=100, step=1
// Number of drawable sections
let sections = 4; // min=1, max=100, step=1
// Starting radius
let R_min = 15; // min=1, max=50, step=1
// Outer radius
let r_max = 62; // min=10, max=500, step=1
// Spacing between rings
let spacing = 2; // min=1, max=50, step=0.5
let spacing_min = spacing;
let spacing_max = 2 * spacing;
// ============================================================
// SPACING MODES
// ============================================================
// 1 = constant
// 2 = increasing
// 3 = decreasing
let spacing_mode = 1; // min=1, max=3, step=1
if (spacing_mode == 1) {
function spacing_slope() {
return spacing;
}
} else if (spacing_mode == 2) {
function spacing_slope(r) {
let t =
(r - R_min) /
(r_max - R_min);
return spacing_min +
(spacing_max - spacing_min) * t;
}
} else {
function spacing_slope(r) {
let t =
(r - R_min) /
(r_max - R_min);
return spacing_min -
(spacing_max - spacing_min) * t;
}
}
// ============================================================
// OVERLAP
// ============================================================
let overlap = 6; // min=1, max=100, step=0.5
// ============================================================
// OVERLAP MODES
// ============================================================
let overlap_mode = 1; // min=1, max=4, step=1
if (overlap_mode == 1) {
function D_slope() {
return overlap;
}
} else if (overlap_mode == 2) {
function D_slope(n) {
return 0.2 * (overlap + n);
}
} else if (overlap_mode == 3) {
function D_slope(n) {
return 0.25 * overlap - n * 0.15;
}
} else {
function D_slope(n) {
return overlap *
(1 + 0.4 * Math.sin(n / 4));
}
}
// ============================================================
// SPIRAL
// ============================================================
let offset = 0; // min=0, max=100, step=1
// ============================================================
// CUTTING MODE
// ============================================================
// 1 = section starts at boundary
// 2 = section shifted by half a section
let mode = 1;
// ============================================================
// POLYGON GEOMETRY
// ============================================================
const sideAngle =
2 * Math.PI / sides;
function side_length(radius) {
return 2 *
radius *
Math.sin(Math.PI / sides);
}
function polygon_point(
radius,
distance,
rotation
) {
let sideLen =
side_length(radius);
let perimeter =
sideLen * sides;
distance =
((distance % perimeter) +
perimeter) % perimeter;
let side =
Math.floor(distance / sideLen);
let t =
(distance - side * sideLen) /
sideLen;
let a1 =
-Math.PI / 2 +
side * sideAngle +
rotation;
let a2 =
-Math.PI / 2 +
(side + 1) * sideAngle +
rotation;
let x1 =
radius * Math.cos(a1);
let y1 =
radius * Math.sin(a1);
let x2 =
radius * Math.cos(a2);
let y2 =
radius * Math.sin(a2);
return {
x: x1 + (x2 - x1) * t,
y: y1 + (y2 - y1) * t
};
}
function section_position(
radius,
sectionIndex
) {
let sideLen =
side_length(radius);
let perimeter =
sideLen * sides;
return (
sectionIndex *
perimeter /
sections
);
}
// ============================================================
// SEGMENT STORAGE
// ============================================================
let segments = [];
function add_segment(p1, p2) {
segments.push({
x1: p1.x,
y1: p1.y,
x2: p2.x,
y2: p2.y
});
}
function collect_polygon_segment(
radius,
start,
end,
rotation
) {
let length =
end - start;
let steps =
Math.max(
2,
Math.ceil(
Math.abs(length) / 2
)
);
let previous = null;
for (let k = 0; k <= steps; k++) {
let d =
start +
length * k / steps;
let p =
polygon_point(
radius,
d,
rotation
);
if (previous !== null) {
add_segment(
previous,
p
);
}
previous = p;
}
}
// ============================================================
// DRAW ONE SECTION
// ============================================================
function draw_section(
radius,
sectionIndex,
rotation,
overlapAmount
) {
let sideLen =
side_length(radius);
let perimeter =
sideLen * sides;
let sectionLength =
perimeter / sections;
let start =
section_position(
radius,
sectionIndex
);
if (mode == 2) {
start +=
sectionLength / 2;
}
let end =
start +
sectionLength;
collect_polygon_segment(
radius,
start - overlapAmount,
end + overlapAmount,
rotation
);
}
// ============================================================
// DUPLICATE REMOVAL
// ============================================================
function deduplicate_segments() {
const precision = 1000000;
let unique = [];
let seen = new Set();
for (let s of segments) {
let a =
Math.round(
s.x1 * precision
) +
"," +
Math.round(
s.y1 * precision
);
let b =
Math.round(
s.x2 * precision
) +
"," +
Math.round(
s.y2 * precision
);
let key =
a < b
? a + "|" + b
: b + "|" + a;
if (!seen.has(key)) {
seen.add(key);
unique.push(s);
}
}
segments = unique;
}
// ============================================================
// OUTPUT
// ============================================================
function output_segments() {
for (let s of segments) {
turtle.penup();
turtle.goto(
scale * s.x1,
scale * s.y1
);
turtle.pendown();
turtle.goto(
scale * s.x2,
scale * s.y2
);
}
}
// ============================================================
// COMPUTE RING COUNT
// ============================================================
let polygon_number = 0;
let temp_r = R_min;
while (temp_r < r_max) {
temp_r +=
spacing_slope(
polygon_number
);
polygon_number++;
}
// ============================================================
// WALK
// ============================================================
function walk(i) {
if (i > 0) return false;
let r = R_min;
let spiral = 0;
for (
let n = 0;
n < polygon_number;
n++
) {
let eps =
D_slope(n);
let firstSection =
n % 2;
for (
let j = firstSection;
j < sections;
j += 2
) {
draw_section(
r,
j,
spiral,
eps
);
spiral +=
offset / r;
}
r +=
spacing_slope(n);
}
deduplicate_segments();
output_segments();
return false;
}
walk(0);