@js-draw/math 1.16.0 → 1.18.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. package/dist/cjs/Mat33.js +6 -1
  2. package/dist/cjs/Vec3.d.ts +23 -1
  3. package/dist/cjs/Vec3.js +33 -7
  4. package/dist/cjs/lib.d.ts +2 -1
  5. package/dist/cjs/lib.js +5 -1
  6. package/dist/cjs/shapes/Abstract2DShape.d.ts +3 -0
  7. package/dist/cjs/shapes/BezierJSWrapper.d.ts +19 -5
  8. package/dist/cjs/shapes/BezierJSWrapper.js +170 -18
  9. package/dist/cjs/shapes/LineSegment2.d.ts +45 -5
  10. package/dist/cjs/shapes/LineSegment2.js +89 -11
  11. package/dist/cjs/shapes/Parameterized2DShape.d.ts +36 -0
  12. package/dist/cjs/shapes/Parameterized2DShape.js +20 -0
  13. package/dist/cjs/shapes/Path.d.ts +131 -13
  14. package/dist/cjs/shapes/Path.js +507 -26
  15. package/dist/cjs/shapes/PointShape2D.d.ts +14 -3
  16. package/dist/cjs/shapes/PointShape2D.js +28 -5
  17. package/dist/cjs/shapes/QuadraticBezier.d.ts +6 -3
  18. package/dist/cjs/shapes/QuadraticBezier.js +21 -7
  19. package/dist/cjs/shapes/Rect2.d.ts +9 -1
  20. package/dist/cjs/shapes/Rect2.js +9 -2
  21. package/dist/cjs/utils/convexHull2Of.d.ts +9 -0
  22. package/dist/cjs/utils/convexHull2Of.js +61 -0
  23. package/dist/cjs/utils/convexHull2Of.test.d.ts +1 -0
  24. package/dist/mjs/Mat33.mjs +6 -1
  25. package/dist/mjs/Vec3.d.ts +23 -1
  26. package/dist/mjs/Vec3.mjs +33 -7
  27. package/dist/mjs/lib.d.ts +2 -1
  28. package/dist/mjs/lib.mjs +2 -1
  29. package/dist/mjs/shapes/Abstract2DShape.d.ts +3 -0
  30. package/dist/mjs/shapes/BezierJSWrapper.d.ts +19 -5
  31. package/dist/mjs/shapes/BezierJSWrapper.mjs +168 -18
  32. package/dist/mjs/shapes/LineSegment2.d.ts +45 -5
  33. package/dist/mjs/shapes/LineSegment2.mjs +89 -11
  34. package/dist/mjs/shapes/Parameterized2DShape.d.ts +36 -0
  35. package/dist/mjs/shapes/Parameterized2DShape.mjs +13 -0
  36. package/dist/mjs/shapes/Path.d.ts +131 -13
  37. package/dist/mjs/shapes/Path.mjs +504 -25
  38. package/dist/mjs/shapes/PointShape2D.d.ts +14 -3
  39. package/dist/mjs/shapes/PointShape2D.mjs +28 -5
  40. package/dist/mjs/shapes/QuadraticBezier.d.ts +6 -3
  41. package/dist/mjs/shapes/QuadraticBezier.mjs +21 -7
  42. package/dist/mjs/shapes/Rect2.d.ts +9 -1
  43. package/dist/mjs/shapes/Rect2.mjs +9 -2
  44. package/dist/mjs/utils/convexHull2Of.d.ts +9 -0
  45. package/dist/mjs/utils/convexHull2Of.mjs +59 -0
  46. package/dist/mjs/utils/convexHull2Of.test.d.ts +1 -0
  47. package/package.json +5 -5
  48. package/src/Mat33.ts +8 -2
  49. package/src/Vec3.test.ts +42 -7
  50. package/src/Vec3.ts +37 -8
  51. package/src/lib.ts +5 -0
  52. package/src/shapes/Abstract2DShape.ts +3 -0
  53. package/src/shapes/BezierJSWrapper.ts +195 -14
  54. package/src/shapes/LineSegment2.test.ts +61 -1
  55. package/src/shapes/LineSegment2.ts +110 -12
  56. package/src/shapes/Parameterized2DShape.ts +44 -0
  57. package/src/shapes/Path.test.ts +233 -5
  58. package/src/shapes/Path.ts +593 -37
  59. package/src/shapes/PointShape2D.ts +33 -6
  60. package/src/shapes/QuadraticBezier.test.ts +69 -12
  61. package/src/shapes/QuadraticBezier.ts +25 -8
  62. package/src/shapes/Rect2.ts +10 -3
  63. package/src/utils/convexHull2Of.test.ts +43 -0
  64. package/src/utils/convexHull2Of.ts +71 -0
