@js-draw/math 1.16.0 → 1.18.0
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/cjs/Mat33.js +6 -1
- package/dist/cjs/Vec3.d.ts +23 -1
- package/dist/cjs/Vec3.js +33 -7
- package/dist/cjs/lib.d.ts +2 -1
- package/dist/cjs/lib.js +5 -1
- package/dist/cjs/shapes/Abstract2DShape.d.ts +3 -0
- package/dist/cjs/shapes/BezierJSWrapper.d.ts +19 -5
- package/dist/cjs/shapes/BezierJSWrapper.js +170 -18
- package/dist/cjs/shapes/LineSegment2.d.ts +45 -5
- package/dist/cjs/shapes/LineSegment2.js +89 -11
- package/dist/cjs/shapes/Parameterized2DShape.d.ts +36 -0
- package/dist/cjs/shapes/Parameterized2DShape.js +20 -0
- package/dist/cjs/shapes/Path.d.ts +131 -13
- package/dist/cjs/shapes/Path.js +507 -26
- package/dist/cjs/shapes/PointShape2D.d.ts +14 -3
- package/dist/cjs/shapes/PointShape2D.js +28 -5
- package/dist/cjs/shapes/QuadraticBezier.d.ts +6 -3
- package/dist/cjs/shapes/QuadraticBezier.js +21 -7
- package/dist/cjs/shapes/Rect2.d.ts +9 -1
- package/dist/cjs/shapes/Rect2.js +9 -2
- 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 +23 -1
- package/dist/mjs/Vec3.mjs +33 -7
- package/dist/mjs/lib.d.ts +2 -1
- package/dist/mjs/lib.mjs +2 -1
- package/dist/mjs/shapes/Abstract2DShape.d.ts +3 -0
- package/dist/mjs/shapes/BezierJSWrapper.d.ts +19 -5
- package/dist/mjs/shapes/BezierJSWrapper.mjs +168 -18
- package/dist/mjs/shapes/LineSegment2.d.ts +45 -5
- package/dist/mjs/shapes/LineSegment2.mjs +89 -11
- package/dist/mjs/shapes/Parameterized2DShape.d.ts +36 -0
- package/dist/mjs/shapes/Parameterized2DShape.mjs +13 -0
- package/dist/mjs/shapes/Path.d.ts +131 -13
- package/dist/mjs/shapes/Path.mjs +504 -25
- package/dist/mjs/shapes/PointShape2D.d.ts +14 -3
- package/dist/mjs/shapes/PointShape2D.mjs +28 -5
- package/dist/mjs/shapes/QuadraticBezier.d.ts +6 -3
- package/dist/mjs/shapes/QuadraticBezier.mjs +21 -7
- package/dist/mjs/shapes/Rect2.d.ts +9 -1
- package/dist/mjs/shapes/Rect2.mjs +9 -2
- 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 +5 -5
- package/src/Mat33.ts +8 -2
- package/src/Vec3.test.ts +42 -7
- package/src/Vec3.ts +37 -8
- package/src/lib.ts +5 -0
- package/src/shapes/Abstract2DShape.ts +3 -0
- package/src/shapes/BezierJSWrapper.ts +195 -14
- package/src/shapes/LineSegment2.test.ts +61 -1
- package/src/shapes/LineSegment2.ts +110 -12
- package/src/shapes/Parameterized2DShape.ts +44 -0
- package/src/shapes/Path.test.ts +233 -5
- package/src/shapes/Path.ts +593 -37
- package/src/shapes/PointShape2D.ts +33 -6
- package/src/shapes/QuadraticBezier.test.ts +69 -12
- package/src/shapes/QuadraticBezier.ts +25 -8
- package/src/shapes/Rect2.ts +10 -3
- package/src/utils/convexHull2Of.test.ts +43 -0
- package/src/utils/convexHull2Of.ts +71 -0
@@ -3,29 +3,52 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
4
4
|
};
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
6
|
-
const
|
6
|
+
const Vec2_1 = require("../Vec2");
|
7
|
+
const Parameterized2DShape_1 = __importDefault(require("./Parameterized2DShape"));
|
7
8
|
const Rect2_1 = __importDefault(require("./Rect2"));
|
8
9
|
/**
|
9
10
|
* Like a {@link Point2}, but with additional functionality (e.g. SDF).
|
10
11
|
*
|
11
12
|
* Access the internal `Point2` using the `p` property.
|
12
13
|
*/
|
13
|
-
class PointShape2D extends
|
14
|
+
class PointShape2D extends Parameterized2DShape_1.default {
|
14
15
|
constructor(p) {
|
15
16
|
super();
|
16
17
|
this.p = p;
|
17
18
|
}
|
18
19
|
signedDistance(point) {
|
19
|
-
return this.p.
|
20
|
+
return this.p.distanceTo(point);
|
20
21
|
}
|
21
|
-
|
22
|
+
argIntersectsLineSegment(lineSegment, epsilon) {
|
22
23
|
if (lineSegment.containsPoint(this.p, epsilon)) {
|
23
|
-
return [
|
24
|
+
return [0];
|
24
25
|
}
|
25
26
|
return [];
|
26
27
|
}
|
27
28
|
getTightBoundingBox() {
|
28
29
|
return new Rect2_1.default(this.p.x, this.p.y, 0, 0);
|
29
30
|
}
|
31
|
+
at(_t) {
|
32
|
+
return this.p;
|
33
|
+
}
|
34
|
+
/**
|
35
|
+
* Returns an arbitrary unit-length vector.
|
36
|
+
*/
|
37
|
+
normalAt(_t) {
|
38
|
+
// Return a vector that makes sense.
|
39
|
+
return Vec2_1.Vec2.unitY;
|
40
|
+
}
|
41
|
+
tangentAt(_t) {
|
42
|
+
return Vec2_1.Vec2.unitX;
|
43
|
+
}
|
44
|
+
splitAt(_t) {
|
45
|
+
return [this];
|
46
|
+
}
|
47
|
+
nearestPointTo(_point) {
|
48
|
+
return {
|
49
|
+
point: this.p,
|
50
|
+
parameterValue: 0,
|
51
|
+
};
|
52
|
+
}
|
30
53
|
}
|
31
54
|
exports.default = PointShape2D;
|
@@ -2,10 +2,9 @@ import { Point2, Vec2 } from '../Vec2';
|
|
2
2
|
import BezierJSWrapper from './BezierJSWrapper';
|
3
3
|
import Rect2 from './Rect2';
|
4
4
|
/**
|
5
|
-
*
|
5
|
+
* Represents a 2D Bézier curve.
|
6
6
|
*
|
7
|
-
*
|
8
|
-
* without loading it at all (e.g. `normal`, `at`, and `approximateDistance`).
|
7
|
+
* **Note**: Many Bézier operations use `bezier-js`'s.
|
9
8
|
*/
|
10
9
|
export declare class QuadraticBezier extends BezierJSWrapper {
|
11
10
|
readonly p0: Point2;
|
@@ -18,11 +17,15 @@ export declare class QuadraticBezier extends BezierJSWrapper {
|
|
18
17
|
*/
|
19
18
|
private static componentAt;
|
20
19
|
private static derivativeComponentAt;
|
20
|
+
private static secondDerivativeComponentAt;
|
21
21
|
/**
|
22
22
|
* @returns the curve evaluated at `t`.
|
23
|
+
*
|
24
|
+
* `t` should be a number in `[0, 1]`.
|
23
25
|
*/
|
24
26
|
at(t: number): Point2;
|
25
27
|
derivativeAt(t: number): Point2;
|
28
|
+
secondDerivativeAt(t: number): Point2;
|
26
29
|
normal(t: number): Vec2;
|
27
30
|
/** @returns an overestimate of this shape's bounding box. */
|
28
31
|
getLooseBoundingBox(): Rect2;
|
@@ -9,10 +9,9 @@ const solveQuadratic_1 = __importDefault(require("../polynomial/solveQuadratic")
|
|
9
9
|
const BezierJSWrapper_1 = __importDefault(require("./BezierJSWrapper"));
|
10
10
|
const Rect2_1 = __importDefault(require("./Rect2"));
|
11
11
|
/**
|
12
|
-
*
|
12
|
+
* Represents a 2D Bézier curve.
|
13
13
|
*
|
14
|
-
*
|
15
|
-
* without loading it at all (e.g. `normal`, `at`, and `approximateDistance`).
|
14
|
+
* **Note**: Many Bézier operations use `bezier-js`'s.
|
16
15
|
*/
|
17
16
|
class QuadraticBezier extends BezierJSWrapper_1.default {
|
18
17
|
constructor(p0, p1, p2) {
|
@@ -31,10 +30,19 @@ class QuadraticBezier extends BezierJSWrapper_1.default {
|
|
31
30
|
static derivativeComponentAt(t, p0, p1, p2) {
|
32
31
|
return -2 * p0 + 2 * p1 + 2 * t * (p0 - 2 * p1 + p2);
|
33
32
|
}
|
33
|
+
static secondDerivativeComponentAt(t, p0, p1, p2) {
|
34
|
+
return 2 * (p0 - 2 * p1 + p2);
|
35
|
+
}
|
34
36
|
/**
|
35
37
|
* @returns the curve evaluated at `t`.
|
38
|
+
*
|
39
|
+
* `t` should be a number in `[0, 1]`.
|
36
40
|
*/
|
37
41
|
at(t) {
|
42
|
+
if (t === 0)
|
43
|
+
return this.p0;
|
44
|
+
if (t === 1)
|
45
|
+
return this.p2;
|
38
46
|
const p0 = this.p0;
|
39
47
|
const p1 = this.p1;
|
40
48
|
const p2 = this.p2;
|
@@ -46,6 +54,12 @@ class QuadraticBezier extends BezierJSWrapper_1.default {
|
|
46
54
|
const p2 = this.p2;
|
47
55
|
return Vec2_1.Vec2.of(QuadraticBezier.derivativeComponentAt(t, p0.x, p1.x, p2.x), QuadraticBezier.derivativeComponentAt(t, p0.y, p1.y, p2.y));
|
48
56
|
}
|
57
|
+
secondDerivativeAt(t) {
|
58
|
+
const p0 = this.p0;
|
59
|
+
const p1 = this.p1;
|
60
|
+
const p2 = this.p2;
|
61
|
+
return Vec2_1.Vec2.of(QuadraticBezier.secondDerivativeComponentAt(t, p0.x, p1.x, p2.x), QuadraticBezier.secondDerivativeComponentAt(t, p0.y, p1.y, p2.y));
|
62
|
+
}
|
49
63
|
normal(t) {
|
50
64
|
const tangent = this.derivativeAt(t);
|
51
65
|
return tangent.orthog().normalized();
|
@@ -106,10 +120,10 @@ class QuadraticBezier extends BezierJSWrapper_1.default {
|
|
106
120
|
}
|
107
121
|
const at1 = this.at(min1);
|
108
122
|
const at2 = this.at(min2);
|
109
|
-
const sqrDist1 = at1.
|
110
|
-
const sqrDist2 = at2.
|
111
|
-
const sqrDist3 = this.at(0).
|
112
|
-
const sqrDist4 = this.at(1).
|
123
|
+
const sqrDist1 = at1.squareDistanceTo(point);
|
124
|
+
const sqrDist2 = at2.squareDistanceTo(point);
|
125
|
+
const sqrDist3 = this.at(0).squareDistanceTo(point);
|
126
|
+
const sqrDist4 = this.at(1).squareDistanceTo(point);
|
113
127
|
return Math.sqrt(Math.min(sqrDist1, sqrDist2, sqrDist3, sqrDist4));
|
114
128
|
}
|
115
129
|
getPoints() {
|
@@ -3,7 +3,7 @@ import Mat33 from '../Mat33';
|
|
3
3
|
import { Point2, Vec2 } from '../Vec2';
|
4
4
|
import Abstract2DShape from './Abstract2DShape';
|
5
5
|
import Vec3 from '../Vec3';
|
6
|
-
/** An object that can be converted to a Rect2. */
|
6
|
+
/** An object that can be converted to a {@link Rect2}. */
|
7
7
|
export interface RectTemplate {
|
8
8
|
x: number;
|
9
9
|
y: number;
|
@@ -12,6 +12,11 @@ export interface RectTemplate {
|
|
12
12
|
width?: number;
|
13
13
|
height?: number;
|
14
14
|
}
|
15
|
+
/**
|
16
|
+
* Represents a rectangle in 2D space, parallel to the XY axes.
|
17
|
+
*
|
18
|
+
* `invariant: w ≥ 0, h ≥ 0, immutable`
|
19
|
+
*/
|
15
20
|
export declare class Rect2 extends Abstract2DShape {
|
16
21
|
readonly x: number;
|
17
22
|
readonly y: number;
|
@@ -25,6 +30,9 @@ export declare class Rect2 extends Abstract2DShape {
|
|
25
30
|
resizedTo(size: Vec2): Rect2;
|
26
31
|
containsPoint(other: Point2): boolean;
|
27
32
|
containsRect(other: Rect2): boolean;
|
33
|
+
/**
|
34
|
+
* @returns true iff this and `other` overlap
|
35
|
+
*/
|
28
36
|
intersects(other: Rect2): boolean;
|
29
37
|
intersection(other: Rect2): Rect2 | null;
|
30
38
|
union(other: Rect2): Rect2;
|
package/dist/cjs/shapes/Rect2.js
CHANGED
@@ -7,7 +7,11 @@ exports.Rect2 = void 0;
|
|
7
7
|
const LineSegment2_1 = __importDefault(require("./LineSegment2"));
|
8
8
|
const Vec2_1 = require("../Vec2");
|
9
9
|
const Abstract2DShape_1 = __importDefault(require("./Abstract2DShape"));
|
10
|
-
|
10
|
+
/**
|
11
|
+
* Represents a rectangle in 2D space, parallel to the XY axes.
|
12
|
+
*
|
13
|
+
* `invariant: w ≥ 0, h ≥ 0, immutable`
|
14
|
+
*/
|
11
15
|
class Rect2 extends Abstract2DShape_1.default {
|
12
16
|
constructor(x, y, w, h) {
|
13
17
|
super();
|
@@ -44,6 +48,9 @@ class Rect2 extends Abstract2DShape_1.default {
|
|
44
48
|
&& this.x + this.w >= other.x + other.w
|
45
49
|
&& this.y + this.h >= other.y + other.h;
|
46
50
|
}
|
51
|
+
/**
|
52
|
+
* @returns true iff this and `other` overlap
|
53
|
+
*/
|
47
54
|
intersects(other) {
|
48
55
|
// Project along x/y axes.
|
49
56
|
const thisMinX = this.x;
|
@@ -130,7 +137,7 @@ class Rect2 extends Abstract2DShape_1.default {
|
|
130
137
|
let closest = null;
|
131
138
|
let closestDist = null;
|
132
139
|
for (const point of closestEdgePoints) {
|
133
|
-
const dist = point.
|
140
|
+
const dist = point.distanceTo(target);
|
134
141
|
if (closestDist === null || dist < closestDist) {
|
135
142
|
closest = point;
|
136
143
|
closestDist = dist;
|
@@ -0,0 +1,9 @@
|
|
1
|
+
import { Point2 } from '../Vec2';
|
2
|
+
/**
|
3
|
+
* Implements Gift Wrapping, in $O(nh)$. This algorithm is not the most efficient in the worst case.
|
4
|
+
*
|
5
|
+
* See https://en.wikipedia.org/wiki/Gift_wrapping_algorithm
|
6
|
+
* and https://www.cs.jhu.edu/~misha/Spring16/06.pdf
|
7
|
+
*/
|
8
|
+
declare const convexHull2Of: (points: Point2[]) => import("../Vec3").Vec3[];
|
9
|
+
export default convexHull2Of;
|
@@ -0,0 +1,61 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
const Vec2_1 = require("../Vec2");
|
4
|
+
/**
|
5
|
+
* Implements Gift Wrapping, in $O(nh)$. This algorithm is not the most efficient in the worst case.
|
6
|
+
*
|
7
|
+
* See https://en.wikipedia.org/wiki/Gift_wrapping_algorithm
|
8
|
+
* and https://www.cs.jhu.edu/~misha/Spring16/06.pdf
|
9
|
+
*/
|
10
|
+
const convexHull2Of = (points) => {
|
11
|
+
if (points.length === 0) {
|
12
|
+
return [];
|
13
|
+
}
|
14
|
+
// 1. Start with a vertex on the hull
|
15
|
+
const lowestPoint = points.reduce((lowest, current) => current.y < lowest.y ? current : lowest, points[0]);
|
16
|
+
const vertices = [lowestPoint];
|
17
|
+
let toProcess = [...points.filter(p => !p.eq(lowestPoint))];
|
18
|
+
let lastBaseDirection = Vec2_1.Vec2.of(-1, 0);
|
19
|
+
// 2. Find the point with greatest angle from the vertex:
|
20
|
+
//
|
21
|
+
// . . .
|
22
|
+
// . . / <- Notice that **all** other points are to the
|
23
|
+
// / **left** of the vector from the current
|
24
|
+
// ./ vertex to the new point.
|
25
|
+
while (toProcess.length > 0) {
|
26
|
+
const lastVertex = vertices[vertices.length - 1];
|
27
|
+
let smallestDotProductSoFar = lastBaseDirection.dot(lowestPoint.minus(lastVertex).normalizedOrZero());
|
28
|
+
let furthestPointSoFar = lowestPoint;
|
29
|
+
for (const point of toProcess) {
|
30
|
+
// Maximizing the angle is the same as minimizing the dot product:
|
31
|
+
// point.minus(lastVertex)
|
32
|
+
// ^
|
33
|
+
// /
|
34
|
+
// /
|
35
|
+
// ϑ /
|
36
|
+
// <-----. lastBaseDirection
|
37
|
+
const currentDotProduct = lastBaseDirection.dot(point.minus(lastVertex).normalizedOrZero());
|
38
|
+
if (currentDotProduct <= smallestDotProductSoFar) {
|
39
|
+
furthestPointSoFar = point;
|
40
|
+
smallestDotProductSoFar = currentDotProduct;
|
41
|
+
}
|
42
|
+
}
|
43
|
+
toProcess = toProcess.filter(p => !p.eq(furthestPointSoFar));
|
44
|
+
const newBaseDirection = furthestPointSoFar.minus(lastVertex).normalized();
|
45
|
+
// If the last vertex is on the same edge as the current, there's no need to include
|
46
|
+
// the previous one.
|
47
|
+
if (Math.abs(newBaseDirection.dot(lastBaseDirection)) === 1 && vertices.length > 1) {
|
48
|
+
vertices.pop();
|
49
|
+
}
|
50
|
+
// Stoping condition: We've gone in a full circle.
|
51
|
+
if (furthestPointSoFar.eq(lowestPoint)) {
|
52
|
+
break;
|
53
|
+
}
|
54
|
+
else {
|
55
|
+
vertices.push(furthestPointSoFar);
|
56
|
+
lastBaseDirection = lastVertex.minus(furthestPointSoFar).normalized();
|
57
|
+
}
|
58
|
+
}
|
59
|
+
return vertices;
|
60
|
+
};
|
61
|
+
exports.default = convexHull2Of;
|
@@ -0,0 +1 @@
|
|
1
|
+
export {};
|
package/dist/mjs/Mat33.mjs
CHANGED
@@ -334,7 +334,11 @@ export class Mat33 {
|
|
334
334
|
return Mat33.identity;
|
335
335
|
}
|
336
336
|
const parseArguments = (argumentString) => {
|
337
|
-
|
337
|
+
const parsed = argumentString.split(/[, \t\n]+/g).map(argString => {
|
338
|
+
// Handle trailing spaces/commands
|
339
|
+
if (argString.trim() === '') {
|
340
|
+
return null;
|
341
|
+
}
|
338
342
|
let isPercentage = false;
|
339
343
|
if (argString.endsWith('%')) {
|
340
344
|
isPercentage = true;
|
@@ -355,6 +359,7 @@ export class Mat33 {
|
|
355
359
|
}
|
356
360
|
return argNumber;
|
357
361
|
});
|
362
|
+
return parsed.filter(n => n !== null);
|
358
363
|
};
|
359
364
|
const keywordToAction = {
|
360
365
|
matrix: (matrixData) => {
|
package/dist/mjs/Vec3.d.ts
CHANGED
@@ -35,11 +35,31 @@ export declare class Vec3 {
|
|
35
35
|
length(): number;
|
36
36
|
magnitude(): number;
|
37
37
|
magnitudeSquared(): number;
|
38
|
+
/**
|
39
|
+
* Interpreting this vector as a point in ℝ^3, computes the square distance
|
40
|
+
* to another point, `p`.
|
41
|
+
*
|
42
|
+
* Equivalent to `.minus(p).magnitudeSquared()`.
|
43
|
+
*/
|
44
|
+
squareDistanceTo(p: Vec3): number;
|
45
|
+
/**
|
46
|
+
* Interpreting this vector as a point in ℝ³, returns the distance to the point
|
47
|
+
* `p`.
|
48
|
+
*
|
49
|
+
* Equivalent to `.minus(p).magnitude()`.
|
50
|
+
*/
|
51
|
+
distanceTo(p: Vec3): number;
|
38
52
|
/**
|
39
53
|
* Returns the entry of this with the greatest magnitude.
|
40
54
|
*
|
41
55
|
* In other words, returns $\max \{ |x| : x \in {\bf v} \}$, where ${\bf v}$ is the set of
|
42
56
|
* all entries of this vector.
|
57
|
+
*
|
58
|
+
* **Example**:
|
59
|
+
* ```ts,runnable,console
|
60
|
+
* import { Vec3 } from '@js-draw/math';
|
61
|
+
* console.log(Vec3.of(-1, -10, 8).maximumEntryMagnitude()); // -> 10
|
62
|
+
* ```
|
43
63
|
*/
|
44
64
|
maximumEntryMagnitude(): number;
|
45
65
|
/**
|
@@ -50,6 +70,7 @@ export declare class Vec3 {
|
|
50
70
|
* As such, observing that `Math.atan2(-0, -1)` $\approx -\pi$ and `Math.atan2(0, -1)`$\approx \pi$
|
51
71
|
* the resultant angle is in the range $[-\pi, pi]$.
|
52
72
|
*
|
73
|
+
* **Example**:
|
53
74
|
* ```ts,runnable,console
|
54
75
|
* import { Vec2 } from '@js-draw/math';
|
55
76
|
* console.log(Vec2.of(-1, -0).angle()); // atan2(-0, -1)
|
@@ -113,7 +134,8 @@ export declare class Vec3 {
|
|
113
134
|
* Returns a vector with each component acted on by `fn`.
|
114
135
|
*
|
115
136
|
* @example
|
116
|
-
* ```
|
137
|
+
* ```ts,runnable,console
|
138
|
+
* import { Vec3 } from '@js-draw/math';
|
117
139
|
* console.log(Vec3.of(1, 2, 3).map(val => val + 1)); // → Vec(2, 3, 4)
|
118
140
|
* ```
|
119
141
|
*/
|
package/dist/mjs/Vec3.mjs
CHANGED
@@ -55,11 +55,38 @@ export class Vec3 {
|
|
55
55
|
magnitudeSquared() {
|
56
56
|
return this.dot(this);
|
57
57
|
}
|
58
|
+
/**
|
59
|
+
* Interpreting this vector as a point in ℝ^3, computes the square distance
|
60
|
+
* to another point, `p`.
|
61
|
+
*
|
62
|
+
* Equivalent to `.minus(p).magnitudeSquared()`.
|
63
|
+
*/
|
64
|
+
squareDistanceTo(p) {
|
65
|
+
const dx = this.x - p.x;
|
66
|
+
const dy = this.y - p.y;
|
67
|
+
const dz = this.z - p.z;
|
68
|
+
return dx * dx + dy * dy + dz * dz;
|
69
|
+
}
|
70
|
+
/**
|
71
|
+
* Interpreting this vector as a point in ℝ³, returns the distance to the point
|
72
|
+
* `p`.
|
73
|
+
*
|
74
|
+
* Equivalent to `.minus(p).magnitude()`.
|
75
|
+
*/
|
76
|
+
distanceTo(p) {
|
77
|
+
return Math.sqrt(this.squareDistanceTo(p));
|
78
|
+
}
|
58
79
|
/**
|
59
80
|
* Returns the entry of this with the greatest magnitude.
|
60
81
|
*
|
61
82
|
* In other words, returns $\max \{ |x| : x \in {\bf v} \}$, where ${\bf v}$ is the set of
|
62
83
|
* all entries of this vector.
|
84
|
+
*
|
85
|
+
* **Example**:
|
86
|
+
* ```ts,runnable,console
|
87
|
+
* import { Vec3 } from '@js-draw/math';
|
88
|
+
* console.log(Vec3.of(-1, -10, 8).maximumEntryMagnitude()); // -> 10
|
89
|
+
* ```
|
63
90
|
*/
|
64
91
|
maximumEntryMagnitude() {
|
65
92
|
return Math.max(Math.abs(this.x), Math.max(Math.abs(this.y), Math.abs(this.z)));
|
@@ -72,6 +99,7 @@ export class Vec3 {
|
|
72
99
|
* As such, observing that `Math.atan2(-0, -1)` $\approx -\pi$ and `Math.atan2(0, -1)`$\approx \pi$
|
73
100
|
* the resultant angle is in the range $[-\pi, pi]$.
|
74
101
|
*
|
102
|
+
* **Example**:
|
75
103
|
* ```ts,runnable,console
|
76
104
|
* import { Vec2 } from '@js-draw/math';
|
77
105
|
* console.log(Vec2.of(-1, -0).angle()); // atan2(-0, -1)
|
@@ -175,7 +203,8 @@ export class Vec3 {
|
|
175
203
|
* Returns a vector with each component acted on by `fn`.
|
176
204
|
*
|
177
205
|
* @example
|
178
|
-
* ```
|
206
|
+
* ```ts,runnable,console
|
207
|
+
* import { Vec3 } from '@js-draw/math';
|
179
208
|
* console.log(Vec3.of(1, 2, 3).map(val => val + 1)); // → Vec(2, 3, 4)
|
180
209
|
* ```
|
181
210
|
*/
|
@@ -199,12 +228,9 @@ export class Vec3 {
|
|
199
228
|
* ```
|
200
229
|
*/
|
201
230
|
eq(other, fuzz = 1e-10) {
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
}
|
206
|
-
}
|
207
|
-
return true;
|
231
|
+
return (Math.abs(other.x - this.x) <= fuzz
|
232
|
+
&& Math.abs(other.y - this.y) <= fuzz
|
233
|
+
&& Math.abs(other.z - this.z) <= fuzz);
|
208
234
|
}
|
209
235
|
toString() {
|
210
236
|
return `Vec(${this.x}, ${this.y}, ${this.z})`;
|
package/dist/mjs/lib.d.ts
CHANGED
@@ -17,8 +17,9 @@
|
|
17
17
|
* @packageDocumentation
|
18
18
|
*/
|
19
19
|
export { LineSegment2 } from './shapes/LineSegment2';
|
20
|
-
export { Path, PathCommandType, PathCommand, LinePathCommand, MoveToPathCommand, QuadraticBezierPathCommand, CubicBezierPathCommand, } from './shapes/Path';
|
20
|
+
export { Path, IntersectionResult as PathIntersectionResult, CurveIndexRecord as PathCurveIndex, stepCurveIndexBy as stepPathIndexBy, compareCurveIndices as comparePathIndices, PathCommandType, PathCommand, LinePathCommand, MoveToPathCommand, QuadraticBezierPathCommand, CubicBezierPathCommand, } from './shapes/Path';
|
21
21
|
export { Rect2 } from './shapes/Rect2';
|
22
|
+
export { Parameterized2DShape } from './shapes/Parameterized2DShape';
|
22
23
|
export { QuadraticBezier } from './shapes/QuadraticBezier';
|
23
24
|
export { Abstract2DShape } from './shapes/Abstract2DShape';
|
24
25
|
export { Mat33, Mat33Array } from './Mat33';
|
package/dist/mjs/lib.mjs
CHANGED
@@ -17,8 +17,9 @@
|
|
17
17
|
* @packageDocumentation
|
18
18
|
*/
|
19
19
|
export { LineSegment2 } from './shapes/LineSegment2.mjs';
|
20
|
-
export { Path, PathCommandType, } from './shapes/Path.mjs';
|
20
|
+
export { Path, stepCurveIndexBy as stepPathIndexBy, compareCurveIndices as comparePathIndices, PathCommandType, } from './shapes/Path.mjs';
|
21
21
|
export { Rect2 } from './shapes/Rect2.mjs';
|
22
|
+
export { Parameterized2DShape } from './shapes/Parameterized2DShape.mjs';
|
22
23
|
export { QuadraticBezier } from './shapes/QuadraticBezier.mjs';
|
23
24
|
export { Abstract2DShape } from './shapes/Abstract2DShape.mjs';
|
24
25
|
export { Mat33 } from './Mat33.mjs';
|
@@ -38,6 +38,9 @@ export declare abstract class Abstract2DShape {
|
|
38
38
|
containsPoint(point: Point2, epsilon?: number): boolean;
|
39
39
|
/**
|
40
40
|
* Returns a bounding box that precisely fits the content of this shape.
|
41
|
+
*
|
42
|
+
* **Note**: This bounding box should aligned with the x/y axes. (Thus, it may be
|
43
|
+
* possible to find a tighter bounding box not axes-aligned).
|
41
44
|
*/
|
42
45
|
abstract getTightBoundingBox(): Rect2;
|
43
46
|
/**
|
@@ -1,21 +1,22 @@
|
|
1
1
|
import { Bezier } from 'bezier-js';
|
2
2
|
import { Point2, Vec2 } from '../Vec2';
|
3
|
-
import Abstract2DShape from './Abstract2DShape';
|
4
3
|
import LineSegment2 from './LineSegment2';
|
5
4
|
import Rect2 from './Rect2';
|
5
|
+
import Parameterized2DShape from './Parameterized2DShape';
|
6
6
|
/**
|
7
7
|
* A lazy-initializing wrapper around Bezier-js.
|
8
8
|
*
|
9
9
|
* Subclasses may override `at`, `derivativeAt`, and `normal` with functions
|
10
10
|
* that do not initialize a `bezier-js` `Bezier`.
|
11
11
|
*
|
12
|
-
* Do not use this class directly
|
12
|
+
* **Do not use this class directly.** It may be removed/replaced in a future release.
|
13
13
|
* @internal
|
14
14
|
*/
|
15
|
-
declare abstract class BezierJSWrapper extends
|
15
|
+
export declare abstract class BezierJSWrapper extends Parameterized2DShape {
|
16
16
|
#private;
|
17
|
+
protected constructor(bezierJsBezier?: Bezier);
|
17
18
|
/** Returns the start, control points, and end point of this Bézier. */
|
18
|
-
abstract getPoints(): Point2[];
|
19
|
+
abstract getPoints(): readonly Point2[];
|
19
20
|
protected getBezier(): Bezier;
|
20
21
|
signedDistance(point: Point2): number;
|
21
22
|
/**
|
@@ -29,8 +30,21 @@ declare abstract class BezierJSWrapper extends Abstract2DShape {
|
|
29
30
|
*/
|
30
31
|
at(t: number): Point2;
|
31
32
|
derivativeAt(t: number): Point2;
|
33
|
+
secondDerivativeAt(t: number): Point2;
|
32
34
|
normal(t: number): Vec2;
|
35
|
+
normalAt(t: number): Vec2;
|
36
|
+
tangentAt(t: number): Vec2;
|
33
37
|
getTightBoundingBox(): Rect2;
|
34
|
-
|
38
|
+
argIntersectsLineSegment(line: LineSegment2): number[];
|
39
|
+
splitAt(t: number): [BezierJSWrapper] | [BezierJSWrapper, BezierJSWrapper];
|
40
|
+
nearestPointTo(point: Point2): {
|
41
|
+
parameterValue: number;
|
42
|
+
point: import("../Vec3").Vec3;
|
43
|
+
};
|
44
|
+
intersectsBezier(other: BezierJSWrapper): {
|
45
|
+
parameterValue: number;
|
46
|
+
point: import("../Vec3").Vec3;
|
47
|
+
}[];
|
48
|
+
toString(): string;
|
35
49
|
}
|
36
50
|
export default BezierJSWrapper;
|