loosely based on Advent of Code 2024 - 05
loose cannon printer
boy oh boy oh boy do I hate clipping segments
Log in to post a comment.
// Forked from "intersect rect" by OiWeiWei
// https://turtletoy.net/turtle/7e326711bc
Canvas.setpenopacity(-1.0);
const t = new Turtle();
function clip_local(x1, y1, x2, y2, rx, ry, w, h) {
let s_c = [];
let iy1_t = (rx - x1) / (x2 - x1);
let iy1 = y1 + (y2 - y1) * iy1_t;
let iy1_in = (iy1 >= ry) && (iy1 <= ry + h) && (iy1_t >= 0) && (iy1_t <= 1);
let iy2_t = (rx + w - x1) / (x2 - x1);
let iy2 = y1 + (y2 - y1) * iy2_t;
let iy2_in = (iy2 >= ry) && (iy2 <= ry + h) && (iy2_t >= 0) && (iy2_t <= 1);
let ix1_t = (ry + h - y1) / (y2 - y1);
let ix1 = x1 + (x2 - x1) * ix1_t;
let ix1_in = (ix1 >= rx) && (ix1 <= rx + w) && (ix1_t >= 0) && (ix1_t <= 1);
let ix2_t = (ry - y1) / (y2 - y1)
let ix2 = x1 + (x2 - x1) * ix2_t;
let ix2_in = (ix2 >= rx) && (ix2 <= rx + w) && (ix2_t >= 0) && (ix2_t <= 1);
let p1_in = (x1 >= rx) && (x1 <= rx + w) && (y1 >= ry) && (y1 <= ry + h);
let p2_in = (x2 >= rx) && (x2 <= rx + w) && (y2 >= ry) && (y2 <= ry + h);
if (p1_in && p2_in) {
// return nothing
}
else if (!iy1_in && !iy2_in && !ix1_in && !ix2_in) {
s_c.push([x1, y1, x2, y2]);
}
else if (p1_in && !p2_in) {
if (iy1_in) {
s_c.push([x2, y2, rx, iy1]);
}
if (iy2_in) {
s_c.push([x2, y2, rx + w, iy2]);
}
if (ix1_in) {
s_c.push([x2, y2, ix1, ry + h]);
}
if (ix2_in) {
s_c.push([x2, y2, ix2, ry]);
}
}
else if (!p1_in && p2_in) {
if (iy1_in) {
s_c.push([x1, y1, rx, iy1]);
}
if (iy2_in) {
s_c.push([x1, y1, rx + w, iy2]);
}
if (ix1_in) {
s_c.push([x1, y1, ix1, ry + h]);
}
if (ix2_in) {
s_c.push([x1, y1, ix2, ry]);
}
}
else {
if (iy1_in) {
if (x1 <= rx) {
s_c.push([x1, y1, rx, iy1]);
}
else {
s_c.push([x2, y2, rx, iy1]);
}
}
if (iy2_in) {
if (x2 > rx + w) {
s_c.push([rx + w, iy2, x2, y2]);
}
else {
s_c.push([rx + w, iy2, x1, y1]);
}
}
if (ix1_in) {
if (y2 > ry + h) {
s_c.push([ix1, ry + h, x2, y2]);
}
else {
s_c.push([ix1, ry + h, x1, y1]);
}
}
if (ix2_in) {
if (y1 < ry) {
s_c.push([ix2, ry, x1, y1]);
}
else {
s_c.push([ix2, ry, x2, y2]);
}
}
}
return s_c;
}
function clip(x1, y1, x2, y2, rx, ry, ax, ay, w, h) {
let x1_loc = (x1 - rx) * ax + (y1 - ry) * ay;
let y1_loc = (x1 - rx) * (-ay) + (y1 - ry) * ax;
let x2_loc = (x2 - rx) * ax + (y2 - ry) * ay;
let y2_loc = (x2 - rx) * (-ay) + (y2 - ry) * ax;
let sc = clip_local(x1_loc, y1_loc, x2_loc, y2_loc, 0, 0, w, h);
for (let i = 0; i < sc.length; i++) {
let cx1 = sc[i][0], cy1 = sc[i][1];
sc[i][0] = cx1 * ax + cy1 * -ay + rx;
sc[i][1] = cx1 * ay + cy1 * ax + ry;
let cx2 = sc[i][2], cy2 = sc[i][3];
sc[i][2] = cx2 * ax + cy2 * -ay + rx;
sc[i][3] = cx2 * ay + cy2 * ax + ry;
}
return sc;
}
let pages = [];
function clip_pages(x1, y1, x2, y2) {
let result = [[x1, y1, x2, y2]];
for (let i = 0; i < pages.length; i++) {
let rx = pages[i][0], ry = pages[i][1];
let ax = pages[i][2], ay = pages[i][3];
let w = pages[i][4], h = pages[i][5];
let new_result = [];
for (let j = 0; j < result.length; j++) {
let cx1 = result[j][0], cy1 = result[j][1];
let cx2 = result[j][2], cy2 = result[j][3];
let sc = clip(cx1, cy1, cx2, cy2, rx, ry, ax, ay, w, h);
for (let k = 0; k < sc.length; k++) {
new_result.push(sc[k]);
}
}
result = new_result;
}
return result;
}
function draw_clipped(x1, y1, x2, y2) {
s_c = clip_pages(x1, y1, x2, y2);
for (let j = 0; j < s_c.length; j++) {
t.jump(s_c[j][0], s_c[j][1]);
t.goto(s_c[j][2], s_c[j][3]);
}
return (s_c.length > 0);
}
function point_is_seen(px, py) {
for (let i = 0; i < pages.length; i++) {
let rx = pages[i][0], ry = pages[i][1];
let ax = pages[i][2], ay = pages[i][3];
let w = pages[i][4], h = pages[i][5];
let px_loc = (px - rx) * ax + (py - ry) * ay;
let py_loc = (px - rx) * (-ay) + (py - ry) * ax;
if ((px_loc >= 0) && (px_loc <= w) && (py_loc >= 0) && (py_loc <= h)) {
return false;
}
}
return true;
}
function draw_page(rx, ry, ax, ay, w, h) {
const x1 = rx, y1 = ry;
const x2 = x1 + ax * w, y2 = y1 + ay * w;
const x3 = x2 - ay * h, y3 = y2 + ax * h;
const x4 = x1 - ay * h, y4 = y1 + ax * h;
let d1 = draw_clipped(x1, y1, x2, y2);
let d2 = draw_clipped(x2, y2, x3, y3);
let d3 = draw_clipped(x3, y3, x4, y4);
let d4 = draw_clipped(x4, y4, x1, y1);
let seen = d1 || d2 || d3 || d4;
for (let y = 2; y < h - 2; y += 1) {
for (let x = 2; x < w - 2; x += 1) {
if (Math.random() < 0.5) {
let px = rx + x * ax + y * -ay;
let py = ry + x * ay + y * ax;
if (point_is_seen(px, py)) {
t.jump(px, py);
t.goto(px + ax * 0.75, py + ay * 0.75);
}
}
}
}
if (seen) {
pages.push([rx, ry, ax, ay, w, h]);
}
}
for (let i = 0; i < 600; i++) {
let R = 10 + 131 * Math.random();
let psi = 2 * Math.PI * Math.random();
let rx = R * Math.cos(psi), ry = R * Math.sin(psi);
// let rx = -100 + 200 * Math.random();
// let ry = -100 + 200 * Math.random();
let phi = Math.atan2(ry, rx);// + Math.PI * 0.1 * (-0.5 + Math.random());
let ax = Math.cos(phi), ay = Math.sin(phi);
let scale = 0.25 + 1.5 * Math.sqrt(rx * rx + ry * ry) / Math.sqrt(100*100*2);
let w = 21 * scale, h = 29.7 * scale;
draw_page(rx, ry, ax, ay, w, h);
}