@thi.ng/geom-axidraw 0.2.0 → 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-29T20:56:59Z
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,17 @@ 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
+
12
23
  ## [0.2.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/geom-axidraw@0.2.0) (2022-12-29)
13
24
 
14
25
  #### 🚀 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/as-axidraw.js CHANGED
@@ -6,6 +6,7 @@ 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";
9
10
  import { takeNth } from "@thi.ng/transducers/take-nth";
10
11
  import { pointsByNearestNeighbor } from "./sort.js";
11
12
  /**
@@ -69,13 +70,15 @@ export const asAxiDraw = defmulti(__dispatch, {
69
70
  });
70
71
  function* __group($, opts) {
71
72
  const { skip, sort } = __axiAttribs($.attribs);
73
+ const sopts = __sampleAttribs(opts?.samples, $.attribs);
72
74
  const children = skip ? [...takeNth(skip + 1, $.children)] : $.children;
73
75
  const childrenIter = sort ? sort(children) : children;
74
76
  for (let child of childrenIter) {
75
77
  const shape = applyTransforms(child);
76
78
  shape.attribs = {
77
- ...shape.attribs,
78
79
  ...$.attribs,
80
+ ...shape.attribs,
81
+ __samples: __sampleAttribs(sopts, shape.attribs),
79
82
  };
80
83
  yield* asAxiDraw(shape, opts);
81
84
  }
@@ -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.2.0",
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,22 +34,22 @@
34
34
  "test": "testament test"
35
35
  },
36
36
  "dependencies": {
37
- "@thi.ng/api": "^8.6.2",
38
- "@thi.ng/arrays": "^2.5.0",
39
- "@thi.ng/axidraw": "^0.3.0",
40
- "@thi.ng/compare": "^2.1.21",
41
- "@thi.ng/defmulti": "^2.1.26",
42
- "@thi.ng/geom": "^4.1.1",
43
- "@thi.ng/geom-accel": "^3.2.32",
44
- "@thi.ng/geom-api": "^3.3.24",
45
- "@thi.ng/geom-clip-line": "^2.2.4",
46
- "@thi.ng/geom-isec": "^2.1.41",
47
- "@thi.ng/transducers": "^8.3.29",
48
- "@thi.ng/vectors": "^7.5.30"
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"
49
49
  },
50
50
  "devDependencies": {
51
51
  "@microsoft/api-extractor": "^7.33.7",
52
- "@thi.ng/testament": "^0.3.8",
52
+ "@thi.ng/testament": "^0.3.9",
53
53
  "rimraf": "^3.0.2",
54
54
  "tools": "^0.0.1",
55
55
  "typedoc": "^0.23.22",
@@ -106,6 +106,9 @@
106
106
  "./as-axidraw": {
107
107
  "default": "./as-axidraw.js"
108
108
  },
109
+ "./as-geometry": {
110
+ "default": "./as-geometry.js"
111
+ },
109
112
  "./sort": {
110
113
  "default": "./sort.js"
111
114
  }
@@ -118,5 +121,5 @@
118
121
  "status": "alpha",
119
122
  "year": 2022
120
123
  },
121
- "gitHead": "28bb74c67217a352d673b6efdab234921d4a370e\n"
124
+ "gitHead": "3f0b3e2a7c82aefc7e46fb4338369836b5e1b8cf\n"
122
125
  }