@thi.ng/geom-axidraw 0.2.0 → 0.3.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.
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-17T10:57:27Z
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)
@@ -27,11 +28,12 @@ This project is part of the
27
28
 
28
29
  ## About
29
30
 
30
- 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
+ Conversion and preparation of thi.ng/geom shapes & shape groups to/from 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
- is responsible for the actual plotter output...
36
+ package is responsible for the actual plotter output...
35
37
 
36
38
  ### Supported shape types
37
39
 
@@ -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,21 @@ 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
+
126
+ ![Example draw command visualization based on the code example in this readme](https://raw.githubusercontent.com/thi-ng/umbrella/develop/assets/geom-axidraw/readme-commands.png)
127
+
111
128
  ### Basic usage & examples
112
129
 
113
130
  The main function of this package is the polymorphic function
@@ -160,10 +177,18 @@ import { map, range } from "@thi.ng/transducers";
160
177
  (Result: https://mastodon.thi.ng/@toxi/109483553358349473)
161
178
 
162
179
  ```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";
180
+ import { AxiDraw } from "@thi.ng/axidraw";
181
+ import {
182
+ asSvg,
183
+ circle,
184
+ group,
185
+ starWithCentroid,
186
+ svgDoc,
187
+ vertices,
188
+ } from "@thi.ng/geom";
189
+ import { asAxiDraw, asGeometry } from "@thi.ng/geom-axidraw";
166
190
  import { map, range } from "@thi.ng/transducers";
191
+ import { writeFileSync } from "fs";
167
192
 
168
193
  (async () => {
169
194
  const origin = [100, 100];
@@ -172,13 +197,26 @@ import { map, range } from "@thi.ng/transducers";
172
197
  // group of concentric circles using boundary as clip polygon
173
198
  const geo = group({}, [
174
199
  boundary,
175
- group({ __samples: 40, __axi: { clip: vertices(boundary) } }, [
200
+ group({ __samples: 60, __axi: { clip: vertices(boundary) } }, [
176
201
  ...map((r) => circle(origin, r), range(2, radius, 2)),
177
202
  ]),
178
203
  ]);
204
+
205
+ // convert into AxiDraw command sequence
206
+ const commands = [...asAxiDraw(geo)];
207
+
208
+ // now visualize command sequence (convert back to geometry, incl. pen movements)
209
+ const { paths, rapids, ups, downs } = asGeometry(commands);
210
+ // write visualization as SVG
211
+ writeFileSync(
212
+ "export/clipping-commands.svg",
213
+ asSvg(svgDoc({ width: 600, weight: 0.2 }, paths, rapids, ups, downs))
214
+ );
215
+
216
+ // actually connect & send to plotter
179
217
  const axi = new AxiDraw();
180
218
  await axi.connect();
181
- await axi.draw(asAxiDraw(geo));
219
+ await axi.draw(commands);
182
220
  })();
183
221
  ```
184
222
 
@@ -212,7 +250,7 @@ For Node.js REPL:
212
250
  const geomAxidraw = await import("@thi.ng/geom-axidraw");
213
251
  ```
214
252
 
215
- Package sizes (brotli'd, pre-treeshake): ESM: 856 bytes
253
+ Package sizes (brotli'd, pre-treeshake): ESM: 1.31 KB
216
254
 
217
255
  ## Dependencies
218
256
 
@@ -226,6 +264,7 @@ Package sizes (brotli'd, pre-treeshake): ESM: 856 bytes
226
264
  - [@thi.ng/geom-api](https://github.com/thi-ng/umbrella/tree/develop/packages/geom-api)
227
265
  - [@thi.ng/geom-clip-line](https://github.com/thi-ng/umbrella/tree/develop/packages/geom-clip-line)
228
266
  - [@thi.ng/geom-isec](https://github.com/thi-ng/umbrella/tree/develop/packages/geom-isec)
267
+ - [@thi.ng/transducers](https://github.com/thi-ng/umbrella/tree/develop/packages/transducers)
229
268
  - [@thi.ng/vectors](https://github.com/thi-ng/umbrella/tree/develop/packages/vectors)
230
269
 
231
270
  ## API
@@ -251,4 +290,4 @@ If this project contributes to an academic publication, please cite it as:
251
290
 
252
291
  ## License
253
292
 
254
- © 2022 Karsten Schmidt // Apache License 2.0
293
+ © 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,7 +1,7 @@
1
1
  {
2
2
  "name": "@thi.ng/geom-axidraw",
3
- "version": "0.2.0",
4
- "description": "Conversion and preparation of thi.ng/geom shapes & shape groups to AxiDraw pen plotter draw commands",
3
+ "version": "0.3.1",
4
+ "description": "Conversion and preparation of thi.ng/geom shapes & shape groups to/from AxiDraw pen plotter draw commands",
5
5
  "type": "module",
6
6
  "module": "./index.js",
7
7
  "typings": "./index.d.ts",
@@ -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": "02425e5d92d381af664430d56609ee82948b4f59\n"
122
125
  }