@thi.ng/geom
Version:
Functional, polymorphic API for 2D geometry types & SVG generation
89 lines (88 loc) • 2.06 kB
JavaScript
import { mixCubic } from "@thi.ng/vectors/mix-cubic";
import { __copyShape } from "../internal/copy.js";
import { __ensureNumVerts } from "../internal/pclike.js";
import { APC } from "./apc.js";
class BPatch extends APC {
type = "bpatch";
dim = 2;
constructor(points, attribs) {
super(points, attribs);
__ensureNumVerts(this.points.length, 16);
}
copy() {
return __copyShape(BPatch, this);
}
copyTransformed(fn) {
return __copyShape(BPatch, this, fn(this.points));
}
withAttribs(attribs) {
return new BPatch(this.points, attribs);
}
edges() {
const p = this.points;
return [
[ ],
[ ],
[ ],
[ ],
[ ],
[ ],
[ ],
[ ],
[ ],
[ ],
[ ],
[ ],
[ ],
[ ],
[ ],
[ ],
[ ],
[ ],
[ ],
[ ],
[ ],
[ ],
[ ],
[ ]
].map(([a, b]) => [p[a], p[b]]);
}
unmapPoint(uv, out) {
const cp = this.points;
const [u, v] = uv;
return mixCubic(
out || null,
mixCubic([], cp[0], cp[4], cp[8], cp[12], v),
mixCubic([], cp[1], cp[5], cp[9], cp[13], v),
mixCubic([], cp[2], cp[6], cp[10], cp[14], v),
mixCubic([], cp[3], cp[7], cp[11], cp[15], v),
u
);
}
toHiccup() {
const attribs = this.attribs;
const acc = ["g", { fill: "none", ...attribs }];
if (attribs?.res) {
const res = attribs.res - 1;
const delta = 1 / res;
for (let u = 0; u <= res; u++) {
const col = [];
const row = [];
const uu = u * delta;
for (let v = 0; v <= res; v++) {
const p = [uu, v * delta];
col.push(this.unmapPoint(p));
row.push(this.unmapPoint([p[1], p[0]]));
}
acc.push(["polyline", {}, col]);
acc.push(["polyline", {}, row]);
}
} else {
this.edges().forEach((l) => acc.push(["line", {}, ...l]));
}
return acc;
}
}
export {
BPatch
};