@js-draw/math 1.16.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 +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;
|