Files
Foundry-VTT-Docker/resources/app/node_modules/@pixi/graphics-smooth/lib/shapes/PolyBuilder.mjs
2025-01-04 00:34:03 +01:00

287 lines
8.1 KiB
JavaScript

import { JOINT_TYPE } from '../core/const.mjs';
import { Point, utils } from '@pixi/core';
const tempArr = [];
function fixOrientation(points, hole = false) {
const m = points.length;
if (m < 6) {
return;
}
let area = 0;
for (let i = 0, x1 = points[m - 2], y1 = points[m - 1]; i < m; i += 2) {
const x2 = points[i];
const y2 = points[i + 1];
area += (x2 - x1) * (y2 + y1);
x1 = x2;
y1 = y2;
}
if (!hole && area > 0 || hole && area <= 0) {
const n = m / 2;
for (let i = n + n % 2; i < m; i += 2) {
const i1 = m - i - 2;
const i2 = m - i - 1;
const i3 = i;
const i4 = i + 1;
[points[i1], points[i3]] = [points[i3], points[i1]];
[points[i2], points[i4]] = [points[i4], points[i2]];
}
}
}
class PolyBuilder {
path(graphicsData, buildData) {
const shape = graphicsData.shape;
const points = graphicsData.points = shape.points.slice();
const eps = buildData.closePointEps;
const eps2 = eps * eps;
if (points.length === 0) {
return;
}
const firstPoint = new Point(points[0], points[1]);
const lastPoint = new Point(points[points.length - 2], points[points.length - 1]);
const closedShape = graphicsData.closeStroke = shape.closeStroke;
let len = points.length;
let newLen = 2;
for (let i = 2; i < len; i += 2) {
const x1 = points[i - 2];
const y1 = points[i - 1];
const x2 = points[i];
const y2 = points[i + 1];
let flag = true;
if (Math.abs(x1 - x2) < eps && Math.abs(y1 - y2) < eps) {
flag = false;
}
if (flag) {
points[newLen] = points[i];
points[newLen + 1] = points[i + 1];
newLen += 2;
}
}
points.length = len = newLen;
newLen = 2;
for (let i = 2; i + 2 < len; i += 2) {
let x1 = points[i - 2];
let y1 = points[i - 1];
const x2 = points[i];
const y2 = points[i + 1];
let x3 = points[i + 2];
let y3 = points[i + 3];
x1 -= x2;
y1 -= y2;
x3 -= x2;
y3 -= y2;
let flag = true;
if (Math.abs(x3 * y1 - y3 * x1) < eps2) {
if (x1 * x3 + y1 * y3 < -eps2) {
flag = false;
}
}
if (flag) {
points[newLen] = points[i];
points[newLen + 1] = points[i + 1];
newLen += 2;
}
}
points[newLen] = points[len - 2];
points[newLen + 1] = points[len - 1];
newLen += 2;
points.length = len = newLen;
if (len <= 2) {
return;
}
if (closedShape) {
const closedPath = Math.abs(firstPoint.x - lastPoint.x) < eps && Math.abs(firstPoint.y - lastPoint.y) < eps;
if (closedPath) {
points.pop();
points.pop();
}
}
}
line(graphicsData, buildData) {
const { closeStroke, points } = graphicsData;
const len = points.length;
if (len <= 2) {
return;
}
const { verts, joints } = buildData;
const joint = graphicsData.jointType();
const cap = graphicsData.capType();
let prevCap = 0;
let prevX;
let prevY;
if (closeStroke) {
prevX = points[len - 2];
prevY = points[len - 1];
joints.push(JOINT_TYPE.NONE);
} else {
prevX = points[2];
prevY = points[3];
if (cap === JOINT_TYPE.CAP_ROUND) {
verts.push(points[0], points[1]);
joints.push(JOINT_TYPE.NONE);
joints.push(JOINT_TYPE.CAP_ROUND);
prevCap = 0;
} else {
prevCap = cap;
joints.push(JOINT_TYPE.NONE);
}
}
verts.push(prevX, prevY);
for (let i = 0; i < len; i += 2) {
const x1 = points[i];
const y1 = points[i + 1];
let endJoint = joint;
if (i + 2 >= len) {
if (!closeStroke) {
endJoint = JOINT_TYPE.NONE;
}
} else if (i + 4 >= len) {
if (!closeStroke) {
if (cap === JOINT_TYPE.CAP_ROUND) {
endJoint = JOINT_TYPE.JOINT_CAP_ROUND;
}
if (cap === JOINT_TYPE.CAP_BUTT) {
endJoint = JOINT_TYPE.JOINT_CAP_BUTT;
}
if (cap === JOINT_TYPE.CAP_SQUARE) {
endJoint = JOINT_TYPE.JOINT_CAP_SQUARE;
}
}
}
endJoint += prevCap;
prevCap = 0;
verts.push(x1, y1);
joints.push(endJoint);
prevX = x1;
prevY = y1;
}
if (closeStroke) {
verts.push(points[0], points[1]);
joints.push(JOINT_TYPE.NONE);
verts.push(points[2], points[3]);
joints.push(JOINT_TYPE.NONE);
} else {
verts.push(points[len - 4], points[len - 3]);
joints.push(JOINT_TYPE.NONE);
}
}
fill(graphicsData, buildData) {
let points = graphicsData.points;
const holes = graphicsData.holes;
const eps = buildData.closePointEps;
const { verts, joints } = buildData;
if (points.length < 6) {
return;
}
const holeArray = [];
let len = points.length;
fixOrientation(points, false);
for (let i = 0; i < holes.length; i++) {
const hole = holes[i];
fixOrientation(hole.points, true);
holeArray.push(points.length / 2);
points = points.concat(hole.points);
}
const pn = tempArr;
if (pn.length < points.length) {
pn.length = points.length;
}
let start = 0;
for (let i = 0; i <= holeArray.length; i++) {
let finish = len / 2;
if (i > 0) {
if (i < holeArray.length) {
finish = holeArray[i];
} else {
finish = points.length >> 1;
}
}
pn[start * 2] = finish - 1;
pn[(finish - 1) * 2 + 1] = start;
for (let j = start; j + 1 < finish; j++) {
pn[j * 2 + 1] = j + 1;
pn[j * 2 + 2] = j;
}
start = finish;
}
graphicsData.triangles = utils.earcut(points, holeArray, 2);
if (!graphicsData.triangles) {
return;
}
if (!graphicsData.fillAA) {
for (let i = 0; i < points.length; i += 2) {
verts.push(points[i], points[i + 1]);
joints.push(JOINT_TYPE.FILL);
}
return;
}
const { triangles } = graphicsData;
len = points.length;
for (let i = 0; i < triangles.length; i += 3) {
let flag = 0;
for (let j = 0; j < 3; j++) {
const ind1 = triangles[i + j];
const ind2 = triangles[i + (j + 1) % 3];
if (pn[ind1 * 2] === ind2 || pn[ind1 * 2 + 1] === ind2) {
flag |= 1 << j;
}
}
joints.push(JOINT_TYPE.FILL_EXPAND + flag);
joints.push(JOINT_TYPE.NONE);
joints.push(JOINT_TYPE.NONE);
joints.push(JOINT_TYPE.NONE);
joints.push(JOINT_TYPE.NONE);
joints.push(JOINT_TYPE.NONE);
}
for (let ind = 0; ind < len / 2; ind++) {
const prev = pn[ind * 2];
const next = pn[ind * 2 + 1];
let nx1 = points[next * 2 + 1] - points[ind * 2 + 1];
let ny1 = -(points[next * 2] - points[ind * 2]);
let nx2 = points[ind * 2 + 1] - points[prev * 2 + 1];
let ny2 = -(points[ind * 2] - points[prev * 2]);
const D1 = Math.sqrt(nx1 * nx1 + ny1 * ny1);
nx1 /= D1;
ny1 /= D1;
const D2 = Math.sqrt(nx2 * nx2 + ny2 * ny2);
nx2 /= D2;
ny2 /= D2;
let bx = nx1 + nx2;
let by = ny1 + ny2;
const D = bx * nx1 + by * ny1;
if (Math.abs(D) < eps) {
bx = nx1;
by = ny1;
} else {
bx /= D;
by /= D;
}
pn[ind * 2] = bx;
pn[ind * 2 + 1] = by;
}
for (let i = 0; i < triangles.length; i += 3) {
const prev = triangles[i];
const ind = triangles[i + 1];
const next = triangles[i + 2];
const nx1 = points[next * 2 + 1] - points[ind * 2 + 1];
const ny1 = -(points[next * 2] - points[ind * 2]);
const nx2 = points[ind * 2 + 1] - points[prev * 2 + 1];
const ny2 = -(points[ind * 2] - points[prev * 2]);
let j1 = 1;
if (nx1 * ny2 - nx2 * ny1 > 0) {
j1 = 2;
}
for (let j = 0; j < 3; j++) {
const ind2 = triangles[i + j * j1 % 3];
verts.push(points[ind2 * 2], points[ind2 * 2 + 1]);
}
for (let j = 0; j < 3; j++) {
const ind2 = triangles[i + j * j1 % 3];
verts.push(pn[ind2 * 2], pn[ind2 * 2 + 1]);
}
}
}
}
export { PolyBuilder };
//# sourceMappingURL=PolyBuilder.mjs.map