@js-draw/math 1.18.0 → 1.19.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.
@@ -1,42 +1,5 @@
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
- }
1
+ import { Vec3, Vec2 } from './Vec3';
41
2
  export type Point2 = Vec3;
42
3
  export type Vec2 = Vec3;
4
+ export { Vec3, Vec2 };
5
+ export default Vec2;
package/dist/cjs/Vec2.js CHANGED
@@ -1,48 +1,10 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.Vec2 = void 0;
7
- const Vec3_1 = __importDefault(require("./Vec3"));
8
- /**
9
- * Utility functions that facilitate treating `Vec3`s as 2D vectors.
10
- *
11
- * @example
12
- * ```ts,runnable,console
13
- * import { Vec2 } from '@js-draw/math';
14
- * console.log(Vec2.of(1, 2));
15
- * ```
16
- */
17
- var Vec2;
18
- (function (Vec2) {
19
- /**
20
- * Creates a `Vec2` from an x and y coordinate.
21
- *
22
- * For example,
23
- * ```ts
24
- * const v = Vec2.of(3, 4); // x=3, y=4.
25
- * ```
26
- */
27
- Vec2.of = (x, y) => {
28
- return Vec3_1.default.of(x, y, 0);
29
- };
30
- /**
31
- * Creates a `Vec2` from an object containing x and y coordinates.
32
- *
33
- * For example,
34
- * ```ts
35
- * const v1 = Vec2.ofXY({ x: 3, y: 4.5 });
36
- * const v2 = Vec2.ofXY({ x: -123.4, y: 1 });
37
- * ```
38
- */
39
- Vec2.ofXY = ({ x, y }) => {
40
- return Vec3_1.default.of(x, y, 0);
41
- };
42
- /** A vector of length 1 in the X direction (→). */
43
- Vec2.unitX = Vec2.of(1, 0);
44
- /** A vector of length 1 in the Y direction (↑). */
45
- Vec2.unitY = Vec2.of(0, 1);
46
- /** The zero vector: A vector with x=0, y=0. */
47
- Vec2.zero = Vec2.of(0, 0);
48
- })(Vec2 || (exports.Vec2 = Vec2 = {}));
3
+ exports.Vec2 = exports.Vec3 = void 0;
4
+ // Internally, we define Vec2 as a namespace within Vec3 --
5
+ // this allows referencing Vec2s from Vec3 constructors without
6
+ // cyclic references.
7
+ const Vec3_1 = require("./Vec3");
8
+ Object.defineProperty(exports, "Vec3", { enumerable: true, get: function () { return Vec3_1.Vec3; } });
9
+ Object.defineProperty(exports, "Vec2", { enumerable: true, get: function () { return Vec3_1.Vec2; } });
10
+ exports.default = Vec3_1.Vec2;
@@ -17,22 +17,23 @@
17
17
  * console.log('As an array:', Vec3.unitZ.asArray());
