@js-draw/math 1.21.2 → 1.22.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.
Files changed (63) hide show
  1. package/build-config.json +1 -1
  2. package/dist/cjs/Color4.js +2 -2
  3. package/dist/cjs/Mat33.d.ts +1 -11
  4. package/dist/cjs/Mat33.js +8 -24
  5. package/dist/cjs/Vec3.js +9 -7
  6. package/dist/cjs/shapes/BezierJSWrapper.js +20 -13
  7. package/dist/cjs/shapes/LineSegment2.js +13 -17
  8. package/dist/cjs/shapes/Parameterized2DShape.js +1 -1
  9. package/dist/cjs/shapes/Path.js +49 -47
  10. package/dist/cjs/shapes/Rect2.js +13 -15
  11. package/dist/cjs/shapes/Triangle.js +4 -5
  12. package/dist/cjs/utils/convexHull2Of.js +3 -3
  13. package/dist/mjs/Color4.mjs +2 -2
  14. package/dist/mjs/Mat33.d.ts +1 -11
  15. package/dist/mjs/Mat33.mjs +8 -24
  16. package/dist/mjs/Vec3.mjs +9 -7
  17. package/dist/mjs/shapes/BezierJSWrapper.mjs +20 -13
  18. package/dist/mjs/shapes/LineSegment2.mjs +13 -17
  19. package/dist/mjs/shapes/Parameterized2DShape.mjs +1 -1
  20. package/dist/mjs/shapes/Path.mjs +49 -47
  21. package/dist/mjs/shapes/Rect2.mjs +13 -15
  22. package/dist/mjs/shapes/Triangle.mjs +4 -5
  23. package/dist/mjs/utils/convexHull2Of.mjs +3 -3
  24. package/dist-test/test_imports/test-require.cjs +1 -1
  25. package/package.json +3 -3
  26. package/src/Color4.test.ts +16 -21
  27. package/src/Color4.ts +22 -17
  28. package/src/Mat33.fromCSSMatrix.test.ts +31 -45
  29. package/src/Mat33.test.ts +58 -96
  30. package/src/Mat33.ts +61 -104
  31. package/src/Vec2.test.ts +3 -3
  32. package/src/Vec3.test.ts +2 -3
  33. package/src/Vec3.ts +34 -58
  34. package/src/lib.ts +0 -2
  35. package/src/polynomial/solveQuadratic.test.ts +39 -13
  36. package/src/polynomial/solveQuadratic.ts +5 -6
  37. package/src/rounding/cleanUpNumber.test.ts +1 -1
  38. package/src/rounding/constants.ts +1 -3
  39. package/src/rounding/getLenAfterDecimal.ts +1 -2
  40. package/src/rounding/lib.ts +1 -2
  41. package/src/rounding/toRoundedString.test.ts +1 -1
  42. package/src/rounding/toStringOfSamePrecision.test.ts +1 -2
  43. package/src/rounding/toStringOfSamePrecision.ts +1 -1
  44. package/src/shapes/BezierJSWrapper.ts +54 -37
  45. package/src/shapes/CubicBezier.ts +3 -3
  46. package/src/shapes/LineSegment2.test.ts +24 -17
  47. package/src/shapes/LineSegment2.ts +26 -29
  48. package/src/shapes/Parameterized2DShape.ts +5 -4
  49. package/src/shapes/Path.fromString.test.ts +5 -5
  50. package/src/shapes/Path.test.ts +122 -120
  51. package/src/shapes/Path.toString.test.ts +7 -7
  52. package/src/shapes/Path.ts +378 -352
  53. package/src/shapes/PointShape2D.ts +3 -3
  54. package/src/shapes/QuadraticBezier.test.ts +27 -21
  55. package/src/shapes/QuadraticBezier.ts +4 -9
  56. package/src/shapes/Rect2.test.ts +44 -75
  57. package/src/shapes/Rect2.ts +30 -35
  58. package/src/shapes/Triangle.test.ts +31 -29
  59. package/src/shapes/Triangle.ts +17 -18
  60. package/src/utils/convexHull2Of.test.ts +54 -15
  61. package/src/utils/convexHull2Of.ts +9 -7
  62. package/tsconfig.json +1 -3
  63. package/typedoc.json +2 -2
