remove geometry.ts
This commit is contained in:
@@ -1,147 +0,0 @@
|
||||
export interface Point {
|
||||
x: number;
|
||||
y: number;
|
||||
}
|
||||
|
||||
export type Polygon = Point[];
|
||||
|
||||
export const signedDistanceToEdge = (edgeStart: Point, edgeEnd: Point, point: Point): number =>
|
||||
(edgeEnd.x - edgeStart.x) * (point.y - edgeStart.y)
|
||||
- (edgeEnd.y - edgeStart.y) * (point.x - edgeStart.x);
|
||||
|
||||
export const iterateEdges = (
|
||||
polygon: Polygon,
|
||||
callback: (current: Point, next: Point, index: number) => boolean | void,
|
||||
): void => {
|
||||
if (!Array.isArray(polygon) || polygon.length === 0) {
|
||||
return;
|
||||
}
|
||||
for (let index = 0; index < polygon.length; index += 1) {
|
||||
const current = polygon[index];
|
||||
const next = polygon[(index + 1) % polygon.length];
|
||||
if (callback(current, next, index) === false) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const forEachVertex = (
|
||||
polygon: Polygon,
|
||||
callback: (current: Point, previous: Point, index: number) => boolean | void,
|
||||
): void => {
|
||||
if (!Array.isArray(polygon) || polygon.length === 0) {
|
||||
return;
|
||||
}
|
||||
for (let index = 0; index < polygon.length; index += 1) {
|
||||
const current = polygon[index];
|
||||
const prev = polygon[(index - 1 + polygon.length) % polygon.length];
|
||||
if (callback(current, prev, index) === false) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const lineIntersection = (p1: Point, p2: Point, cp1: Point, cp2: Point): Point => {
|
||||
const A1 = p2.y - p1.y;
|
||||
const B1 = p1.x - p2.x;
|
||||
const C1 = A1 * p1.x + B1 * p1.y;
|
||||
|
||||
const A2 = cp2.y - cp1.y;
|
||||
const B2 = cp1.x - cp2.x;
|
||||
const C2 = A2 * cp1.x + B2 * cp1.y;
|
||||
|
||||
const det = A1 * B2 - A2 * B1;
|
||||
if (Math.abs(det) < 1e-6) {
|
||||
return { x: cp1.x, y: cp1.y };
|
||||
}
|
||||
return {
|
||||
x: (B2 * C1 - B1 * C2) / det,
|
||||
y: (A1 * C2 - A2 * C1) / det,
|
||||
};
|
||||
};
|
||||
|
||||
export const clipPolygon = (subject: Polygon, clipper: Polygon): Polygon => {
|
||||
if (!Array.isArray(subject) || !subject.length) {
|
||||
return [];
|
||||
}
|
||||
let output = subject;
|
||||
iterateEdges(clipper, (cp1, cp2) => {
|
||||
const input = output;
|
||||
output = [];
|
||||
if (!Array.isArray(input) || !input.length) {
|
||||
return false;
|
||||
}
|
||||
forEachVertex(input, (current, prev) => {
|
||||
const currentInside = signedDistanceToEdge(cp1, cp2, current) >= 0;
|
||||
const prevInside = signedDistanceToEdge(cp1, cp2, prev) >= 0;
|
||||
if (currentInside) {
|
||||
if (!prevInside) {
|
||||
output.push(lineIntersection(prev, current, cp1, cp2));
|
||||
}
|
||||
output.push(current);
|
||||
} else if (prevInside) {
|
||||
output.push(lineIntersection(prev, current, cp1, cp2));
|
||||
}
|
||||
return true;
|
||||
});
|
||||
return output.length > 0;
|
||||
});
|
||||
return output;
|
||||
};
|
||||
|
||||
export const isPointInsideConvex = (point: Point, polygon: Polygon): boolean => {
|
||||
if (!polygon?.length) {
|
||||
return false;
|
||||
}
|
||||
let sign = 0;
|
||||
let inside = true;
|
||||
iterateEdges(polygon, (a, b) => {
|
||||
const cross = signedDistanceToEdge(a, b, point);
|
||||
if (cross === 0) {
|
||||
return true;
|
||||
}
|
||||
const currentSign = cross > 0 ? 1 : -1;
|
||||
if (sign === 0) {
|
||||
sign = currentSign;
|
||||
return true;
|
||||
}
|
||||
if (sign !== currentSign) {
|
||||
inside = false;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
return inside;
|
||||
};
|
||||
|
||||
export const polygonCentroid = (polygon: Polygon): Point => {
|
||||
if (!polygon?.length) {
|
||||
return { x: 0, y: 0 };
|
||||
}
|
||||
let area = 0;
|
||||
let cx = 0;
|
||||
let cy = 0;
|
||||
iterateEdges(polygon, (current, next) => {
|
||||
const cross = current.x * next.y - next.x * current.y;
|
||||
area += cross;
|
||||
cx += (current.x + next.x) * cross;
|
||||
cy += (current.y + next.y) * cross;
|
||||
});
|
||||
if (Math.abs(area) < 1e-6) {
|
||||
let sumX = 0;
|
||||
let sumY = 0;
|
||||
forEachVertex(polygon, (point) => {
|
||||
sumX += point.x;
|
||||
sumY += point.y;
|
||||
});
|
||||
return {
|
||||
x: sumX / polygon.length,
|
||||
y: sumY / polygon.length,
|
||||
};
|
||||
}
|
||||
const areaFactor = 1 / (3 * area);
|
||||
return {
|
||||
x: cx * areaFactor,
|
||||
y: cy * areaFactor,
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user