@thi.ng/geom-axidraw 0.1.3 → 0.3.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.
package/CHANGELOG.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Change Log
2
2
 
3
- - **Last updated**: 2022-12-22T21:47:07Z
3
+ - **Last updated**: 2023-01-10T15:20:18Z
4
4
  - **Generator**: [thi.ng/monopub](https://thi.ng/monopub)
5
5
 
6
6
  All notable changes to this project will be documented in this file.
@@ -9,6 +9,32 @@ See [Conventional Commits](https://conventionalcommits.org/) for commit guidelin
9
9
  **Note:** Unlisted _patch_ versions only involve non-code or otherwise excluded changes
10
10
  and/or version bumps of transitive dependencies.
11
11
 
12
+ ## [0.3.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/geom-axidraw@0.3.0) (2023-01-10)
13
+
14
+ #### 🚀 Features
15
+
16
+ - add asGeometry() command visualization ([78199ba](https://github.com/thi-ng/umbrella/commit/78199ba))
17
+
18
+ #### 🩹 Bug fixes
19
+
20
+ - update group attrib handling ([7f5d9a3](https://github.com/thi-ng/umbrella/commit/7f5d9a3))
21
+ - ensure `__samples` attrib is being properly merged
22
+
23
+ ## [0.2.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/geom-axidraw@0.2.0) (2022-12-29)
24
+
25
+ #### 🚀 Features
26
+
27
+ - add shapesByNearestNeighbor() ([0059766](https://github.com/thi-ng/umbrella/commit/0059766))
28
+ - add skip attrib ([4675151](https://github.com/thi-ng/umbrella/commit/4675151))
29
+ - update group & points conversion fns
30
+ - update deps
31
+
32
+ #### ♻️ Refactoring
33
+
34
+ - update pointsByNearestNeighbor() ([8a171e0](https://github.com/thi-ng/umbrella/commit/8a171e0))
35
+ - lift `accel` spatial index impl as arg
36
+ - update doc strings
37
+
12
38
  ## [0.1.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/geom-axidraw@0.1.0) (2022-12-10)
13
39
 
14
40
  #### 🚀 Features
package/README.md CHANGED
@@ -14,6 +14,7 @@ This project is part of the
14
14
  - [AxiDraw specific shape attributes](#axidraw-specific-shape-attributes)
15
15
  - [Shape interpolation/resampling](#shape-interpolationresampling)
16
16
  - [Draw order](#draw-order)
17
+ - [Command visualization](#command-visualization)
17
18
  - [Basic usage & examples](#basic-usage--examples)
18
19
  - [Interpolated polygons](#interpolated-polygons)
19
20
  - [Clipping](#clipping)
@@ -29,7 +30,8 @@ This project is part of the
29
30
 
30
31
  Conversion and preparation of thi.ng/geom shapes & shape groups to AxiDraw pen plotter draw commands. This is a support package for [@thi.ng/geom](https://github.com/thi-ng/umbrella/tree/develop/packages/geom).
31
32
 
32
- This package only deals with the conversion aspects. The
33
+ This package only deals with the (bi-directional) conversion aspects between
34
+ geometry and plotter commands. The
33
35
  [@thi.ng/axidraw](https://github.com/thi-ng/umbrella/blob/develop/packages/axidraw)
34
36
  is responsible for the actual plotter output...
35
37
 
@@ -73,6 +75,9 @@ any package-specific attribs must be stored under the `__axi` key:
73
75
  reset to globally configured default at the end of the shape.
74
76
  - `speed`: Speed factor (multiple of globally configured draw speed). Depending
75
77
  on pen used, slower speeds might result in thicker strokes.
78
+ - `skip`: Only used for groups or point clouds. If given, only every (n+1)th
79
+ child shape or point is being processed and the others ignored. Useful for low
80
+ detail test runs.
76
81
  - `sort`: Ordering function (in lieu of full path planning/optimization, which
77
82
  is planned for a later stage). For shapes other than `points()`, order of
78
83
  appearance is used by default.
@@ -105,9 +110,19 @@ Currently, the following ordering functions are available, but custom
105
110
  implementations can be provided too...
106
111
 
107
112
  - [`pointsByNearestNeighbor()`](https://docs.thi.ng/umbrella/geom-axidraw/functions/pointsByNearestNeighbor.html)
113
+ - [`shapesByNearestNeighbor()`](https://docs.thi.ng/umbrella/geom-axidraw/functions/shapesByNearestNeighbor.html)
108
114
  - [`pointsByProximity()`](https://docs.thi.ng/umbrella/geom-axidraw/functions/pointsByProximity.html)
109
115
  - [`shapesByProximity()`](https://docs.thi.ng/umbrella/geom-axidraw/functions/shapesByProximity.html)
110
116
 
117
+ ### Command visualization
118
+
119
+ For debug, optimization & visualization purposes it's useful to convert a
120
+ sequence of plotter commands back into 2D geometry. This can be done via the
121
+ supplied
122
+ [`asGeometry()`](https://docs.thi.ng/umbrella/geom-axidraw/functions/asGeometry.html)
123
+ function, which also takes several options to customize the resulting output.
124
+ One of the [examples](#clipping) below is demonstrating basic usage.
125
+
111
126
  ### Basic usage & examples
112
127
 
113
128
  The main function of this package is the polymorphic function
@@ -160,10 +175,18 @@ import { map, range } from "@thi.ng/transducers";
160
175
  (Result: https://mastodon.thi.ng/@toxi/109483553358349473)
161
176
 
162
177
  ```ts tangle:export/readme-clipping.ts
163
- import { AxiDraw, complete } from "@thi.ng/axidraw";
164
- import { circle, group, starWithCentroid, vertices } from "@thi.ng/geom";
165
- import { asAxiDraw } from "@thi.ng/geom-axidraw";
178
+ import { AxiDraw } from "@thi.ng/axidraw";
179
+ import {
180
+ asSvg,
181
+ circle,
182
+ group,
183
+ starWithCentroid,
184
+ svgDoc,
185
+ vertices,
186
+ } from "@thi.ng/geom";
187
+ import { asAxiDraw, asGeometry } from "@thi.ng/geom-axidraw";
166
188
  import { map, range } from "@thi.ng/transducers";
189
+ import { writeFileSync } from "fs";
167
190
 
168
191
  (async () => {
169
192
  const origin = [100, 100];
@@ -172,13 +195,26 @@ import { map, range } from "@thi.ng/transducers";
172
195
  // group of concentric circles using boundary as clip polygon
173
196
  const geo = group({}, [
174
197
  boundary,
175
- group({ __samples: 40, __axi: { clip: vertices(boundary) } }, [
198
+ group({ __samples: 60, __axi: { clip: vertices(boundary) } }, [
176
199
  ...map((r) => circle(origin, r), range(2, radius, 2)),
177
200
  ]),
178
201
  ]);
202
+
203
+ // convert into AxiDraw command sequence
204
+ const commands = [...asAxiDraw(geo)];
205
+
206
+ // now visualize command sequence (convert back to geometry, incl. pen movements)
207
+ const { paths, rapids, ups, downs } = asGeometry(commands);
208
+ // write visualization as SVG
209
+ writeFileSync(
210
+ "export/clipping-commands.svg",
211
+ asSvg(svgDoc({ width: 600, weight: 0.2 }, paths, rapids, ups, downs))
212
+ );
213
+
214
+ // actually connect & send to plotter
179
215
  const axi = new AxiDraw();
180
216
  await axi.connect();
181
- await axi.draw(asAxiDraw(geo));
217
+ await axi.draw(commands);
182
218
  })();
183
219
  ```
184
220
 
@@ -212,7 +248,7 @@ For Node.js REPL:
212
248
  const geomAxidraw = await import("@thi.ng/geom-axidraw");
213
249
  ```
214
250
 
215
- Package sizes (brotli'd, pre-treeshake): ESM: 856 bytes
251
+ Package sizes (brotli'd, pre-treeshake): ESM: 1.31 KB
216
252
 
217
253
  ## Dependencies
218
254
 
@@ -226,6 +262,7 @@ Package sizes (brotli'd, pre-treeshake): ESM: 856 bytes
226
262
  - [@thi.ng/geom-api](https://github.com/thi-ng/umbrella/tree/develop/packages/geom-api)
227
263
  - [@thi.ng/geom-clip-line](https://github.com/thi-ng/umbrella/tree/develop/packages/geom-clip-line)
228
264
  - [@thi.ng/geom-isec](https://github.com/thi-ng/umbrella/tree/develop/packages/geom-isec)
265
+ - [@thi.ng/transducers](https://github.com/thi-ng/umbrella/tree/develop/packages/transducers)
229
266
  - [@thi.ng/vectors](https://github.com/thi-ng/umbrella/tree/develop/packages/vectors)
230
267
 
231
268
  ## API
@@ -251,4 +288,4 @@ If this project contributes to an academic publication, please cite it as:
251
288
 
252
289
  ## License
253
290
 
254
- © 2022 Karsten Schmidt // Apache License 2.0
291
+ © 2022 - 2023 Karsten Schmidt // Apache License 2.0
package/api.d.ts CHANGED
@@ -52,6 +52,12 @@ export interface AxiDrawAttribs {
52
52
  * - {@link shapesByProximity} (for `group()`)
53
53
  */
54
54
  sort: PointOrdering | ShapeOrdering;
55
+ /**
56
+ * Only used for groups or point clouds. If given, only every (n+1)th child
57
+ * shape or point is being processed and the others ignored. Useful for low
58
+ * detail test runs.
59
+ */
60
+ skip: number;
55
61
  }
56
62
  export interface AsAxiDrawOpts {
57
63
  /**
package/as-axidraw.js CHANGED
@@ -6,6 +6,8 @@ import { pointInPolygon2 } from "@thi.ng/geom-isec/point";
6
6
  import { applyTransforms } from "@thi.ng/geom/apply-transforms";
7
7
  import { asPolyline } from "@thi.ng/geom/as-polyline";
8
8
  import { __dispatch } from "@thi.ng/geom/internal/dispatch";
9
+ import { __sampleAttribs } from "@thi.ng/geom/internal/vertices";
10
+ import { takeNth } from "@thi.ng/transducers/take-nth";
9
11
  import { pointsByNearestNeighbor } from "./sort.js";
10
12
  /**
11
13
  * Lazily converts given shape (or group) into an iterable of thi.ng/axidraw
@@ -67,13 +69,16 @@ export const asAxiDraw = defmulti(__dispatch, {
67
69
  group: ($, opts) => __group($, opts),
68
70
  });
69
71
  function* __group($, opts) {
70
- const { sort } = __axiAttribs($.attribs);
71
- const children = sort ? sort($.children) : $.children;
72
- for (let child of children) {
72
+ const { skip, sort } = __axiAttribs($.attribs);
73
+ const sopts = __sampleAttribs(opts?.samples, $.attribs);
74
+ const children = skip ? [...takeNth(skip + 1, $.children)] : $.children;
75
+ const childrenIter = sort ? sort(children) : children;
76
+ for (let child of childrenIter) {
73
77
  const shape = applyTransforms(child);
74
78
  shape.attribs = {
75
- ...shape.attribs,
76
79
  ...$.attribs,
80
+ ...shape.attribs,
81
+ __samples: __sampleAttribs(sopts, shape.attribs),
77
82
  };
78
83
  yield* asAxiDraw(shape, opts);
79
84
  }
@@ -81,7 +86,7 @@ function* __group($, opts) {
81
86
  function* __points(pts, attribs, opts) {
82
87
  if (!pts.length)
83
88
  return;
84
- const { clip, delayDown, delayUp, down, speed, sort } = {
89
+ const { clip, delayDown, delayUp, down, skip, speed, sort } = {
85
90
  sort: pointsByNearestNeighbor(),
86
91
  ...__axiAttribs(attribs),
87
92
  };
@@ -91,6 +96,9 @@ function* __points(pts, attribs, opts) {
91
96
  if (!pts.length)
92
97
  return;
93
98
  }
99
+ if (skip) {
100
+ pts = [...takeNth(skip + 1, pts)];
101
+ }
94
102
  yield UP;
95
103
  if (down != undefined)
96
104
  yield ["pen", down];
@@ -0,0 +1,47 @@
1
+ import type { DrawCommand } from "@thi.ng/axidraw";
2
+ import type { Attribs } from "@thi.ng/geom-api";
3
+ export interface AsGeometryOpts {
4
+ /**
5
+ * If true (default), records all movements whilst pen is up (otherwise only
6
+ * whilst pen is down)
7
+ */
8
+ rapids: boolean;
9
+ /**
10
+ * If true (default), records all pen up/down positions.
11
+ */
12
+ pen: boolean;
13
+ /**
14
+ * Attributes for result groups/pointclouds.
15
+ */
16
+ attribs: Partial<{
17
+ paths: Attribs;
18
+ rapids: Attribs;
19
+ ups: Attribs;
20
+ downs: Attribs;
21
+ }>;
22
+ }
23
+ /**
24
+ * Converts a sequence of
25
+ * [DrawCommands](https://docs.thi.ng/umbrella/axidraw/types/DrawCommand.html)
26
+ * into thi.ng/geom geometry. Returns an object of shapes. The conversion can be
27
+ * controlled via given options.
28
+ *
29
+ * @remarks
30
+ * The returned object contains groups & shapes which are being color coded by
31
+ * default:
32
+ *
33
+ * - `paths`: a group of polylines for which pen is down (#000)
34
+ * - `rapids`: a group of polylines for which pen is up (#0ff)
35
+ * - `ups`: a point cloud of positions where pen is being lifted (#0f0)
36
+ * - `downs`: a point cloud of positions where pen is being placed down (#f00)
37
+ *
38
+ * @param src
39
+ * @param opts
40
+ */
41
+ export declare const asGeometry: (src: Iterable<DrawCommand>, opts?: Partial<AsGeometryOpts>) => {
42
+ paths: import("@thi.ng/geom").Group;
43
+ rapids: import("@thi.ng/geom").Group;
44
+ ups: import("@thi.ng/geom").Points;
45
+ downs: import("@thi.ng/geom").Points;
46
+ };
47
+ //# sourceMappingURL=as-geometry.d.ts.map
package/as-geometry.js ADDED
@@ -0,0 +1,106 @@
1
+ import { group } from "@thi.ng/geom/group";
2
+ import { points } from "@thi.ng/geom/points";
3
+ import { polyline } from "@thi.ng/geom/polyline";
4
+ import { copy } from "@thi.ng/vectors";
5
+ const DEFAULT_ATTRIBS = {
6
+ paths: { stroke: "#000" },
7
+ rapids: { stroke: "#0ff" },
8
+ ups: { fill: "#0f0", stroke: "none" },
9
+ downs: { fill: "#f00", stroke: "none" },
10
+ };
11
+ /**
12
+ * Converts a sequence of
13
+ * [DrawCommands](https://docs.thi.ng/umbrella/axidraw/types/DrawCommand.html)
14
+ * into thi.ng/geom geometry. Returns an object of shapes. The conversion can be
15
+ * controlled via given options.
16
+ *
17
+ * @remarks
18
+ * The returned object contains groups & shapes which are being color coded by
19
+ * default:
20
+ *
21
+ * - `paths`: a group of polylines for which pen is down (#000)
22
+ * - `rapids`: a group of polylines for which pen is up (#0ff)
23
+ * - `ups`: a point cloud of positions where pen is being lifted (#0f0)
24
+ * - `downs`: a point cloud of positions where pen is being placed down (#f00)
25
+ *
26
+ * @param src
27
+ * @param opts
28
+ */
29
+ export const asGeometry = (src, opts = {}) => {
30
+ opts = {
31
+ rapids: true,
32
+ pen: true,
33
+ ...opts,
34
+ attribs: { ...DEFAULT_ATTRIBS, ...opts.attribs },
35
+ };
36
+ const rapids = [];
37
+ const paths = [];
38
+ const downs = [];
39
+ const ups = [];
40
+ let penDown = false;
41
+ let pts = null;
42
+ let currPos = [0, 0];
43
+ for (let cmd of src) {
44
+ switch (cmd[0]) {
45
+ case "m":
46
+ {
47
+ const newPos = copy(cmd[1]);
48
+ if (penDown || opts.rapids) {
49
+ if (!pts)
50
+ pts = [copy(currPos), newPos];
51
+ else
52
+ pts.push(newPos);
53
+ }
54
+ currPos = newPos;
55
+ }
56
+ break;
57
+ case "u":
58
+ if (pts) {
59
+ if (penDown)
60
+ paths.push(pts);
61
+ else if (opts.rapids)
62
+ rapids.push(pts);
63
+ pts = null;
64
+ }
65
+ if (opts.pen)
66
+ ups.push(copy(currPos));
67
+ penDown = false;
68
+ break;
69
+ case "d":
70
+ if (pts) {
71
+ if (!penDown) {
72
+ if (opts.rapids)
73
+ rapids.push(pts);
74
+ }
75
+ else
76
+ paths.push(pts);
77
+ pts = null;
78
+ }
79
+ if (opts.pen)
80
+ downs.push(copy(currPos));
81
+ penDown = true;
82
+ break;
83
+ case "home":
84
+ currPos = [0, 0];
85
+ if (!pts)
86
+ pts = [currPos];
87
+ else
88
+ pts.push(currPos);
89
+ break;
90
+ default:
91
+ console.log("skipping command", cmd);
92
+ }
93
+ }
94
+ if (pts) {
95
+ if (penDown)
96
+ paths.push(pts);
97
+ else
98
+ rapids.push(pts);
99
+ }
100
+ return {
101
+ paths: group(opts.attribs.paths, paths.map((pts) => polyline(pts))),
102
+ rapids: group(opts.attribs.rapids, rapids.map((pts) => polyline(pts))),
103
+ ups: points(ups, opts.attribs.ups),
104
+ downs: points(downs, opts.attribs.downs),
105
+ };
106
+ };
package/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export * from "./api.js";
2
2
  export * from "./as-axidraw.js";
3
+ export * from "./as-geometry.js";
3
4
  export * from "./sort.js";
4
5
  //# sourceMappingURL=index.d.ts.map
package/index.js CHANGED
@@ -1,3 +1,4 @@
1
1
  export * from "./api.js";
2
2
  export * from "./as-axidraw.js";
3
+ export * from "./as-geometry.js";
3
4
  export * from "./sort.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thi.ng/geom-axidraw",
3
- "version": "0.1.3",
3
+ "version": "0.3.0",
4
4
  "description": "Conversion and preparation of thi.ng/geom shapes & shape groups to AxiDraw pen plotter draw commands",
5
5
  "type": "module",
6
6
  "module": "./index.js",
@@ -34,21 +34,22 @@
34
34
  "test": "testament test"
35
35
  },
36
36
  "dependencies": {
37
- "@thi.ng/api": "^8.6.2",
38
- "@thi.ng/arrays": "^2.4.7",
39
- "@thi.ng/axidraw": "^0.2.3",
40
- "@thi.ng/compare": "^2.1.21",
41
- "@thi.ng/defmulti": "^2.1.26",
42
- "@thi.ng/geom": "^4.1.0",
43
- "@thi.ng/geom-accel": "^3.2.31",
44
- "@thi.ng/geom-api": "^3.3.23",
45
- "@thi.ng/geom-clip-line": "^2.2.3",
46
- "@thi.ng/geom-isec": "^2.1.40",
47
- "@thi.ng/vectors": "^7.5.29"
37
+ "@thi.ng/api": "^8.6.3",
38
+ "@thi.ng/arrays": "^2.5.1",
39
+ "@thi.ng/axidraw": "^0.4.0",
40
+ "@thi.ng/compare": "^2.1.22",
41
+ "@thi.ng/defmulti": "^2.1.27",
42
+ "@thi.ng/geom": "^4.2.0",
43
+ "@thi.ng/geom-accel": "^3.2.33",
44
+ "@thi.ng/geom-api": "^3.4.0",
45
+ "@thi.ng/geom-clip-line": "^2.3.0",
46
+ "@thi.ng/geom-isec": "^2.1.42",
47
+ "@thi.ng/transducers": "^8.3.30",
48
+ "@thi.ng/vectors": "^7.5.31"
48
49
  },
49
50
  "devDependencies": {
50
51
  "@microsoft/api-extractor": "^7.33.7",
51
- "@thi.ng/testament": "^0.3.8",
52
+ "@thi.ng/testament": "^0.3.9",
52
53
  "rimraf": "^3.0.2",
53
54
  "tools": "^0.0.1",
54
55
  "typedoc": "^0.23.22",
@@ -105,6 +106,9 @@
105
106
  "./as-axidraw": {
106
107
  "default": "./as-axidraw.js"
107
108
  },
109
+ "./as-geometry": {
110
+ "default": "./as-geometry.js"
111
+ },
108
112
  "./sort": {
109
113
  "default": "./sort.js"
110
114
  }
@@ -117,5 +121,5 @@
117
121
  "status": "alpha",
118
122
  "year": 2022
119
123
  },
120
- "gitHead": "bc6f7f5e2765bb96fe64db804eaf4b2443b47fc6\n"
124
+ "gitHead": "3f0b3e2a7c82aefc7e46fb4338369836b5e1b8cf\n"
121
125
  }
package/sort.d.ts CHANGED
@@ -1,19 +1,22 @@
1
+ import type { IRegionQuery, IShape, ISpatialMap, ISpatialSet } from "@thi.ng/geom-api";
1
2
  import { ReadonlyVec } from "@thi.ng/vectors/api";
2
3
  import type { PointOrdering, ShapeOrdering } from "./api.js";
3
4
  /**
4
- * Higher order point ordering fn. Lazily sorts points by nearest neighbor
5
+ * Higher order point ordering fn. Adds points to given spatial
6
+ * index/acceleration structure and then lazily sorts them by nearest neighbor
5
7
  * distance, starting selection of first point based on given `ref` point
6
8
  * (default: [0, 0]).
7
9
  *
8
10
  * @remarks
9
- * Internally uses a
11
+ * By default is using a
10
12
  * [`KdTreeSet`](https://docs.thi.ng/umbrella/geom-accel/classes/KdTreeSet.html)
11
13
  * to index all points and then successively perform efficient nearest neighbor
12
14
  * searches (always w.r.t the most recent result point).
13
15
  *
16
+ * @param accel
14
17
  * @param ref
15
18
  */
16
- export declare const pointsByNearestNeighbor: (ref?: ReadonlyVec) => PointOrdering;
19
+ export declare const pointsByNearestNeighbor: (accel?: ISpatialSet<ReadonlyVec> & IRegionQuery<ReadonlyVec, ReadonlyVec, number>, ref?: ReadonlyVec) => PointOrdering;
17
20
  /**
18
21
  * Higher order point ordering fn. Sorts points by proximity to given `ref` point
19
22
  * (default: [0, 0]).
@@ -28,4 +31,19 @@ export declare const pointsByProximity: (ref?: ReadonlyVec) => PointOrdering;
28
31
  * @param ref
29
32
  */
30
33
  export declare const shapesByProximity: (ref?: ReadonlyVec) => ShapeOrdering;
34
+ /**
35
+ * Similar to {@link pointsByNearestNeighbor}, however for shapes and requiring
36
+ * an
37
+ * [`ISpatialMap`](https://docs.thi.ng/umbrella/geom-api/interfaces/ISpatialMap.html)
38
+ * implementation and is using shape centroid (auto-computed) to perform
39
+ * indexing and nearest neighbor queries.
40
+ *
41
+ * @remarks
42
+ * Currently recommended to use
43
+ * [`NdQuadtreeMap`](https://docs.thi.ng/umbrella/geom-accel/classes/NdQuadtreeMap.html).
44
+ *
45
+ * @param accel
46
+ * @param ref
47
+ */
48
+ export declare const shapesByNearestNeighbor: (accel: ISpatialMap<ReadonlyVec, IShape> & IRegionQuery<ReadonlyVec, IShape, number>, ref?: ReadonlyVec) => ShapeOrdering;
31
49
  //# sourceMappingURL=sort.d.ts.map
package/sort.js CHANGED
@@ -5,23 +5,26 @@ import { centroid } from "@thi.ng/geom/centroid";
5
5
  import { ZERO2 } from "@thi.ng/vectors/api";
6
6
  import { distSq2 } from "@thi.ng/vectors/distsq";
7
7
  /**
8
- * Higher order point ordering fn. Lazily sorts points by nearest neighbor
8
+ * Higher order point ordering fn. Adds points to given spatial
9
+ * index/acceleration structure and then lazily sorts them by nearest neighbor
9
10
  * distance, starting selection of first point based on given `ref` point
10
11
  * (default: [0, 0]).
11
12
  *
12
13
  * @remarks
13
- * Internally uses a
14
+ * By default is using a
14
15
  * [`KdTreeSet`](https://docs.thi.ng/umbrella/geom-accel/classes/KdTreeSet.html)
15
16
  * to index all points and then successively perform efficient nearest neighbor
16
17
  * searches (always w.r.t the most recent result point).
17
18
  *
19
+ * @param accel
18
20
  * @param ref
19
21
  */
20
- export const pointsByNearestNeighbor = (ref = ZERO2) => function* (pts) {
21
- const index = new KdTreeSet(2, pts);
22
- while (index.size) {
23
- ref = index.queryKeys(ref, 1e4, 1)[0];
24
- index.remove(ref);
22
+ export const pointsByNearestNeighbor = (accel = new KdTreeSet(2), ref = ZERO2) => function* (pts) {
23
+ accel.into(pts);
24
+ // const index = new KdTreeSet(2, pts);
25
+ while (accel.size) {
26
+ ref = accel.queryKeys(ref, 1e4, 1)[0];
27
+ accel.remove(ref);
25
28
  yield ref;
26
29
  }
27
30
  };
@@ -43,3 +46,26 @@ export const pointsByProximity = (ref = ZERO2) => (pts) => {
43
46
  export const shapesByProximity = (ref = ZERO2) => (shapes) => {
44
47
  return sortByCachedKey(shapes.slice(), (s) => distSq2(centroid(s) || ZERO2, ref), compareNumAsc);
45
48
  };
49
+ /**
50
+ * Similar to {@link pointsByNearestNeighbor}, however for shapes and requiring
51
+ * an
52
+ * [`ISpatialMap`](https://docs.thi.ng/umbrella/geom-api/interfaces/ISpatialMap.html)
53
+ * implementation and is using shape centroid (auto-computed) to perform
54
+ * indexing and nearest neighbor queries.
55
+ *
56
+ * @remarks
57
+ * Currently recommended to use
58
+ * [`NdQuadtreeMap`](https://docs.thi.ng/umbrella/geom-accel/classes/NdQuadtreeMap.html).
59
+ *
60
+ * @param accel
61
+ * @param ref
62
+ */
63
+ export const shapesByNearestNeighbor = (accel, ref = ZERO2) => function* (shapes) {
64
+ accel.into(shapes.map((s) => [centroid(s) || [0, 0], s]));
65
+ while (accel.size) {
66
+ const pair = accel.query(ref, 1e4, 1)[0];
67
+ ref = pair[0];
68
+ accel.remove(ref);
69
+ yield pair[1];
70
+ }
71
+ };