@thi.ng/geom-tessellate 2.1.131 → 3.0.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 +47 -1
- package/README.md +162 -8
- package/api.d.ts +81 -0
- package/api.js +0 -0
- package/earcut-complex.d.ts +74 -0
- package/earcut-complex.js +415 -0
- package/earcut.d.ts +2 -7
- package/earcut.js +28 -26
- package/edge-split.d.ts +8 -1
- package/edge-split.js +11 -23
- package/index.d.ts +5 -0
- package/index.js +5 -0
- package/inset.d.ts +2 -2
- package/inset.js +11 -19
- package/package.json +33 -14
- package/quad-fan.d.ts +1 -1
- package/quad-fan.js +13 -17
- package/rim-tris.d.ts +1 -1
- package/rim-tris.js +21 -26
- package/tessellate.d.ts +7 -4
- package/tessellate.js +24 -17
- package/tessellation.d.ts +26 -0
- package/tessellation.js +59 -0
- package/tri-fan-boundary.d.ts +3 -0
- package/tri-fan-boundary.js +11 -0
- package/tri-fan-split.d.ts +9 -0
- package/tri-fan-split.js +26 -0
- package/tri-fan.d.ts +1 -1
- package/tri-fan.js +7 -16
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thi.ng/geom-tessellate",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "2D/3D convex polygon tessellators",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "./index.js",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"type": "git",
|
|
11
11
|
"url": "https://github.com/thi-ng/umbrella.git"
|
|
12
12
|
},
|
|
13
|
-
"homepage": "https://
|
|
13
|
+
"homepage": "https://thi.ng/geom-tessellate",
|
|
14
14
|
"funding": [
|
|
15
15
|
{
|
|
16
16
|
"type": "github",
|
|
@@ -33,21 +33,25 @@
|
|
|
33
33
|
"doc:readme": "bun ../../tools/src/module-stats.ts && bun ../../tools/src/readme.ts",
|
|
34
34
|
"pub": "yarn npm publish --access public",
|
|
35
35
|
"test": "bun test",
|
|
36
|
-
"tool:tangle": "../../node_modules/.bin/tangle src/**/*.ts"
|
|
36
|
+
"tool:tangle": "../../node_modules/.bin/tangle src/**/*.ts",
|
|
37
|
+
"tool:viz": "bun tools/visualize.ts"
|
|
37
38
|
},
|
|
38
39
|
"dependencies": {
|
|
39
|
-
"@thi.ng/
|
|
40
|
-
"@thi.ng/
|
|
41
|
-
"@thi.ng/geom-
|
|
42
|
-
"@thi.ng/geom-
|
|
43
|
-
"@thi.ng/
|
|
44
|
-
"@thi.ng/
|
|
40
|
+
"@thi.ng/api": "^8.11.3",
|
|
41
|
+
"@thi.ng/checks": "^3.6.5",
|
|
42
|
+
"@thi.ng/geom-accel": "^4.0.0",
|
|
43
|
+
"@thi.ng/geom-isec": "^4.0.0",
|
|
44
|
+
"@thi.ng/geom-poly-utils": "^3.0.0",
|
|
45
|
+
"@thi.ng/math": "^5.11.0",
|
|
46
|
+
"@thi.ng/morton": "^3.1.87",
|
|
47
|
+
"@thi.ng/transducers": "^9.0.6",
|
|
48
|
+
"@thi.ng/vectors": "^7.11.0"
|
|
45
49
|
},
|
|
46
50
|
"devDependencies": {
|
|
47
|
-
"@microsoft/api-extractor": "^7.
|
|
48
|
-
"esbuild": "^0.
|
|
49
|
-
"typedoc": "^0.25.
|
|
50
|
-
"typescript": "^5.
|
|
51
|
+
"@microsoft/api-extractor": "^7.47.0",
|
|
52
|
+
"esbuild": "^0.21.5",
|
|
53
|
+
"typedoc": "^0.25.13",
|
|
54
|
+
"typescript": "^5.5.2"
|
|
51
55
|
},
|
|
52
56
|
"keywords": [
|
|
53
57
|
"2d",
|
|
@@ -74,6 +78,12 @@
|
|
|
74
78
|
".": {
|
|
75
79
|
"default": "./index.js"
|
|
76
80
|
},
|
|
81
|
+
"./api": {
|
|
82
|
+
"default": "./api.js"
|
|
83
|
+
},
|
|
84
|
+
"./earcut-complex": {
|
|
85
|
+
"default": "./earcut-complex.js"
|
|
86
|
+
},
|
|
77
87
|
"./earcut": {
|
|
78
88
|
"default": "./earcut.js"
|
|
79
89
|
},
|
|
@@ -92,6 +102,15 @@
|
|
|
92
102
|
"./tessellate": {
|
|
93
103
|
"default": "./tessellate.js"
|
|
94
104
|
},
|
|
105
|
+
"./tessellation": {
|
|
106
|
+
"default": "./tessellation.js"
|
|
107
|
+
},
|
|
108
|
+
"./tri-fan-boundary": {
|
|
109
|
+
"default": "./tri-fan-boundary.js"
|
|
110
|
+
},
|
|
111
|
+
"./tri-fan-split": {
|
|
112
|
+
"default": "./tri-fan-split.js"
|
|
113
|
+
},
|
|
95
114
|
"./tri-fan": {
|
|
96
115
|
"default": "./tri-fan.js"
|
|
97
116
|
}
|
|
@@ -100,5 +119,5 @@
|
|
|
100
119
|
"parent": "@thi.ng/geom",
|
|
101
120
|
"year": 2013
|
|
102
121
|
},
|
|
103
|
-
"gitHead": "
|
|
122
|
+
"gitHead": "154c95cf9d6bab32174498ec3b5b5d87e42be7f9\n"
|
|
104
123
|
}
|
package/quad-fan.d.ts
CHANGED
package/quad-fan.js
CHANGED
|
@@ -1,21 +1,17 @@
|
|
|
1
1
|
import { centroid } from "@thi.ng/geom-poly-utils/centroid";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
),
|
|
16
|
-
push(),
|
|
17
|
-
wrapSides(points)
|
|
18
|
-
);
|
|
2
|
+
import { addmN } from "@thi.ng/vectors";
|
|
3
|
+
const quadFan = (tess, faces, pids) => {
|
|
4
|
+
const points = tess.pointsForIDs(pids);
|
|
5
|
+
const c = tess.addPoint(centroid(points));
|
|
6
|
+
const n = pids.length - 1;
|
|
7
|
+
let m0 = tess.addPoint(addmN([], points[n], points[0], 0.5));
|
|
8
|
+
let mprev = m0;
|
|
9
|
+
for (let i = 0; i <= n; i++) {
|
|
10
|
+
const m = i < n ? tess.addPoint(addmN([], points[i], points[i + 1], 0.5)) : m0;
|
|
11
|
+
faces.push([c, mprev, pids[i], m]);
|
|
12
|
+
mprev = m;
|
|
13
|
+
}
|
|
14
|
+
return faces;
|
|
19
15
|
};
|
|
20
16
|
export {
|
|
21
17
|
quadFan
|
package/rim-tris.d.ts
CHANGED
package/rim-tris.js
CHANGED
|
@@ -1,29 +1,24 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
),
|
|
23
|
-
push(),
|
|
24
|
-
[edgeCentroids],
|
|
25
|
-
wrapSides([...zip(edgeCentroids, points)], 1, 0)
|
|
26
|
-
);
|
|
1
|
+
import { addmN } from "@thi.ng/vectors/addmn";
|
|
2
|
+
const rimTris = (tess, faces, pids) => {
|
|
3
|
+
const points = tess.pointsForIDs(pids);
|
|
4
|
+
const n = pids.length - 1;
|
|
5
|
+
const mids = [
|
|
6
|
+
tess.addPoint(addmN([], points[n], points[0], 0.5))
|
|
7
|
+
];
|
|
8
|
+
let mprev = mids[0];
|
|
9
|
+
for (let i = 0; i <= n; i++) {
|
|
10
|
+
let m;
|
|
11
|
+
if (i < n) {
|
|
12
|
+
m = tess.addPoint(addmN([], points[i], points[i + 1], 0.5));
|
|
13
|
+
mids.push(m);
|
|
14
|
+
} else {
|
|
15
|
+
m = mids[0];
|
|
16
|
+
}
|
|
17
|
+
faces.push([mprev, pids[i], m]);
|
|
18
|
+
mprev = m;
|
|
19
|
+
}
|
|
20
|
+
faces.push(mids);
|
|
21
|
+
return faces;
|
|
27
22
|
};
|
|
28
23
|
export {
|
|
29
24
|
rimTris
|
package/tessellate.d.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
3
|
-
export declare function tessellate(points: ReadonlyVec[],
|
|
4
|
-
export declare function tessellate(points: ReadonlyVec[],
|
|
1
|
+
import type { ReadonlyVec } from "@thi.ng/vectors";
|
|
2
|
+
import type { ITessellation, Tessellator } from "./api.js";
|
|
3
|
+
export declare function tessellate(points: ReadonlyVec[], tessellators: Tessellator, iter?: number): ITessellation;
|
|
4
|
+
export declare function tessellate(points: ReadonlyVec[], tessellators: Iterable<Tessellator>): ITessellation;
|
|
5
|
+
export declare function tessellateWith(tessel: ITessellation, points: ReadonlyVec[], tessellators: Tessellator, iter?: number): ITessellation;
|
|
6
|
+
export declare function tessellateWith(tessel: ITessellation, points: ReadonlyVec[], tessellators: Iterable<Tessellator>): ITessellation;
|
|
7
|
+
export declare const tessellateFaces: (tessel: ITessellation, faces: number[][], tessellators: Iterable<Tessellator>) => ITessellation;
|
|
5
8
|
//# sourceMappingURL=tessellate.d.ts.map
|
package/tessellate.js
CHANGED
|
@@ -1,23 +1,30 @@
|
|
|
1
1
|
import { isFunction } from "@thi.ng/checks/is-function";
|
|
2
|
-
import { last } from "@thi.ng/transducers/last";
|
|
3
|
-
import { mapcat } from "@thi.ng/transducers/mapcat";
|
|
4
|
-
import { push } from "@thi.ng/transducers/push";
|
|
5
|
-
import { reducer } from "@thi.ng/transducers/reduce";
|
|
6
2
|
import { repeat } from "@thi.ng/transducers/repeat";
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
() => [args[0]],
|
|
14
|
-
(acc, fn) => transduce(mapcat(fn), push(), acc)
|
|
15
|
-
)
|
|
16
|
-
),
|
|
17
|
-
last(),
|
|
18
|
-
isFunction(args[1]) ? repeat(args[1], args[2] || 1) : args[1]
|
|
3
|
+
import { BasicTessellation } from "./tessellation.js";
|
|
4
|
+
function tessellate(points, ...args) {
|
|
5
|
+
return tessellateWith(
|
|
6
|
+
new BasicTessellation(),
|
|
7
|
+
points,
|
|
8
|
+
...args
|
|
19
9
|
);
|
|
20
10
|
}
|
|
11
|
+
function tessellateWith(tessel, points, ...args) {
|
|
12
|
+
const fns = isFunction(args[0]) ? repeat(args[0], args[1] ?? 1) : args[0];
|
|
13
|
+
return tessellateFaces(tessel, [tessel.addPoints(points)], fns);
|
|
14
|
+
}
|
|
15
|
+
const tessellateFaces = (tessel, faces, tessellators) => {
|
|
16
|
+
for (let fn of tessellators) {
|
|
17
|
+
let newFaces = [];
|
|
18
|
+
for (let face of faces) {
|
|
19
|
+
fn(tessel, newFaces, face);
|
|
20
|
+
}
|
|
21
|
+
faces = newFaces;
|
|
22
|
+
}
|
|
23
|
+
tessel.addFaces(faces);
|
|
24
|
+
return tessel;
|
|
25
|
+
};
|
|
21
26
|
export {
|
|
22
|
-
tessellate
|
|
27
|
+
tessellate,
|
|
28
|
+
tessellateFaces,
|
|
29
|
+
tessellateWith
|
|
23
30
|
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { KdTreeMap } from "@thi.ng/geom-accel/kd-tree-map";
|
|
2
|
+
import type { ReadonlyVec } from "@thi.ng/vectors";
|
|
3
|
+
import type { ITessellation } from "./api.js";
|
|
4
|
+
export declare abstract class ATessellation implements ITessellation {
|
|
5
|
+
points: ReadonlyVec[];
|
|
6
|
+
faces: number[][];
|
|
7
|
+
constructor(points?: ReadonlyVec[], faces?: number[][]);
|
|
8
|
+
abstract empty(): ITessellation;
|
|
9
|
+
abstract addPoint(p: ReadonlyVec): number;
|
|
10
|
+
addPoints(points: ReadonlyVec[]): number[];
|
|
11
|
+
addFaces(faces: number[][]): this;
|
|
12
|
+
pointsForIDs(indices: number[]): ReadonlyVec[];
|
|
13
|
+
pointsForFaces(faces?: number[][]): ReadonlyVec[][];
|
|
14
|
+
}
|
|
15
|
+
export declare class BasicTessellation extends ATessellation {
|
|
16
|
+
empty(): BasicTessellation;
|
|
17
|
+
addPoint(p: ReadonlyVec): number;
|
|
18
|
+
}
|
|
19
|
+
export declare class MeshTessellation extends ATessellation {
|
|
20
|
+
eps: number;
|
|
21
|
+
tree: KdTreeMap<ReadonlyVec, number>;
|
|
22
|
+
constructor(dim: 2 | 3, points?: ReadonlyVec[], faces?: number[][], eps?: number);
|
|
23
|
+
empty(): MeshTessellation;
|
|
24
|
+
addPoint(p: ReadonlyVec): number;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=tessellation.d.ts.map
|
package/tessellation.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { KdTreeMap } from "@thi.ng/geom-accel/kd-tree-map";
|
|
2
|
+
import { distSq2, distSq3 } from "@thi.ng/vectors/distsq";
|
|
3
|
+
class ATessellation {
|
|
4
|
+
constructor(points = [], faces = []) {
|
|
5
|
+
this.points = points;
|
|
6
|
+
this.faces = faces;
|
|
7
|
+
}
|
|
8
|
+
addPoints(points) {
|
|
9
|
+
return points.map((p) => this.addPoint(p));
|
|
10
|
+
}
|
|
11
|
+
addFaces(faces) {
|
|
12
|
+
this.faces.push(...faces);
|
|
13
|
+
return this;
|
|
14
|
+
}
|
|
15
|
+
pointsForIDs(indices) {
|
|
16
|
+
return indices.map((i) => this.points[i]);
|
|
17
|
+
}
|
|
18
|
+
pointsForFaces(faces = this.faces) {
|
|
19
|
+
return faces.map((ids) => this.pointsForIDs(ids));
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
class BasicTessellation extends ATessellation {
|
|
23
|
+
empty() {
|
|
24
|
+
return new BasicTessellation();
|
|
25
|
+
}
|
|
26
|
+
addPoint(p) {
|
|
27
|
+
return this.points.push(p) - 1;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
class MeshTessellation extends ATessellation {
|
|
31
|
+
constructor(dim, points = [], faces = [], eps = 1e-6) {
|
|
32
|
+
super(points, faces);
|
|
33
|
+
this.eps = eps;
|
|
34
|
+
this.tree = new KdTreeMap(
|
|
35
|
+
dim,
|
|
36
|
+
void 0,
|
|
37
|
+
dim === 2 ? distSq2 : distSq3
|
|
38
|
+
);
|
|
39
|
+
this.addPoints(points);
|
|
40
|
+
}
|
|
41
|
+
tree;
|
|
42
|
+
empty() {
|
|
43
|
+
return new MeshTessellation(this.tree.dim);
|
|
44
|
+
}
|
|
45
|
+
addPoint(p) {
|
|
46
|
+
const tree = this.tree;
|
|
47
|
+
let id = tree.get(p, this.eps);
|
|
48
|
+
if (id !== void 0) return id;
|
|
49
|
+
id = tree.size;
|
|
50
|
+
tree.set(p, id, this.eps);
|
|
51
|
+
this.points.push(p);
|
|
52
|
+
return id;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
export {
|
|
56
|
+
ATessellation,
|
|
57
|
+
BasicTessellation,
|
|
58
|
+
MeshTessellation
|
|
59
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Tessellator } from "./api.js";
|
|
2
|
+
/**
|
|
3
|
+
* Combined tessellator of {@link triFan}, followed by {@link rimTris}, but in a
|
|
4
|
+
* single pass.
|
|
5
|
+
*
|
|
6
|
+
* @param points
|
|
7
|
+
*/
|
|
8
|
+
export declare const triFanSplit: Tessellator;
|
|
9
|
+
//# sourceMappingURL=tri-fan-split.d.ts.map
|
package/tri-fan-split.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { centroid } from "@thi.ng/geom-poly-utils/centroid";
|
|
2
|
+
import { addmN } from "@thi.ng/vectors/addmn";
|
|
3
|
+
const triFanSplit = (tess, faces, pids) => {
|
|
4
|
+
const points = tess.pointsForIDs(pids);
|
|
5
|
+
const c = centroid(points);
|
|
6
|
+
const cid = tess.addPoint(c);
|
|
7
|
+
const n = pids.length - 1;
|
|
8
|
+
for (let i = 0; i <= n; i++) {
|
|
9
|
+
const j = i < n ? i + 1 : 0;
|
|
10
|
+
const a = points[i];
|
|
11
|
+
const b = points[j];
|
|
12
|
+
const mab = tess.addPoint(addmN([], a, b, 0.5));
|
|
13
|
+
const mac = tess.addPoint(addmN([], a, c, 0.5));
|
|
14
|
+
const mbc = tess.addPoint(addmN([], b, c, 0.5));
|
|
15
|
+
faces.push(
|
|
16
|
+
[pids[i], mab, mac],
|
|
17
|
+
[mab, pids[j], mbc],
|
|
18
|
+
[mac, mab, mbc],
|
|
19
|
+
[mac, mbc, cid]
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
return faces;
|
|
23
|
+
};
|
|
24
|
+
export {
|
|
25
|
+
triFanSplit
|
|
26
|
+
};
|
package/tri-fan.d.ts
CHANGED
package/tri-fan.js
CHANGED
|
@@ -1,20 +1,11 @@
|
|
|
1
1
|
import { centroid } from "@thi.ng/geom-poly-utils/centroid";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const c = centroid(points);
|
|
10
|
-
return transduce(
|
|
11
|
-
comp(
|
|
12
|
-
partition(2, 1),
|
|
13
|
-
map(([a, b]) => [a, b, c])
|
|
14
|
-
),
|
|
15
|
-
push(),
|
|
16
|
-
wrapSides(points, 0, 1)
|
|
17
|
-
);
|
|
2
|
+
const triFan = (tess, faces, pids) => {
|
|
3
|
+
const c = tess.addPoint(centroid(tess.pointsForIDs(pids)));
|
|
4
|
+
const n = pids.length - 1;
|
|
5
|
+
for (let i = 0; i <= n; i++) {
|
|
6
|
+
faces.push([c, pids[i], pids[i < n ? i + 1 : 0]]);
|
|
7
|
+
}
|
|
8
|
+
return faces;
|
|
18
9
|
};
|
|
19
10
|
export {
|
|
20
11
|
triFan
|