@js-draw/math 1.18.0 → 1.21.1

Sign up to get free protection for your applications and to get access to all the features.
package/src/Vec3.ts CHANGED
@@ -19,49 +19,25 @@
19
19
  * console.log('As an array:', Vec3.unitZ.asArray());
20
20
  * ```
21
21
  */
22
- export class Vec3 {
23
- private constructor(
24
- public readonly x: number,
25
- public readonly y: number,
26
- public readonly z: number
27
- ) {
28
- }
29
-
30
- /** Returns the x, y components of this. */
31
- public get xy(): { x: number; y: number } {
32
- // Useful for APIs that behave differently if .z is present.
33
- return {
34
- x: this.x,
35
- y: this.y,
36
- };
37
- }
22
+ export interface Vec3 {
23
+ readonly x: number;
24
+ readonly y: number;
25
+ readonly z: number;
38
26
 
39
- /** Construct a vector from three components. */
40
- public static of(x: number, y: number, z: number): Vec3 {
41
- return new Vec3(x, y, z);
42
- }
43
-
44
- /** Returns this' `idx`th component. For example, `Vec3.of(1, 2, 3).at(1) → 2`. */
45
- public at(idx: number): number {
46
- if (idx === 0) return this.x;
47
- if (idx === 1) return this.y;
48
- if (idx === 2) return this.z;
49
-
50
- throw new Error(`${idx} out of bounds!`);
51
- }
52
-
53
- /** Alias for this.magnitude. */
54
- public length(): number {
55
- return this.magnitude();
56
- }
27
+ /**
28
+ * Returns the x, y components of this.
29
+ * May be implemented as a getter method.
30
+ */
31
+ readonly xy: { x: number, y: number };
57
32
 
58
- public magnitude(): number {
59
- return Math.sqrt(this.dot(this));
60
- }
33
+ /** Returns the vector's `idx`th component. For example, `Vec3.of(1, 2, 3).at(1) 2`. */
34
+ at(i: number): number;
61
35
 
62
- public magnitudeSquared(): number {
63
- return this.dot(this);
64
- }
36
+ /** Alias for `.magnitude`. */
37
+ length(): number;
38
+ /** Returns the length of this vector in ℝ^3. */
39
+ magnitude(): number;
40
+ magnitudeSquared(): number;
65
41
 
66
42
  /**
67
43
  * Interpreting this vector as a point in ℝ^3, computes the square distance
@@ -69,12 +45,7 @@ export class Vec3 {
69
45
  *
70
46
  * Equivalent to `.minus(p).magnitudeSquared()`.
71
47
  */
72
- public squareDistanceTo(p: Vec3) {
73
- const dx = this.x - p.x;
74
- const dy = this.y - p.y;
75
- const dz = this.z - p.z;
76
- return dx * dx + dy * dy + dz * dz;
77
- }
48
+ squareDistanceTo(other: Vec3): number;
78
49
 
79
50
  /**
80
51
  * Interpreting this vector as a point in ℝ³, returns the distance to the point
@@ -82,9 +53,7 @@ export class Vec3 {
82
53
  *
83
54
  * Equivalent to `.minus(p).magnitude()`.
84
55
  */
85
- public distanceTo(p: Vec3) {
86
- return Math.sqrt(this.squareDistanceTo(p));
87
- }
56
+ distanceTo(p: Vec3): number;
88
57
 
89
58
  /**
90
59
  * Returns the entry of this with the greatest magnitude.
@@ -98,9 +67,7 @@ export class Vec3 {
98
67
  * console.log(Vec3.of(-1, -10, 8).maximumEntryMagnitude()); // -> 10
99
68
  * ```
100
69
  */
101
- public maximumEntryMagnitude(): number {
102
- return Math.max(Math.abs(this.x), Math.max(Math.abs(this.y), Math.abs(this.z)));
103
- }
70
+ maximumEntryMagnitude(): number;
104
71
 