18
18
  * ```
19
19
  */
20
- export declare class Vec3 {
20
+ export interface Vec3 {
21
21
  readonly x: number;
22
22
  readonly y: number;
23
23
  readonly z: number;
24
- private constructor();
25
- /** Returns the x, y components of this. */
26
- get xy(): {
24
+ /**
25
+ * Returns the x, y components of this.
26
+ * May be implemented as a getter method.
27
+ */
28
+ readonly xy: {
27
29
  x: number;
28
30
  y: number;
29
31
  };
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. */
32
+ /** Returns the vector's `idx`th component. For example, `Vec3.of(1, 2, 3).at(1) → 2`. */
33
+ at(i: number): number;
34
+ /** Alias for `.magnitude`. */
35
35
  length(): number;
36
+ /** Returns the length of this vector in ℝ^3. */
36
37
  magnitude(): number;
37
38
  magnitudeSquared(): number;
38
39
  /**
@@ -41,7 +42,7 @@ export declare class Vec3 {
41
42
  *
42
43
  * Equivalent to `.minus(p).magnitudeSquared()`.
43
44
  */
44
- squareDistanceTo(p: Vec3): number;
45
+ squareDistanceTo(other: Vec3): number;
45
46
  /**
46
47
  * Interpreting this vector as a point in ℝ³, returns the distance to the point
47
48
  * `p`.
@@ -90,10 +91,17 @@ export declare class Vec3 {
90
91
  normalizedOrZero(): Vec3;
91
92
  /** @returns A copy of `this` multiplied by a scalar. */
92
93
  times(c: number): Vec3;
94
+ /** Performs vector addition. */
93
95
  plus(v: Vec3): Vec3;
94
96
  minus(v: Vec3): Vec3;
95
- dot(other: Vec3): number;
96
- cross(other: Vec3): Vec3;
97
+ /**
98
+ * Computes the scalar product between this and `v`.
99
+ *
100
+ * In particular, `a.dot(b)` is equivalent to `a.x * b.x + a.y * b.y + a.z * b.z`.
101
+ */
102
+ dot(v: Vec3): number;
103
+ /** Computes the cross product between this and `v` */
104
+ cross(v: Vec3): Vec3;
97
105
  /**
98
106
  * If `other` is a `Vec3`, multiplies `this` component-wise by `other`. Otherwise,
99
107
  * if `other is a `number`, returns the result of scalar multiplication.
