@js-draw/math 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. package/README.md +3 -0
  2. package/build-config.json +4 -0
  3. package/dist/cjs/Color4.d.ts +83 -0
  4. package/dist/cjs/Color4.js +277 -0
  5. package/dist/cjs/Mat33.d.ts +131 -0
  6. package/dist/cjs/Mat33.js +345 -0
  7. package/dist/cjs/Vec2.d.ts +42 -0
  8. package/dist/cjs/Vec2.js +48 -0
  9. package/dist/cjs/Vec3.d.ts +126 -0
  10. package/dist/cjs/Vec3.js +203 -0
  11. package/dist/cjs/lib.d.ts +27 -0
  12. package/dist/cjs/lib.js +42 -0
  13. package/dist/cjs/polynomial/solveQuadratic.d.ts +9 -0
  14. package/dist/cjs/polynomial/solveQuadratic.js +39 -0
  15. package/dist/cjs/rounding.d.ts +15 -0
  16. package/dist/cjs/rounding.js +146 -0
  17. package/dist/cjs/shapes/Abstract2DShape.d.ts +49 -0
  18. package/dist/cjs/shapes/Abstract2DShape.js +38 -0
  19. package/dist/cjs/shapes/BezierJSWrapper.d.ts +36 -0
  20. package/dist/cjs/shapes/BezierJSWrapper.js +94 -0
  21. package/dist/cjs/shapes/CubicBezier.d.ts +17 -0
  22. package/dist/cjs/shapes/CubicBezier.js +35 -0
  23. package/dist/cjs/shapes/LineSegment2.d.ts +70 -0
  24. package/dist/cjs/shapes/LineSegment2.js +183 -0
  25. package/dist/cjs/shapes/Path.d.ts +96 -0
  26. package/dist/cjs/shapes/Path.js +766 -0
  27. package/dist/cjs/shapes/PointShape2D.d.ts +18 -0
  28. package/dist/cjs/shapes/PointShape2D.js +31 -0
  29. package/dist/cjs/shapes/QuadraticBezier.d.ts +35 -0
  30. package/dist/cjs/shapes/QuadraticBezier.js +120 -0
  31. package/dist/cjs/shapes/Rect2.d.ts +58 -0
  32. package/dist/cjs/shapes/Rect2.js +259 -0
  33. package/dist/cjs/shapes/Triangle.d.ts +46 -0
  34. package/dist/cjs/shapes/Triangle.js +126 -0
  35. package/dist/mjs/Color4.d.ts +83 -0
  36. package/dist/mjs/Color4.mjs +271 -0
  37. package/dist/mjs/Mat33.d.ts +131 -0
  38. package/dist/mjs/Mat33.mjs +338 -0
  39. package/dist/mjs/Vec2.d.ts +42 -0
  40. package/dist/mjs/Vec2.mjs +42 -0
  41. package/dist/mjs/Vec3.d.ts +126 -0
  42. package/dist/mjs/Vec3.mjs +199 -0
  43. package/dist/mjs/lib.d.ts +27 -0
  44. package/dist/mjs/lib.mjs +29 -0
  45. package/dist/mjs/polynomial/solveQuadratic.d.ts +9 -0
  46. package/dist/mjs/polynomial/solveQuadratic.mjs +37 -0
  47. package/dist/mjs/rounding.d.ts +15 -0
  48. package/dist/mjs/rounding.mjs +139 -0
  49. package/dist/mjs/shapes/Abstract2DShape.d.ts +49 -0
  50. package/dist/mjs/shapes/Abstract2DShape.mjs +36 -0
  51. package/dist/mjs/shapes/BezierJSWrapper.d.ts +36 -0
  52. package/dist/mjs/shapes/BezierJSWrapper.mjs +89 -0
  53. package/dist/mjs/shapes/CubicBezier.d.ts +17 -0
  54. package/dist/mjs/shapes/CubicBezier.mjs +30 -0
  55. package/dist/mjs/shapes/LineSegment2.d.ts +70 -0
  56. package/dist/mjs/shapes/LineSegment2.mjs +176 -0
  57. package/dist/mjs/shapes/Path.d.ts +96 -0
  58. package/dist/mjs/shapes/Path.mjs +759 -0
  59. package/dist/mjs/shapes/PointShape2D.d.ts +18 -0
  60. package/dist/mjs/shapes/PointShape2D.mjs +26 -0
  61. package/dist/mjs/shapes/QuadraticBezier.d.ts +35 -0
  62. package/dist/mjs/shapes/QuadraticBezier.mjs +113 -0
  63. package/dist/mjs/shapes/Rect2.d.ts +58 -0
  64. package/dist/mjs/shapes/Rect2.mjs +252 -0
  65. package/dist/mjs/shapes/Triangle.d.ts +46 -0
  66. package/dist/mjs/shapes/Triangle.mjs +121 -0
  67. package/package.json +48 -0
  68. package/tsconfig.json +7 -0
  69. package/typedoc.json +5 -0
