@thi.ng/geom 6.1.9 → 7.0.1

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 (85) hide show
  1. package/CHANGELOG.md +114 -1
  2. package/README.md +34 -29
  3. package/api/arc.js +1 -1
  4. package/api/complex-polygon.d.ts +14 -0
  5. package/api/complex-polygon.js +44 -0
  6. package/api/path.d.ts +11 -3
  7. package/api/path.js +45 -29
  8. package/apply-transforms.js +5 -10
  9. package/arc-length.d.ts +1 -0
  10. package/arc-length.js +12 -0
  11. package/arc.d.ts +51 -1
  12. package/arc.js +12 -1
  13. package/area.d.ts +1 -0
  14. package/area.js +4 -1
  15. package/as-cubic.d.ts +2 -0
  16. package/as-cubic.js +10 -2
  17. package/as-path.d.ts +19 -3
  18. package/as-path.js +54 -1
  19. package/as-polygon.d.ts +7 -5
  20. package/as-polygon.js +14 -1
  21. package/as-polyline.d.ts +6 -4
  22. package/as-polyline.js +19 -5
  23. package/bounds.js +14 -7
  24. package/centroid.d.ts +3 -2
  25. package/centroid.js +10 -1
  26. package/classify-point.d.ts +5 -2
  27. package/clip-convex.d.ts +22 -3
  28. package/clip-convex.js +39 -12
  29. package/closest-point.d.ts +2 -0
  30. package/closest-point.js +34 -0
  31. package/complex-polygon-from-path.d.ts +14 -0
  32. package/complex-polygon-from-path.js +9 -0
  33. package/complex-polygon.d.ts +23 -0
  34. package/complex-polygon.js +6 -0
  35. package/convex-hull.d.ts +1 -0
  36. package/convex-hull.js +2 -0
  37. package/edges.d.ts +2 -0
  38. package/edges.js +7 -3
  39. package/fit-into-bounds.js +5 -10
  40. package/flip.d.ts +1 -0
  41. package/flip.js +5 -0
  42. package/index.d.ts +5 -0
  43. package/index.js +5 -0
  44. package/internal/bounds.js +3 -6
  45. package/internal/copy.d.ts +3 -1
  46. package/internal/copy.js +9 -3
  47. package/internal/transform.d.ts +20 -7
  48. package/internal/transform.js +10 -0
  49. package/intersects.js +3 -6
  50. package/package.json +48 -33
  51. package/path-builder.d.ts +21 -1
  52. package/path-builder.js +31 -14
  53. package/path-from-svg.d.ts +13 -1
  54. package/path-from-svg.js +10 -14
  55. package/path.d.ts +59 -2
  56. package/path.js +44 -19
  57. package/point-inside.d.ts +12 -9
  58. package/point-inside.js +3 -0
  59. package/proximity.d.ts +11 -0
  60. package/proximity.js +9 -0
  61. package/resample.d.ts +1 -0
  62. package/resample.js +7 -1
  63. package/rotate.d.ts +1 -0
  64. package/rotate.js +13 -10
  65. package/scale-with-center.d.ts +20 -0
  66. package/scale-with-center.js +7 -0
  67. package/scale.d.ts +1 -0
  68. package/scale.js +12 -9
  69. package/scatter.js +1 -2
  70. package/simplify.d.ts +4 -3
  71. package/simplify.js +39 -27
  72. package/split-arclength.d.ts +1 -1
  73. package/split-arclength.js +4 -6
  74. package/subdiv-curve.d.ts +5 -1
  75. package/subdiv-curve.js +10 -8
  76. package/transform-vertices.d.ts +1 -0
  77. package/transform-vertices.js +19 -19
  78. package/transform.d.ts +1 -0
  79. package/transform.js +17 -16
  80. package/translate.d.ts +1 -0
  81. package/translate.js +17 -12
  82. package/vertices.d.ts +18 -17
  83. package/vertices.js +22 -11
  84. package/with-attribs.d.ts +1 -1
  85. package/with-attribs.js +1 -1
package/convex-hull.d.ts CHANGED
@@ -11,6 +11,7 @@ import type { IShape } from "@thi.ng/geom-api";
11
11
  *
12
12
  * - {@link Arc}
13
13
  * - {@link Circle}
14
+ * - {@link ComplexPolygon}
14
15
  * - {@link Ellipse}
15
16
  * - {@link Group} (only the listed child shape types are considered)
16
17
  * - {@link Points}