@@ -6,9 +6,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.LineSegment2 = void 0;
7
7
  const Rect2_1 = __importDefault(require("./Rect2"));
8
8
  const Vec2_1 = require("../Vec2");
9
- const Abstract2DShape_1 = __importDefault(require("./Abstract2DShape"));
9
+ const Parameterized2DShape_1 = __importDefault(require("./Parameterized2DShape"));
10
10
  /** Represents a line segment. A `LineSegment2` is immutable. */
11
- class LineSegment2 extends Abstract2DShape_1.default {
11
+ class LineSegment2 extends Parameterized2DShape_1.default {
12
12
  /** Creates a new `LineSegment2` from its endpoints. */
13
13
  constructor(point1, point2) {
14
14
  super();
@@ -22,6 +22,28 @@ class LineSegment2 extends Abstract2DShape_1.default {
22
22
  this.direction = this.direction.times(1 / this.length);
23
23
  }
24
24
  }
25
+ /**
26
+ * Returns the smallest line segment that contains all points in `points`, or `null`
27
+ * if no such line segment exists.
28
+ *
29
+ * @example
30
+ * ```ts,runnable
31
+ * import {LineSegment2, Vec2} from '@js-draw/math';
32
+ * console.log(LineSegment2.ofSmallestContainingPoints([Vec2.of(1, 0), Vec2.of(0, 1)]));
33
+ * ```
34
+ */
35
+ static ofSmallestContainingPoints(points) {
36
+ if (points.length <= 1)
37
+ return null;
38
+ const sorted = [...points].sort((a, b) => a.x !== b.x ? a.x - b.x : a.y - b.y);
39
+ const line = new LineSegment2(sorted[0], sorted[sorted.length - 1]);
40
+ for (const point of sorted) {
41
+ if (!line.containsPoint(point)) {
42
+ return null;
43
+ }
44
+ }
45
+ return line;
46
+ }
25
47
  // Accessors to make LineSegment2 compatible with bezier-js's
26
48
  // interface
27
49
  /** Alias for `point1`. */
@@ -32,8 +54,11 @@ class LineSegment2 extends Abstract2DShape_1.default {
32
54
  get p2() {
33
55
  return this.point2;
34
56
  }
57
+ get center() {
58
+ return this.point1.lerp(this.point2, 0.5);
59
+ }
35
60
  /**
36
- * Gets a point a distance `t` along this line.
61
+ * Gets a point a **distance** `t` along this line.
37
62
  *
38
63
  * @deprecated
39
64
  */
@@ -50,7 +75,31 @@ class LineSegment2 extends Abstract2DShape_1.default {
50
75
  at(t) {
51
76
  return this.get(t * this.length);
52
77
  }
78
+ normalAt(_t) {
79
+ return this.direction.orthog();
80
+ }
81
+ tangentAt(_t) {
82
+ return this.direction;
83
+ }
84
+ splitAt(t) {
85
+ if (t <= 0 || t >= 1) {
86
+ return [this];
87
+ }
88
+ return [
89
+ new LineSegment2(this.point1, this.at(t)),
90
+ new LineSegment2(this.at(t), this.point2),
91
+ ];
92
+ }
93
+ /**
94
+ * Returns the intersection of this with another line segment.
95
+ *
96
+ * **WARNING**: The parameter value returned by this method does not range from 0 to 1 and
97
+ * is currently a length.
98
+ * This will change in a future release.
99
+ * @deprecated
100
+ */
53
101
  intersection(other) {
102
+ // TODO(v2.0.0): Make this return a `t` value from `0` to `1`.
54
103
  // We want x₁(t) = x₂(t) and y₁(t) = y₂(t)
55
104
  // Observe that
56
105
  // x = this.point1.x + this.direction.x · t₁
@@ -77,7 +126,10 @@ class LineSegment2 extends Abstract2DShape_1.default {
77
126
  // = ((o₁ᵧ - o₂ᵧ)((d₁ₓd₂ₓ)) + (d₂ᵧd₁ₓ)(o₂ₓ) - (d₁ᵧd₂ₓ)(o₁ₓ))/(d₂ᵧd₁ₓ - d₁ᵧd₂ₓ)
78
127
  // ⇒ y = o₁ᵧ + d₁ᵧ · (x - o₁ₓ) / d₁ₓ = ...
79
128
  let resultPoint, resultT;
80
- if (this.direction.x === 0) {
129
+ // Consider very-near-vertical lines to be vertical --- not doing so can lead to
130
+ // precision error when dividing by this.direction.x.
131
+ const small = 4e-13;
132
+ if (Math.abs(this.direction.x) < small) {
81
133
  // Vertical line: Where does the other have x = this.point1.x?
82
134
  // x = o₁ₓ = o₂ₓ + d₂ₓ · (y - o₂ᵧ) / d₂ᵧ
83
135
  // ⇒ (o₁ₓ - o₂ₓ)(d₂ᵧ/d₂ₓ) + o₂ᵧ = y
@@ -109,10 +161,10 @@ class LineSegment2 extends Abstract2DShape_1.default {
109
161
  resultT = (xIntersect - this.point1.x) / this.direction.x;
110
162
  }
111
163
  // Ensure the result is in this/the other segment.
112
- const resultToP1 = resultPoint.minus(this.point1).magnitude();
113
- const resultToP2 = resultPoint.minus(this.point2).magnitude();
114
- const resultToP3 = resultPoint.minus(other.point1).magnitude();
115
- const resultToP4 = resultPoint.minus(other.point2).magnitude();
164
+ const resultToP1 = resultPoint.distanceTo(this.point1);
165
+ const resultToP2 = resultPoint.distanceTo(this.point2);
166
+ const resultToP3 = resultPoint.distanceTo(other.point1);
167
+ const resultToP4 = resultPoint.distanceTo(other.point2);
116
168
  if (resultToP1 > this.length
117
169
  || resultToP2 > this.length
118
170
  || resultToP3 > other.length
@@ -127,6 +179,13 @@ class LineSegment2 extends Abstract2DShape_1.default {
127
179
  intersects(other) {
128
180
  return this.intersection(other) !== null;
129
181
  }
182
+ argIntersectsLineSegment(lineSegment) {
183
+ const intersection = this.intersection(lineSegment);
184
+ if (intersection) {
185
+ return [intersection.t / this.length];
186
+ }
187
+ return [];
188
+ }
130
189
  /**
131
190
  * Returns the points at which this line segment intersects the
132
191
  * given line segment.
@@ -144,18 +203,21 @@ class LineSegment2 extends Abstract2DShape_1.default {
144
203
  }
145
204
  // Returns the closest point on this to [target]
146
205
  closestPointTo(target) {
206
+ return this.nearestPointTo(target).point;
207
+ }
208
+ nearestPointTo(target) {
147
209
  // Distance from P1 along this' direction.
148
210
  const projectedDistFromP1 = target.minus(this.p1).dot(this.direction);
149
211
  const projectedDistFromP2 = this.length - projectedDistFromP1;
150
212
  const projection = this.p1.plus(this.direction.times(projectedDistFromP1));
151
213
  if (projectedDistFromP1 > 0 && projectedDistFromP1 < this.length) {
152
- return projection;
214
+ return { point: projection, parameterValue: projectedDistFromP1 / this.length };
153
215
  }
154
216
  if (Math.abs(projectedDistFromP2) < Math.abs(projectedDistFromP1)) {
155
- return this.p2;
217
+ return { point: this.p2, parameterValue: 1 };
156
218
  }
157
219
  else {
158
- return this.p1;
220
+ return { point: this.p1, parameterValue: 0 };
159
221
  }
160
222
  }
161
223
  /**
@@ -178,6 +240,22 @@ class LineSegment2 extends Abstract2DShape_1.default {
178
240
  toString() {
179
241
  return `LineSegment(${this.p1.toString()}, ${this.p2.toString()})`;
180
242
  }
243
+ /**
244
+ * Returns `true` iff this is equivalent to `other`.
245
+ *
246
+ * **Options**:
247
+ * - `tolerance`: The maximum difference between endpoints. (Default: 0)
248
+ * - `ignoreDirection`: Allow matching a version of `this` with opposite direction. (Default: `true`)
249
+ */
250
+ eq(other, options) {
251
+ if (!(other instanceof LineSegment2)) {
252
+ return false;
253
+ }
254
+ const tolerance = options?.tolerance;
255
+ const ignoreDirection = options?.ignoreDirection ?? true;
256
+ return ((other.p1.eq(this.p1, tolerance) && other.p2.eq(this.p2, tolerance))
257
+ || (ignoreDirection && other.p1.eq(this.p2, tolerance) && other.p2.eq(this.p1, tolerance)));
258
+ }
181
259
  }
182
260
  exports.LineSegment2 = LineSegment2;
183
261
  exports.default = LineSegment2;
@@ -0,0 +1,36 @@
1
+ import { Point2, Vec2 } from '../Vec2';
2
+ import Abstract2DShape from './Abstract2DShape';
3
+ import LineSegment2 from './LineSegment2';
4
+ /**
5
+ * A 2-dimensional path with parameter interval $t \in [0, 1]$.
6
+ *
7
+ * **Note:** Avoid extending this class outside of `js-draw` --- new abstract methods
8
+ * may be added between minor versions.
9
+ */
10
+ export declare abstract class Parameterized2DShape extends Abstract2DShape {
11
+ /** Returns this at a given parameter. $t \in [0, 1]$ */
12
+ abstract at(t: number): Point2;
13
+ /** Computes the unit normal vector at $t$. */
14
+ abstract normalAt(t: number): Vec2;
15
+ abstract tangentAt(t: number): Vec2;
16
+ /**
17
+ * Divides this shape into two separate shapes at parameter value $t$.
18
+ */
19
+ abstract splitAt(t: number): [Parameterized2DShape] | [Parameterized2DShape, Parameterized2DShape];
20
+ /**
21
+ * Returns the nearest point on `this` to `point` and the `parameterValue` at which
22
+ * that point occurs.
23
+ */
24
+ abstract nearestPointTo(point: Point2): {
25
+ point: Point2;
26
+ parameterValue: number;
27
+ };
28
+ /**
29
+ * Returns the **parameter values** at which `lineSegment` intersects this shape.
30
+ *
31
+ * See also {@link intersectsLineSegment}
32
+ */
33
+ abstract argIntersectsLineSegment(lineSegment: LineSegment2): number[];
34
+ intersectsLineSegment(line: LineSegment2): Point2[];
35
+ }
36
+ export default Parameterized2DShape;
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.Parameterized2DShape = void 0;
7
+ const Abstract2DShape_1 = __importDefault(require("./Abstract2DShape"));
8
+ /**
9
+ * A 2-dimensional path with parameter interval $t \in [0, 1]$.
10
+ *
11
+ * **Note:** Avoid extending this class outside of `js-draw` --- new abstract methods
12
+ * may be added between minor versions.
13
+ */
14
+ class Parameterized2DShape extends Abstract2DShape_1.default {
15
+ intersectsLineSegment(line) {
16
+ return this.argIntersectsLineSegment(line).map(t => this.at(t));
17
+ }
18
+ }
19
+ exports.Parameterized2DShape = Parameterized2DShape;
20
+ exports.default = Parameterized2DShape;
@@ -2,7 +2,7 @@ import LineSegment2 from './LineSegment2';
2
2
  import Mat33 from '../Mat33';
3
3
  import Rect2 from './Rect2';
4
4
  import { Point2 } from '../Vec2';
5
- import Abstract2DShape from './Abstract2DShape';
5
+ import Parameterized2DShape from './Parameterized2DShape';
6
6
  export declare enum PathCommandType {
7
7
  LineTo = 0,
8
8
  MoveTo = 1,
@@ -29,14 +29,68 @@ export interface MoveToPathCommand {
29
29
  point: Point2;
30
30
  }
31
31
  export type PathCommand = CubicBezierPathCommand | QuadraticBezierPathCommand | MoveToPathCommand | LinePathCommand;
32
- interface IntersectionResult {
33
- curve: Abstract2DShape;
34
- /** @internal @deprecated */
35
- parameterValue?: number;
32
+ export interface IntersectionResult {
33
+ curve: Parameterized2DShape;
34
+ curveIndex: number;
35
+ /** Parameter value for the closest point **on** the path to the intersection. @internal */
36
+ parameterValue: number;
37
+ /** Point at which the intersection occured. */
36
38
  point: Point2;
37
39
  }
40
+ /** Options for {@link Path.splitNear} and {@link Path.splitAt} */
41
+ export interface PathSplitOptions {
42
+ /**
43
+ * Allows mapping points on newly added segments. This is useful, for example,
44
+ * to round points to prevent long decimals when later saving.
45
+ */
46
+ mapNewPoint?: (point: Point2) => Point2;
47
+ }
48
+ /**
49
+ * Allows indexing a particular part of a path.
50
+ *
51
+ * @see {@link Path.at} {@link Path.tangentAt}
52
+ */
53
+ export interface CurveIndexRecord {
54
+ curveIndex: number;
55
+ parameterValue: number;
56
+ }
57
+ /** Returns a positive number if `a` comes after `b`, 0 if equal, and negative otherwise. */
58
+ export declare const compareCurveIndices: (a: CurveIndexRecord, b: CurveIndexRecord) => number;
59
+ /**
60
+ * Returns a version of `index` with its parameter value incremented by `stepBy`
61
+ * (which can be either positive or negative).
62
+ */
63
+ export declare const stepCurveIndexBy: (index: CurveIndexRecord, stepBy: number) => CurveIndexRecord;
38
64
  /**
39
65
  * Represents a union of lines and curves.
66
+ *
67
+ * To create a path from a string, see {@link fromString}.
68
+ *
69
+ * @example
70
+ * ```ts,runnable,console
71
+ * import {Path, Mat33, Vec2, LineSegment2} from '@js-draw/math';
72
+ *
73
+ * // Creates a path from an SVG path string.
74
+ * // In this case,
75
+ * // 1. Move to (0,0)
76
+ * // 2. Line to (100,0)
77
+ * const path = Path.fromString('M0,0 L100,0');
78
+ *
79
+ * // Logs the distance from (10,0) to the curve 1 unit
80
+ * // away from path. This curve forms a stroke with the path at
81
+ * // its center.
82
+ * const strokeRadius = 1;
83
+ * console.log(path.signedDistance(Vec2.of(10,0), strokeRadius));
84
+ *
85
+ * // Log a version of the path that's scaled by a factor of 4.
86
+ * console.log(path.transformedBy(Mat33.scaling2D(4)).toString());
87
+ *
88
+ * // Log all intersections of a stroked version of the path with
89
+ * // a vertical line segment.
90
+ * // (Try removing the `strokeRadius` parameter).
91
+ * const segment = new LineSegment2(Vec2.of(5, -100), Vec2.of(5, 100));
92
+ * console.log(path.intersection(segment, strokeRadius).map(i => i.point));
93
+ * ```
40
94
  */
41
95
  export declare class Path {
42
96
  readonly startPoint: Point2;
@@ -55,9 +109,15 @@ export declare class Path {
55
109
  * See also {@link fromString}
56
110
  */
57
111
  constructor(startPoint: Point2, parts: Readonly<PathCommand>[]);
112
+ /**
113
+ * Computes and returns the full bounding box for this path.
114
+ *
115
+ * If a slight over-estimate of a path's bounding box is sufficient, use
116
+ * {@link bbox} instead.
117
+ */
58
118
  getExactBBox(): Rect2;
59
119
  private cachedGeometry;
60
- get geometry(): Abstract2DShape[];
120
+ get geometry(): Parameterized2DShape[];
61
121
  /**
62
122
  * Iterates through the start/end points of each component in this path.
63
123
  *
@@ -68,7 +128,20 @@ export declare class Path {
68
128
  private cachedPolylineApproximation;
69
129
  polylineApproximation(): LineSegment2[];
70
130
  static computeBBoxForSegment(startPoint: Point2, part: PathCommand): Rect2;
71
- /** **Note**: `strokeRadius = strokeWidth / 2` */
131
+ /**
132
+ * Returns the signed distance between `point` and a curve `strokeRadius` units
133
+ * away from this path.
134
+ *
135
+ * This returns the **signed distance**, which means that points inside this shape
136
+ * have their distance negated. For example,
137
+ * ```ts,runnable,console
138
+ * import {Path, Vec2} from '@js-draw/math';
139
+ * console.log(Path.fromString('m0,0 L100,0').signedDistance(Vec2.zero, 1));
140
+ * ```
141
+ * would print `-1` because (0,0) is on `m0,0 L100,0` and thus one unit away from its boundary.
142
+ *
143
+ * **Note**: `strokeRadius = strokeWidth / 2`
144
+ */
72
145
  signedDistance(point: Point2, strokeRadius: number): number;
73
146
  /**
74
147
  * Let `S` be a closed path a distance `strokeRadius` from this path.
@@ -86,11 +159,49 @@ export declare class Path {
86
159
  * **Note**: `strokeRadius` is half of a stroke's width.
87
160
  */
88
161
  intersection(line: LineSegment2, strokeRadius?: number): IntersectionResult[];
162
+ /**
163
+ * @returns the nearest point on this path to the given `point`.
164
+ */
165
+ nearestPointTo(point: Point2): IntersectionResult;
166
+ at(index: CurveIndexRecord): import("../Vec3").Vec3;
167
+ tangentAt(index: CurveIndexRecord): import("../Vec3").Vec3;
168
+ /** Splits this path in two near the given `point`. */
169
+ splitNear(point: Point2, options?: PathSplitOptions): [Path] | [Path, Path];
170
+ /**
171
+ * Returns a copy of this path with `deleteFrom` until `deleteUntil` replaced with `insert`.
172
+ *
173
+ * This method is analogous to {@link Array.toSpliced}.
174
+ */
175
+ spliced(deleteFrom: CurveIndexRecord, deleteTo: CurveIndexRecord, insert: Path | undefined, options?: PathSplitOptions): Path;
176
+ splitAt(at: CurveIndexRecord, options?: PathSplitOptions): [Path] | [Path, Path];
177
+ splitAt(at: CurveIndexRecord[], options?: PathSplitOptions): Path[];
178
+ /**
179
+ * Replaces all `MoveTo` commands with `LineTo` commands and connects the end point of this
180
+ * path to the start point.
181
+ */
182
+ asClosed(): Path;
89
183
  private static mapPathCommand;
90
184
  mapPoints(mapping: (point: Point2) => Point2): Path;
91
185
  transformedBy(affineTransfm: Mat33): Path;
92
- union(other: Path | null): Path;
93
- private getEndPoint;
186
+ /**
187
+ * @internal
188
+ */
189
+ closedContainsPoint(point: Point2): boolean;
190
+ union(other: Path | PathCommand[] | null, options?: {
191
+ allowReverse?: boolean;
192
+ }): Path;
193
+ /**
194
+ * @returns a version of this path with the direction reversed.
195
+ *
196
+ * Example:
197
+ * ```ts,runnable,console
198
+ * import {Path} from '@js-draw/math';
199
+ * console.log(Path.fromString('m0,0l1,1').reversed()); // -> M1,1 L0,0
200
+ * ```
201
+ */
202
+ reversed(): Path;
203
+ /** Computes and returns the end point of this path */
204
+ getEndPoint(): import("../Vec3").Vec3;
94
205
  /**
95
206
  * Like {@link closedRoughlyIntersects} except takes stroke width into account.
96
207
  *
@@ -102,7 +213,15 @@ export declare class Path {
102
213
  * `strokeRadius` is half of `strokeWidth`.
103
214
  */
104
215
  roughlyIntersects(rect: Rect2, strokeWidth?: number): boolean;
216
+ /**
217
+ * Treats this as a closed path and returns true if part of `rect` is *roughly* within
218
+ * this path's interior.
219
+ *
220
+ * **Note**: Assumes that this is a closed, non-self-intersecting path.
221
+ */
105
222
  closedRoughlyIntersects(rect: Rect2): boolean;
223
+ /** @returns true if all points on this are equivalent to the points on `other` */
224
+ eq(other: Path, tolerance?: number): boolean;
106
225
  /**
107
226
  * Returns a path that outlines `rect`.
108
227
  *
@@ -126,10 +245,8 @@ export declare class Path {
126
245
  /**
127
246
  * Create a `Path` from a subset of the SVG path specification.
128
247
  *
129
- * ## To-do
130
- * - TODO: Support a larger subset of SVG paths
131
- * - Elliptical arcs are currently unsupported.
132
- * - TODO: Support `s`,`t` commands shorthands.
248
+ * Currently, this does not support elliptical arcs or `s` and `t` command
249
+ * shorthands. See https://github.com/personalizedrefrigerator/js-draw/pull/19.
133
250
  *
134
251
  * @example
135
252
  * ```ts,runnable,console
@@ -140,6 +257,7 @@ export declare class Path {
140
257
  * ```
141
258
  */
142
259
  static fromString(pathString: string): Path;
260
+ static fromConvexHullOf(points: Point2[]): Path;
143
261
  static empty: Path;
144
262
  }
145
263
  export default Path;