@thi.ng/geom-sdf 0.3.33 → 0.4.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 +15 -1
- package/README.md +24 -3
- package/as-sdf.d.ts +2 -1
- package/as-sdf.js +25 -5
- package/bounds.js +2 -4
- package/dist.js +1 -2
- package/ops.js +9 -18
- package/package.json +18 -18
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
-
- **Last updated**: 2024-
|
|
3
|
+
- **Last updated**: 2024-05-08T18:24:32Z
|
|
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,20 @@ 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.4.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/geom-sdf@0.4.0) (2024-05-08)
|
|
13
|
+
|
|
14
|
+
#### 🚀 Features
|
|
15
|
+
|
|
16
|
+
- add rdom-klist example project, update readmes ([cd458ac](https://github.com/thi-ng/umbrella/commit/cd458ac))
|
|
17
|
+
- add rdom-klist example project, update readmes ([531437f](https://github.com/thi-ng/umbrella/commit/531437f))
|
|
18
|
+
- support path & complexpoly sub-shapes in asSDF() ([e924dc2](https://github.com/thi-ng/umbrella/commit/e924dc2))
|
|
19
|
+
|
|
20
|
+
#### ♻️ Refactoring
|
|
21
|
+
|
|
22
|
+
- update internal polyline handling ([f758425](https://github.com/thi-ng/umbrella/commit/f758425))
|
|
23
|
+
- add/update asSDF() impls for ComplexPoly & Path ([3337a0e](https://github.com/thi-ng/umbrella/commit/3337a0e))
|
|
24
|
+
- update docs
|
|
25
|
+
|
|
12
26
|
## [0.3.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/geom-sdf@0.3.0) (2024-01-23)
|
|
13
27
|
|
|
14
28
|
#### 🚀 Features
|
package/README.md
CHANGED
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
- [About](#about)
|
|
18
18
|
- [SDF creation](#sdf-creation)
|
|
19
|
+
- [Supported thi.ng/geom shape types](#supported-thinggeom-shape-types)
|
|
19
20
|
- [SDF combinators](#sdf-combinators)
|
|
20
21
|
- [SDF discretization, sampling & domain modifiers](#sdf-discretization-sampling--domain-modifiers)
|
|
21
22
|
- [Status](#status)
|
|
@@ -60,6 +61,25 @@ import { asSDF } from "@thi.ng/geom-sdf";
|
|
|
60
61
|
const f = asSDF(group({}, [circle([-50, 0], 100), circle([50, 0], 100)]));
|
|
61
62
|
```
|
|
62
63
|
|
|
64
|
+
### Supported thi.ng/geom shape types
|
|
65
|
+
|
|
66
|
+
([shape type descriptions](https://github.com/thi-ng/umbrella/blob/develop/packages/geom/README.md#shape-types))
|
|
67
|
+
|
|
68
|
+
- circle
|
|
69
|
+
- complexPoly (polygon w/ holes)
|
|
70
|
+
- cubic
|
|
71
|
+
- ellipse
|
|
72
|
+
- group (of supported shapes)
|
|
73
|
+
- line
|
|
74
|
+
- path (w/ holes and/or sub-paths, multiple curves)
|
|
75
|
+
- points
|
|
76
|
+
- polygon
|
|
77
|
+
- polyline
|
|
78
|
+
- quad
|
|
79
|
+
- quadratic
|
|
80
|
+
- rect
|
|
81
|
+
- triangle
|
|
82
|
+
|
|
63
83
|
### SDF combinators
|
|
64
84
|
|
|
65
85
|
The following table illustrates various options how SDFs can be combined. When
|
|
@@ -147,7 +167,7 @@ For Node.js REPL:
|
|
|
147
167
|
const sdf = await import("@thi.ng/geom-sdf");
|
|
148
168
|
```
|
|
149
169
|
|
|
150
|
-
Package sizes (brotli'd, pre-treeshake): ESM: 3.
|
|
170
|
+
Package sizes (brotli'd, pre-treeshake): ESM: 3.76 KB
|
|
151
171
|
|
|
152
172
|
## Dependencies
|
|
153
173
|
|
|
@@ -166,13 +186,14 @@ Package sizes (brotli'd, pre-treeshake): ESM: 3.65 KB
|
|
|
166
186
|
|
|
167
187
|
## Usage examples
|
|
168
188
|
|
|
169
|
-
|
|
189
|
+
Several projects in this repo's
|
|
170
190
|
[/examples](https://github.com/thi-ng/umbrella/tree/develop/examples)
|
|
171
|
-
directory
|
|
191
|
+
directory are using this package:
|
|
172
192
|
|
|
173
193
|
| Screenshot | Description | Live demo | Source |
|
|
174
194
|
|:---------------------------------------------------------------------------------------------------------------------|:------------------------------------------------------------------|:----------------------------------------------------|:---------------------------------------------------------------------------------|
|
|
175
195
|
| <img src="https://raw.githubusercontent.com/thi-ng/umbrella/develop/assets/examples/geom-sdf-logo.jpg" width="240"/> | (Re)Constructing the thi.ng logo using a 2D signed-distance field | [Demo](https://demo.thi.ng/umbrella/geom-sdf-logo/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/geom-sdf-logo) |
|
|
196
|
+
| <img src="https://raw.githubusercontent.com/thi-ng/umbrella/develop/assets/examples/geom-sdf-path.png" width="240"/> | SVG path to SDF, applying deformation and converting back to SVG | [Demo](https://demo.thi.ng/umbrella/geom-sdf-path/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/geom-sdf-path) |
|
|
176
197
|
|
|
177
198
|
## API
|
|
178
199
|
|
package/as-sdf.d.ts
CHANGED
|
@@ -13,10 +13,11 @@ import type { SDFn } from "./api.js";
|
|
|
13
13
|
*
|
|
14
14
|
* - circle
|
|
15
15
|
* - cubic (auto-converted to polyline)
|
|
16
|
+
* - complexpoly (boundary only, holes ignored)
|
|
16
17
|
* - ellipse
|
|
17
18
|
* - group
|
|
18
19
|
* - line
|
|
19
|
-
* - path (auto-converted to polygon
|
|
20
|
+
* - path (auto-converted to polyline or complex polygon)
|
|
20
21
|
* - points
|
|
21
22
|
* - polygon
|
|
22
23
|
* - polyline
|
package/as-sdf.js
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { DEFAULT, defmulti } from "@thi.ng/defmulti/defmulti";
|
|
2
2
|
import { assert } from "@thi.ng/errors/assert";
|
|
3
3
|
import { unsupported } from "@thi.ng/errors/unsupported";
|
|
4
|
+
import { Path } from "@thi.ng/geom/api/path";
|
|
5
|
+
import { Polygon } from "@thi.ng/geom/api/polygon";
|
|
4
6
|
import { asPolygon } from "@thi.ng/geom/as-polygon";
|
|
5
7
|
import { asPolyline } from "@thi.ng/geom/as-polyline";
|
|
6
|
-
import { simplify } from "@thi.ng/geom/simplify";
|
|
7
8
|
import { __dispatch } from "@thi.ng/geom/internal/dispatch";
|
|
9
|
+
import { simplify } from "@thi.ng/geom/simplify";
|
|
10
|
+
import { withAttribs } from "@thi.ng/geom/with-attribs";
|
|
8
11
|
import { add2 } from "@thi.ng/vectors/add";
|
|
9
12
|
import { mulN2 } from "@thi.ng/vectors/muln";
|
|
10
13
|
import {
|
|
@@ -25,9 +28,9 @@ import {
|
|
|
25
28
|
union
|
|
26
29
|
} from "./ops.js";
|
|
27
30
|
import {
|
|
31
|
+
DEFAULT_ATTRIBS,
|
|
28
32
|
box2,
|
|
29
33
|
circle2,
|
|
30
|
-
DEFAULT_ATTRIBS,
|
|
31
34
|
ellipse2,
|
|
32
35
|
line2,
|
|
33
36
|
points2,
|
|
@@ -45,9 +48,14 @@ const asSDF = defmulti(
|
|
|
45
48
|
{
|
|
46
49
|
[DEFAULT]: ($) => unsupported(`shape type: ${$.type}`),
|
|
47
50
|
circle: ($) => circle2($.pos, $.r, __sdfAttribs($.attribs)),
|
|
51
|
+
complexpoly: ($) => diff(
|
|
52
|
+
[$.boundary, ...$.children].map(
|
|
53
|
+
(poly) => asSDF(withAttribs(poly, $.attribs))
|
|
54
|
+
)
|
|
55
|
+
),
|
|
48
56
|
cubic: ($) => asSDF(
|
|
49
57
|
simplify(
|
|
50
|
-
asPolyline($, (__sdfAttribs($.attribs) || {}).samples),
|
|
58
|
+
asPolyline($, (__sdfAttribs($.attribs) || {}).samples)[0],
|
|
51
59
|
0
|
|
52
60
|
)
|
|
53
61
|
),
|
|
@@ -96,9 +104,21 @@ const asSDF = defmulti(
|
|
|
96
104
|
line: ({ points: [a, b], attribs }) => line2(a, b, __sdfAttribs(attribs)),
|
|
97
105
|
path: ($) => {
|
|
98
106
|
const n = (__sdfAttribs($.attribs) || {}).samples;
|
|
99
|
-
|
|
100
|
-
|
|
107
|
+
const path = new Path($.segments, [], $.attribs);
|
|
108
|
+
const boundary = asSDF(
|
|
109
|
+
simplify(
|
|
110
|
+
$.closed ? asPolygon(path, n)[0] : asPolyline(path, n)[0],
|
|
111
|
+
0
|
|
112
|
+
)
|
|
101
113
|
);
|
|
114
|
+
if (!$.subPaths.length) return boundary;
|
|
115
|
+
const fields = [
|
|
116
|
+
boundary,
|
|
117
|
+
...$.subPaths.map(
|
|
118
|
+
(segments) => asSDF(new Path(segments, [], $.attribs))
|
|
119
|
+
)
|
|
120
|
+
];
|
|
121
|
+
return $.closed ? diff(fields) : union(fields);
|
|
102
122
|
},
|
|
103
123
|
points: ($) => points2($.points, __sdfAttribs($.attribs)),
|
|
104
124
|
poly: ($) => polygon2($.points, __sdfAttribs($.attribs)),
|
package/bounds.js
CHANGED
|
@@ -7,8 +7,7 @@ function withBoundingCircle(sdf, ...args) {
|
|
|
7
7
|
let [[cx, cy], r] = args.length === 1 ? boundingCircle(args[0]) : args;
|
|
8
8
|
r *= r;
|
|
9
9
|
return (p, minD = Infinity) => {
|
|
10
|
-
if (minD === Infinity)
|
|
11
|
-
return sdf(p, minD);
|
|
10
|
+
if (minD === Infinity) return sdf(p, minD);
|
|
12
11
|
const dx = p[0] - cx;
|
|
13
12
|
const dy = p[1] - cy;
|
|
14
13
|
return dx * dx + dy * dy - r < minD * minD ? sdf(p, minD) : minD;
|
|
@@ -20,8 +19,7 @@ function withBoundingRect(sdf, ...args) {
|
|
|
20
19
|
const hSize = submN2([], max, min, 0.5);
|
|
21
20
|
const t = [0, 0];
|
|
22
21
|
return (p, minD = Infinity) => {
|
|
23
|
-
if (minD === Infinity)
|
|
24
|
-
return sdf(p, minD);
|
|
22
|
+
if (minD === Infinity) return sdf(p, minD);
|
|
25
23
|
return distBox2(sub2(t, p, centroid), hSize) < minD ? sdf(p, minD) : minD;
|
|
26
24
|
};
|
|
27
25
|
}
|
package/dist.js
CHANGED
|
@@ -39,8 +39,7 @@ const distPolygon2 = (p, pts) => {
|
|
|
39
39
|
const w = sub2(t2, p, pi);
|
|
40
40
|
d = min(d, distSq2(w, mulN2(t3, e, clamp01(dot2(w, e) / magSq2(e)))));
|
|
41
41
|
const c = [py >= pi[1], py < pj[1], e[0] * w[1] > e[1] * w[0]];
|
|
42
|
-
if (every3(c) || !some3(c))
|
|
43
|
-
s *= -1;
|
|
42
|
+
if (every3(c) || !some3(c)) s *= -1;
|
|
44
43
|
}
|
|
45
44
|
return s * sqrt(d);
|
|
46
45
|
};
|
package/ops.js
CHANGED
|
@@ -22,18 +22,13 @@ const withSDFModifiers = (fn, mods) => {
|
|
|
22
22
|
min: $min2,
|
|
23
23
|
max: $max2
|
|
24
24
|
} = { ...DEFAULT_MODS, ...mods };
|
|
25
|
-
if ($abs2)
|
|
26
|
-
|
|
27
|
-
if (
|
|
28
|
-
fn = offset(fn, $offset);
|
|
29
|
-
if ($flip)
|
|
30
|
-
fn = flip(fn);
|
|
25
|
+
if ($abs2) fn = abs(fn);
|
|
26
|
+
if (isFunction($offset) || $offset > 0) fn = offset(fn, $offset);
|
|
27
|
+
if ($flip) fn = flip(fn);
|
|
31
28
|
if ($min2 >= -Infinity) {
|
|
32
|
-
if ($max2 < Infinity)
|
|
33
|
-
return clamp(fn, $min2, $max2);
|
|
29
|
+
if ($max2 < Infinity) return clamp(fn, $min2, $max2);
|
|
34
30
|
fn = max(fn, $min2);
|
|
35
|
-
} else if ($max2 < Infinity)
|
|
36
|
-
fn = min(fn, $max2);
|
|
31
|
+
} else if ($max2 < Infinity) fn = min(fn, $max2);
|
|
37
32
|
return fn;
|
|
38
33
|
};
|
|
39
34
|
const abs = (sdf) => (p, minD) => $abs(sdf(p, minD));
|
|
@@ -47,12 +42,10 @@ const defOp = (op) => (children) => {
|
|
|
47
42
|
const n = children.length;
|
|
48
43
|
return (p, minD = Infinity) => {
|
|
49
44
|
let res = children[0](p, minD);
|
|
50
|
-
if (res < minD)
|
|
51
|
-
minD = res;
|
|
45
|
+
if (res < minD) minD = res;
|
|
52
46
|
for (let i = 1; i < n; i++) {
|
|
53
47
|
const d = children[i](p, minD);
|
|
54
|
-
if (d < minD)
|
|
55
|
-
minD = d;
|
|
48
|
+
if (d < minD) minD = d;
|
|
56
49
|
res = op(res, d);
|
|
57
50
|
}
|
|
58
51
|
return res;
|
|
@@ -68,12 +61,10 @@ const defParamOp = (op) => (k, children) => {
|
|
|
68
61
|
return (p, minD = Infinity) => {
|
|
69
62
|
const $k = kfield(p);
|
|
70
63
|
let res = children[0](p, minD);
|
|
71
|
-
if (res < minD)
|
|
72
|
-
minD = res;
|
|
64
|
+
if (res < minD) minD = res;
|
|
73
65
|
for (let i = 1; i < n; i++) {
|
|
74
66
|
const d = children[i](p, minD);
|
|
75
|
-
if (d < minD)
|
|
76
|
-
minD = d;
|
|
67
|
+
if (d < minD) minD = d;
|
|
77
68
|
res = op(res, d, $k);
|
|
78
69
|
}
|
|
79
70
|
return res;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thi.ng/geom-sdf",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "2D Signed Distance Field creation from @thi.ng/geom shapes, conversions, sampling, combinators",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "./index.js",
|
|
@@ -36,24 +36,24 @@
|
|
|
36
36
|
"tool:tangle": "../../node_modules/.bin/tangle src/**/*.ts"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@thi.ng/api": "^8.11.
|
|
40
|
-
"@thi.ng/checks": "^3.6.
|
|
41
|
-
"@thi.ng/defmulti": "^3.0.
|
|
42
|
-
"@thi.ng/errors": "^2.5.
|
|
43
|
-
"@thi.ng/geom": "^
|
|
44
|
-
"@thi.ng/geom-api": "^4.0.
|
|
45
|
-
"@thi.ng/geom-isoline": "^2.1.
|
|
46
|
-
"@thi.ng/geom-poly-utils": "^2.
|
|
47
|
-
"@thi.ng/geom-resample": "^2.3.
|
|
48
|
-
"@thi.ng/math": "^5.10.
|
|
49
|
-
"@thi.ng/transducers": "^9.0.
|
|
50
|
-
"@thi.ng/vectors": "^7.10.
|
|
39
|
+
"@thi.ng/api": "^8.11.2",
|
|
40
|
+
"@thi.ng/checks": "^3.6.4",
|
|
41
|
+
"@thi.ng/defmulti": "^3.0.39",
|
|
42
|
+
"@thi.ng/errors": "^2.5.7",
|
|
43
|
+
"@thi.ng/geom": "^7.0.1",
|
|
44
|
+
"@thi.ng/geom-api": "^4.0.10",
|
|
45
|
+
"@thi.ng/geom-isoline": "^2.1.127",
|
|
46
|
+
"@thi.ng/geom-poly-utils": "^2.4.0",
|
|
47
|
+
"@thi.ng/geom-resample": "^2.3.53",
|
|
48
|
+
"@thi.ng/math": "^5.10.13",
|
|
49
|
+
"@thi.ng/transducers": "^9.0.5",
|
|
50
|
+
"@thi.ng/vectors": "^7.10.31"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
|
-
"@microsoft/api-extractor": "^7.43.
|
|
54
|
-
"esbuild": "^0.
|
|
55
|
-
"typedoc": "^0.25.
|
|
56
|
-
"typescript": "^5.4.
|
|
53
|
+
"@microsoft/api-extractor": "^7.43.2",
|
|
54
|
+
"esbuild": "^0.21.1",
|
|
55
|
+
"typedoc": "^0.25.13",
|
|
56
|
+
"typescript": "^5.4.5"
|
|
57
57
|
},
|
|
58
58
|
"keywords": [
|
|
59
59
|
"2d",
|
|
@@ -128,5 +128,5 @@
|
|
|
128
128
|
"status": "alpha",
|
|
129
129
|
"year": 2022
|
|
130
130
|
},
|
|
131
|
-
"gitHead": "
|
|
131
|
+
"gitHead": "41bd769068da804eeace622ec7db50e4d48f1dc9\n"
|
|
132
132
|
}
|