105
72
  /**
106
73
  * Return this' angle in the XY plane (treats this as a Vec2).
@@ -117,23 +84,175 @@ export class Vec3 {
117
84
  * console.log(Vec2.of(-1, 0).angle()); // atan2(0, -1)
118
85
  * ```
119
86
  */
120
- public angle(): number {
121
- return Math.atan2(this.y, this.x);
122
- }
87
+ angle(): number;
123
88
 
124
89
  /**
125
90
  * Returns a unit vector in the same direction as this.
126
91
  *
127
92
  * If `this` has zero length, the resultant vector has `NaN` components.
128
93
  */
94
+ normalized(): Vec3;
95
+
96
+ /**
97
+ * Like {@link normalized}, except returns zero if this has zero magnitude.
98
+ */
99
+ normalizedOrZero(): Vec3;
100
+
101
+ /** @returns A copy of `this` multiplied by a scalar. */
102
+ times(c: number): Vec3;
103
+
104
+ /** Performs vector addition. */
105
+ plus(v: Vec3): Vec3;
106
+ minus(v: Vec3): Vec3;
107
+
108
+ /**
109
+ * Computes the scalar product between this and `v`.
110
+ *
111
+ * In particular, `a.dot(b)` is equivalent to `a.x * b.x + a.y * b.y + a.z * b.z`.
112
+ */
113
+ dot(v: Vec3): number;
114
+
115
+ /** Computes the cross product between this and `v` */
116
+ cross(v: Vec3): Vec3;
117
+
118
+ /**
119
+ * If `other` is a `Vec3`, multiplies `this` component-wise by `other`. Otherwise,
120
+ * if `other is a `number`, returns the result of scalar multiplication.
121
+ *
122
+ * @example
123
+ * ```
124
+ * Vec3.of(1, 2, 3).scale(Vec3.of(2, 4, 6)); // → Vec3(2, 8, 18)
125
+ * ```
126
+ */
127
+ scale(other: Vec3|number): Vec3;
128
+
129
+ /**
130
+ * Returns a vector orthogonal to this. If this is a Vec2, returns `this` rotated
131
+ * 90 degrees counter-clockwise.
132
+ */
133
+ orthog(): Vec3;
134
+
135
+ /** Returns this plus a vector of length `distance` in `direction`. */
136
+ extend(distance: number, direction: Vec3): Vec3;
137
+
138
+ /** Returns a vector `fractionTo` of the way to target from this. */
139
+ lerp(target: Vec3, fractionTo: number): Vec3;
140
+
141
+ /**
142
+ * `zip` Maps a component of this and a corresponding component of
143
+ * `other` to a component of the output vector.
144
+ *
145
+ * @example
146
+ * ```
147
+ * const a = Vec3.of(1, 2, 3);
148
+ * const b = Vec3.of(0.5, 2.1, 2.9);
149
+ *
150
+ * const zipped = a.zip(b, (aComponent, bComponent) => {
151
+ * return Math.min(aComponent, bComponent);
152
+ * });
153
+ *
154
+ * console.log(zipped.toString()); // → Vec(0.5, 2, 2.9)
155
+ * ```
156
+ */
157
+ zip(
158
+ other: Vec3, zip: (componentInThis: number, componentInOther: number)=> number
159
+ ): Vec3;
160
+
161
+ /**
162
+ * Returns a vector with each component acted on by `fn`.
163
+ *
164
+ * @example
165
+ * ```ts,runnable,console
166
+ * import { Vec3 } from '@js-draw/math';
167
+ * console.log(Vec3.of(1, 2, 3).map(val => val + 1)); // → Vec(2, 3, 4)
168
+ * ```
169
+ */
170
+ map(fn: (component: number, index: number)=> number): Vec3;
171
+
172
+ asArray(): [ number, number, number ];
173
+
174
+
175
+ /**
176
+ * [fuzz] The maximum difference between two components for this and [other]
177
+ * to be considered equal.
178
+ *
179
+ * @example
180
+ * ```
181
+ * Vec3.of(1, 2, 3).eq(Vec3.of(4, 5, 6), 100); // → true
182
+ * Vec3.of(1, 2, 3).eq(Vec3.of(4, 5, 6), 0.1); // → false
183
+ * Vec3.of(1, 2, 3).eq(Vec3.of(4, 5, 6), 3); // → true
184
+ * Vec3.of(1, 2, 3).eq(Vec3.of(4, 5, 6), 3.01); // → true
185
+ * Vec3.of(1, 2, 3).eq(Vec3.of(4, 5, 6), 2.99); // → false
186
+ * ```
187
+ */
188
+ eq(other: Vec3, tolerance?: number): boolean;
189
+
190
+ toString(): string;
191
+ }
192
+
193
+ const defaultEqlTolerance = 1e-10;
194
+
195
+ class Vec3Impl implements Vec3 {
196
+ public constructor(
197
+ public readonly x: number,
198
+ public readonly y: number,
199
+ public readonly z: number
200
+ ) {
201
+ }
202
+
203
+ public get xy(): { x: number; y: number } {
204
+ // Useful for APIs that behave differently if .z is present.
205
+ return {
206
+ x: this.x,
207
+ y: this.y,
208
+ };
209
+ }
210
+
211
+ /** Returns this' `idx`th component. For example, `Vec3.of(1, 2, 3).at(1) → 2`. */
212
+ public at(idx: number): number {
213
+ if (idx === 0) return this.x;
214
+ if (idx === 1) return this.y;
215
+ if (idx === 2) return this.z;
216
+
217
+ throw new Error(`${idx} out of bounds!`);
218
+ }
219
+
220
+ public length(): number {
221
+ return this.magnitude();
222
+ }
223
+
224
+ public magnitude(): number {
225
+ return Math.sqrt(this.magnitudeSquared());
226
+ }
227
+
228
+ public magnitudeSquared(): number {
229
+ return this.x * this.x + this.y * this.y + this.z * this.z;
230
+ }
231
+
232
+ public squareDistanceTo(p: Vec3) {
233
+ const dx = this.x - p.x;
234
+ const dy = this.y - p.y;
235
+ const dz = this.z - p.z;
236
+ return dx * dx + dy * dy + dz * dz;
237
+ }
238
+
239
+ public distanceTo(p: Vec3) {
240
+ return Math.sqrt(this.squareDistanceTo(p));
241
+ }
242
+
243
+ public maximumEntryMagnitude(): number {
244
+ return Math.max(Math.abs(this.x), Math.max(Math.abs(this.y), Math.abs(this.z)));
245
+ }
246
+
247
+ public angle(): number {
248
+ return Math.atan2(this.y, this.x);
249
+ }
250
+
129
251
  public normalized(): Vec3 {
130
252
  const norm = this.magnitude();
131
253
  return Vec3.of(this.x / norm, this.y / norm, this.z / norm);
132
254
  }
133
255
 
134
- /**
135
- * Like {@link normalized}, except returns zero if this has zero magnitude.
136
- */
137
256
  public normalizedOrZero(): Vec3 {
138
257
  if (this.eq(Vec3.zero)) {
139
258
  return Vec3.zero;
@@ -142,7 +261,6 @@ export class Vec3 {
142
261
  return this.normalized();
143
262
  }
144
263
 
145
- /** @returns A copy of `this` multiplied by a scalar. */
146
264
  public times(c: number): Vec3 {
147
265
  return Vec3.of(this.x * c, this.y * c, this.z * c);
148
266
  }
@@ -166,19 +284,10 @@ export class Vec3 {
166
284
  return Vec3.of(
167
285
  this.y * other.z - other.y * this.z,
168
286
  other.x * this.z - this.x * other.z,
169
- this.x * other.y - other.x * this.y
287
+ this.x * other.y - other.x * this.y,
170
288
  );
171
289
  }
172
290
 
173
- /**
174
- * If `other` is a `Vec3`, multiplies `this` component-wise by `other`. Otherwise,
175
- * if `other is a `number`, returns the result of scalar multiplication.
176
- *
177
- * @example
178
- * ```
179
- * Vec3.of(1, 2, 3).scale(Vec3.of(2, 4, 6)); // → Vec3(2, 8, 18)
180
- * ```
181
- */
182
291
  public scale(other: Vec3|number): Vec3 {
183
292
  if (typeof other === 'number') {
184
293
  return this.times(other);
@@ -191,10 +300,6 @@ export class Vec3 {
191
300
  );
192
301
  }
193
302
 
194
- /**
195
- * Returns a vector orthogonal to this. If this is a Vec2, returns `this` rotated
196
- * 90 degrees counter-clockwise.
197
- */
198
303
  public orthog(): Vec3 {
199
304
  // If parallel to the z-axis
200
305
  if (this.dot(Vec3.unitX) === 0 && this.dot(Vec3.unitY) === 0) {
@@ -204,32 +309,14 @@ export class Vec3 {
204
309
  return this.cross(Vec3.unitZ.times(-1)).normalized();
205
310
  }
206
311
 
207
- /** Returns this plus a vector of length `distance` in `direction`. */
208
312
  public extend(distance: number, direction: Vec3): Vec3 {
209
313
  return this.plus(direction.normalized().times(distance));
210
314
  }
211
315
 
212
- /** Returns a vector `fractionTo` of the way to target from this. */
213
316
  public lerp(target: Vec3, fractionTo: number): Vec3 {
214
317
  return this.times(1 - fractionTo).plus(target.times(fractionTo));
215
318
  }
216
319
 
217
- /**
218
- * `zip` Maps a component of this and a corresponding component of
219
- * `other` to a component of the output vector.
220
- *
221
- * @example
222
- * ```
223
- * const a = Vec3.of(1, 2, 3);
224
- * const b = Vec3.of(0.5, 2.1, 2.9);
225
- *
226
- * const zipped = a.zip(b, (aComponent, bComponent) => {
227
- * return Math.min(aComponent, bComponent);
228
- * });
229
- *
230
- * console.log(zipped.toString()); // → Vec(0.5, 2, 2.9)
231
- * ```
232
- */
233
320
  public zip(
234
321
  other: Vec3, zip: (componentInThis: number, componentInOther: number)=> number
235
322
  ): Vec3 {
@@ -240,39 +327,15 @@ export class Vec3 {
240
327
  );
241
328
  }
242
329
 
243
- /**
244
- * Returns a vector with each component acted on by `fn`.
245
- *
246
- * @example
247
- * ```ts,runnable,console
248
- * import { Vec3 } from '@js-draw/math';
249
- * console.log(Vec3.of(1, 2, 3).map(val => val + 1)); // → Vec(2, 3, 4)
250
- * ```
251
- */
252
330
  public map(fn: (component: number, index: number)=> number): Vec3 {
253
- return Vec3.of(
254
- fn(this.x, 0), fn(this.y, 1), fn(this.z, 2)
255
- );
331
+ return Vec3.of(fn(this.x, 0), fn(this.y, 1), fn(this.z, 2));
256
332
  }
257
333
 
258
334
  public asArray(): [ number, number, number ] {
259
335
  return [this.x, this.y, this.z];
260
336
  }
261
337
 
262
- /**
263
- * [fuzz] The maximum difference between two components for this and [other]
264
- * to be considered equal.
265
- *
266
- * @example
267
- * ```
268
- * Vec3.of(1, 2, 3).eq(Vec3.of(4, 5, 6), 100); // → true
269
- * Vec3.of(1, 2, 3).eq(Vec3.of(4, 5, 6), 0.1); // → false
270
- * Vec3.of(1, 2, 3).eq(Vec3.of(4, 5, 6), 3); // → true
271
- * Vec3.of(1, 2, 3).eq(Vec3.of(4, 5, 6), 3.01); // → true
272
- * Vec3.of(1, 2, 3).eq(Vec3.of(4, 5, 6), 2.99); // → false
273
- * ```
274
- */
275
- public eq(other: Vec3, fuzz: number = 1e-10): boolean {
338
+ public eq(other: Vec3, fuzz: number = defaultEqlTolerance): boolean {
276
339
  return (
277
340
  Math.abs(other.x - this.x) <= fuzz
278
341
  && Math.abs(other.y - this.y) <= fuzz
@@ -283,11 +346,235 @@ export class Vec3 {
283
346
  public toString(): string {
284
347
  return `Vec(${this.x}, ${this.y}, ${this.z})`;
285
348
  }
349
+ }
350
+
351
+ class Vec2Impl implements Vec3 {
352
+ public constructor(
353
+ public readonly x: number,
354
+ public readonly y: number,
355
+ ) {
356
+ }
357
+
358
+ public get z() { return 0; }
359
+
360
+ public get xy(): { x: number; y: number } {
361
+ // Useful for APIs that behave differently if .z is present.
362
+ return {
363
+ x: this.x,
364
+ y: this.y,
365
+ };
366
+ }
367
+
368
+ public at(idx: number): number {
369
+ if (idx === 0) return this.x;
370
+ if (idx === 1) return this.y;
371
+ if (idx === 2) return 0;
372
+
373
+ throw new Error(`${idx} out of bounds!`);
374
+ }
375
+
376
+ public length(): number {
377
+ return this.magnitude();
378
+ }
379
+
380
+ public magnitude(): number {
381
+ return Math.sqrt(this.x * this.x + this.y * this.y);
382
+ }
383
+
384
+ public magnitudeSquared(): number {
385
+ return this.x * this.x + this.y * this.y;
386
+ }
387
+
388
+ public squareDistanceTo(p: Vec3) {
389
+ const dx = this.x - p.x;
390
+ const dy = this.y - p.y;
391
+ return dx * dx + dy * dy + p.z * p.z;
392
+ }
286
393
 
394
+ public distanceTo(p: Vec3) {
395
+ return Math.sqrt(this.squareDistanceTo(p));
396
+ }
397
+
398
+ public maximumEntryMagnitude(): number {
399
+ return Math.max(Math.abs(this.x), Math.abs(this.y));
400
+ }
401
+
402
+ public angle(): number {
403
+ return Math.atan2(this.y, this.x);
404
+ }
405
+
406
+ public normalized(): Vec3 {
407
+ const norm = this.magnitude();
408
+ return Vec2.of(this.x / norm, this.y / norm);
409
+ }
410
+
411
+ public normalizedOrZero(): Vec3 {
412
+ if (this.eq(Vec3.zero)) {
413
+ return Vec3.zero;
414
+ }
415
+
416
+ return this.normalized();
417
+ }
418
+
419
+ public times(c: number): Vec3 {
420
+ return Vec2.of(this.x * c, this.y * c);
421
+ }
422
+
423
+ public plus(v: Vec3): Vec3 {
424
+ return Vec3.of(this.x + v.x, this.y + v.y, v.z);
425
+ }
426
+
427
+ public minus(v: Vec3): Vec3 {
428
+ return Vec3.of(this.x - v.x, this.y - v.y, -v.z);
429
+ }
287
430
 
288
- public static unitX = Vec3.of(1, 0, 0);
289
- public static unitY = Vec3.of(0, 1, 0);
290
- public static unitZ = Vec3.of(0, 0, 1);
291
- public static zero = Vec3.of(0, 0, 0);
431
+ public dot(other: Vec3): number {
432
+ return this.x * other.x + this.y * other.y;
433
+ }
434
+
435
+ public cross(other: Vec3): Vec3 {
436
+ // | i j k |
437
+ // | x1 y1 z1| = (i)(y1z2 - y2z1) - (j)(x1z2 - x2z1) + (k)(x1y2 - x2y1)
438
+ // | x2 y2 z2|
439
+ return Vec3.of(
440
+ this.y * other.z,
441
+ -this.x * other.z,
442
+ this.x * other.y - other.x * this.y,
443
+ );
444
+ }
445
+
446
+ public scale(other: Vec3|number): Vec3 {
447
+ if (typeof other === 'number') {
448
+ return this.times(other);
449
+ }
450
+
451
+ return Vec2.of(
452
+ this.x * other.x,
453
+ this.y * other.y,
454
+ );
455
+ }
456
+
457
+ public orthog(): Vec3 {
458
+ // If parallel to the z-axis
459
+ if (this.dot(Vec3.unitX) === 0 && this.dot(Vec3.unitY) === 0) {
460
+ return this.dot(Vec3.unitX) === 0 ? Vec3.unitX : this.cross(Vec3.unitX).normalized();
461
+ }
462
+
463
+ return this.cross(Vec3.unitZ.times(-1)).normalized();
464
+ }
465
+
466
+ public extend(distance: number, direction: Vec3): Vec3 {
467
+ return this.plus(direction.normalized().times(distance));
468
+ }
469
+
470
+ public lerp(target: Vec3, fractionTo: number): Vec3 {
471
+ return this.times(1 - fractionTo).plus(target.times(fractionTo));
472
+ }
473
+
474
+ public zip(
475
+ other: Vec3, zip: (componentInThis: number, componentInOther: number)=> number
476
+ ): Vec3 {
477
+ return Vec3.of(
478
+ zip(other.x, this.x),
479
+ zip(other.y, this.y),
480
+ zip(other.z, 0),
481
+ );
482
+ }
483
+
484
+ public map(fn: (component: number, index: number)=> number): Vec3 {
485
+ return Vec3.of(
486
+ fn(this.x, 0), fn(this.y, 1), fn(0, 2)
487
+ );
488
+ }
489
+
490
+ public asArray(): [ number, number, number ] {
491
+ return [this.x, this.y, 0];
492
+ }
493
+
494
+ public eq(other: Vec3, fuzz: number = defaultEqlTolerance): boolean {
495
+ return (
496
+ Math.abs(other.x - this.x) <= fuzz
497
+ && Math.abs(other.y - this.y) <= fuzz
498
+ && Math.abs(other.z) <= fuzz
499
+ );
500
+ }
501
+
502
+ public toString(): string {
503
+ return `Vec(${this.x}, ${this.y})`;
504
+ }
505
+ }
506
+
507
+ /**
508
+ * A `Vec2` is a `Vec3` optimized for working in a plane. As such, they have an
509
+ * always-zero `z` component.
510
+ *
511
+ * ```ts,runnable,console
512
+ * import { Vec2 } from '@js-draw/math';
513
+ * console.log(Vec2.of(1, 2));
514
+ * ```
515
+ */
516
+ export namespace Vec2 {
517
+ /**
518
+ * Creates a `Vec2` from an x and y coordinate.
519
+ *
520
+ * @example
521
+ * ```ts,runnable,console
522
+ * import { Vec2 } from '@js-draw/math';
523
+ * const v = Vec2.of(3, 4); // x=3, y=4.
524
+ * ```
525
+ */
526
+ export const of = (x: number, y: number) => {
527
+ return new Vec2Impl(x, y);
528
+ };
529
+
530
+ /**
531
+ * Creates a `Vec2` from an object containing `x` and `y` coordinates.
532
+ *
533
+ * @example
534
+ * ```ts,runnable,console
535
+ * import { Vec2 } from '@js-draw/math';
536
+ * const v1 = Vec2.ofXY({ x: 3, y: 4.5 });
537
+ * const v2 = Vec2.ofXY({ x: -123.4, y: 1 });
538
+ * ```
539
+ */
540
+ export const ofXY = ({x, y}: {x: number, y: number}) => {
541
+ return Vec2.of(x, y);
542
+ };
543
+
544
+ /** A vector of length 1 in the X direction (→). */
545
+ export const unitX = Vec2.of(1, 0);
546
+
547
+ /** A vector of length 1 in the Y direction (↑). */
548
+ export const unitY = Vec2.of(0, 1);
549
+
550
+ /** The zero vector: A vector with x=0, y=0. */
551
+ export const zero = Vec2.of(0, 0);
292
552
  }
553
+
554
+ export namespace Vec3 {
555
+ /**
556
+ * Construct a vector from three components.
557
+ *
558
+ * @example
559
+ * ```ts,runnable,console
560
+ * import { Vec3 } from '@js-draw/math';
561
+ * const v1 = Vec3.of(1, 2, 3);
562
+ * ```
563
+ */
564
+ export const of = (x: number, y: number, z: number): Vec3 => {
565
+ if (z === 0) {
566
+ return Vec2.of(x, y);
567
+ } else {
568
+ return new Vec3Impl(x, y, z);
569
+ }
570
+ };
571
+
572
+ export const unitX = Vec2.unitX;
573
+ export const unitY = Vec2.unitY;
574
+ export const zero = Vec2.zero;
575
+
576
+ /** A vector of length 1 in the z direction. */
577
+ export const unitZ = Vec3.of(0, 0, 1);
578
+ }
579
+
293
580
  export default Vec3;
@@ -118,7 +118,7 @@ export abstract class BezierJSWrapper extends Parameterized2DShape {
118
118
  }
119
119
 
120
120
  return t;
121
- }).filter(entry => entry !== null) as number[];
121
+ }).filter(entry => entry !== null);
122
122
  }
123
123
 
124
124
  public override splitAt(t: number): [BezierJSWrapper] | [BezierJSWrapper, BezierJSWrapper] {
@@ -9,7 +9,18 @@ interface IntersectionResult {
9
9
  t: number;
10
10
  }
11
11
 
12
- /** Represents a line segment. A `LineSegment2` is immutable. */
12
+ /**
13
+ * Represents a line segment. A `LineSegment2` is immutable.
14
+ *
15
+ * @example
16
+ * ```ts,runnable,console
17
+ * import {LineSegment2, Vec2} from '@js-draw/math';
18
+ * const l = new LineSegment2(Vec2.of(1, 1), Vec2.of(2, 2));
19
+ * console.log('length: ', l.length);
20
+ * console.log('direction: ', l.direction);
21
+ * console.log('bounding box: ', l.bbox);
22
+ * ```
23
+ */
13
24
  export class LineSegment2 extends Parameterized2DShape {
14
25
  // invariant: ||direction|| = 1
15
26
 
@@ -51,7 +62,7 @@ export class LineSegment2 extends Parameterized2DShape {
51
62
  * if no such line segment exists.
52
63
  *
53
64
  * @example
54
- * ```ts,runnable
65
+ * ```ts,runnable,console
55
66
  * import {LineSegment2, Vec2} from '@js-draw/math';
56
67
  * console.log(LineSegment2.ofSmallestContainingPoints([Vec2.of(1, 0), Vec2.of(0, 1)]));
57
68
  * ```
@@ -298,9 +298,9 @@ export class Rect2 extends Abstract2DShape {
298
298
  return Rect2.bboxOf(this.corners.map(corner => affineTransform.transformVec2(corner)));
299
299
  }
300
300
 
301
- /** @return true iff this is equal to [other] ± fuzz */
302
- public eq(other: Rect2, fuzz: number = 0): boolean {
303
- return this.topLeft.eq(other.topLeft, fuzz) && this.size.eq(other.size, fuzz);
301
+ /** @return true iff this is equal to `other ± tolerance` */
302
+ public eq(other: Rect2, tolerance: number = 0): boolean {
303
+ return this.topLeft.eq(other.topLeft, tolerance) && this.size.eq(other.size, tolerance);
304
304
  }
305
305
 
306
306
  public override toString(): string {
@@ -1,13 +0,0 @@
1
- {
2
- "name": "js-draw-math-test-imports",
3
- "version": "0.0.1",
4
- "lockfileVersion": 3,
5
- "requires": true,
6
- "packages": {
7
- "": {
8
- "name": "js-draw-math-test-imports",
9
- "version": "0.0.1",
10
- "license": "MIT"
11
- }
12
- }
13
- }