@js-draw/math 1.18.0 → 1.19.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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;