@@ -154,11 +162,99 @@ export declare class Vec3 {
154
162
  * Vec3.of(1, 2, 3).eq(Vec3.of(4, 5, 6), 2.99); // → false
155
163
  * ```
156
164
  */
165
+ eq(other: Vec3, tolerance?: number): boolean;
166
+ toString(): string;
167
+ }
168
+ declare class Vec2Impl implements Vec3 {
169
+ readonly x: number;
170
+ readonly y: number;
171
+ constructor(x: number, y: number);
172
+ get z(): number;
173
+ get xy(): {
174
+ x: number;
175
+ y: number;
176
+ };
177
+ at(idx: number): number;
178
+ length(): number;
179
+ magnitude(): number;
180
+ magnitudeSquared(): number;
181
+ squareDistanceTo(p: Vec3): number;
182
+ distanceTo(p: Vec3): number;
183
+ maximumEntryMagnitude(): number;
184
+ angle(): number;
185
+ normalized(): Vec3;
186
+ normalizedOrZero(): Vec3;
187
+ times(c: number): Vec3;
188
+ plus(v: Vec3): Vec3;
189
+ minus(v: Vec3): Vec3;
190
+ dot(other: Vec3): number;
191
+ cross(other: Vec3): Vec3;
192
+ scale(other: Vec3 | number): Vec3;
193
+ orthog(): Vec3;
194
+ extend(distance: number, direction: Vec3): Vec3;
195
+ lerp(target: Vec3, fractionTo: number): Vec3;
196
+ zip(other: Vec3, zip: (componentInThis: number, componentInOther: number) => number): Vec3;
197
+ map(fn: (component: number, index: number) => number): Vec3;
198
+ asArray(): [number, number, number];
157
199
  eq(other: Vec3, fuzz?: number): boolean;
158
200
  toString(): string;
159
- static unitX: Vec3;
160
- static unitY: Vec3;
161
- static unitZ: Vec3;
162
- static zero: Vec3;
201
+ }
202
+ /**
203
+ * A `Vec2` is a `Vec3` optimized for working in a plane. As such, they have an
204
+ * always-zero `z` component.
205
+ *
206
+ * ```ts,runnable,console
207
+ * import { Vec2 } from '@js-draw/math';
208
+ * console.log(Vec2.of(1, 2));
209
+ * ```
210
+ */
211
+ export declare namespace Vec2 {
212
+ /**
213
+ * Creates a `Vec2` from an x and y coordinate.
214
+ *
215
+ * @example
216
+ * ```ts,runnable,console
217
+ * import { Vec2 } from '@js-draw/math';
218
+ * const v = Vec2.of(3, 4); // x=3, y=4.
219
+ * ```
220
+ */
221
+ const of: (x: number, y: number) => Vec2Impl;
222
+ /**
223
+ * Creates a `Vec2` from an object containing `x` and `y` coordinates.
224
+ *
225
+ * @example
226
+ * ```ts,runnable,console
227
+ * import { Vec2 } from '@js-draw/math';
228
+ * const v1 = Vec2.ofXY({ x: 3, y: 4.5 });
229
+ * const v2 = Vec2.ofXY({ x: -123.4, y: 1 });
230
+ * ```
231
+ */
232
+ const ofXY: ({ x, y }: {
233
+ x: number;
234
+ y: number;
235
+ }) => Vec2Impl;
236
+ /** A vector of length 1 in the X direction (→). */
237
+ const unitX: Vec2Impl;
238
+ /** A vector of length 1 in the Y direction (↑). */
239
+ const unitY: Vec2Impl;
240
+ /** The zero vector: A vector with x=0, y=0. */
241
+ const zero: Vec2Impl;
242
+ }
243
+ export declare namespace Vec3 {
244
+ /**
245
+ * Construct a vector from three components.
246
+ *
247
+ * @example
248
+ * ```ts,runnable,console
249
+ * import { Vec3 } from '@js-draw/math';
250
+ * const v1 = Vec3.of(1, 2, 3);
251
+ * ```
252
+ */
253
+ const of: (x: number, y: number, z: number) => Vec3;
254
+ const unitX: Vec2Impl;
255
+ const unitY: Vec2Impl;
256
+ const zero: Vec2Impl;
257
+ /** A vector of length 1 in the z direction. */
258
+ const unitZ: Vec3;
163
259
  }
164
260
  export default Vec3;
package/dist/cjs/Vec3.js CHANGED
@@ -1,32 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Vec3 = void 0;
4
- /**
5
- * A vector with three components, $\begin{pmatrix} x \\ y \\ z \end{pmatrix}$.
6
- * Can also be used to represent a two-component vector.
7
- *
8
- * A `Vec3` is immutable.
9
- *
10
- * @example
11
- *
12
- * ```ts,runnable,console
13
- * import { Vec3 } from '@js-draw/math';
14
- *
15
- * console.log('Vector addition:', Vec3.of(1, 2, 3).plus(Vec3.of(0, 1, 0)));
16
- * console.log('Scalar multiplication:', Vec3.of(1, 2, 3).times(2));
17
- * console.log('Cross products:', Vec3.unitX.cross(Vec3.unitY));
18
- * console.log('Magnitude:', Vec3.of(1, 2, 3).length(), 'or', Vec3.of(1, 2, 3).magnitude());
19
- * console.log('Square Magnitude:', Vec3.of(1, 2, 3).magnitudeSquared());
20
- * console.log('As an array:', Vec3.unitZ.asArray());
21
- * ```
22
- */
23
- class Vec3 {
3
+ exports.Vec3 = exports.Vec2 = void 0;
4
+ const defaultEqlTolerance = 1e-10;
5
+ class Vec3Impl {
24
6
  constructor(x, y, z) {
25
7
  this.x = x;
26
8
  this.y = y;
27
9
  this.z = z;
28
10
  }
29
- /** Returns the x, y components of this. */
30
11
  get xy() {
31
12
  // Useful for APIs that behave differently if .z is present.
32
13
  return {
@@ -34,10 +15,6 @@ class Vec3 {
34
15
  y: this.y,
35
16
  };
36
17
  }
37
- /** Construct a vector from three components. */
38
- static of(x, y, z) {
39
- return new Vec3(x, y, z);
40
- }
41
18
  /** Returns this' `idx`th component. For example, `Vec3.of(1, 2, 3).at(1) → 2`. */
42
19
  at(idx) {
43
20
  if (idx === 0)
@@ -48,89 +25,40 @@ class Vec3 {
48
25
  return this.z;
49
26
  throw new Error(`${idx} out of bounds!`);
50
27
  }
51
- /** Alias for this.magnitude. */
52
28
  length() {
53
29
  return this.magnitude();
54
30
  }
55
31
  magnitude() {
56
- return Math.sqrt(this.dot(this));
32
+ return Math.sqrt(this.magnitudeSquared());
57
33
  }
58
34
  magnitudeSquared() {
59
- return this.dot(this);
35
+ return this.x * this.x + this.y * this.y + this.z * this.z;
60
36
  }
61
- /**
62
- * Interpreting this vector as a point in ℝ^3, computes the square distance
63
- * to another point, `p`.
64
- *
65
- * Equivalent to `.minus(p).magnitudeSquared()`.
66
- */
67
37
  squareDistanceTo(p) {
68
38
  const dx = this.x - p.x;
69
39
  const dy = this.y - p.y;
70
40
  const dz = this.z - p.z;
71
41
  return dx * dx + dy * dy + dz * dz;
72
42
  }
73
- /**
74
- * Interpreting this vector as a point in ℝ³, returns the distance to the point
75
- * `p`.
76
- *
77
- * Equivalent to `.minus(p).magnitude()`.
78
- */
79
43
  distanceTo(p) {
80
44
  return Math.sqrt(this.squareDistanceTo(p));
81
45
  }
82
- /**
83
- * Returns the entry of this with the greatest magnitude.
84
- *
85
- * In other words, returns $\max \{ |x| : x \in {\bf v} \}$, where ${\bf v}$ is the set of
86
- * all entries of this vector.
87
- *
88
- * **Example**:
89
- * ```ts,runnable,console
90
- * import { Vec3 } from '@js-draw/math';
91
- * console.log(Vec3.of(-1, -10, 8).maximumEntryMagnitude()); // -> 10
92
- * ```
93
- */
94
46
  maximumEntryMagnitude() {
95
47
  return Math.max(Math.abs(this.x), Math.max(Math.abs(this.y), Math.abs(this.z)));
96
48
  }
97
- /**
98
- * Return this' angle in the XY plane (treats this as a Vec2).
99
- *
100
- * This is equivalent to `Math.atan2(vec.y, vec.x)`.
101
- *
102
- * As such, observing that `Math.atan2(-0, -1)` $\approx -\pi$ and `Math.atan2(0, -1)`$\approx \pi$
103
- * the resultant angle is in the range $[-\pi, pi]$.
104
- *
105
- * **Example**:
106
- * ```ts,runnable,console
107
- * import { Vec2 } from '@js-draw/math';
108
- * console.log(Vec2.of(-1, -0).angle()); // atan2(-0, -1)
109
- * console.log(Vec2.of(-1, 0).angle()); // atan2(0, -1)
110
- * ```
111
- */
112
49
  angle() {
113
50
  return Math.atan2(this.y, this.x);
114
51
  }
115
- /**
116
- * Returns a unit vector in the same direction as this.
117
- *
118
- * If `this` has zero length, the resultant vector has `NaN` components.
119
- */
120
52
  normalized() {
121
53
  const norm = this.magnitude();
122
54
  return Vec3.of(this.x / norm, this.y / norm, this.z / norm);
123
55
  }
124
- /**
125
- * Like {@link normalized}, except returns zero if this has zero magnitude.
126
- */
127
56
  normalizedOrZero() {
128
57
  if (this.eq(Vec3.zero)) {
129
58
  return Vec3.zero;
130
59
  }
131
60
  return this.normalized();
132
61
  }
133
- /** @returns A copy of `this` multiplied by a scalar. */
134
62
  times(c) {
135
63
  return Vec3.of(this.x * c, this.y * c, this.z * c);
136
64
  }
@@ -149,25 +77,12 @@ class Vec3 {
149
77
  // | x2 y2 z2|
150
78
  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);
151
79
  }
152
- /**
153
- * If `other` is a `Vec3`, multiplies `this` component-wise by `other`. Otherwise,
154
- * if `other is a `number`, returns the result of scalar multiplication.
155
- *
156
- * @example
157
- * ```
158
- * Vec3.of(1, 2, 3).scale(Vec3.of(2, 4, 6)); // → Vec3(2, 8, 18)
159
- * ```
160
- */
161
80
  scale(other) {
162
81
  if (typeof other === 'number') {
163
82
  return this.times(other);
164
83
  }
165
84
  return Vec3.of(this.x * other.x, this.y * other.y, this.z * other.z);
166
85
  }
167
- /**
168
- * Returns a vector orthogonal to this. If this is a Vec2, returns `this` rotated
169
- * 90 degrees counter-clockwise.
170
- */
171
86
  orthog() {
172
87
  // If parallel to the z-axis
173
88
  if (this.dot(Vec3.unitX) === 0 && this.dot(Vec3.unitY) === 0) {
@@ -175,62 +90,22 @@ class Vec3 {
175
90
  }
176
91
  return this.cross(Vec3.unitZ.times(-1)).normalized();
177
92
  }
178
- /** Returns this plus a vector of length `distance` in `direction`. */
179
93
  extend(distance, direction) {
180
94
  return this.plus(direction.normalized().times(distance));
181
95
  }
182
- /** Returns a vector `fractionTo` of the way to target from this. */
183
96
  lerp(target, fractionTo) {
184
97
  return this.times(1 - fractionTo).plus(target.times(fractionTo));
185
98
  }
186
- /**
187
- * `zip` Maps a component of this and a corresponding component of
188
- * `other` to a component of the output vector.
189
- *
190
- * @example
191
- * ```
192
- * const a = Vec3.of(1, 2, 3);
193
- * const b = Vec3.of(0.5, 2.1, 2.9);
194
- *
195
- * const zipped = a.zip(b, (aComponent, bComponent) => {
196
- * return Math.min(aComponent, bComponent);
197
- * });
198
- *
199
- * console.log(zipped.toString()); // → Vec(0.5, 2, 2.9)
200
- * ```
201
- */
202
99
  zip(other, zip) {
203
100
  return Vec3.of(zip(other.x, this.x), zip(other.y, this.y), zip(other.z, this.z));
204
101
  }
205
- /**
206
- * Returns a vector with each component acted on by `fn`.
207
- *
208
- * @example
209
- * ```ts,runnable,console
210
- * import { Vec3 } from '@js-draw/math';
211
- * console.log(Vec3.of(1, 2, 3).map(val => val + 1)); // → Vec(2, 3, 4)
212
- * ```
213
- */
214
102
  map(fn) {
215
103
  return Vec3.of(fn(this.x, 0), fn(this.y, 1), fn(this.z, 2));
216
104
  }
217
105
  asArray() {
218
106
  return [this.x, this.y, this.z];
219
107
  }
220
- /**
221
- * [fuzz] The maximum difference between two components for this and [other]
222
- * to be considered equal.
223
- *
224
- * @example
225
- * ```
226
- * Vec3.of(1, 2, 3).eq(Vec3.of(4, 5, 6), 100); // → true
227
- * Vec3.of(1, 2, 3).eq(Vec3.of(4, 5, 6), 0.1); // → false
228
- * Vec3.of(1, 2, 3).eq(Vec3.of(4, 5, 6), 3); // → true
229
- * Vec3.of(1, 2, 3).eq(Vec3.of(4, 5, 6), 3.01); // → true
230
- * Vec3.of(1, 2, 3).eq(Vec3.of(4, 5, 6), 2.99); // → false
231
- * ```
232
- */
233
- eq(other, fuzz = 1e-10) {
108
+ eq(other, fuzz = defaultEqlTolerance) {
234
109
  return (Math.abs(other.x - this.x) <= fuzz
235
110
  && Math.abs(other.y - this.y) <= fuzz
236
111
  && Math.abs(other.z - this.z) <= fuzz);
@@ -239,9 +114,182 @@ class Vec3 {
239
114
  return `Vec(${this.x}, ${this.y}, ${this.z})`;
240
115
  }
241
116
  }
242
- exports.Vec3 = Vec3;
243
- Vec3.unitX = Vec3.of(1, 0, 0);
244
- Vec3.unitY = Vec3.of(0, 1, 0);
245
- Vec3.unitZ = Vec3.of(0, 0, 1);
246
- Vec3.zero = Vec3.of(0, 0, 0);
117
+ class Vec2Impl {
118
+ constructor(x, y) {
119
+ this.x = x;
120
+ this.y = y;
121
+ }
122
+ get z() { return 0; }
123
+ get xy() {
124
+ // Useful for APIs that behave differently if .z is present.
125
+ return {
126
+ x: this.x,
127
+ y: this.y,
128
+ };
129
+ }
130
+ at(idx) {
131
+ if (idx === 0)
132
+ return this.x;
133
+ if (idx === 1)
134
+ return this.y;
135
+ if (idx === 2)
136
+ return 0;
137
+ throw new Error(`${idx} out of bounds!`);
138
+ }
139
+ length() {
140
+ return this.magnitude();
141
+ }
142
+ magnitude() {
143
+ return Math.sqrt(this.x * this.x + this.y * this.y);
144
+ }
145
+ magnitudeSquared() {
146
+ return this.x * this.x + this.y * this.y;
147
+ }
148
+ squareDistanceTo(p) {
149
+ const dx = this.x - p.x;
150
+ const dy = this.y - p.y;
151
+ return dx * dx + dy * dy + p.z * p.z;
152
+ }
153
+ distanceTo(p) {
154
+ return Math.sqrt(this.squareDistanceTo(p));
155
+ }
156
+ maximumEntryMagnitude() {
157
+ return Math.max(Math.abs(this.x), Math.abs(this.y));
158
+ }
159
+ angle() {
160
+ return Math.atan2(this.y, this.x);
161
+ }
162
+ normalized() {
163
+ const norm = this.magnitude();
164
+ return Vec2.of(this.x / norm, this.y / norm);
165
+ }
166
+ normalizedOrZero() {
167
+ if (this.eq(Vec3.zero)) {
168
+ return Vec3.zero;
169
+ }
170
+ return this.normalized();
171
+ }
172
+ times(c) {
173
+ return Vec2.of(this.x * c, this.y * c);
174
+ }
175
+ plus(v) {
176
+ return Vec3.of(this.x + v.x, this.y + v.y, v.z);
177
+ }
178
+ minus(v) {
179
+ return Vec3.of(this.x - v.x, this.y - v.y, -v.z);
180
+ }
181
+ dot(other) {
182
+ return this.x * other.x + this.y * other.y;
183
+ }
184
+ cross(other) {
185
+ // | i j k |
186
+ // | x1 y1 z1| = (i)(y1z2 - y2z1) - (j)(x1z2 - x2z1) + (k)(x1y2 - x2y1)
187
+ // | x2 y2 z2|
188
+ return Vec3.of(this.y * other.z, -this.x * other.z, this.x * other.y - other.x * this.y);
189
+ }
190
+ scale(other) {
191
+ if (typeof other === 'number') {
192
+ return this.times(other);
193
+ }
194
+ return Vec2.of(this.x * other.x, this.y * other.y);
195
+ }
196
+ orthog() {
197
+ // If parallel to the z-axis
198
+ if (this.dot(Vec3.unitX) === 0 && this.dot(Vec3.unitY) === 0) {
199
+ return this.dot(Vec3.unitX) === 0 ? Vec3.unitX : this.cross(Vec3.unitX).normalized();
200
+ }
201
+ return this.cross(Vec3.unitZ.times(-1)).normalized();
202
+ }
203
+ extend(distance, direction) {
204
+ return this.plus(direction.normalized().times(distance));
205
+ }
206
+ lerp(target, fractionTo) {
207
+ return this.times(1 - fractionTo).plus(target.times(fractionTo));
208
+ }
209
+ zip(other, zip) {
210
+ return Vec3.of(zip(other.x, this.x), zip(other.y, this.y), zip(other.z, 0));
211
+ }
212
+ map(fn) {
213
+ return Vec3.of(fn(this.x, 0), fn(this.y, 1), fn(0, 2));
214
+ }
215
+ asArray() {
216
+ return [this.x, this.y, 0];
217
+ }
218
+ eq(other, fuzz = defaultEqlTolerance) {
219
+ return (Math.abs(other.x - this.x) <= fuzz
220
+ && Math.abs(other.y - this.y) <= fuzz
221
+ && Math.abs(other.z) <= fuzz);
222
+ }
223
+ toString() {
224
+ return `Vec(${this.x}, ${this.y})`;
225
+ }
226
+ }
227
+ /**
228
+ * A `Vec2` is a `Vec3` optimized for working in a plane. As such, they have an
229
+ * always-zero `z` component.
230
+ *
231
+ * ```ts,runnable,console
232
+ * import { Vec2 } from '@js-draw/math';
233
+ * console.log(Vec2.of(1, 2));
234
+ * ```
235
+ */
236
+ var Vec2;
237
+ (function (Vec2) {
238
+ /**
239
+ * Creates a `Vec2` from an x and y coordinate.
240
+ *
241
+ * @example
242
+ * ```ts,runnable,console
243
+ * import { Vec2 } from '@js-draw/math';
244
+ * const v = Vec2.of(3, 4); // x=3, y=4.
245
+ * ```
246
+ */
247
+ Vec2.of = (x, y) => {
248
+ return new Vec2Impl(x, y);
249
+ };
250
+ /**
251
+ * Creates a `Vec2` from an object containing `x` and `y` coordinates.
252
+ *
253
+ * @example
254
+ * ```ts,runnable,console
255
+ * import { Vec2 } from '@js-draw/math';
256
+ * const v1 = Vec2.ofXY({ x: 3, y: 4.5 });
257
+ * const v2 = Vec2.ofXY({ x: -123.4, y: 1 });
258
+ * ```
259
+ */
260
+ Vec2.ofXY = ({ x, y }) => {
261
+ return Vec2.of(x, y);
262
+ };
263
+ /** A vector of length 1 in the X direction (→). */
264
+ Vec2.unitX = Vec2.of(1, 0);
265
+ /** A vector of length 1 in the Y direction (↑). */
266
+ Vec2.unitY = Vec2.of(0, 1);
267
+ /** The zero vector: A vector with x=0, y=0. */
268
+ Vec2.zero = Vec2.of(0, 0);
269
+ })(Vec2 || (exports.Vec2 = Vec2 = {}));
270
+ var Vec3;
271
+ (function (Vec3) {
272
+ /**
273
+ * Construct a vector from three components.
274
+ *
275
+ * @example
276
+ * ```ts,runnable,console
277
+ * import { Vec3 } from '@js-draw/math';
278
+ * const v1 = Vec3.of(1, 2, 3);
279
+ * ```
280
+ */
281
+ Vec3.of = (x, y, z) => {
282
+ if (z === 0) {
283
+ return Vec2.of(x, y);
284
+ }
285
+ else {
286
+ return new Vec3Impl(x, y, z);
287
+ }
288
+ };
289
+ Vec3.unitX = Vec2.unitX;
290
+ Vec3.unitY = Vec2.unitY;
291
+ Vec3.zero = Vec2.zero;
292
+ /** A vector of length 1 in the z direction. */
293
+ Vec3.unitZ = Vec3.of(0, 0, 1);
294
+ })(Vec3 || (exports.Vec3 = Vec3 = {}));
247
295
  exports.default = Vec3;