@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 +12 -1
- package/README.md +49 -10
- 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 +19 -16
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
-
- **Last updated**:
|
|
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
|
|
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
|
+

|
|
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
|
|
164
|
-
import {
|
|
165
|
-
|
|
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:
|
|
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(
|
|
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:
|
|
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
|
}
|
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,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thi.ng/geom-axidraw",
|
|
3
|
-
"version": "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.
|
|
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": "02425e5d92d381af664430d56609ee82948b4f59\n"
|
|
122
125
|
}
|