@@ -0,0 +1,338 @@
1
+ import { Vec2 } from './Vec2.mjs';
2
+ import Vec3 from './Vec3.mjs';
3
+ /**
4
+ * Represents a three dimensional linear transformation or
5
+ * a two-dimensional affine transformation. (An affine transformation scales/rotates/shears
6
+ * **and** translates while a linear transformation just scales/rotates/shears).
7
+ */
8
+ export class Mat33 {
9
+ /**
10
+ * Creates a matrix from inputs in the form,
11
+ * $$
12
+ * \begin{bmatrix}
13
+ * a1 & a2 & a3 \\
14
+ * b1 & b2 & b3 \\
15
+ * c1 & c2 & c3
16
+ * \end{bmatrix}
17
+ * $$
18
+ */
19
+ constructor(a1, a2, a3, b1, b2, b3, c1, c2, c3) {
20
+ this.a1 = a1;
21
+ this.a2 = a2;
22
+ this.a3 = a3;
23
+ this.b1 = b1;
24
+ this.b2 = b2;
25
+ this.b3 = b3;
26
+ this.c1 = c1;
27
+ this.c2 = c2;
28
+ this.c3 = c3;
29
+ this.cachedInverse = undefined;
30
+ this.rows = [
31
+ Vec3.of(a1, a2, a3),
32
+ Vec3.of(b1, b2, b3),
33
+ Vec3.of(c1, c2, c3),
34
+ ];
35
+ }
36
+ /**
37
+ * Creates a matrix from the given rows:
38
+ * $$
39
+ * \begin{bmatrix}
40
+ * \texttt{r1.x} & \texttt{r1.y} & \texttt{r1.z}\\
41
+ * \texttt{r2.x} & \texttt{r2.y} & \texttt{r2.z}\\
42
+ * \texttt{r3.x} & \texttt{r3.y} & \texttt{r3.z}\\
43
+ * \end{bmatrix}
44
+ * $$
45
+ */
46
+ static ofRows(r1, r2, r3) {
47
+ return new Mat33(r1.x, r1.y, r1.z, r2.x, r2.y, r2.z, r3.x, r3.y, r3.z);
48
+ }
49
+ /**
50
+ * Either returns the inverse of this, or, if this matrix is singular/uninvertable,
51
+ * returns Mat33.identity.
52
+ *
53
+ * This may cache the computed inverse and return the cached version instead of recomputing
54
+ * it.
55
+ */
56
+ inverse() {
57
+ return this.computeInverse() ?? Mat33.identity;
58
+ }
59
+ invertable() {
60
+ return this.computeInverse() !== null;
61
+ }
62
+ computeInverse() {
63
+ if (this.cachedInverse !== undefined) {
64
+ return this.cachedInverse;
65
+ }
66
+ const toIdentity = [
67
+ this.rows[0],
68
+ this.rows[1],
69
+ this.rows[2],
70
+ ];
71
+ const toResult = [
72
+ Vec3.unitX,
73
+ Vec3.unitY,
74
+ Vec3.unitZ,
75
+ ];
76
+ // Convert toIdentity to the identity matrix and
77
+ // toResult to the inverse through elementary row operations
78
+ for (let cursor = 0; cursor < 3; cursor++) {
79
+ // Select the [cursor]th diagonal entry
80
+ let pivot = toIdentity[cursor].at(cursor);
81
+ // Don't divide by zero (treat very small numbers as zero).
82
+ const minDivideBy = 1e-10;
83
+ if (Math.abs(pivot) < minDivideBy) {
84
+ let swapIndex = -1;
85
+ // For all other rows,
86
+ for (let i = 1; i <= 2; i++) {
87
+ const otherRowIdx = (cursor + i) % 3;
88
+ if (Math.abs(toIdentity[otherRowIdx].at(cursor)) >= minDivideBy) {
89
+ swapIndex = otherRowIdx;
90
+ break;
91
+ }
92
+ }
93
+ // Can't swap with another row?
94
+ if (swapIndex === -1) {
95
+ this.cachedInverse = null;
96
+ return null;
97
+ }
98
+ const tmpIdentityRow = toIdentity[cursor];
99
+ const tmpResultRow = toResult[cursor];
100
+ // Swap!
101
+ toIdentity[cursor] = toIdentity[swapIndex];
102
+ toResult[cursor] = toResult[swapIndex];
103
+ toIdentity[swapIndex] = tmpIdentityRow;
104
+ toResult[swapIndex] = tmpResultRow;
105
+ pivot = toIdentity[cursor].at(cursor);
106
+ }
107
+ // Make toIdentity[k = cursor] = 1
108
+ let scale = 1.0 / pivot;
109
+ toIdentity[cursor] = toIdentity[cursor].times(scale);
110
+ toResult[cursor] = toResult[cursor].times(scale);
111
+ const cursorToIdentityRow = toIdentity[cursor];
112
+ const cursorToResultRow = toResult[cursor];
113
+ // Make toIdentity[k ≠ cursor] = 0
114
+ for (let i = 1; i <= 2; i++) {
115
+ const otherRowIdx = (cursor + i) % 3;
116
+ scale = -toIdentity[otherRowIdx].at(cursor);
117
+ toIdentity[otherRowIdx] = toIdentity[otherRowIdx].plus(cursorToIdentityRow.times(scale));
118
+ toResult[otherRowIdx] = toResult[otherRowIdx].plus(cursorToResultRow.times(scale));
119
+ }
120
+ }
121
+ const inverse = Mat33.ofRows(toResult[0], toResult[1], toResult[2]);
122
+ this.cachedInverse = inverse;
123
+ return inverse;
124
+ }
125
+ transposed() {
126
+ return new Mat33(this.a1, this.b1, this.c1, this.a2, this.b2, this.c2, this.a3, this.b3, this.c3);
127
+ }
128
+ rightMul(other) {
129
+ other = other.transposed();
130
+ const at = (row, col) => {
131
+ return this.rows[row].dot(other.rows[col]);
132
+ };
133
+ return new Mat33(at(0, 0), at(0, 1), at(0, 2), at(1, 0), at(1, 1), at(1, 2), at(2, 0), at(2, 1), at(2, 2));
134
+ }
135
+ /**
136
+ * Applies this as an **affine** transformation to the given vector.
137
+ * Returns a transformed version of `other`.
138
+ *
139
+ * Unlike {@link transformVec3}, this **does** translate the given vector.
140
+ */
141
+ transformVec2(other) {
142
+ // When transforming a Vec2, we want to use the z transformation
143
+ // components of this for translation:
144
+ // ⎡ . . tX ⎤
145
+ // ⎢ . . tY ⎥
146
+ // ⎣ 0 0 1 ⎦
147
+ // For this, we need other's z component to be 1 (so that tX and tY
148
+ // are scaled by 1):
149
+ let intermediate = Vec3.of(other.x, other.y, 1);
150
+ intermediate = this.transformVec3(intermediate);
151
+ // Drop the z=1 to allow magnitude to work as expected
152
+ return Vec2.of(intermediate.x, intermediate.y);
153
+ }
154
+ /**
155
+ * Applies this as a linear transformation to the given vector (doesn't translate).
156
+ * This is the standard way of transforming vectors in ℝ³.
157
+ */
158
+ transformVec3(other) {
159
+ return Vec3.of(this.rows[0].dot(other), this.rows[1].dot(other), this.rows[2].dot(other));
160
+ }
161
+ /** @returns true iff this is the identity matrix. */
162
+ isIdentity() {
163
+ if (this === Mat33.identity) {
164
+ return true;
165
+ }
166
+ return this.eq(Mat33.identity);
167
+ }
168
+ /** Returns true iff this = other ± fuzz */
169
+ eq(other, fuzz = 0) {
170
+ for (let i = 0; i < 3; i++) {
171
+ if (!this.rows[i].eq(other.rows[i], fuzz)) {
172
+ return false;
173
+ }
174
+ }
175
+ return true;
176
+ }
177
+ toString() {
178
+ let result = '';
179
+ const maxColumnLens = [0, 0, 0];
180
+ // Determine the longest item in each column so we can pad the others to that
181
+ // length.
182
+ for (const row of this.rows) {
183
+ for (let i = 0; i < 3; i++) {
184
+ maxColumnLens[i] = Math.max(maxColumnLens[0], `${row.at(i)}`.length);
185
+ }
186
+ }
187
+ for (let i = 0; i < 3; i++) {
188
+ if (i === 0) {
189
+ result += '⎡ ';
190
+ }
191
+ else if (i === 1) {
192
+ result += '⎢ ';
193
+ }
194
+ else {
195
+ result += '⎣ ';
196
+ }
197
+ // Add each component of the ith row (after padding it)
198
+ for (let j = 0; j < 3; j++) {
199
+ const val = this.rows[i].at(j).toString();
200
+ let padding = '';
201
+ for (let i = val.length; i < maxColumnLens[j]; i++) {
202
+ padding += ' ';
203
+ }
204
+ result += val + ', ' + padding;
205
+ }
206
+ if (i === 0) {
207
+ result += ' ⎤';
208
+ }
209
+ else if (i === 1) {
210
+ result += ' ⎥';
211
+ }
212
+ else {
213
+ result += ' ⎦';
214
+ }
215
+ result += '\n';
216
+ }
217
+ return result.trimEnd();
218
+ }
219
+ /**
220
+ * ```
221
+ * result[0] = top left element
222
+ * result[1] = element at row zero, column 1
223
+ * ...
224
+ * ```
225
+ */
226
+ toArray() {
227
+ return [
228
+ this.a1, this.a2, this.a3,
229
+ this.b1, this.b2, this.b3,
230
+ this.c1, this.c2, this.c3,
231
+ ];
232
+ }
233
+ /**
234
+ * Returns a new `Mat33` where each entry is the output of the function
235
+ * `mapping`.
236
+ *
237
+ * @example
238
+ * ```
239
+ * new Mat33(
240
+ * 1, 2, 3,
241
+ * 4, 5, 6,
242
+ * 7, 8, 9,
243
+ * ).mapEntries(component => component - 1);
244
+ * // → ⎡ 0, 1, 2 ⎤
245
+ * // ⎢ 3, 4, 5 ⎥
246
+ * // ⎣ 6, 7, 8 ⎦
247
+ * ```
248
+ */
249
+ mapEntries(mapping) {
250
+ return new Mat33(mapping(this.a1, [0, 0]), mapping(this.a2, [0, 1]), mapping(this.a3, [0, 2]), mapping(this.b1, [1, 0]), mapping(this.b2, [1, 1]), mapping(this.b3, [1, 2]), mapping(this.c1, [2, 0]), mapping(this.c2, [2, 1]), mapping(this.c3, [2, 2]));
251
+ }
252
+ /** Estimate the scale factor of this matrix (based on the first row). */
253
+ getScaleFactor() {
254
+ return Math.hypot(this.a1, this.a2);
255
+ }
256
+ /**
257
+ * Constructs a 3x3 translation matrix (for translating `Vec2`s) using
258
+ * **transformVec2**.
259
+ */
260
+ static translation(amount) {
261
+ // When transforming Vec2s by a 3x3 matrix, we give the input
262
+ // Vec2s z = 1. As such,
263
+ // outVec2.x = inVec2.x * 1 + inVec2.y * 0 + 1 * amount.x
264
+ // ...
265
+ return new Mat33(1, 0, amount.x, 0, 1, amount.y, 0, 0, 1);
266
+ }
267
+ static zRotation(radians, center = Vec2.zero) {
268
+ if (radians === 0) {
269
+ return Mat33.identity;
270
+ }
271
+ const cos = Math.cos(radians);
272
+ const sin = Math.sin(radians);
273
+ // Translate everything so that rotation is about the origin
274
+ let result = Mat33.translation(center);
275
+ result = result.rightMul(new Mat33(cos, -sin, 0, sin, cos, 0, 0, 0, 1));
276
+ return result.rightMul(Mat33.translation(center.times(-1)));
277
+ }
278
+ static scaling2D(amount, center = Vec2.zero) {
279
+ let result = Mat33.translation(center);
280
+ let xAmount, yAmount;
281
+ if (typeof amount === 'number') {
282
+ xAmount = amount;
283
+ yAmount = amount;
284
+ }
285
+ else {
286
+ xAmount = amount.x;
287
+ yAmount = amount.y;
288
+ }
289
+ result = result.rightMul(new Mat33(xAmount, 0, 0, 0, yAmount, 0, 0, 0, 1));
290
+ // Translate such that [center] goes to (0, 0)
291
+ return result.rightMul(Mat33.translation(center.times(-1)));
292
+ }
293
+ /** @see {@link fromCSSMatrix} */
294
+ toCSSMatrix() {
295
+ return `matrix(${this.a1},${this.b1},${this.a2},${this.b2},${this.a3},${this.b3})`;
296
+ }
297
+ /**
298
+ * Converts a CSS-form `matrix(a, b, c, d, e, f)` to a Mat33.
299
+ *
300
+ * Note that such a matrix has the form,
301
+ * ```
302
+ * ⎡ a c e ⎤
303
+ * ⎢ b d f ⎥
304
+ * ⎣ 0 0 1 ⎦
305
+ * ```
306
+ */
307
+ static fromCSSMatrix(cssString) {
308
+ if (cssString === '' || cssString === 'none') {
309
+ return Mat33.identity;
310
+ }
311
+ const numberExp = '([-]?\\d*(?:\\.\\d*)?(?:[eE][-]?\\d+)?)';
312
+ const numberSepExp = '[, \\t\\n]';
313
+ const regExpSource = `^\\s*matrix\\s*\\(${[
314
+ // According to MDN, matrix(a,b,c,d,e,f) has form:
315
+ // ⎡ a c e ⎤
316
+ // ⎢ b d f ⎥
317
+ // ⎣ 0 0 1 ⎦
318
+ numberExp, numberExp, numberExp,
319
+ numberExp, numberExp, numberExp, // b, d, f
320
+ ].join(`${numberSepExp}+`)}${numberSepExp}*\\)\\s*$`;
321
+ const matrixExp = new RegExp(regExpSource, 'i');
322
+ const match = matrixExp.exec(cssString);
323
+ if (!match) {
324
+ throw new Error(`Unsupported transformation: ${cssString}`);
325
+ }
326
+ const matrixData = match.slice(1).map(entry => parseFloat(entry));
327
+ const a = matrixData[0];
328
+ const b = matrixData[1];
329
+ const c = matrixData[2];
330
+ const d = matrixData[3];
331
+ const e = matrixData[4];
332
+ const f = matrixData[5];
333
+ const transform = new Mat33(a, c, e, b, d, f, 0, 0, 1);
334
+ return transform;
335
+ }
336
+ }
337
+ Mat33.identity = new Mat33(1, 0, 0, 0, 1, 0, 0, 0, 1);
338
+ export default Mat33;
@@ -0,0 +1,42 @@
1
+ import Vec3 from './Vec3';
2
+ /**
3
+ * Utility functions that facilitate treating `Vec3`s as 2D vectors.
4
+ *
5
+ * @example
6
+ * ```ts,runnable,console
7
+ * import { Vec2 } from '@js-draw/math';
8
+ * console.log(Vec2.of(1, 2));
9
+ * ```
10
+ */
11
+ export declare namespace Vec2 {
12
+ /**
13
+ * Creates a `Vec2` from an x and y coordinate.
14
+ *
15
+ * For example,
16
+ * ```ts
17
+ * const v = Vec2.of(3, 4); // x=3, y=4.
18
+ * ```
19
+ */
20
+ const of: (x: number, y: number) => Vec2;
21
+ /**
22
+ * Creates a `Vec2` from an object containing x and y coordinates.
23
+ *
24
+ * For example,
25
+ * ```ts
26
+ * const v1 = Vec2.ofXY({ x: 3, y: 4.5 });
27
+ * const v2 = Vec2.ofXY({ x: -123.4, y: 1 });
28
+ * ```
29
+ */
30
+ const ofXY: ({ x, y }: {
31
+ x: number;
32
+ y: number;
33
+ }) => Vec2;
34
+ /** A vector of length 1 in the X direction (→). */
35
+ const unitX: Vec3;
36
+ /** A vector of length 1 in the Y direction (↑). */
37
+ const unitY: Vec3;
38
+ /** The zero vector: A vector with x=0, y=0. */
39
+ const zero: Vec3;
40
+ }
41
+ export type Point2 = Vec3;
42
+ export type Vec2 = Vec3;
@@ -0,0 +1,42 @@
1
+ import Vec3 from './Vec3.mjs';
2
+ /**
3
+ * Utility functions that facilitate treating `Vec3`s as 2D vectors.
4
+ *
5
+ * @example
6
+ * ```ts,runnable,console
7
+ * import { Vec2 } from '@js-draw/math';
8
+ * console.log(Vec2.of(1, 2));
9
+ * ```
10
+ */
11
+ export var Vec2;
12
+ (function (Vec2) {
13
+ /**
14
+ * Creates a `Vec2` from an x and y coordinate.
15
+ *
16
+ * For example,
17
+ * ```ts
18
+ * const v = Vec2.of(3, 4); // x=3, y=4.
19
+ * ```
20
+ */
21
+ Vec2.of = (x, y) => {
22
+ return Vec3.of(x, y, 0);
23
+ };
24
+ /**
25
+ * Creates a `Vec2` from an object containing x and y coordinates.
26
+ *
27
+ * For example,
28
+ * ```ts
29
+ * const v1 = Vec2.ofXY({ x: 3, y: 4.5 });
30
+ * const v2 = Vec2.ofXY({ x: -123.4, y: 1 });
31
+ * ```
32
+ */
33
+ Vec2.ofXY = ({ x, y }) => {
34
+ return Vec3.of(x, y, 0);
35
+ };
36
+ /** A vector of length 1 in the X direction (→). */
37
+ Vec2.unitX = Vec2.of(1, 0);
38
+ /** A vector of length 1 in the Y direction (↑). */
39
+ Vec2.unitY = Vec2.of(0, 1);
40
+ /** The zero vector: A vector with x=0, y=0. */
41
+ Vec2.zero = Vec2.of(0, 0);
42
+ })(Vec2 || (Vec2 = {}));
@@ -0,0 +1,126 @@
1
+ /**
2
+ * A vector with three components, $\begin{pmatrix} x \\ y \\ z \end{pmatrix}$.
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 declare class Vec3 {
21
+ readonly x: number;
22
+ readonly y: number;
23
+ readonly z: number;
24
+ private constructor();
25
+ /** Returns the x, y components of this. */
26
+ get xy(): {
27
+ x: number;
28
+ y: number;
29
+ };
30
+ /** Construct a vector from three components. */
31
+ static of(x: number, y: number, z: number): Vec3;
32
+ /** Returns this' `idx`th component. For example, `Vec3.of(1, 2, 3).at(1) → 2`. */
33
+ at(idx: number): number;
34
+ /** Alias for this.magnitude. */
35
+ length(): number;
36
+ magnitude(): number;
37
+ magnitudeSquared(): number;
38
+ /**
39
+ * Return this' angle in the XY plane (treats this as a Vec2).
40
+ *
41
+ * This is equivalent to `Math.atan2(vec.y, vec.x)`.
42
+ */
43
+ angle(): number;
44
+ /**
45
+ * Returns a unit vector in the same direction as this.
46
+ *
47
+ * If `this` has zero length, the resultant vector has `NaN` components.
48
+ */
49
+ normalized(): Vec3;
50
+ /**
51
+ * Like {@link normalized}, except returns zero if this has zero magnitude.
52
+ */
53
+ normalizedOrZero(): Vec3;
54
+ /** @returns A copy of `this` multiplied by a scalar. */
55
+ times(c: number): Vec3;
56
+ plus(v: Vec3): Vec3;
57
+ minus(v: Vec3): Vec3;
58
+ dot(other: Vec3): number;
59
+ cross(other: Vec3): Vec3;
60
+ /**
61
+ * If `other` is a `Vec3`, multiplies `this` component-wise by `other`. Otherwise,
62
+ * if `other is a `number`, returns the result of scalar multiplication.
63
+ *
64
+ * @example
65
+ * ```
66
+ * Vec3.of(1, 2, 3).scale(Vec3.of(2, 4, 6)); // → Vec3(2, 8, 18)
67
+ * ```
68
+ */
69
+ scale(other: Vec3 | number): Vec3;
70
+ /**
71
+ * Returns a vector orthogonal to this. If this is a Vec2, returns `this` rotated
72
+ * 90 degrees counter-clockwise.
73
+ */
74
+ orthog(): Vec3;
75
+ /** Returns this plus a vector of length `distance` in `direction`. */
76
+ extend(distance: number, direction: Vec3): Vec3;
77
+ /** Returns a vector `fractionTo` of the way to target from this. */
78
+ lerp(target: Vec3, fractionTo: number): Vec3;
79
+ /**
80
+ * `zip` Maps a component of this and a corresponding component of
81
+ * `other` to a component of the output vector.
82
+ *
83
+ * @example
84
+ * ```
85
+ * const a = Vec3.of(1, 2, 3);
86
+ * const b = Vec3.of(0.5, 2.1, 2.9);
87
+ *
88
+ * const zipped = a.zip(b, (aComponent, bComponent) => {
89
+ * return Math.min(aComponent, bComponent);
90
+ * });
91
+ *
92
+ * console.log(zipped.toString()); // → Vec(0.5, 2, 2.9)
93
+ * ```
94
+ */
95
+ zip(other: Vec3, zip: (componentInThis: number, componentInOther: number) => number): Vec3;
96
+ /**
97
+ * Returns a vector with each component acted on by `fn`.
98
+ *
99
+ * @example
100
+ * ```
101
+ * console.log(Vec3.of(1, 2, 3).map(val => val + 1)); // → Vec(2, 3, 4)
102
+ * ```
103
+ */
104
+ map(fn: (component: number, index: number) => number): Vec3;
105
+ asArray(): [number, number, number];
106
+ /**
107
+ * [fuzz] The maximum difference between two components for this and [other]
108
+ * to be considered equal.
109
+ *
110
+ * @example
111
+ * ```
112
+ * Vec3.of(1, 2, 3).eq(Vec3.of(4, 5, 6), 100); // → true
113
+ * Vec3.of(1, 2, 3).eq(Vec3.of(4, 5, 6), 0.1); // → false
114
+ * Vec3.of(1, 2, 3).eq(Vec3.of(4, 5, 6), 3); // → true
115
+ * Vec3.of(1, 2, 3).eq(Vec3.of(4, 5, 6), 3.01); // → true
116
+ * Vec3.of(1, 2, 3).eq(Vec3.of(4, 5, 6), 2.99); // → false
117
+ * ```
118
+ */
119
+ eq(other: Vec3, fuzz?: number): boolean;
120
+ toString(): string;
121
+ static unitX: Vec3;
122
+ static unitY: Vec3;
123
+ static unitZ: Vec3;
124
+ static zero: Vec3;
125
+ }
126
+ export default Vec3;