package/convex-hull.js CHANGED
@@ -12,6 +12,7 @@ const convexHull = defmulti(
12
12
  cubic: "group",
13
13
  ellipse: "tri",
14
14
  line: "tri",
15
+ path: "group",
15
16
  poly: "points",
16
17
  polyline: "points",
17
18
  quad: "points",
@@ -19,6 +20,7 @@ const convexHull = defmulti(
19
20
  rect: "tri"
20
21
  },
21
22
  {
23
+ complexpoly: ($) => convexHull($.boundary),
22
24
  group: ($) => new Polygon(grahamScan2(vertices($)), __copyAttribs($)),
23
25
  points: ($) => new Polygon(grahamScan2($.points), __copyAttribs($)),
24
26
  tri: ($) => new Polygon(vertices($), __copyAttribs($))
package/edges.d.ts CHANGED
@@ -15,6 +15,7 @@ import type { VecPair } from "@thi.ng/vectors";
15
15
  * - {@link Arc}
16
16
  * - {@link BPatch}
17
17
  * - {@link Circle}
18
+ * - {@link ComplexPolygon}
18
19
  * - {@link Cubic}
19
20
  * - {@link Ellipse}
20
21
  * - {@link Group}
@@ -31,6 +32,7 @@ import type { VecPair } from "@thi.ng/vectors";
31
32
  * [`SamplingOpts`](https://docs.thi.ng/umbrella/geom-api/interfaces/SamplingOpts.html)
32
33
  * (all others do):
33
34
  *
35
+ * - {@link AABB}
34
36
  * - {@link Line}
35
37
  * - {@link Polygon}
36
38
  * - {@link Polyline}
package/edges.js CHANGED
@@ -37,11 +37,15 @@ const edges = defmulti(
37
37
  // right
38
38
  ];
39
39
  },
40
- arc: ($, opts) => __edges(asPolyline($, opts).points, false),
40
+ arc: ($, opts) => __edges(asPolyline($, opts)[0].points),
41
41
  bpatch: ($) => $.edges(),
42
- circle: ($, opts) => __edges(asPolygon($, opts).points, true),
42
+ circle: ($, opts) => __edges(asPolygon($, opts)[0].points, true),
43
+ complexpoly: ($) => mapcat(
44
+ (poly) => __edges(poly.points, true),
45
+ [$.boundary, ...$.children]
46
+ ),
43
47
  group: ($, opts) => mapcat((c) => edges(c, opts), $.children),
44
- path: ($, opts) => __edges(asPolygon($, opts).points, $.closed),
48
+ path: ($, opts) => mapcat((poly) => __edges(poly.points), asPolyline($, opts)),
45
49
  poly: ($) => __edges($.points, true),
46
50
  polyline: ($) => __edges($.points),
47
51
  rect: ($) => __edges(vertices($), true)
@@ -18,11 +18,9 @@ const __translateScale = (tmat, smat, shape, preTrans, postTrans, scale) => tran
18
18
  );
19
19
  const fitIntoBounds2 = (shape, dest) => {
20
20
  const src = bounds(shape);
21
- if (!src)
22
- return;
21
+ if (!src) return;
23
22
  const c = centroid(src);
24
- if (!c)
25
- return;
23
+ if (!c) return;
26
24
  return __translateScale(
27
25
  translation23,
28
26
  scale23,
@@ -37,11 +35,9 @@ const fitIntoBounds2 = (shape, dest) => {
37
35
  };
38
36
  const fitIntoBounds3 = (shape, dest) => {
39
37
  const src = bounds(shape);
40
- if (!src)
41
- return;
38
+ if (!src) return;
42
39
  const c = centroid(src);
43
- if (!c)
44
- return;
40
+ if (!c) return;
45
41
  return __translateScale(
46
42
  translation44,
47
43
  scale44,
@@ -57,8 +53,7 @@ const fitIntoBounds3 = (shape, dest) => {
57
53
  };
58
54
  const fitAllIntoBounds2 = (shapes, dest) => {
59
55
  const sbraw = __collBounds(shapes, bounds);
60
- if (!sbraw)
61
- return;
56
+ if (!sbraw) return;
62
57
  const src = new Rect(...sbraw);
63
58
  const sx = safeDiv(dest.size[0], src.size[0]);
64
59
  const sy = safeDiv(dest.size[1], src.size[1]);
package/flip.d.ts CHANGED
@@ -8,6 +8,7 @@ import type { IShape } from "@thi.ng/geom-api";
8
8
  * Currently implemented for:
9
9
  *
10
10
  * - {@link Arc}
11
+ * - {@link ComplexPolygon}
11
12
  * - {@link Cubic}
12
13
  * - {@link Group} (only eligible shapes)
13
14
  * - {@link Line}
package/flip.js CHANGED
@@ -22,6 +22,11 @@ const flip = defmulti(
22
22
  $.cw = !$.cw;
23
23
  return $;
24
24
  },
25
+ complexpoly: ($) => {
26
+ flip($.boundary);
27
+ for (let c of $.children) flip(c);
28
+ return $;
29
+ },
25
30
  group: ($) => {
26
31
  $.children.forEach(flip);
27
32
  return $;
package/index.d.ts CHANGED
@@ -3,6 +3,7 @@ export * from "./api/apc.js";
3
3
  export * from "./api/arc.js";
4
4
  export * from "./api/bpatch.js";
5
5
  export * from "./api/circle.js";
6
+ export * from "./api/complex-polygon.js";
6
7
  export * from "./api/cubic.js";
7
8
  export * from "./api/ellipse.js";
8
9
  export * from "./api/group.js";
@@ -24,6 +25,8 @@ export * from "./aabb.js";
24
25
  export * from "./arc.js";
25
26
  export * from "./bpatch.js";
26
27
  export * from "./circle.js";
28
+ export * from "./complex-polygon.js";
29
+ export * from "./complex-polygon-from-path.js";
27
30
  export * from "./cubic.js";
28
31
  export * from "./ellipse.js";
29
32
  export * from "./group.js";
@@ -35,6 +38,7 @@ export * from "./plane.js";
35
38
  export * from "./points.js";
36
39
  export * from "./polygon.js";
37
40
  export * from "./polyline.js";
41
+ export * from "./proximity.js";
38
42
  export * from "./quad.js";
39
43
  export * from "./quadratic.js";
40
44
  export * from "./ray.js";
@@ -67,6 +71,7 @@ export * from "./point-inside.js";
67
71
  export * from "./resample.js";
68
72
  export * from "./rotate.js";
69
73
  export * from "./scale.js";
74
+ export * from "./scale-with-center.js";
70
75
  export * from "./scatter.js";
71
76
  export * from "./simplify.js";
72
77
  export * from "./split-arclength.js";
package/index.js CHANGED
@@ -3,6 +3,7 @@ export * from "./api/apc.js";
3
3
  export * from "./api/arc.js";
4
4
  export * from "./api/bpatch.js";
5
5
  export * from "./api/circle.js";
6
+ export * from "./api/complex-polygon.js";
6
7
  export * from "./api/cubic.js";
7
8
  export * from "./api/ellipse.js";
8
9
  export * from "./api/group.js";
@@ -24,6 +25,8 @@ export * from "./aabb.js";
24
25
  export * from "./arc.js";
25
26
  export * from "./bpatch.js";
26
27
  export * from "./circle.js";
28
+ export * from "./complex-polygon.js";
29
+ export * from "./complex-polygon-from-path.js";
27
30
  export * from "./cubic.js";
28
31
  export * from "./ellipse.js";
29
32
  export * from "./group.js";
@@ -35,6 +38,7 @@ export * from "./plane.js";
35
38
  export * from "./points.js";
36
39
  export * from "./polygon.js";
37
40
  export * from "./polyline.js";
41
+ export * from "./proximity.js";
38
42
  export * from "./quad.js";
39
43
  export * from "./quadratic.js";
40
44
  export * from "./ray.js";
@@ -67,6 +71,7 @@ export * from "./point-inside.js";
67
71
  export * from "./resample.js";
68
72
  export * from "./rotate.js";
69
73
  export * from "./scale.js";
74
+ export * from "./scale-with-center.js";
70
75
  export * from "./scatter.js";
71
76
  export * from "./simplify.js";
72
77
  export * from "./split-arclength.js";
@@ -4,16 +4,13 @@ import { min } from "@thi.ng/vectors/min";
4
4
  import { sub } from "@thi.ng/vectors/sub";
5
5
  const __collBounds = (shapes, bounds) => {
6
6
  let n = shapes.length - 1;
7
- if (n < 0)
8
- return;
7
+ if (n < 0) return;
9
8
  let b = bounds(shapes[n]);
10
- if (!b)
11
- return;
9
+ if (!b) return;
12
10
  let { pos, size } = b;
13
11
  for (; n-- > 0; ) {
14
12
  b = bounds(shapes[n]);
15
- if (!b)
16
- continue;
13
+ if (!b) continue;
17
14
  [pos, size] = __unionBounds(pos, size, b.pos, b.size);
18
15
  }
19
16
  return [pos, size];
@@ -1,4 +1,4 @@
1
- import type { Attribs, IShape, PCLike, PCLikeConstructor } from "@thi.ng/geom-api";
1
+ import type { Attribs, IShape, PCLike, PCLikeConstructor, PathSegment } from "@thi.ng/geom-api";
2
2
  /**
3
3
  * Creates a shallow copy of shape's attribs. Any `exclude` keys will be removed
4
4
  * from result attribs.
@@ -17,4 +17,6 @@ export declare const __copyAttribs: ($: IShape, ...exclude: string[]) => Attribs
17
17
  export declare const __copyAttribsNoSamples: (x: IShape) => Attribs | undefined;
18
18
  /** @internal */
19
19
  export declare const __copyShape: <T extends PCLike>(ctor: PCLikeConstructor, inst: T) => T;
20
+ /** @internal */
21
+ export declare const __copySegment: (s: PathSegment) => PathSegment;
20
22
  //# sourceMappingURL=copy.d.ts.map
package/internal/copy.js CHANGED
@@ -1,15 +1,21 @@
1
1
  import { withoutKeysObj } from "@thi.ng/associative/without-keys";
2
- import { copyVectors } from "@thi.ng/vectors/copy";
2
+ import { copy, copyVectors } from "@thi.ng/vectors/copy";
3
3
  const __copyAttribs = ($, ...exclude) => {
4
- if (!$.attribs)
5
- return;
4
+ if (!$.attribs) return;
6
5
  const attribs = { ...$.attribs };
7
6
  return exclude.length ? withoutKeysObj(attribs, exclude) : attribs;
8
7
  };
9
8
  const __copyAttribsNoSamples = (x) => __copyAttribs(x, "__samples");
10
9
  const __copyShape = (ctor, inst) => new ctor(copyVectors(inst.points), __copyAttribs(inst));
10
+ const __copySegment = (s) => {
11
+ const d = { type: s.type };
12
+ if (s.geo) d.geo = s.geo.copy();
13
+ else if (s.point) d.point = copy(s.point);
14
+ return d;
15
+ };
11
16
  export {
12
17
  __copyAttribs,
13
18
  __copyAttribsNoSamples,
19
+ __copySegment,
14
20
  __copyShape
15
21
  };
@@ -1,16 +1,29 @@
1
- import type { Fn } from "@thi.ng/api";
2
- import type { PCLike, PCLikeConstructor } from "@thi.ng/geom-api";
1
+ import type { Fn, FnU } from "@thi.ng/api";
2
+ import type { IShape, PCLike, PCLikeConstructor, PathSegment } from "@thi.ng/geom-api";
3
3
  import type { MatOpMV, ReadonlyMat } from "@thi.ng/matrices";
4
- import type { ReadonlyVec } from "@thi.ng/vectors";
4
+ import type { ReadonlyVec, Vec } from "@thi.ng/vectors";
5
+ /** @internal */
5
6
  export declare const __transformPoints: (pts: ReadonlyVec[], mat: ReadonlyMat, op?: MatOpMV) => ReadonlyVec[];
6
- export declare const __transformedPoints: (pts: ReadonlyVec[], mat: ReadonlyMat, op?: MatOpMV) => import("@thi.ng/vectors").Vec[];
7
+ /** @internal */
8
+ export declare const __transformedPoints: (pts: ReadonlyVec[], mat: ReadonlyMat, op?: MatOpMV) => Vec[];
9
+ /** @internal */
7
10
  export declare const __transformPointsWith: (pts: ReadonlyVec[], fn: Fn<ReadonlyVec, ReadonlyMat>, op?: MatOpMV) => ReadonlyVec[];
8
- export declare const __transformedPointsWith: (pts: ReadonlyVec[], fn: Fn<ReadonlyVec, ReadonlyMat>, op?: MatOpMV) => import("@thi.ng/vectors").Vec[];
11
+ /** @internal */
12
+ export declare const __transformedPointsWith: (pts: ReadonlyVec[], fn: Fn<ReadonlyVec, ReadonlyMat>, op?: MatOpMV) => Vec[];
13
+ /** @internal */
9
14
  export declare const __transformedShape: (ctor: PCLikeConstructor) => ($: PCLike, mat: ReadonlyMat) => PCLike;
15
+ /** @internal */
10
16
  export declare const __transformedShapePoints: (ctor: PCLikeConstructor) => ($: PCLike, fn: Fn<ReadonlyVec, ReadonlyMat>) => PCLike;
17
+ /** @internal */
11
18
  export declare const __transformPoints3: (pts: ReadonlyVec[], mat: ReadonlyMat) => ReadonlyVec[];
12
- export declare const __transformedPoints3: (pts: ReadonlyVec[], mat: ReadonlyMat) => import("@thi.ng/vectors").Vec[];
13
- export declare const __transformedPointsWith3: (pts: ReadonlyVec[], fn: Fn<ReadonlyVec, ReadonlyMat>) => import("@thi.ng/vectors").Vec[];
19
+ /** @internal */
20
+ export declare const __transformedPoints3: (pts: ReadonlyVec[], mat: ReadonlyMat) => Vec[];
21
+ /** @internal */
22
+ export declare const __transformedPointsWith3: (pts: ReadonlyVec[], fn: Fn<ReadonlyVec, ReadonlyMat>) => Vec[];
23
+ /** @internal */
14
24
  export declare const __transformedShape3: (ctor: PCLikeConstructor) => ($: PCLike, mat: ReadonlyMat) => PCLike;
25
+ /** @internal */
15
26
  export declare const __transformedShapePoints3: (ctor: PCLikeConstructor) => ($: PCLike, fn: Fn<ReadonlyVec, ReadonlyMat>) => PCLike;
27
+ /** @internal */
28
+ export declare const __segmentTransformer: (txGeo: FnU<IShape>, txPoint: FnU<Vec>) => (segments: PathSegment[]) => PathSegment[];
16
29
  //# sourceMappingURL=transform.d.ts.map
@@ -11,7 +11,17 @@ const __transformedPoints3 = (pts, mat) => __transformedPoints(pts, mat, mulV344
11
11
  const __transformedPointsWith3 = (pts, fn) => __transformedPointsWith(pts, fn, mulV344);
12
12
  const __transformedShape3 = (ctor) => ($, mat) => new ctor(__transformedPoints3($.points, mat), __copyAttribs($));
13
13
  const __transformedShapePoints3 = (ctor) => ($, fn) => new ctor(__transformedPointsWith3($.points, fn), __copyAttribs($));
14
+ const __segmentTransformer = (txGeo, txPoint) => (segments) => segments.map(
15
+ (s) => s.geo ? {
16
+ type: s.type,
17
+ geo: txGeo(s.geo)
18
+ } : s.point ? {
19
+ type: s.type,
20
+ point: txPoint(s.point)
21
+ } : { ...s }
22
+ );
14
23
  export {
24
+ __segmentTransformer,
15
25
  __transformPoints,
16
26
  __transformPoints3,
17
27
  __transformPointsWith,
package/intersects.js CHANGED
@@ -43,8 +43,7 @@ const intersects = defmulti(
43
43
  group,
44
44
  opts
45
45
  );
46
- if (res === NONE)
47
- return res;
46
+ if (res === NONE) return res;
48
47
  res.isec = res.isec.filter((p) => distSq2(a, p) <= max);
49
48
  if (res.isec.length) {
50
49
  res.alpha = dist2(a, res.isec[0]);
@@ -65,10 +64,8 @@ const intersects = defmulti(
65
64
  let inside = false;
66
65
  for (let child of children) {
67
66
  let $res = intersects(ray, child, opts);
68
- if ($res.type !== IntersectionType.INTERSECT)
69
- continue;
70
- if ($res.inside)
71
- inside = true;
67
+ if ($res.type !== IntersectionType.INTERSECT) continue;
68
+ if ($res.inside) inside = true;
72
69
  const first = $res.isec[0];
73
70
  const alpha = $res.alpha !== void 0 ? $res.alpha : dist2(ray.pos, first);
74
71
  if (all) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thi.ng/geom",
3
- "version": "6.1.9",
3
+ "version": "7.0.1",
4
4
  "description": "Functional, polymorphic API for 2D geometry types & SVG generation",
5
5
  "type": "module",
6
6
  "module": "./index.js",
@@ -37,39 +37,39 @@
37
37
  "tool:tangle": "../../node_modules/.bin/tangle src/**/*.ts"
38
38
  },
39
39
  "dependencies": {
40
- "@thi.ng/api": "^8.11.1",
41
- "@thi.ng/arrays": "^2.9.5",
42
- "@thi.ng/associative": "^6.3.59",
43
- "@thi.ng/checks": "^3.6.3",
44
- "@thi.ng/defmulti": "^3.0.38",
45
- "@thi.ng/equiv": "^2.1.57",
46
- "@thi.ng/errors": "^2.5.6",
47
- "@thi.ng/geom-api": "^4.0.9",
48
- "@thi.ng/geom-arc": "^2.1.131",
49
- "@thi.ng/geom-clip-line": "^2.3.88",
50
- "@thi.ng/geom-clip-poly": "^2.1.130",
51
- "@thi.ng/geom-closest-point": "^2.1.126",
52
- "@thi.ng/geom-hull": "^2.1.126",
53
- "@thi.ng/geom-isec": "^3.0.9",
54
- "@thi.ng/geom-poly-utils": "^2.3.114",
55
- "@thi.ng/geom-resample": "^2.3.52",
56
- "@thi.ng/geom-splines": "^2.2.105",
57
- "@thi.ng/geom-subdiv-curve": "^2.1.130",
58
- "@thi.ng/geom-tessellate": "^2.1.131",
59
- "@thi.ng/hiccup": "^5.2.0",
60
- "@thi.ng/hiccup-svg": "^5.2.36",
61
- "@thi.ng/math": "^5.10.12",
62
- "@thi.ng/matrices": "^2.3.36",
63
- "@thi.ng/random": "^3.7.5",
64
- "@thi.ng/strings": "^3.7.32",
65
- "@thi.ng/transducers": "^9.0.4",
66
- "@thi.ng/vectors": "^7.10.30"
40
+ "@thi.ng/api": "^8.11.2",
41
+ "@thi.ng/arrays": "^2.9.6",
42
+ "@thi.ng/associative": "^6.3.60",
43
+ "@thi.ng/checks": "^3.6.4",
44
+ "@thi.ng/defmulti": "^3.0.39",
45
+ "@thi.ng/equiv": "^2.1.58",
46
+ "@thi.ng/errors": "^2.5.7",
47
+ "@thi.ng/geom-api": "^4.0.10",
48
+ "@thi.ng/geom-arc": "^2.1.132",
49
+ "@thi.ng/geom-clip-line": "^2.3.89",
50
+ "@thi.ng/geom-clip-poly": "^2.1.131",
51
+ "@thi.ng/geom-closest-point": "^2.1.127",
52
+ "@thi.ng/geom-hull": "^2.1.127",
53
+ "@thi.ng/geom-isec": "^3.1.0",
54
+ "@thi.ng/geom-poly-utils": "^2.4.0",
55
+ "@thi.ng/geom-resample": "^2.3.53",
56
+ "@thi.ng/geom-splines": "^2.2.106",
57
+ "@thi.ng/geom-subdiv-curve": "^2.1.131",
58
+ "@thi.ng/geom-tessellate": "^2.1.132",
59
+ "@thi.ng/hiccup": "^5.2.1",
60
+ "@thi.ng/hiccup-svg": "^5.2.37",
61
+ "@thi.ng/math": "^5.10.13",
62
+ "@thi.ng/matrices": "^2.3.37",
63
+ "@thi.ng/random": "^3.8.0",
64
+ "@thi.ng/strings": "^3.7.33",
65
+ "@thi.ng/transducers": "^9.0.5",
66
+ "@thi.ng/vectors": "^7.10.31"
67
67
  },
68
68
  "devDependencies": {
69
- "@microsoft/api-extractor": "^7.43.0",
70
- "esbuild": "^0.20.2",
71
- "typedoc": "^0.25.12",
72
- "typescript": "^5.4.3"
69
+ "@microsoft/api-extractor": "^7.43.2",
70
+ "esbuild": "^0.21.1",
71
+ "typedoc": "^0.25.13",
72
+ "typescript": "^5.4.5"
73
73
  },
74
74
  "keywords": [
75
75
  "2d",
@@ -127,6 +127,9 @@
127
127
  "./api/circle": {
128
128
  "default": "./api/circle.js"
129
129
  },
130
+ "./api/complex-polygon": {
131
+ "default": "./api/complex-polygon.js"
132
+ },
130
133
  "./api/cubic": {
131
134
  "default": "./api/cubic.js"
132
135
  },
@@ -229,6 +232,12 @@
229
232
  "./closest-point": {
230
233
  "default": "./closest-point.js"
231
234
  },
235
+ "./complex-polygon-from-path": {
236
+ "default": "./complex-polygon-from-path.js"
237
+ },
238
+ "./complex-polygon": {
239
+ "default": "./complex-polygon.js"
240
+ },
232
241
  "./convex-hull": {
233
242
  "default": "./convex-hull.js"
234
243
  },
@@ -304,6 +313,9 @@
304
313
  "./polyline": {
305
314
  "default": "./polyline.js"
306
315
  },
316
+ "./proximity": {
317
+ "default": "./proximity.js"
318
+ },
307
319
  "./quad": {
308
320
  "default": "./quad.js"
309
321
  },
@@ -322,6 +334,9 @@
322
334
  "./rotate": {
323
335
  "default": "./rotate.js"
324
336
  },
337
+ "./scale-with-center": {
338
+ "default": "./scale-with-center.js"
339
+ },
325
340
  "./scale": {
326
341
  "default": "./scale.js"
327
342
  },
@@ -398,5 +413,5 @@
398
413
  ],
399
414
  "year": 2013
400
415
  },
401
- "gitHead": "aed3421c21044c005fbcb7cc37965ccf85a870d2\n"
416
+ "gitHead": "41bd769068da804eeace622ec7db50e4d48f1dc9\n"
402
417
  }
package/path-builder.d.ts CHANGED
@@ -15,6 +15,9 @@ export interface PathBuilderOpts {
15
15
  export declare class PathBuilder {
16
16
  attribs?: Attribs | undefined;
17
17
  opts: Partial<PathBuilderOpts>;
18
+ /**
19
+ * Array of all paths which have been built already (incl. the current)
20
+ */
18
21
  paths: Path[];
19
22
  protected curr: Path;
20
23
  protected currP: Vec;
@@ -22,7 +25,14 @@ export declare class PathBuilder {
22
25
  protected startP: Vec;
23
26
  constructor(attribs?: Attribs | undefined, opts?: Partial<PathBuilderOpts>);
24
27
  [Symbol.iterator](): Generator<Path, void, undefined>;
28
+ /**
29
+ * Returns the current path being constructed.
30
+ */
25
31
  current(): Path;
32
+ /**
33
+ * Starts a new path and makes it the current one. Any future build commands
34
+ * will only act on this new path.
35
+ */
26
36
  newPath(): void;
27
37
  moveTo(p: Vec, relative?: boolean): PathBuilder;
28
38
  lineTo(p: Vec, relative?: boolean): PathBuilder;
@@ -33,12 +43,22 @@ export declare class PathBuilder {
33
43
  cubicChainTo(cp2: Vec, p: Vec, relative?: boolean): this;
34
44
  quadraticChainTo(p: Vec, relative?: boolean): this;
35
45
  arcTo(p: Vec, r: Vec, xaxis: number, xl: boolean, clockwise: boolean, relative?: boolean): PathBuilder;
36
- closePath(): this;
46
+ close(): this;
37
47
  protected updateCurrent(p: Vec, relative: boolean): Vec;
38
48
  protected absPoint(p: Vec, relative: boolean): Vec;
39
49
  protected addHVLine(p: number, i: number, relative: boolean): void;
40
50
  protected addCubic(cp1: Vec, cp2: Vec, p: Vec, relative: boolean): void;
41
51
  protected addQuadratic(cp: Vec, p: Vec, relative: boolean): void;
42
52
  }
53
+ /**
54
+ * Creates a new {@link PathBuilder} instance to construct a path step-by-step
55
+ * via a fluent builder API to append various segments and/or sub-paths.
56
+ *
57
+ * @remarks
58
+ * Also see {@link pathFromSvg} and {@link roundedRect}.
59
+ *
60
+ * @param attribs
61
+ * @param opts
62
+ */
43
63
  export declare const pathBuilder: (attribs?: Attribs, opts?: Partial<PathBuilderOpts>) => PathBuilder;
44
64
  //# sourceMappingURL=path-builder.d.ts.map
package/path-builder.js CHANGED
@@ -2,6 +2,7 @@ import { peek } from "@thi.ng/arrays/peek";
2
2
  import { eqDelta } from "@thi.ng/math/eqdelta";
3
3
  import { add2 } from "@thi.ng/vectors/add";
4
4
  import { copy } from "@thi.ng/vectors/copy";
5
+ import { eqDelta2 } from "@thi.ng/vectors/eqdelta";
5
6
  import { mulN2 } from "@thi.ng/vectors/muln";
6
7
  import { set2 } from "@thi.ng/vectors/set";
7
8
  import { zeroes } from "@thi.ng/vectors/setn";
@@ -19,6 +20,9 @@ class PathBuilder {
19
20
  this.attribs = attribs;
20
21
  this.newPath();
21
22
  }
23
+ /**
24
+ * Array of all paths which have been built already (incl. the current)
25
+ */
22
26
  paths;
23
27
  curr;
24
28
  currP;
@@ -27,11 +31,22 @@ class PathBuilder {
27
31
  *[Symbol.iterator]() {
28
32
  yield* this.paths;
29
33
  }
34
+ /**
35
+ * Returns the current path being constructed.
36
+ */
30
37
  current() {
31
38
  return this.curr;
32
39
  }
40
+ /**
41
+ * Starts a new path and makes it the current one. Any future build commands
42
+ * will only act on this new path.
43
+ */
33
44
  newPath() {
34
- this.curr = new Path([], this.attribs);
45
+ this.curr = new Path(
46
+ [],
47
+ [],
48
+ this.attribs ? { ...this.attribs } : void 0
49
+ );
35
50
  this.paths.push(this.curr);
36
51
  this.currP = zeroes(2);
37
52
  this.bezierP = zeroes(2);
@@ -39,20 +54,20 @@ class PathBuilder {
39
54
  }
40
55
  moveTo(p, relative = false) {
41
56
  if (this.opts.autoSplit !== false && this.curr.segments.length > 0) {
42
- this.curr = new Path([], this.attribs);
57
+ this.curr = new Path([], [], this.attribs);
43
58
  this.paths.push(this.curr);
44
59
  }
45
60
  p = this.updateCurrent(p, relative);
46
61
  set2(this.startP, p);
47
62
  set2(this.bezierP, p);
48
- this.curr.add({
63
+ this.curr.addSegments({
49
64
  point: p,
50
65
  type: "m"
51
66
  });
52
67
  return this;
53
68
  }
54
69
  lineTo(p, relative = false) {
55
- this.curr.add({
70
+ this.curr.addSegments({
56
71
  geo: new Line([copy(this.currP), this.updateCurrent(p, relative)]),
57
72
  type: "l"
58
73
  });
@@ -96,7 +111,7 @@ class PathBuilder {
96
111
  return this.lineTo(p, relative);
97
112
  }
98
113
  const prev = copy(this.currP);
99
- this.curr.add({
114
+ this.curr.addSegments({
100
115
  geo: arcFrom2Points(
101
116
  prev,
102
117
  this.updateCurrent(p, relative),
@@ -110,12 +125,14 @@ class PathBuilder {
110
125
  set2(this.bezierP, this.currP);
111
126
  return this;
112
127
  }
113
- closePath() {
114
- this.curr.add({
115
- geo: new Line([copy(this.currP), copy(this.startP)]),
116
- type: "l"
117
- });
118
- this.curr.closed = true;
128
+ close() {
129
+ if (!eqDelta2(this.startP, this.currP)) {
130
+ this.curr.addSegments({
131
+ geo: new Line([copy(this.currP), copy(this.startP)]),
132
+ type: "l"
133
+ });
134
+ }
135
+ this.curr.close();
119
136
  return this;
120
137
  }
121
138
  updateCurrent(p, relative) {
@@ -129,7 +146,7 @@ class PathBuilder {
129
146
  const prev = copy(this.currP);
130
147
  this.currP[i] = relative ? this.currP[i] + p : p;
131
148
  set2(this.bezierP, this.currP);
132
- this.curr.add({
149
+ this.curr.addSegments({
133
150
  geo: new Line([prev, copy(this.currP)]),
134
151
  type: "l"
135
152
  });
@@ -137,7 +154,7 @@ class PathBuilder {
137
154
  addCubic(cp1, cp2, p, relative) {
138
155
  cp2 = this.absPoint(cp2, relative);
139
156
  set2(this.bezierP, cp2);
140
- this.curr.add({
157
+ this.curr.addSegments({
141
158
  geo: new Cubic([
142
159
  copy(this.currP),
143
160
  cp1,
@@ -149,7 +166,7 @@ class PathBuilder {
149
166
  }
150
167
  addQuadratic(cp, p, relative) {
151
168
  set2(this.bezierP, cp);
152
- this.curr.add({
169
+ this.curr.addSegments({
153
170
  geo: new Quadratic([
154
171
  copy(this.currP),
155
172
  cp,
@@ -1,2 +1,14 @@
1
- export declare const pathFromSvg: (svg: string) => import("./index.js").Path[];
1
+ import type { Attribs } from "@thi.ng/geom-api";
2
+ /**
3
+ * Takes a SVG path string and parses it into a {@link Path} shape, optionally
4
+ * with given attributes.
5
+ *
6
+ * @remarks
7
+ * If the path contains multiple sub-paths (e.g. holes or multiple curves), they
8
+ * will be added as sub-paths to the returned main path.
9
+ *
10
+ * @param svg
11
+ * @param attribs
12
+ */
13
+ export declare const pathFromSvg: (svg: string, attribs?: Attribs) => import("./index.js").Path;
2
14
  //# sourceMappingURL=path-from-svg.d.ts.map