@@ -1,3 +1 @@
1
-
2
-
3
- export const numberRegex = /^([-]?)(\d*)[.](\d+)$/;
1
+ export const numberRegex = /^([-]?)(\d*)[.](\d+)$/;
@@ -1,6 +1,5 @@
1
1
  import { numberRegex } from './constants';
2
2
 
3
-
4
3
  /**
5
4
  * Returns the length of `numberAsString` after a decimal point.
6
5
  *
@@ -16,7 +15,7 @@ export const getLenAfterDecimal = (numberAsString: string) => {
16
15
  // like NaN or Infinity)
17
16
  if (numberAsString.search(/[eE]/) !== -1 || /^[a-zA-Z]+$/.exec(numberAsString)) {
18
17
  return -1;
19
- // Or it has no decimal point
18
+ // Or it has no decimal point
20
19
  } else {
21
20
  return 0;
22
21
  }
@@ -1,2 +1 @@
1
-
2
- export { toRoundedString } from './toRoundedString';
1
+ export { toRoundedString } from './toRoundedString';
@@ -29,4 +29,4 @@ describe('toRoundedString', () => {
29
29
  expect(toRoundedString(-10.123499)).toBe('-10.123499');
30
30
  expect(toRoundedString(0.00123499)).toBe('.00123499');
31
31
  });
32
- });
32
+ });
@@ -1,6 +1,5 @@
1
1
  import { toStringOfSamePrecision } from './toStringOfSamePrecision';
2
2
 
3
-
4
3
  it('toStringOfSamePrecision', () => {
5
4
  expect(toStringOfSamePrecision(1.23456, '1.12')).toBe('1.23');
6
5
  expect(toStringOfSamePrecision(1.23456, '1.120')).toBe('1.235');
@@ -18,4 +17,4 @@ it('toStringOfSamePrecision', () => {
18
17
  expect(toStringOfSamePrecision(-0.9999999999999432, '291.3')).toBe('-1');
19
18
  expect(toStringOfSamePrecision(9998.9, '.1', '-11')).toBe('9998.9');
20
19
  expect(toStringOfSamePrecision(-14.20000000000002, '.000001', '-11')).toBe('-14.2');
21
- });
20
+ });
@@ -60,4 +60,4 @@ export const toStringOfSamePrecision = (num: number, ...references: string[]): s
60
60
  return cleanUpNumber(`${negativeSign}${preDecimal}.${postDecimal}`);
61
61
  };
62
62
 
63
- export default toStringOfSamePrecision;
63
+ export default toStringOfSamePrecision;
@@ -14,11 +14,9 @@ import Parameterized2DShape from './Parameterized2DShape';
14
14
  * @internal
15
15
  */
