Polygone kirigami
Polygone kirigami (outter boundary uncomment at the end)
Log in to post a comment.
Canvas.setpenopacity(1);
const turtle = new Turtle();
// adjust to fit canvas
let scale = 1; // min=0, max=20, step=0.1
// ----------------------
// PARAMETERS
// ----------------------
// Number of polygon sides
// AND number of possible sections
let part = 4; // min=2, max=50, step=2
// 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 polygon 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(n) {
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 if (spacing_mode == 3) {
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=0, max=20, step=0.1
// ----------------------
// OVERLAP MODES
// ----------------------
let overlap_mode = 1; // min=1, max=4, step=1
if (overlap_mode == 1) {
function D_slope(n) {
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=20, step=0.5
// ----------------------
// Cutting mode
// ----------------------
let mode = 0; // min=1, max=2, step=1
// ----------------------
// POLYGON GEOMETRY
// ----------------------
const sideAngle =
2 * Math.PI / part;
// Length of one polygon side
function side_length(radius) {
return 2 *
radius *
Math.sin(Math.PI / part);
}
// Get point along polygon perimeter
function polygon_point(
radius,
distance,
rotation
) {
let sideLen =
side_length(radius);
let perimeter =
sideLen * part;
// Wrap distance around perimeter
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
};
}
// ----------------------
// ----------------------
// ----------------------
// DRAW ONE SECTION
// ----------------------
//
// mode 1:
// Sections start/end at polygon corners.
//
// part = 4:
//
// Ring 0 -> section 0, section 2
// Ring 1 -> section 1, section 3
//
//
// mode 2:
// Sections are shifted by HALF A SIDE.
//
// The boundaries are now at the
// middle of polygon sides.
//
// This means the section passes through
// a polygon corner:
//
// midpoint |--- corner ---| midpoint
//
// ----------------------
function draw_polygon_side(
radius,
side,
rotation,
overlapAmount
) {
let sideLen =
side_length(radius);
// ==================================================
// MODE 1
// ==================================================
//
// Normal polygon sections.
//
// Start and end at polygon corners.
//
// overlap
// ↓
//
// <===================>
// ↑ ↑
// corner corner
//
// ==================================================
if (mode == 1) {
let start =
side * sideLen -
overlapAmount;
let end =
(side + 1) * sideLen +
overlapAmount;
draw_polygon_segment(
radius,
start,
end,
rotation
);
return;
}
// ==================================================
// MODE 2
// ==================================================
//
// Shift the section by HALF A SIDE.
//
// Therefore the section runs from the
// midpoint of one side, through a corner,
// to the midpoint of the next side.
//
//
// midpoint midpoint
// | |
// |---- overlap ----| |
// corner
//
// ==================================================
if (mode == 2) {
let halfSide =
sideLen / 2;
// Start/end of the section are shifted
// by half a side.
//
// Original:
//
// side -------- side
//
// New:
//
// midpoint -- corner -- midpoint
let start =
side * sideLen +
halfSide -
overlapAmount;
let end =
(side + 1) * sideLen +
halfSide +
overlapAmount;
draw_polygon_segment(
radius,
start,
end,
rotation
);
}
}
// ----------------------
// DRAW POLYGON SEGMENT
// ----------------------
function draw_polygon_segment(
radius,
start,
end,
rotation
) {
let length =
end - start;
let steps =
Math.max(
2,
Math.ceil(length / 2)
);
for (let k = 0; k <= steps; k++) {
let d =
start +
length * k / steps;
let p =
polygon_point(
radius,
d,
rotation
);
let x =
scale * p.x;
let y =
scale * p.y;
if (k === 0) {
turtle.penup();
turtle.goto(x, y);
turtle.pendown();
} else {
turtle.goto(x, y);
}
}
}
// ----------------------
// DRAW FULL POLYGON
// ----------------------
function draw_polygon(
radius,
rotation
) {
let sideLen =
side_length(radius);
let perimeter =
sideLen * part;
let steps =
Math.max(
2 * part,
Math.floor(perimeter)
);
for (let k = 0; k <= steps; k++) {
let d =
perimeter * k / steps;
let p =
polygon_point(
radius,
d,
rotation
);
let x =
scale * p.x;
let y =
scale * p.y;
if (k === 0) {
turtle.penup();
turtle.goto(x, y);
turtle.pendown();
} else {
turtle.goto(x, y);
}
}
}
// ----------------------
// COMPUTE NUMBER OF RINGS
// ----------------------
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;
// Cumulative spiral rotation
let spiral = 0;
for (
let n = 0;
n < polygon_number;
n++
) {
let eps =
D_slope(n);
// ======================================
// ======================================
// ALTERNATING POSITIONS
// ======================================
//
// mode 1:
//
// Ring 0 -> sides 0, 2, 4...
// Ring 1 -> sides 1, 3, 5...
//
//
// mode 2:
//
// Ring 0 -> middle of sides 0, 2, 4...
// Ring 1 -> middle of sides 1, 3, 5...
//
// ======================================
let firstSide = n % 2;
for (
let j = firstSide;
j < part;
j += 2
) {
draw_polygon_side(
r,
j,
spiral,
eps
);
spiral += offset / r;
}
// Next polygon ring
r += spacing_slope(n);
}
// ----------------------
// OUTER BOUNDARY
// ----------------------
//draw_polygon(r+10,spiral);
return false;
}
walk(0);