@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/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;
@@ -7,7 +7,18 @@ interface IntersectionResult {
7
7
  point: Point2;
8
8
  t: number;
9
9
  }
10
- /** Represents a line segment. A `LineSegment2` is immutable. */
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
  * ```
@@ -7,7 +7,18 @@ exports.LineSegment2 = void 0;
7
7
  const Rect2_1 = __importDefault(require("./Rect2"));
8
8
  const Vec2_1 = require("../Vec2");
9
9
  const Parameterized2DShape_1 = __importDefault(require("./Parameterized2DShape"));
10
- /** Represents a line segment. A `LineSegment2` is immutable. */
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
  class LineSegment2 extends Parameterized2DShape_1.default {
12
23
  /** Creates a new `LineSegment2` from its endpoints. */
13
24
  constructor(point1, point2) {
@@ -27,7 +38,7 @@ class LineSegment2 extends Parameterized2DShape_1.default {
27
38
  * if no such line segment exists.
28
39
  *
29
40
  * @example
30
- * ```ts,runnable
41
+ * ```ts,runnable,console
31
42
  * import {LineSegment2, Vec2} from '@js-draw/math';
32
43
  * console.log(LineSegment2.ofSmallestContainingPoints([Vec2.of(1, 0), Vec2.of(0, 1)]));
33
44
  * ```
@@ -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): Vec3;
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(): Vec3;
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 [other] ± fuzz */
67
- eq(other: Rect2, fuzz?: number): boolean;
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;
@@ -227,9 +227,9 @@ class Rect2 extends Abstract2DShape_1.default {
227
227
  transformedBoundingBox(affineTransform) {
228
228
  return Rect2.bboxOf(this.corners.map(corner => affineTransform.transformVec2(corner)));
229
229
  }
230
- /** @return true iff this is equal to [other] ± fuzz */
231
- eq(other, fuzz = 0) {
232
- return this.topLeft.eq(other.topLeft, fuzz) && this.size.eq(other.size, fuzz);
230
+ /** @return true iff this is equal to `other ± tolerance` */
231
+ eq(other, tolerance = 0) {
232
+ return this.topLeft.eq(other.topLeft, tolerance) && this.size.eq(other.size, tolerance);
233
233
  }
234
234
  toString() {
235
235
  return `Rect(point(${this.x}, ${this.y}), size(${this.w}, ${this.h}))`;