16
16
  export abstract class BezierJSWrapper extends Parameterized2DShape {
17
- #bezierJs: Bezier|null = null;
17
+ #bezierJs: Bezier | null = null;
18
18
 
19
- protected constructor(
20
- bezierJsBezier?: Bezier
21
- ) {
19
+ protected constructor(bezierJsBezier?: Bezier) {
22
20
  super();
23
21
 
24
22
  if (bezierJsBezier) {
@@ -31,7 +29,7 @@ export abstract class BezierJSWrapper extends Parameterized2DShape {
31
29
 
32
30
  protected getBezier() {
33
31
  if (!this.#bezierJs) {
34
- this.#bezierJs = new Bezier(this.getPoints().map(p => p.xy));
32
+ this.#bezierJs = new Bezier(this.getPoints().map((p) => p.xy));
35
33
  }
36
34
  return this.#bezierJs;
37
35
  }
@@ -96,41 +94,49 @@ export abstract class BezierJSWrapper extends Parameterized2DShape {
96
94
  const asLine = LineSegment2.ofSmallestContainingPoints(this.getPoints());
97
95
  if (asLine) {
98
96
  const intersection = asLine.intersectsLineSegment(line);
99
- return intersection.map(p => this.nearestPointTo(p).parameterValue);
97
+ return intersection.map((p) => this.nearestPointTo(p).parameterValue);
100
98
  }
101
99
 
102
100
  const bezier = this.getBezier();
103
101
 
104
- return bezier.intersects(line).map(t => {
105
- // We're using the .intersects(line) function, which is documented
106
- // to always return numbers. However, to satisfy the type checker (and
107
- // possibly improperly-defined types),
108
- if (typeof t === 'string') {
109
- t = parseFloat(t);
110
- }
111
-
112
- const point = Vec2.ofXY(this.at(t));
113
-
114
- // Ensure that the intersection is on the line segment
115
- if (point.distanceTo(line.p1) > line.length
116
- || point.distanceTo(line.p2) > line.length) {
117
- return null;
118
- }
119
-
120
- return t;
121
- }).filter(entry => entry !== null);
102
+ return bezier
103
+ .intersects(line)
104
+ .map((t) => {
105
+ // We're using the .intersects(line) function, which is documented
106
+ // to always return numbers. However, to satisfy the type checker (and
107
+ // possibly improperly-defined types),
108
+ if (typeof t === 'string') {
109
+ t = parseFloat(t);
110
+ }
111
+
112
+ const point = Vec2.ofXY(this.at(t));
113
+
114
+ // Ensure that the intersection is on the line segment
115
+ if (point.distanceTo(line.p1) > line.length || point.distanceTo(line.p2) > line.length) {
116
+ return null;
117
+ }
118
+
119
+ return t;
120
+ })
121
+ .filter((entry) => entry !== null);
122
122
  }
123
123
 
124
124
  public override splitAt(t: number): [BezierJSWrapper] | [BezierJSWrapper, BezierJSWrapper] {
125
125
  if (t <= 0 || t >= 1) {
126
- return [ this ];
126
+ return [this];
127
127
  }
128
128
 
129
129
  const bezier = this.getBezier();
130
130
  const split = bezier.split(t);
131
131
  return [
132
- new BezierJSWrapperImpl(split.left.points.map(point => Vec2.ofXY(point)), split.left),
133
- new BezierJSWrapperImpl(split.right.points.map(point => Vec2.ofXY(point)), split.right),
132
+ new BezierJSWrapperImpl(
133
+ split.left.points.map((point) => Vec2.ofXY(point)),
134
+ split.left,
135
+ ),
136
+ new BezierJSWrapperImpl(
137
+ split.right.points.map((point) => Vec2.ofXY(point)),
138
+ split.right,
139
+ ),
134
140
  ];
135
141
  }
136
142
 
@@ -162,7 +168,7 @@ export abstract class BezierJSWrapper extends Parameterized2DShape {
162
168
 
163
169
  // Start by testing a few points:
164
170
  const pointsToTest = 4;
165
- for (let i = 0; i < pointsToTest; i ++) {
171
+ for (let i = 0; i < pointsToTest; i++) {
166
172
  const testT = i / (pointsToTest - 1);
167
173
  const testMinSqrDist = sqrDistAt(testT);
168
174
 
@@ -181,8 +187,12 @@ export abstract class BezierJSWrapper extends Parameterized2DShape {
181
187
  const bPrime = this.derivativeAt(t);
182
188
  const bPrimePrime = this.secondDerivativeAt(t);
183
189
  return (
184
- 2 * bPrime.x * bPrime.x + 2 * b.x * bPrimePrime.x - 2 * point.x * bPrimePrime.x
185
- + 2 * bPrime.y * bPrime.y + 2 * b.y * bPrimePrime.y - 2 * point.y * bPrimePrime.y
190
+ 2 * bPrime.x * bPrime.x +
191
+ 2 * b.x * bPrimePrime.x -
192
+ 2 * point.x * bPrimePrime.x +
193
+ 2 * bPrime.y * bPrime.y +
194
+ 2 * b.y * bPrimePrime.y -
195
+ 2 * point.y * bPrimePrime.y
186
196
  );
187
197
  };
188
198
  // Because we're zeroing f'(t), we also need to be able to compute it:
@@ -191,8 +201,7 @@ export abstract class BezierJSWrapper extends Parameterized2DShape {
191
201
  const b = this.at(t);
192
202
  const bPrime = this.derivativeAt(t);
193
203
  return (
194
- 2 * b.x * bPrime.x - 2 * point.x * bPrime.x
195
- + 2 * b.y * bPrime.y - 2 * point.y * bPrime.y
204
+ 2 * b.x * bPrime.x - 2 * point.x * bPrime.x + 2 * b.y * bPrime.y - 2 * point.y * bPrime.y
196
205
  );
197
206
  };
198
207
 
@@ -226,7 +235,10 @@ export abstract class BezierJSWrapper extends Parameterized2DShape {
226
235
  }
227
236
 
228
237
  public intersectsBezier(other: BezierJSWrapper) {
229
- const intersections = this.getBezier().intersects(other.getBezier()) as (string[] | null | undefined);
238
+ const intersections = this.getBezier().intersects(other.getBezier()) as
239
+ | string[]
240
+ | null
241
+ | undefined;
230
242
  if (!intersections || intersections.length === 0) {
231
243
  return [];
232
244
  }
@@ -239,7 +251,7 @@ export abstract class BezierJSWrapper extends Parameterized2DShape {
239
251
 
240
252
  if (!match) {
241
253
  throw new Error(
242
- `Incorrect format returned by .intersects: ${intersections} should be array of "number/number"!`
254
+ `Incorrect format returned by .intersects: ${intersections} should be array of "number/number"!`,
243
255
  );
244
256
  }
245
257
 
@@ -253,7 +265,9 @@ export abstract class BezierJSWrapper extends Parameterized2DShape {
253
265
  }
254
266
 
255
267
  public override toString() {
256
- return `Bézier(${this.getPoints().map(point => point.toString()).join(', ')})`;
268
+ return `Bézier(${this.getPoints()
269
+ .map((point) => point.toString())
270
+ .join(', ')})`;
257
271
  }
258
272
  }
259
273
 
@@ -262,7 +276,10 @@ export abstract class BezierJSWrapper extends Parameterized2DShape {
262
276
  * around a `Bezier`.
263
277
  */
264
278
  class BezierJSWrapperImpl extends BezierJSWrapper {
265
- public constructor(private controlPoints: readonly Point2[], curve?: Bezier) {
279
+ public constructor(
280
+ private controlPoints: readonly Point2[],
281
+ curve?: Bezier,
282
+ ) {
266
283
  super(curve);
267
284
  }
268
285
 
@@ -271,4 +288,4 @@ class BezierJSWrapperImpl extends BezierJSWrapper {
271
288
  }
272
289
  }
273
290
 
274
- export default BezierJSWrapper;
291
+ export default BezierJSWrapper;
@@ -23,13 +23,13 @@ class CubicBezier extends BezierJSWrapper {
23
23
  }
24
24
 
25
25
  public override getPoints() {
26
- return [ this.p0, this.p1, this.p2, this.p3 ];
26
+ return [this.p0, this.p1, this.p2, this.p3];
27
27
  }
28
28
 
29
29
  /** Returns an overestimate of this shape's bounding box. */
30
30
  public override getLooseBoundingBox(): Rect2 {
31
- return Rect2.bboxOf([ this.p0, this.p1, this.p2, this.p3 ]);
31
+ return Rect2.bboxOf([this.p0, this.p1, this.p2, this.p3]);
32
32
  }
33
33
  }
34
34
 
35
- export default CubicBezier;
35
+ export default CubicBezier;
@@ -2,7 +2,6 @@ import LineSegment2 from './LineSegment2';
2
2
  import { Vec2 } from '../Vec2';
3
3
  import Mat33 from '../Mat33';
4
4
 
5
-
6
5
  describe('Line2', () => {
7
6
  it('x and y axes should intersect at (0, 0)', () => {
8
7
  const xAxis = new LineSegment2(Vec2.of(-10, 0), Vec2.of(10, 0));
@@ -65,7 +64,7 @@ describe('Line2', () => {
65
64
  // Points taken from issue observed directly in editor
66
65
  const p1 = Vec2.of(769.6126045442547, 221.037877485765);
67
66
  const p2 = Vec2.of(770.3873954557453, 224.962122514235);
68
- const p3 = Vec2.of( 763.3590010920082, 223.66723995850086);
67
+ const p3 = Vec2.of(763.3590010920082, 223.66723995850086);
69
68
  const p4 = Vec2.of(763.5494167642871, 223.66723995850086);
70
69
 
71
70
  const line1 = new LineSegment2(p1, p2);
@@ -115,7 +114,7 @@ describe('Line2', () => {
115
114
  // Halving
116
115
  //
117
116
  expect(lineSegment.at(0.5)).objEq(midpoint);
118
- const [ firstHalf, secondHalf ] = lineSegment.splitAt(0.5);
117
+ const [firstHalf, secondHalf] = lineSegment.splitAt(0.5);
119
118
 
120
119
  if (!secondHalf) {
121
120
  throw new Error('Splitting a line segment in half should yield two line segments.');
@@ -136,24 +135,32 @@ describe('Line2', () => {
136
135
  it('equivalence check should allow ignoring direction', () => {
137
136
  expect(new LineSegment2(Vec2.zero, Vec2.unitX)).objEq(new LineSegment2(Vec2.zero, Vec2.unitX));
138
137
  expect(new LineSegment2(Vec2.zero, Vec2.unitX)).objEq(new LineSegment2(Vec2.unitX, Vec2.zero));
139
- expect(new LineSegment2(Vec2.zero, Vec2.unitX)).not.objEq(new LineSegment2(Vec2.unitX, Vec2.zero), { ignoreDirection: false });
138
+ expect(new LineSegment2(Vec2.zero, Vec2.unitX)).not.objEq(
139
+ new LineSegment2(Vec2.unitX, Vec2.zero),
140
+ { ignoreDirection: false },
141
+ );
140
142
  });
141
143
 
142
144
  it('should support creating from a collection of points', () => {
143
145
  expect(LineSegment2.ofSmallestContainingPoints([])).toBeNull();
144
146
  expect(LineSegment2.ofSmallestContainingPoints([Vec2.of(1, 1)])).toBeNull();
145
- expect(LineSegment2.ofSmallestContainingPoints(
146
- [Vec2.of(1, 1), Vec2.of(1, 2), Vec2.of(3, 3)]
147
- )).toBeNull();
148
-
149
- expect(LineSegment2.ofSmallestContainingPoints(
150
- [Vec2.of(1, 1), Vec2.of(1, 2)]
151
- )).objEq(new LineSegment2(Vec2.of(1, 1), Vec2.of(1, 2)));
152
- expect(LineSegment2.ofSmallestContainingPoints(
153
- [Vec2.of(1, 1), Vec2.of(2, 2), Vec2.of(3, 3)]
154
- )).objEq(new LineSegment2(Vec2.of(1, 1), Vec2.of(3, 3)));
155
- expect(LineSegment2.ofSmallestContainingPoints(
156
- [Vec2.of(3, 3), Vec2.of(2, 2), Vec2.of(2.4, 2.4), Vec2.of(3, 3)]
157
- )).objEq(new LineSegment2(Vec2.of(2, 2), Vec2.of(3, 3)));
147
+ expect(
148
+ LineSegment2.ofSmallestContainingPoints([Vec2.of(1, 1), Vec2.of(1, 2), Vec2.of(3, 3)]),
149
+ ).toBeNull();
150
+
151
+ expect(LineSegment2.ofSmallestContainingPoints([Vec2.of(1, 1), Vec2.of(1, 2)])).objEq(
152
+ new LineSegment2(Vec2.of(1, 1), Vec2.of(1, 2)),
153
+ );
154
+ expect(
155
+ LineSegment2.ofSmallestContainingPoints([Vec2.of(1, 1), Vec2.of(2, 2), Vec2.of(3, 3)]),
156
+ ).objEq(new LineSegment2(Vec2.of(1, 1), Vec2.of(3, 3)));
157
+ expect(
158
+ LineSegment2.ofSmallestContainingPoints([
159
+ Vec2.of(3, 3),
160
+ Vec2.of(2, 2),
161
+ Vec2.of(2.4, 2.4),
162
+ Vec2.of(3, 3),
163
+ ]),
164
+ ).objEq(new LineSegment2(Vec2.of(2, 2), Vec2.of(3, 3)));
158
165
  });
159
166
  });
@@ -42,7 +42,7 @@ export class LineSegment2 extends Parameterized2DShape {
42
42
  /** Creates a new `LineSegment2` from its endpoints. */
43
43
  public constructor(
44
44
  private readonly point1: Point2,
45
- private readonly point2: Point2
45
+ private readonly point2: Point2,
46
46
  ) {
47
47
  super();
48
48
 
@@ -70,7 +70,7 @@ export class LineSegment2 extends Parameterized2DShape {
70
70
  public static ofSmallestContainingPoints(points: readonly Point2[]) {
71
71
  if (points.length <= 1) return null;
72
72
 
73
- const sorted = [...points].sort((a, b) => a.x !== b.x ? a.x - b.x : a.y - b.y);
73
+ const sorted = [...points].sort((a, b) => (a.x !== b.x ? a.x - b.x : a.y - b.y));
74
74
  const line = new LineSegment2(sorted[0], sorted[sorted.length - 1]);
75
75
 
76
76
  for (const point of sorted) {
@@ -127,15 +127,12 @@ export class LineSegment2 extends Parameterized2DShape {
127
127
  return this.direction;
128
128
  }
129
129
 
130
- public splitAt(t: number): [LineSegment2]|[LineSegment2,LineSegment2] {
130
+ public splitAt(t: number): [LineSegment2] | [LineSegment2, LineSegment2] {
131
131
  if (t <= 0 || t >= 1) {
132
132
  return [this];
133
133
  }
134
134
 
135
- return [
136
- new LineSegment2(this.point1, this.at(t)),
137
- new LineSegment2(this.at(t), this.point2),
138
- ];
135
+ return [new LineSegment2(this.point1, this.at(t)), new LineSegment2(this.at(t), this.point2)];
139
136
  }
140
137
 
141
138
  /**
@@ -146,7 +143,7 @@ export class LineSegment2 extends Parameterized2DShape {
146
143
  * This will change in a future release.
147
144
  * @deprecated
148
145
  */
149
- public intersection(other: LineSegment2): IntersectionResult|null {
146
+ public intersection(other: LineSegment2): IntersectionResult | null {
150
147
  // TODO(v2.0.0): Make this return a `t` value from `0` to `1`.
151
148
 
152
149
  // We want x₁(t) = x₂(t) and y₁(t) = y₂(t)
@@ -191,21 +188,18 @@ export class LineSegment2 extends Parameterized2DShape {
191
188
 
192
189
  const xIntersect = this.point1.x;
193
190
  const yIntersect =
194
- (this.point1.x - other.point1.x) * other.direction.y / other.direction.x + other.point1.y;
191
+ ((this.point1.x - other.point1.x) * other.direction.y) / other.direction.x + other.point1.y;
195
192
  resultPoint = Vec2.of(xIntersect, yIntersect);
196
193
  resultT = (yIntersect - this.point1.y) / this.direction.y;
197
194
  } else {
198
195
  // From above,
199
196
  // x = ((o₁ᵧ - o₂ᵧ)(d₁ₓd₂ₓ) + (d₂ᵧd₁ₓ)(o₂ₓ) - (d₁ᵧd₂ₓ)(o₁ₓ))/(d₂ᵧd₁ₓ - d₁ᵧd₂ₓ)
200
- const numerator = (
201
- (this.point1.y - other.point1.y) * this.direction.x * other.direction.x
202
- + this.direction.x * other.direction.y * other.point1.x
203
- - this.direction.y * other.direction.x * this.point1.x
204
- );
205
- const denominator = (
206
- other.direction.y * this.direction.x
207
- - this.direction.y * other.direction.x
208
- );
197
+ const numerator =
198
+ (this.point1.y - other.point1.y) * this.direction.x * other.direction.x +
199
+ this.direction.x * other.direction.y * other.point1.x -
200
+ this.direction.y * other.direction.x * this.point1.x;
201
+ const denominator =
202
+ other.direction.y * this.direction.x - this.direction.y * other.direction.x;
209
203
 
210
204
  // Avoid dividing by zero. It means there is no intersection
211
205
  if (denominator === 0) {
@@ -225,10 +219,12 @@ export class LineSegment2 extends Parameterized2DShape {
225
219
  const resultToP3 = resultPoint.distanceTo(other.point1);
226
220
  const resultToP4 = resultPoint.distanceTo(other.point2);
227
221
 
228
- if (resultToP1 > this.length
229
- || resultToP2 > this.length
230
- || resultToP3 > other.length
231
- || resultToP4 > other.length) {
222
+ if (
223
+ resultToP1 > this.length ||
224
+ resultToP2 > this.length ||
225
+ resultToP3 > other.length ||
226
+ resultToP4 > other.length
227
+ ) {
232
228
  return null;
233
229
  }
234
230
 
@@ -246,7 +242,7 @@ export class LineSegment2 extends Parameterized2DShape {
246
242
  const intersection = this.intersection(lineSegment);
247
243
 
248
244
  if (intersection) {
249
- return [ intersection.t / this.length ];
245
+ return [intersection.t / this.length];
250
246
  }
251
247
  return [];
252
248
  }
@@ -263,7 +259,7 @@ export class LineSegment2 extends Parameterized2DShape {
263
259
  const intersection = this.intersection(lineSegment);
264
260
 
265
261
  if (intersection) {
266
- return [ intersection.point ];
262
+ return [intersection.point];
267
263
  }
268
264
  return [];
269
265
  }
@@ -273,7 +269,7 @@ export class LineSegment2 extends Parameterized2DShape {
273
269
  return this.nearestPointTo(target).point;
274
270
  }
275
271
 
276
- public override nearestPointTo(target: Vec3): { point: Vec3; parameterValue: number; } {
272
+ public override nearestPointTo(target: Vec3): { point: Vec3; parameterValue: number } {
277
273
  // Distance from P1 along this' direction.
278
274
  const projectedDistFromP1 = target.minus(this.p1).dot(this.direction);
279
275
  const projectedDistFromP2 = this.length - projectedDistFromP1;
@@ -304,7 +300,8 @@ export class LineSegment2 extends Parameterized2DShape {
304
300
  /** Returns a copy of this line segment transformed by the given `affineTransfm`. */
305
301
  public transformedBy(affineTransfm: Mat33): LineSegment2 {
306
302
  return new LineSegment2(
307
- affineTransfm.transformVec2(this.p1), affineTransfm.transformVec2(this.p2)
303
+ affineTransfm.transformVec2(this.p1),
304
+ affineTransfm.transformVec2(this.p2),
308
305
  );
309
306
  }
310
307
 
@@ -324,7 +321,7 @@ export class LineSegment2 extends Parameterized2DShape {
324
321
  * - `tolerance`: The maximum difference between endpoints. (Default: 0)
325
322
  * - `ignoreDirection`: Allow matching a version of `this` with opposite direction. (Default: `true`)
326
323
  */
327
- public eq(other: LineSegment2, options?: { tolerance?: number, ignoreDirection?: boolean }) {
324
+ public eq(other: LineSegment2, options?: { tolerance?: number; ignoreDirection?: boolean }) {
328
325
  if (!(other instanceof LineSegment2)) {
329
326
  return false;
330
327
  }
@@ -333,8 +330,8 @@ export class LineSegment2 extends Parameterized2DShape {
333
330
  const ignoreDirection = options?.ignoreDirection ?? true;
334
331
 
335
332
  return (
336
- (other.p1.eq(this.p1, tolerance) && other.p2.eq(this.p2, tolerance))
337
- || (ignoreDirection && other.p1.eq(this.p2, tolerance) && other.p2.eq(this.p1, tolerance))
333
+ (other.p1.eq(this.p1, tolerance) && other.p2.eq(this.p2, tolerance)) ||
334
+ (ignoreDirection && other.p1.eq(this.p2, tolerance) && other.p2.eq(this.p1, tolerance))
338
335
  );
339
336
  }
340
337
  }
@@ -20,13 +20,15 @@ export abstract class Parameterized2DShape extends Abstract2DShape {
20
20
  /**
21
21
  * Divides this shape into two separate shapes at parameter value $t$.
22
22
  */
23
- abstract splitAt(t: number): [ Parameterized2DShape ] | [ Parameterized2DShape, Parameterized2DShape ];
23
+ abstract splitAt(
24
+ t: number,
25
+ ): [Parameterized2DShape] | [Parameterized2DShape, Parameterized2DShape];
24
26
 
25
27
  /**
26
28
  * Returns the nearest point on `this` to `point` and the `parameterValue` at which
27
29
  * that point occurs.
28
30
  */
29
- abstract nearestPointTo(point: Point2): { point: Point2, parameterValue: number };
31
+ abstract nearestPointTo(point: Point2): { point: Point2; parameterValue: number };
30
32
 
31
33
  /**
32
34
  * Returns the **parameter values** at which `lineSegment` intersects this shape.
@@ -35,9 +37,8 @@ export abstract class Parameterized2DShape extends Abstract2DShape {
35
37
  */
36
38
  public abstract argIntersectsLineSegment(lineSegment: LineSegment2): number[];
37
39
 
38
-
39
40
  public override intersectsLineSegment(line: LineSegment2): Point2[] {
40
- return this.argIntersectsLineSegment(line).map(t => this.at(t));
41
+ return this.argIntersectsLineSegment(line).map((t) => this.at(t));
41
42
  }
42
43
  }
43
44
 
@@ -27,7 +27,7 @@ describe('Path.fromString', () => {
27
27
  },
28
28
  {
29
29
  kind: PathCommandType.MoveTo,
30
- point: Vec2.of(3,3),
30
+ point: Vec2.of(3, 3),
31
31
  },
32
32
  ]);
33
33
  expect(path3.startPoint).toMatchObject(Vec2.of(1, 1));
@@ -71,7 +71,7 @@ describe('Path.fromString', () => {
71
71
  const path1 = Path.fromString('m3,3 l1,2 l1,1 z');
72
72
  const path2 = Path.fromString('m3,3 l1,2 l1,1 Z');
73
73
 
74
- expect(path1.startPoint).toMatchObject(Vec2.of(3,3));
74
+ expect(path1.startPoint).toMatchObject(Vec2.of(3, 3));
75
75
  expect(path2.startPoint).toMatchObject(path1.startPoint);
76
76
  expect(path1.parts).toMatchObject(path2.parts);
77
77
  expect(path1.parts).toMatchObject([
@@ -86,7 +86,7 @@ describe('Path.fromString', () => {
86
86
  {
87
87
  kind: PathCommandType.LineTo,
88
88
  point: path1.startPoint,
89
- }
89
+ },
90
90
  ]);
91
91
  });
92
92
 
@@ -128,7 +128,7 @@ describe('Path.fromString', () => {
128
128
  controlPoint1: Vec2.of(1, 1),
129
129
  controlPoint2: Vec2.of(0.1, 0.1),
130
130
  endPoint: Vec2.zero,
131
- }
131
+ },
132
132
  ]);
133
133
  });
134
134
 
@@ -220,4 +220,4 @@ describe('Path.fromString', () => {
220
220
  ]);
221
221
  expect(path.startPoint).toMatchObject(Vec2.of(5, 10));
222
222
  });
223
- });
223
+ });