Skip to content

Instantly share code, notes, and snippets.

@afternoon2
Created March 5, 2023 22:29
Show Gist options
  • Save afternoon2/8f27430e6c59cfe817d2f7aa989cbb39 to your computer and use it in GitHub Desktop.
Save afternoon2/8f27430e6c59cfe817d2f7aa989cbb39 to your computer and use it in GitHub Desktop.
// polygon transform with using svgpathdata.js matrix utility class
// results in the same polygon as in case of using svgpathdata directly
// but without the need of stringifying path data before processing.
// useful when working on polygons data instead of svg paths.
// Input format utilizes JS Clipper Lib polygon format:
// type PolygonRing = { X: number, Y: number }[];
// type Polygon = PolygonRing[];
//
// usage:
// const polygon = new Polygon(data)
// .translate(30, 40)
// .rotate(20)
// .scale(304)
// .skewX(20)
// .calc()
// .round(2);
import Matrix from 'svgpath/lib/matrix';
class Polygon {
#queue = [];
constructor(data) {
this.data = data;
}
translate(tx, ty) {
this.#queue.push(['translate', [tx, ty]]);
return this;
}
scale(sx, sy) {
this.#queue.push(['scale', [sx, sy]]);
return this;
}
rotate(angle, rx = 0, ry = 0) {
this.#queue.push(['rotate', [angle, rx, ry]]);
return this;
}
skewX(angle) {
if (angle !== 0) {
this.#queue.push(['skewX', [angle]]);
}
return this;
}
skewY(angle) {
if (angle !== 0) {
this.#queue.push(['skewY', [angle]]);
}
return this;
}
round(precision) {
this.data = this.data.map((ring) =>
ring.map((pt) => ({
X: parseFloat(pt.X.toFixed(precision)),
Y: parseFloat(pt.Y.toFixed(precision)),
}))
);
return this;
}
calc() {
this.data = this.data.map((ring) =>
ring.map((pt) => {
const mt = this.#queue.reduce((m, [cmd, args]) => {
m[cmd](...args);
return m;
}, new Matrix());
const res = mt.calc(pt.X, pt.Y);
return {
X: res[0],
Y: res[1],
};
})
);
return this;
}
}
export default Polygon;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment