@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 +12 -1
- package/README.md +45 -8
- package/as-axidraw.js +4 -1
- package/as-geometry.d.ts +47 -0
- package/as-geometry.js +106 -0
- package/index.d.ts +1 -0
- package/index.js +1 -0
- package/package.json +18 -15
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
-
- **Last updated**:
|
|
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
|
|
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
|
|
164
|
-
import {
|
|
165
|
-
|
|
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:
|
|
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(
|
|
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:
|
|
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
|
}
|
package/as-geometry.d.ts
ADDED
|
@@ -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
package/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thi.ng/geom-axidraw",
|
|
3
|
-
"version": "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.
|
|
38
|
-
"@thi.ng/arrays": "^2.5.
|
|
39
|
-
"@thi.ng/axidraw": "^0.
|
|
40
|
-
"@thi.ng/compare": "^2.1.
|
|
41
|
-
"@thi.ng/defmulti": "^2.1.
|
|
42
|
-
"@thi.ng/geom": "^4.
|
|
43
|
-
"@thi.ng/geom-accel": "^3.2.
|
|
44
|
-
"@thi.ng/geom-api": "^3.
|
|
45
|
-
"@thi.ng/geom-clip-line": "^2.
|
|
46
|
-
"@thi.ng/geom-isec": "^2.1.
|
|
47
|
-
"@thi.ng/transducers": "^8.3.
|
|
48
|
-
"@thi.ng/vectors": "^7.5.
|
|
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.
|
|
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": "
|
|
124
|
+
"gitHead": "3f0b3e2a7c82aefc7e46fb4338369836b5e1b8cf\n"
|
|
122
125
|
}
|