@thi.ng/rasterize
Version:
Headless 2D shape drawing, filling & rasterization for arbitrary targets/purposes (no canvas required)
55 lines (54 loc) • 1.49 kB
JavaScript
import { ensureShader2D } from "./checks.js";
const fillPoly = (grid, pts, val) => {
const numP = pts.length;
const [width, height] = grid.size;
const shader = ensureShader2D(val);
let minX = Infinity;
let minY = Infinity;
let maxX = -Infinity;
let maxY = -Infinity;
for (let i2 = numP; i2-- > 0; ) {
const { 0: x, 1: y } = pts[i2];
minX = Math.min(minX, x);
maxX = Math.max(maxX, x);
minY = Math.min(minY, y);
maxY = Math.max(maxY, y);
}
minX = Math.max(minX | 0, 0);
maxX = Math.min(maxX | 0, width - 1);
minY = Math.max(minY | 0, 0);
maxY = Math.min(maxY | 0, height - 1);
if (minX >= width || maxX < 0 || minY >= height || maxY < 0) return;
let i = 0;
let k = 0;
let j;
const isec = [];
for (let y = Math.max(0, minY); y <= maxY; y++) {
i = k = 0;
j = numP - 1;
isec.length = 0;
for (; i < numP; j = i, i++) {
const { 0: pix, 1: piy } = pts[i];
const { 0: pjx, 1: pjy } = pts[j];
if (piy < y && pjy >= y || pjy < y && piy >= y) {
isec[k++] = pix + (y - piy) / (pjy - piy) * (pjx - pix) | 0;
}
}
isec.sort((a, b) => a - b);
for (i = 0; i < k; i += 2) {
let x1 = isec[i];
if (x1 > maxX) break;
let x2 = isec[i + 1];
if (x2 > minX) {
x1 < minX && (x1 = minX);
x2 > maxX && (x2 = maxX);
for (let x = x1; x <= x2; x++) {
grid.setAtUnsafe(x, y, shader(grid, x, y));
}
}
}
}
};
export {
fillPoly
};