@js-draw/math 1.18.0 → 1.21.1
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/LICENSE +1 -1
- package/dist/cjs/Mat33.d.ts +91 -0
- package/dist/cjs/Mat33.js +88 -0
- package/dist/cjs/Vec2.d.ts +3 -40
- package/dist/cjs/Vec2.js +8 -46
- package/dist/cjs/Vec3.d.ts +112 -16
- package/dist/cjs/Vec3.js +184 -136
- package/dist/cjs/shapes/LineSegment2.d.ts +13 -2
- package/dist/cjs/shapes/LineSegment2.js +13 -2
- package/dist/cjs/shapes/PointShape2D.d.ts +33 -1
- package/dist/cjs/shapes/Rect2.d.ts +35 -3
- package/dist/cjs/shapes/Rect2.js +3 -3
- package/dist/mjs/Mat33.d.ts +91 -0
- package/dist/mjs/Mat33.mjs +88 -0
- package/dist/mjs/Vec2.d.ts +3 -40
- package/dist/mjs/Vec2.mjs +6 -42
- package/dist/mjs/Vec3.d.ts +112 -16
- package/dist/mjs/Vec3.mjs +183 -134
- package/dist/mjs/shapes/LineSegment2.d.ts +13 -2
- package/dist/mjs/shapes/LineSegment2.mjs +13 -2
- package/dist/mjs/shapes/PointShape2D.d.ts +33 -1
- package/dist/mjs/shapes/Rect2.d.ts +35 -3
- package/dist/mjs/shapes/Rect2.mjs +3 -3
- package/dist-test/test_imports/yarn.lock +12 -0
- package/package.json +6 -7
- package/src/Mat33.ts +92 -1
- package/src/Vec2.test.ts +5 -3
- package/src/Vec2.ts +7 -47
- package/src/Vec3.ts +408 -121
- package/src/shapes/BezierJSWrapper.ts +1 -1
- package/src/shapes/LineSegment2.ts +13 -2
- package/src/shapes/Rect2.ts +3 -3
- package/dist-test/test_imports/package-lock.json +0 -13
package/dist/mjs/Vec3.mjs
CHANGED
@@ -1,29 +1,10 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
* Can also be used to represent a two-component vector.
|
4
|
-
*
|
5
|
-
* A `Vec3` is immutable.
|
6
|
-
*
|
7
|
-
* @example
|
8
|
-
*
|
9
|
-
* ```ts,runnable,console
|
10
|
-
* import { Vec3 } from '@js-draw/math';
|
11
|
-
*
|
12
|
-
* console.log('Vector addition:', Vec3.of(1, 2, 3).plus(Vec3.of(0, 1, 0)));
|
13
|
-
* console.log('Scalar multiplication:', Vec3.of(1, 2, 3).times(2));
|
14
|
-
* console.log('Cross products:', Vec3.unitX.cross(Vec3.unitY));
|
15
|
-
* console.log('Magnitude:', Vec3.of(1, 2, 3).length(), 'or', Vec3.of(1, 2, 3).magnitude());
|
16
|
-
* console.log('Square Magnitude:', Vec3.of(1, 2, 3).magnitudeSquared());
|
17
|
-
* console.log('As an array:', Vec3.unitZ.asArray());
|
18
|
-
* ```
|
19
|
-
*/
|
20
|
-
export class Vec3 {
|
1
|
+
const defaultEqlTolerance = 1e-10;
|
2
|
+
class Vec3Impl {
|
21
3
|
constructor(x, y, z) {
|
22
4
|
this.x = x;
|
23
5
|
this.y = y;
|
24
6
|
this.z = z;
|
25
7
|
}
|
26
|
-
/** Returns the x, y components of this. */
|
27
8
|
get xy() {
|
28
9
|
// Useful for APIs that behave differently if .z is present.
|
29
10
|
return {
|
@@ -31,10 +12,6 @@ export class Vec3 {
|
|
31
12
|
y: this.y,
|
32
13
|
};
|
33
14
|
}
|
34
|
-
/** Construct a vector from three components. */
|
35
|
-
static of(x, y, z) {
|
36
|
-
return new Vec3(x, y, z);
|
37
|
-
}
|
38
15
|
/** Returns this' `idx`th component. For example, `Vec3.of(1, 2, 3).at(1) → 2`. */
|
39
16
|
at(idx) {
|
40
17
|
if (idx === 0)
|
@@ -45,89 +22,40 @@ export class Vec3 {
|
|
45
22
|
return this.z;
|
46
23
|
throw new Error(`${idx} out of bounds!`);
|
47
24
|
}
|
48
|
-
/** Alias for this.magnitude. */
|
49
25
|
length() {
|
50
26
|
return this.magnitude();
|
51
27
|
}
|
52
28
|
magnitude() {
|
53
|
-
return Math.sqrt(this.
|
29
|
+
return Math.sqrt(this.magnitudeSquared());
|
54
30
|
}
|
55
31
|
magnitudeSquared() {
|
56
|
-
return this.
|
32
|
+
return this.x * this.x + this.y * this.y + this.z * this.z;
|
57
33
|
}
|
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
34
|
squareDistanceTo(p) {
|
65
35
|
const dx = this.x - p.x;
|
66
36
|
const dy = this.y - p.y;
|
67
37
|
const dz = this.z - p.z;
|
68
38
|
return dx * dx + dy * dy + dz * dz;
|
69
39
|
}
|
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
40
|
distanceTo(p) {
|
77
41
|
return Math.sqrt(this.squareDistanceTo(p));
|
78
42
|
}
|
79
|
-
/**
|
80
|
-
* Returns the entry of this with the greatest magnitude.
|
81
|
-
*
|
82
|
-
* In other words, returns $\max \{ |x| : x \in {\bf v} \}$, where ${\bf v}$ is the set of
|
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
|
-
* ```
|
90
|
-
*/
|
91
43
|
maximumEntryMagnitude() {
|
92
44
|
return Math.max(Math.abs(this.x), Math.max(Math.abs(this.y), Math.abs(this.z)));
|
93
45
|
}
|
94
|
-
/**
|
95
|
-
* Return this' angle in the XY plane (treats this as a Vec2).
|
96
|
-
*
|
97
|
-
* This is equivalent to `Math.atan2(vec.y, vec.x)`.
|
98
|
-
*
|
99
|
-
* As such, observing that `Math.atan2(-0, -1)` $\approx -\pi$ and `Math.atan2(0, -1)`$\approx \pi$
|
100
|
-
* the resultant angle is in the range $[-\pi, pi]$.
|
101
|
-
*
|
102
|
-
* **Example**:
|
103
|
-
* ```ts,runnable,console
|
104
|
-
* import { Vec2 } from '@js-draw/math';
|
105
|
-
* console.log(Vec2.of(-1, -0).angle()); // atan2(-0, -1)
|
106
|
-
* console.log(Vec2.of(-1, 0).angle()); // atan2(0, -1)
|
107
|
-
* ```
|
108
|
-
*/
|
109
46
|
angle() {
|
110
47
|
return Math.atan2(this.y, this.x);
|
111
48
|
}
|
112
|
-
/**
|
113
|
-
* Returns a unit vector in the same direction as this.
|
114
|
-
*
|
115
|
-
* If `this` has zero length, the resultant vector has `NaN` components.
|
116
|
-
*/
|
117
49
|
normalized() {
|
118
50
|
const norm = this.magnitude();
|
119
51
|
return Vec3.of(this.x / norm, this.y / norm, this.z / norm);
|
120
52
|
}
|
121
|
-
/**
|
122
|
-
* Like {@link normalized}, except returns zero if this has zero magnitude.
|
123
|
-
*/
|
124
53
|
normalizedOrZero() {
|
125
54
|
if (this.eq(Vec3.zero)) {
|
126
55
|
return Vec3.zero;
|
127
56
|
}
|
128
57
|
return this.normalized();
|
129
58
|
}
|
130
|
-
/** @returns A copy of `this` multiplied by a scalar. */
|
131
59
|
times(c) {
|
132
60
|
return Vec3.of(this.x * c, this.y * c, this.z * c);
|
133
61
|
}
|
@@ -146,25 +74,12 @@ export class Vec3 {
|
|
146
74
|
// | x2 y2 z2|
|
147
75
|
return Vec3.of(this.y * other.z - other.y * this.z, other.x * this.z - this.x * other.z, this.x * other.y - other.x * this.y);
|
148
76
|
}
|
149
|
-
/**
|
150
|
-
* If `other` is a `Vec3`, multiplies `this` component-wise by `other`. Otherwise,
|
151
|
-
* if `other is a `number`, returns the result of scalar multiplication.
|
152
|
-
*
|
153
|
-
* @example
|
154
|
-
* ```
|
155
|
-
* Vec3.of(1, 2, 3).scale(Vec3.of(2, 4, 6)); // → Vec3(2, 8, 18)
|
156
|
-
* ```
|
157
|
-
*/
|
158
77
|
scale(other) {
|
159
78
|
if (typeof other === 'number') {
|
160
79
|
return this.times(other);
|
161
80
|
}
|
162
81
|
return Vec3.of(this.x * other.x, this.y * other.y, this.z * other.z);
|
163
82
|
}
|
164
|
-
/**
|
165
|
-
* Returns a vector orthogonal to this. If this is a Vec2, returns `this` rotated
|
166
|
-
* 90 degrees counter-clockwise.
|
167
|
-
*/
|
168
83
|
orthog() {
|
169
84
|
// If parallel to the z-axis
|
170
85
|
if (this.dot(Vec3.unitX) === 0 && this.dot(Vec3.unitY) === 0) {
|
@@ -172,62 +87,22 @@ export class Vec3 {
|
|
172
87
|
}
|
173
88
|
return this.cross(Vec3.unitZ.times(-1)).normalized();
|
174
89
|
}
|
175
|
-
/** Returns this plus a vector of length `distance` in `direction`. */
|
176
90
|
extend(distance, direction) {
|
177
91
|
return this.plus(direction.normalized().times(distance));
|
178
92
|
}
|
179
|
-
/** Returns a vector `fractionTo` of the way to target from this. */
|
180
93
|
lerp(target, fractionTo) {
|
181
94
|
return this.times(1 - fractionTo).plus(target.times(fractionTo));
|
182
95
|
}
|
183
|
-
/**
|
184
|
-
* `zip` Maps a component of this and a corresponding component of
|
185
|
-
* `other` to a component of the output vector.
|
186
|
-
*
|
187
|
-
* @example
|
188
|
-
* ```
|
189
|
-
* const a = Vec3.of(1, 2, 3);
|
190
|
-
* const b = Vec3.of(0.5, 2.1, 2.9);
|
191
|
-
*
|
192
|
-
* const zipped = a.zip(b, (aComponent, bComponent) => {
|
193
|
-
* return Math.min(aComponent, bComponent);
|
194
|
-
* });
|
195
|
-
*
|
196
|
-
* console.log(zipped.toString()); // → Vec(0.5, 2, 2.9)
|
197
|
-
* ```
|
198
|
-
*/
|
199
96
|
zip(other, zip) {
|
200
97
|
return Vec3.of(zip(other.x, this.x), zip(other.y, this.y), zip(other.z, this.z));
|
201
98
|
}
|
202
|
-
/**
|
203
|
-
* Returns a vector with each component acted on by `fn`.
|
204
|
-
*
|
205
|
-
* @example
|
206
|
-
* ```ts,runnable,console
|
207
|
-
* import { Vec3 } from '@js-draw/math';
|
208
|
-
* console.log(Vec3.of(1, 2, 3).map(val => val + 1)); // → Vec(2, 3, 4)
|
209
|
-
* ```
|
210
|
-
*/
|
211
99
|
map(fn) {
|
212
100
|
return Vec3.of(fn(this.x, 0), fn(this.y, 1), fn(this.z, 2));
|
213
101
|
}
|
214
102
|
asArray() {
|
215
103
|
return [this.x, this.y, this.z];
|
216
104
|
}
|
217
|
-
|
218
|
-
* [fuzz] The maximum difference between two components for this and [other]
|
219
|
-
* to be considered equal.
|
220
|
-
*
|
221
|
-
* @example
|
222
|
-
* ```
|
223
|
-
* Vec3.of(1, 2, 3).eq(Vec3.of(4, 5, 6), 100); // → true
|
224
|
-
* Vec3.of(1, 2, 3).eq(Vec3.of(4, 5, 6), 0.1); // → false
|
225
|
-
* Vec3.of(1, 2, 3).eq(Vec3.of(4, 5, 6), 3); // → true
|
226
|
-
* Vec3.of(1, 2, 3).eq(Vec3.of(4, 5, 6), 3.01); // → true
|
227
|
-
* Vec3.of(1, 2, 3).eq(Vec3.of(4, 5, 6), 2.99); // → false
|
228
|
-
* ```
|
229
|
-
*/
|
230
|
-
eq(other, fuzz = 1e-10) {
|
105
|
+
eq(other, fuzz = defaultEqlTolerance) {
|
231
106
|
return (Math.abs(other.x - this.x) <= fuzz
|
232
107
|
&& Math.abs(other.y - this.y) <= fuzz
|
233
108
|
&& Math.abs(other.z - this.z) <= fuzz);
|
@@ -236,8 +111,182 @@ export class Vec3 {
|
|
236
111
|
return `Vec(${this.x}, ${this.y}, ${this.z})`;
|
237
112
|
}
|
238
113
|
}
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
114
|
+
class Vec2Impl {
|
115
|
+
constructor(x, y) {
|
116
|
+
this.x = x;
|
117
|
+
this.y = y;
|
118
|
+
}
|
119
|
+
get z() { return 0; }
|
120
|
+
get xy() {
|
121
|
+
// Useful for APIs that behave differently if .z is present.
|
122
|
+
return {
|
123
|
+
x: this.x,
|
124
|
+
y: this.y,
|
125
|
+
};
|
126
|
+
}
|
127
|
+
at(idx) {
|
128
|
+
if (idx === 0)
|
129
|
+
return this.x;
|
130
|
+
if (idx === 1)
|
131
|
+
return this.y;
|
132
|
+
if (idx === 2)
|
133
|
+
return 0;
|
134
|
+
throw new Error(`${idx} out of bounds!`);
|
135
|
+
}
|
136
|
+
length() {
|
137
|
+
return this.magnitude();
|
138
|
+
}
|
139
|
+
magnitude() {
|
140
|
+
return Math.sqrt(this.x * this.x + this.y * this.y);
|
141
|
+
}
|
142
|
+
magnitudeSquared() {
|
143
|
+
return this.x * this.x + this.y * this.y;
|
144
|
+
}
|
145
|
+
squareDistanceTo(p) {
|
146
|
+
const dx = this.x - p.x;
|
147
|
+
const dy = this.y - p.y;
|
148
|
+
return dx * dx + dy * dy + p.z * p.z;
|
149
|
+
}
|
150
|
+
distanceTo(p) {
|
151
|
+
return Math.sqrt(this.squareDistanceTo(p));
|
152
|
+
}
|
153
|
+
maximumEntryMagnitude() {
|
154
|
+
return Math.max(Math.abs(this.x), Math.abs(this.y));
|
155
|
+
}
|
156
|
+
angle() {
|
157
|
+
return Math.atan2(this.y, this.x);
|
158
|
+
}
|
159
|
+
normalized() {
|
160
|
+
const norm = this.magnitude();
|
161
|
+
return Vec2.of(this.x / norm, this.y / norm);
|
162
|
+
}
|
163
|
+
normalizedOrZero() {
|
164
|
+
if (this.eq(Vec3.zero)) {
|
165
|
+
return Vec3.zero;
|
166
|
+
}
|
167
|
+
return this.normalized();
|
168
|
+
}
|
169
|
+
times(c) {
|
170
|
+
return Vec2.of(this.x * c, this.y * c);
|
171
|
+
}
|
172
|
+
plus(v) {
|
173
|
+
return Vec3.of(this.x + v.x, this.y + v.y, v.z);
|
174
|
+
}
|
175
|
+
minus(v) {
|
176
|
+
return Vec3.of(this.x - v.x, this.y - v.y, -v.z);
|
177
|
+
}
|
178
|
+
dot(other) {
|
179
|
+
return this.x * other.x + this.y * other.y;
|
180
|
+
}
|
181
|
+
cross(other) {
|
182
|
+
// | i j k |
|
183
|
+
// | x1 y1 z1| = (i)(y1z2 - y2z1) - (j)(x1z2 - x2z1) + (k)(x1y2 - x2y1)
|
184
|
+
// | x2 y2 z2|
|
185
|
+
return Vec3.of(this.y * other.z, -this.x * other.z, this.x * other.y - other.x * this.y);
|
186
|
+
}
|
187
|
+
scale(other) {
|
188
|
+
if (typeof other === 'number') {
|
189
|
+
return this.times(other);
|
190
|
+
}
|
191
|
+
return Vec2.of(this.x * other.x, this.y * other.y);
|
192
|
+
}
|
193
|
+
orthog() {
|
194
|
+
// If parallel to the z-axis
|
195
|
+
if (this.dot(Vec3.unitX) === 0 && this.dot(Vec3.unitY) === 0) {
|
196
|
+
return this.dot(Vec3.unitX) === 0 ? Vec3.unitX : this.cross(Vec3.unitX).normalized();
|
197
|
+
}
|
198
|
+
return this.cross(Vec3.unitZ.times(-1)).normalized();
|
199
|
+
}
|
200
|
+
extend(distance, direction) {
|
201
|
+
return this.plus(direction.normalized().times(distance));
|
202
|
+
}
|
203
|
+
lerp(target, fractionTo) {
|
204
|
+
return this.times(1 - fractionTo).plus(target.times(fractionTo));
|
205
|
+
}
|
206
|
+
zip(other, zip) {
|
207
|
+
return Vec3.of(zip(other.x, this.x), zip(other.y, this.y), zip(other.z, 0));
|
208
|
+
}
|
209
|
+
map(fn) {
|
210
|
+
return Vec3.of(fn(this.x, 0), fn(this.y, 1), fn(0, 2));
|
211
|
+
}
|
212
|
+
asArray() {
|
213
|
+
return [this.x, this.y, 0];
|
214
|
+
}
|
215
|
+
eq(other, fuzz = defaultEqlTolerance) {
|
216
|
+
return (Math.abs(other.x - this.x) <= fuzz
|
217
|
+
&& Math.abs(other.y - this.y) <= fuzz
|
218
|
+
&& Math.abs(other.z) <= fuzz);
|
219
|
+
}
|
220
|
+
toString() {
|
221
|
+
return `Vec(${this.x}, ${this.y})`;
|
222
|
+
}
|
223
|
+
}
|
224
|
+
/**
|
225
|
+
* A `Vec2` is a `Vec3` optimized for working in a plane. As such, they have an
|
226
|
+
* always-zero `z` component.
|
227
|
+
*
|
228
|
+
* ```ts,runnable,console
|
229
|
+
* import { Vec2 } from '@js-draw/math';
|
230
|
+
* console.log(Vec2.of(1, 2));
|
231
|
+
* ```
|
232
|
+
*/
|
233
|
+
export var Vec2;
|
234
|
+
(function (Vec2) {
|
235
|
+
/**
|
236
|
+
* Creates a `Vec2` from an x and y coordinate.
|
237
|
+
*
|
238
|
+
* @example
|
239
|
+
* ```ts,runnable,console
|
240
|
+
* import { Vec2 } from '@js-draw/math';
|
241
|
+
* const v = Vec2.of(3, 4); // x=3, y=4.
|
242
|
+
* ```
|
243
|
+
*/
|
244
|
+
Vec2.of = (x, y) => {
|
245
|
+
return new Vec2Impl(x, y);
|
246
|
+
};
|
247
|
+
/**
|
248
|
+
* Creates a `Vec2` from an object containing `x` and `y` coordinates.
|
249
|
+
*
|
250
|
+
* @example
|
251
|
+
* ```ts,runnable,console
|
252
|
+
* import { Vec2 } from '@js-draw/math';
|
253
|
+
* const v1 = Vec2.ofXY({ x: 3, y: 4.5 });
|
254
|
+
* const v2 = Vec2.ofXY({ x: -123.4, y: 1 });
|
255
|
+
* ```
|
256
|
+
*/
|
257
|
+
Vec2.ofXY = ({ x, y }) => {
|
258
|
+
return Vec2.of(x, y);
|
259
|
+
};
|
260
|
+
/** A vector of length 1 in the X direction (→). */
|
261
|
+
Vec2.unitX = Vec2.of(1, 0);
|
262
|
+
/** A vector of length 1 in the Y direction (↑). */
|
263
|
+
Vec2.unitY = Vec2.of(0, 1);
|
264
|
+
/** The zero vector: A vector with x=0, y=0. */
|
265
|
+
Vec2.zero = Vec2.of(0, 0);
|
266
|
+
})(Vec2 || (Vec2 = {}));
|
267
|
+
export var Vec3;
|
268
|
+
(function (Vec3) {
|
269
|
+
/**
|
270
|
+
* Construct a vector from three components.
|
271
|
+
*
|
272
|
+
* @example
|
273
|
+
* ```ts,runnable,console
|
274
|
+
* import { Vec3 } from '@js-draw/math';
|
275
|
+
* const v1 = Vec3.of(1, 2, 3);
|
276
|
+
* ```
|
277
|
+
*/
|
278
|
+
Vec3.of = (x, y, z) => {
|
279
|
+
if (z === 0) {
|
280
|
+
return Vec2.of(x, y);
|
281
|
+
}
|
282
|
+
else {
|
283
|
+
return new Vec3Impl(x, y, z);
|
284
|
+
}
|
285
|
+
};
|
286
|
+
Vec3.unitX = Vec2.unitX;
|
287
|
+
Vec3.unitY = Vec2.unitY;
|
288
|
+
Vec3.zero = Vec2.zero;
|
289
|
+
/** A vector of length 1 in the z direction. */
|
290
|
+
Vec3.unitZ = Vec3.of(0, 0, 1);
|
291
|
+
})(Vec3 || (Vec3 = {}));
|
243
292
|
export default Vec3;
|
@@ -7,7 +7,18 @@ interface IntersectionResult {
|
|
7
7
|
point: Point2;
|
8
8
|
t: number;
|
9
9
|
}
|
10
|
-
/**
|
10
|
+
/**
|
11
|
+
* Represents a line segment. A `LineSegment2` is immutable.
|
12
|
+
*
|
13
|
+
* @example
|
14
|
+
* ```ts,runnable,console
|
15
|
+
* import {LineSegment2, Vec2} from '@js-draw/math';
|
16
|
+
* const l = new LineSegment2(Vec2.of(1, 1), Vec2.of(2, 2));
|
17
|
+
* console.log('length: ', l.length);
|
18
|
+
* console.log('direction: ', l.direction);
|
19
|
+
* console.log('bounding box: ', l.bbox);
|
20
|
+
* ```
|
21
|
+
*/
|
11
22
|
export declare class LineSegment2 extends Parameterized2DShape {
|
12
23
|
private readonly point1;
|
13
24
|
private readonly point2;
|
@@ -30,7 +41,7 @@ export declare class LineSegment2 extends Parameterized2DShape {
|
|
30
41
|
* if no such line segment exists.
|
31
42
|
*
|
32
43
|
* @example
|
33
|
-
* ```ts,runnable
|
44
|
+
* ```ts,runnable,console
|
34
45
|
* import {LineSegment2, Vec2} from '@js-draw/math';
|
35
46
|
* console.log(LineSegment2.ofSmallestContainingPoints([Vec2.of(1, 0), Vec2.of(0, 1)]));
|
36
47
|
* ```
|
@@ -1,7 +1,18 @@
|
|
1
1
|
import Rect2 from './Rect2.mjs';
|
2
2
|
import { Vec2 } from '../Vec2.mjs';
|
3
3
|
import Parameterized2DShape from './Parameterized2DShape.mjs';
|
4
|
-
/**
|
4
|
+
/**
|
5
|
+
* Represents a line segment. A `LineSegment2` is immutable.
|
6
|
+
*
|
7
|
+
* @example
|
8
|
+
* ```ts,runnable,console
|
9
|
+
* import {LineSegment2, Vec2} from '@js-draw/math';
|
10
|
+
* const l = new LineSegment2(Vec2.of(1, 1), Vec2.of(2, 2));
|
11
|
+
* console.log('length: ', l.length);
|
12
|
+
* console.log('direction: ', l.direction);
|
13
|
+
* console.log('bounding box: ', l.bbox);
|
14
|
+
* ```
|
15
|
+
*/
|
5
16
|
export class LineSegment2 extends Parameterized2DShape {
|
6
17
|
/** Creates a new `LineSegment2` from its endpoints. */
|
7
18
|
constructor(point1, point2) {
|
@@ -21,7 +32,7 @@ export class LineSegment2 extends Parameterized2DShape {
|
|
21
32
|
* if no such line segment exists.
|
22
33
|
*
|
23
34
|
* @example
|
24
|
-
* ```ts,runnable
|
35
|
+
* ```ts,runnable,console
|
25
36
|
* import {LineSegment2, Vec2} from '@js-draw/math';
|
26
37
|
* console.log(LineSegment2.ofSmallestContainingPoints([Vec2.of(1, 0), Vec2.of(0, 1)]));
|
27
38
|
* ```
|
@@ -18,7 +18,39 @@ declare class PointShape2D extends Parameterized2DShape {
|
|
18
18
|
/**
|
19
19
|
* Returns an arbitrary unit-length vector.
|
20
20
|
*/
|
21
|
-
normalAt(_t: number):
|
21
|
+
normalAt(_t: number): {
|
22
|
+
readonly x: number;
|
23
|
+
readonly y: number;
|
24
|
+
readonly z: number;
|
25
|
+
readonly xy: {
|
26
|
+
x: number;
|
27
|
+
y: number;
|
28
|
+
};
|
29
|
+
at(idx: number): number;
|
30
|
+
length(): number;
|
31
|
+
magnitude(): number;
|
32
|
+
magnitudeSquared(): number;
|
33
|
+
squareDistanceTo(p: Vec3): number;
|
34
|
+
distanceTo(p: Vec3): number;
|
35
|
+
maximumEntryMagnitude(): number;
|
36
|
+
angle(): number;
|
37
|
+
normalized(): Vec3;
|
38
|
+
normalizedOrZero(): Vec3;
|
39
|
+
times(c: number): Vec3;
|
40
|
+
plus(v: Vec3): Vec3;
|
41
|
+
minus(v: Vec3): Vec3;
|
42
|
+
dot(other: Vec3): number;
|
43
|
+
cross(other: Vec3): Vec3;
|
44
|
+
scale(other: Vec3 | number): Vec3;
|
45
|
+
orthog(): Vec3;
|
46
|
+
extend(distance: number, direction: Vec3): Vec3;
|
47
|
+
lerp(target: Vec3, fractionTo: number): Vec3;
|
48
|
+
zip(other: Vec3, zip: (componentInThis: number, componentInOther: number) => number): Vec3;
|
49
|
+
map(fn: (component: number, index: number) => number): Vec3;
|
50
|
+
asArray(): [number, number, number];
|
51
|
+
eq(other: Vec3, fuzz?: number): boolean;
|
52
|
+
toString(): string;
|
53
|
+
};
|
22
54
|
tangentAt(_t: number): Vec3;
|
23
55
|
splitAt(_t: number): [PointShape2D];
|
24
56
|
nearestPointTo(_point: Point2): {
|
@@ -57,14 +57,46 @@ export declare class Rect2 extends Abstract2DShape {
|
|
57
57
|
get bottomLeft(): Vec3;
|
58
58
|
get width(): number;
|
59
59
|
get height(): number;
|
60
|
-
get center():
|
60
|
+
get center(): {
|
61
|
+
readonly x: number;
|
62
|
+
readonly y: number;
|
63
|
+
readonly z: number;
|
64
|
+
readonly xy: {
|
65
|
+
x: number;
|
66
|
+
y: number;
|
67
|
+
};
|
68
|
+
at(idx: number): number;
|
69
|
+
length(): number;
|
70
|
+
magnitude(): number;
|
71
|
+
magnitudeSquared(): number;
|
72
|
+
squareDistanceTo(p: Vec3): number;
|
73
|
+
distanceTo(p: Vec3): number;
|
74
|
+
maximumEntryMagnitude(): number;
|
75
|
+
angle(): number;
|
76
|
+
normalized(): Vec3;
|
77
|
+
normalizedOrZero(): Vec3;
|
78
|
+
times(c: number): Vec3;
|
79
|
+
plus(v: Vec3): Vec3;
|
80
|
+
minus(v: Vec3): Vec3;
|
81
|
+
dot(other: Vec3): number;
|
82
|
+
cross(other: Vec3): Vec3;
|
83
|
+
scale(other: Vec3 | number): Vec3;
|
84
|
+
orthog(): Vec3;
|
85
|
+
extend(distance: number, direction: Vec3): Vec3;
|
86
|
+
lerp(target: Vec3, fractionTo: number): Vec3;
|
87
|
+
zip(other: Vec3, zip: (componentInThis: number, componentInOther: number) => number): Vec3;
|
88
|
+
map(fn: (component: number, index: number) => number): Vec3;
|
89
|
+
asArray(): [number, number, number];
|
90
|
+
eq(other: Vec3, fuzz?: number): boolean;
|
91
|
+
toString(): string;
|
92
|
+
};
|
61
93
|
getEdges(): LineSegment2[];
|
62
94
|
intersectsLineSegment(lineSegment: LineSegment2): Point2[];
|
63
95
|
signedDistance(point: Vec3): number;
|
64
96
|
getTightBoundingBox(): Rect2;
|
65
97
|
transformedBoundingBox(affineTransform: Mat33): Rect2;
|
66
|
-
/** @return true iff this is equal to
|
67
|
-
eq(other: Rect2,
|
98
|
+
/** @return true iff this is equal to `other ± tolerance` */
|
99
|
+
eq(other: Rect2, tolerance?: number): boolean;
|
68
100
|
toString(): string;
|
69
101
|
static fromCorners(corner1: Point2, corner2: Point2): Rect2;
|
70
102
|
static bboxOf(points: Point2[], margin?: number): Rect2;
|
@@ -221,9 +221,9 @@ export class Rect2 extends Abstract2DShape {
|
|
221
221
|
transformedBoundingBox(affineTransform) {
|
222
222
|
return Rect2.bboxOf(this.corners.map(corner => affineTransform.transformVec2(corner)));
|
223
223
|
}
|
224
|
-
/** @return true iff this is equal to
|
225
|
-
eq(other,
|
226
|
-
return this.topLeft.eq(other.topLeft,
|
224
|
+
/** @return true iff this is equal to `other ± tolerance` */
|
225
|
+
eq(other, tolerance = 0) {
|
226
|
+
return this.topLeft.eq(other.topLeft, tolerance) && this.size.eq(other.size, tolerance);
|
227
227
|
}
|
228
228
|
toString() {
|
229
229
|
return `Rect(point(${this.x}, ${this.y}), size(${this.w}, ${this.h}))`;
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# This file is generated by running "yarn install" inside your project.
|
2
|
+
# Manual changes might be lost - proceed with caution!
|
3
|
+
|
4
|
+
__metadata:
|
5
|
+
version: 8
|
6
|
+
cacheKey: 10c0
|
7
|
+
|
8
|
+
"js-draw-math-test-imports@workspace:.":
|
9
|
+
version: 0.0.0-use.local
|
10
|
+
resolution: "js-draw-math-test-imports@workspace:."
|
11
|
+
languageName: unknown
|
12
|
+
linkType: soft
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@js-draw/math",
|
3
|
-
"version": "1.
|
3
|
+
"version": "1.21.1",
|
4
4
|
"description": "A math library for js-draw. ",
|
5
5
|
"types": "./dist/mjs/lib.d.ts",
|
6
6
|
"main": "./dist/cjs/lib.js",
|
@@ -17,18 +17,17 @@
|
|
17
17
|
},
|
18
18
|
"author": "Henry Heino",
|
19
19
|
"license": "MIT",
|
20
|
-
"private": false,
|
21
20
|
"scripts": {
|
22
|
-
"dist-test": "cd dist-test/test_imports &&
|
23
|
-
"dist": "
|
24
|
-
"build": "
|
21
|
+
"dist-test": "cd dist-test/test_imports && yarn install && yarn run test",
|
22
|
+
"dist": "yarn run build && yarn run dist-test",
|
23
|
+
"build": "build-tool build",
|
25
24
|
"watch": "build-tool watch"
|
26
25
|
},
|
27
26
|
"dependencies": {
|
28
27
|
"bezier-js": "6.1.3"
|
29
28
|
},
|
30
29
|
"devDependencies": {
|
31
|
-
"@js-draw/build-tool": "^1.
|
30
|
+
"@js-draw/build-tool": "^1.21.1",
|
32
31
|
"@types/bezier-js": "4.1.0",
|
33
32
|
"@types/jest": "29.5.5",
|
34
33
|
"@types/jsdom": "21.1.3"
|
@@ -45,5 +44,5 @@
|
|
45
44
|
"svg",
|
46
45
|
"math"
|
47
46
|
],
|
48
|
-
"gitHead": "
|
47
|
+
"gitHead": "a46f0e1c3586e4b3019152eea87cd2784b00282f"
|
49
48
|
}
|