@js-draw/math 1.17.0 → 1.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/Mat33.js +6 -1
- package/dist/cjs/Vec3.d.ts +2 -1
- package/dist/cjs/Vec3.js +5 -7
- package/dist/cjs/lib.d.ts +2 -1
- package/dist/cjs/lib.js +5 -1
- package/dist/cjs/shapes/BezierJSWrapper.d.ts +4 -0
- package/dist/cjs/shapes/BezierJSWrapper.js +35 -0
- package/dist/cjs/shapes/LineSegment2.d.ts +11 -0
- package/dist/cjs/shapes/LineSegment2.js +26 -1
- package/dist/cjs/shapes/Parameterized2DShape.d.ts +6 -1
- package/dist/cjs/shapes/Parameterized2DShape.js +6 -1
- package/dist/cjs/shapes/Path.d.ts +96 -12
- package/dist/cjs/shapes/Path.js +338 -15
- package/dist/cjs/shapes/QuadraticBezier.d.ts +2 -3
- package/dist/cjs/shapes/QuadraticBezier.js +2 -3
- package/dist/cjs/shapes/Rect2.d.ts +6 -1
- package/dist/cjs/shapes/Rect2.js +5 -1
- package/dist/cjs/utils/convexHull2Of.d.ts +9 -0
- package/dist/cjs/utils/convexHull2Of.js +61 -0
- package/dist/cjs/utils/convexHull2Of.test.d.ts +1 -0
- package/dist/mjs/Mat33.mjs +6 -1
- package/dist/mjs/Vec3.d.ts +2 -1
- package/dist/mjs/Vec3.mjs +5 -7
- package/dist/mjs/lib.d.ts +2 -1
- package/dist/mjs/lib.mjs +2 -1
- package/dist/mjs/shapes/BezierJSWrapper.d.ts +4 -0
- package/dist/mjs/shapes/BezierJSWrapper.mjs +35 -0
- package/dist/mjs/shapes/LineSegment2.d.ts +11 -0
- package/dist/mjs/shapes/LineSegment2.mjs +26 -1
- package/dist/mjs/shapes/Parameterized2DShape.d.ts +6 -1
- package/dist/mjs/shapes/Parameterized2DShape.mjs +6 -1
- package/dist/mjs/shapes/Path.d.ts +96 -12
- package/dist/mjs/shapes/Path.mjs +335 -14
- package/dist/mjs/shapes/QuadraticBezier.d.ts +2 -3
- package/dist/mjs/shapes/QuadraticBezier.mjs +2 -3
- package/dist/mjs/shapes/Rect2.d.ts +6 -1
- package/dist/mjs/shapes/Rect2.mjs +5 -1
- package/dist/mjs/utils/convexHull2Of.d.ts +9 -0
- package/dist/mjs/utils/convexHull2Of.mjs +59 -0
- package/dist/mjs/utils/convexHull2Of.test.d.ts +1 -0
- package/package.json +2 -2
- package/src/Mat33.ts +8 -2
- package/src/Vec3.test.ts +16 -0
- package/src/Vec3.ts +7 -8
- package/src/lib.ts +3 -0
- package/src/shapes/BezierJSWrapper.ts +41 -0
- package/src/shapes/LineSegment2.test.ts +26 -0
- package/src/shapes/LineSegment2.ts +31 -1
- package/src/shapes/Parameterized2DShape.ts +6 -1
- package/src/shapes/Path.test.ts +173 -5
- package/src/shapes/Path.ts +390 -18
- package/src/shapes/QuadraticBezier.test.ts +21 -0
- package/src/shapes/QuadraticBezier.ts +2 -3
- package/src/shapes/Rect2.ts +6 -2
- package/src/utils/convexHull2Of.test.ts +43 -0
- package/src/utils/convexHull2Of.ts +71 -0
@@ -0,0 +1,71 @@
|
|
1
|
+
import { Point2, Vec2 } from '../Vec2';
|
2
|
+
|
3
|
+
/**
|
4
|
+
* Implements Gift Wrapping, in $O(nh)$. This algorithm is not the most efficient in the worst case.
|
5
|
+
*
|
6
|
+
* See https://en.wikipedia.org/wiki/Gift_wrapping_algorithm
|
7
|
+
* and https://www.cs.jhu.edu/~misha/Spring16/06.pdf
|
8
|
+
*/
|
9
|
+
const convexHull2Of = (points: Point2[]) => {
|
10
|
+
if (points.length === 0) {
|
11
|
+
return [];
|
12
|
+
}
|
13
|
+
|
14
|
+
// 1. Start with a vertex on the hull
|
15
|
+
const lowestPoint = points.reduce(
|
16
|
+
(lowest, current) => current.y < lowest.y ? current : lowest,
|
17
|
+
points[0]
|
18
|
+
);
|
19
|
+
const vertices = [ lowestPoint ];
|
20
|
+
let toProcess = [...points.filter(p => !p.eq(lowestPoint))];
|
21
|
+
let lastBaseDirection = Vec2.of(-1, 0);
|
22
|
+
|
23
|
+
// 2. Find the point with greatest angle from the vertex:
|
24
|
+
//
|
25
|
+
// . . .
|
26
|
+
// . . / <- Notice that **all** other points are to the
|
27
|
+
// / **left** of the vector from the current
|
28
|
+
// ./ vertex to the new point.
|
29
|
+
while (toProcess.length > 0) {
|
30
|
+
const lastVertex = vertices[vertices.length - 1];
|
31
|
+
|
32
|
+
let smallestDotProductSoFar: number = lastBaseDirection.dot(lowestPoint.minus(lastVertex).normalizedOrZero());
|
33
|
+
let furthestPointSoFar = lowestPoint;
|
34
|
+
for (const point of toProcess) {
|
35
|
+
// Maximizing the angle is the same as minimizing the dot product:
|
36
|
+
// point.minus(lastVertex)
|
37
|
+
// ^
|
38
|
+
// /
|
39
|
+
// /
|
40
|
+
// ϑ /
|
41
|
+
// <-----. lastBaseDirection
|
42
|
+
const currentDotProduct = lastBaseDirection.dot(point.minus(lastVertex).normalizedOrZero());
|
43
|
+
|
44
|
+
if (currentDotProduct <= smallestDotProductSoFar) {
|
45
|
+
furthestPointSoFar = point;
|
46
|
+
smallestDotProductSoFar = currentDotProduct;
|
47
|
+
}
|
48
|
+
}
|
49
|
+
toProcess = toProcess.filter(p => !p.eq(furthestPointSoFar));
|
50
|
+
|
51
|
+
const newBaseDirection = furthestPointSoFar.minus(lastVertex).normalized();
|
52
|
+
|
53
|
+
// If the last vertex is on the same edge as the current, there's no need to include
|
54
|
+
// the previous one.
|
55
|
+
if (Math.abs(newBaseDirection.dot(lastBaseDirection)) === 1 && vertices.length > 1) {
|
56
|
+
vertices.pop();
|
57
|
+
}
|
58
|
+
|
59
|
+
// Stoping condition: We've gone in a full circle.
|
60
|
+
if (furthestPointSoFar.eq(lowestPoint)) {
|
61
|
+
break;
|
62
|
+
} else {
|
63
|
+
vertices.push(furthestPointSoFar);
|
64
|
+
lastBaseDirection = lastVertex.minus(furthestPointSoFar).normalized();
|
65
|
+
}
|
66
|
+
}
|
67
|
+
|
68
|
+
return vertices;
|
69
|
+
};
|
70
|
+
|
71
|
+
export default convexHull2Of;
|