@thi.ng/geom-voronoi 2.3.33 → 2.3.35
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 +1 -1
- package/index.js +296 -296
- package/package.json +16 -14
package/CHANGELOG.md
CHANGED
package/index.js
CHANGED
|
@@ -2,315 +2,315 @@ import { defBitField } from "@thi.ng/bitfield/bitfield";
|
|
|
2
2
|
import { isNumber } from "@thi.ng/checks/is-number";
|
|
3
3
|
import { liangBarsky2 } from "@thi.ng/geom-clip-line/liang-barsky";
|
|
4
4
|
import { sutherlandHodgeman } from "@thi.ng/geom-clip-poly";
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
pointInCircumCircle,
|
|
7
|
+
pointInPolygon2,
|
|
8
|
+
pointInSegment
|
|
9
|
+
} from "@thi.ng/geom-isec/point";
|
|
6
10
|
import { centroid } from "@thi.ng/geom-poly-utils/centroid";
|
|
7
11
|
import { circumCenter2 } from "@thi.ng/geom-poly-utils/circumcenter";
|
|
8
12
|
import { EPS } from "@thi.ng/math/api";
|
|
9
13
|
import { defEdge } from "@thi.ng/quad-edge";
|
|
10
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
ZERO2
|
|
16
|
+
} from "@thi.ng/vectors/api";
|
|
11
17
|
import { eqDelta2 } from "@thi.ng/vectors/eqdelta";
|
|
12
18
|
import { signedArea2 } from "@thi.ng/vectors/signed-area";
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
else {
|
|
36
|
-
this.computeDual();
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* Adds a single new point `p` w/ optional value `val` to the mesh, unless
|
|
41
|
-
* there already is another point existing within radius `eps`. If `update`
|
|
42
|
-
* is true (default), the mesh dual will be automatically updated using
|
|
43
|
-
* {@link DVMesh.computeDual}.
|
|
44
|
-
*
|
|
45
|
-
* @remarks
|
|
46
|
-
* If adding multiple points, ensure `computeDual` will only be called
|
|
47
|
-
* for/after the last point insertion to avoid computational overhead.
|
|
48
|
-
*
|
|
49
|
-
* @param p -
|
|
50
|
-
* @param val -
|
|
51
|
-
* @param eps -
|
|
52
|
-
* @param update -
|
|
53
|
-
*/
|
|
54
|
-
add(p, val, eps = EPS, update = true) {
|
|
55
|
-
let [e, exists] = this.locate(p, eps);
|
|
56
|
-
if (exists)
|
|
57
|
-
return false;
|
|
58
|
-
if (pointInSegment(p, e.origin.pos, e.dest.pos)) {
|
|
59
|
-
e = e.oprev;
|
|
60
|
-
e.onext.remove();
|
|
61
|
-
}
|
|
62
|
-
let base = defEdge(this.nextEID, e.origin, {
|
|
63
|
-
pos: p,
|
|
64
|
-
id: this.nextVID++,
|
|
65
|
-
val,
|
|
66
|
-
});
|
|
67
|
-
base.splice(e);
|
|
68
|
-
this.nextEID += 4;
|
|
69
|
-
const first = base;
|
|
70
|
-
do {
|
|
71
|
-
base = e.connect(base.sym, this.nextEID);
|
|
72
|
-
e = base.oprev;
|
|
73
|
-
this.nextEID += 4;
|
|
74
|
-
} while (e.lnext !== first);
|
|
75
|
-
// enforce delaunay constraints
|
|
76
|
-
do {
|
|
77
|
-
const t = e.oprev;
|
|
78
|
-
if (isRightOf(t.dest.pos, e) &&
|
|
79
|
-
pointInCircumCircle(e.origin.pos, t.dest.pos, e.dest.pos, p)) {
|
|
80
|
-
e.swap();
|
|
81
|
-
e = e.oprev;
|
|
82
|
-
}
|
|
83
|
-
else if (e.onext !== first) {
|
|
84
|
-
e = e.onext.lprev;
|
|
85
|
-
}
|
|
86
|
-
else {
|
|
87
|
-
break;
|
|
88
|
-
}
|
|
89
|
-
} while (true);
|
|
90
|
-
update && this.computeDual();
|
|
91
|
-
return true;
|
|
19
|
+
class DVMesh {
|
|
20
|
+
first;
|
|
21
|
+
nextEID;
|
|
22
|
+
nextVID;
|
|
23
|
+
constructor(pts, size = 1e5) {
|
|
24
|
+
const a = { pos: [0, -size], id: 0 };
|
|
25
|
+
const b = { pos: [size, size], id: 1 };
|
|
26
|
+
const c = { pos: [-size, size], id: 2 };
|
|
27
|
+
const eab = defEdge(0, a, b);
|
|
28
|
+
const ebc = defEdge(4, b, c);
|
|
29
|
+
const eca = defEdge(8, c, a);
|
|
30
|
+
eab.sym.splice(ebc);
|
|
31
|
+
ebc.sym.splice(eca);
|
|
32
|
+
eca.sym.splice(eab);
|
|
33
|
+
this.first = eab;
|
|
34
|
+
this.nextEID = 12;
|
|
35
|
+
this.nextVID = 3;
|
|
36
|
+
if (pts && pts.length) {
|
|
37
|
+
isNumber(pts[0][0]) ? this.addKeys(pts) : this.addAll(pts);
|
|
38
|
+
} else {
|
|
39
|
+
this.computeDual();
|
|
92
40
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Adds a single new point `p` w/ optional value `val` to the mesh, unless
|
|
44
|
+
* there already is another point existing within radius `eps`. If `update`
|
|
45
|
+
* is true (default), the mesh dual will be automatically updated using
|
|
46
|
+
* {@link DVMesh.computeDual}.
|
|
47
|
+
*
|
|
48
|
+
* @remarks
|
|
49
|
+
* If adding multiple points, ensure `computeDual` will only be called
|
|
50
|
+
* for/after the last point insertion to avoid computational overhead.
|
|
51
|
+
*
|
|
52
|
+
* @param p -
|
|
53
|
+
* @param val -
|
|
54
|
+
* @param eps -
|
|
55
|
+
* @param update -
|
|
56
|
+
*/
|
|
57
|
+
add(p, val, eps = EPS, update = true) {
|
|
58
|
+
let [e, exists] = this.locate(p, eps);
|
|
59
|
+
if (exists)
|
|
60
|
+
return false;
|
|
61
|
+
if (pointInSegment(p, e.origin.pos, e.dest.pos)) {
|
|
62
|
+
e = e.oprev;
|
|
63
|
+
e.onext.remove();
|
|
98
64
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
65
|
+
let base = defEdge(this.nextEID, e.origin, {
|
|
66
|
+
pos: p,
|
|
67
|
+
id: this.nextVID++,
|
|
68
|
+
val
|
|
69
|
+
});
|
|
70
|
+
base.splice(e);
|
|
71
|
+
this.nextEID += 4;
|
|
72
|
+
const first = base;
|
|
73
|
+
do {
|
|
74
|
+
base = e.connect(base.sym, this.nextEID);
|
|
75
|
+
e = base.oprev;
|
|
76
|
+
this.nextEID += 4;
|
|
77
|
+
} while (e.lnext !== first);
|
|
78
|
+
do {
|
|
79
|
+
const t = e.oprev;
|
|
80
|
+
if (isRightOf(t.dest.pos, e) && pointInCircumCircle(e.origin.pos, t.dest.pos, e.dest.pos, p)) {
|
|
81
|
+
e.swap();
|
|
82
|
+
e = e.oprev;
|
|
83
|
+
} else if (e.onext !== first) {
|
|
84
|
+
e = e.onext.lprev;
|
|
85
|
+
} else {
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
} while (true);
|
|
89
|
+
update && this.computeDual();
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
addKeys(pts, eps) {
|
|
93
|
+
for (let p of pts) {
|
|
94
|
+
this.add(p, void 0, eps, false);
|
|
104
95
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
*/
|
|
111
|
-
locate(p, eps = EPS) {
|
|
112
|
-
let e = this.first;
|
|
113
|
-
while (true) {
|
|
114
|
-
if (eqDelta2(p, e.origin.pos, eps) ||
|
|
115
|
-
eqDelta2(p, e.dest.pos, eps)) {
|
|
116
|
-
return [e, true];
|
|
117
|
-
}
|
|
118
|
-
else if (isRightOf(p, e)) {
|
|
119
|
-
e = e.sym;
|
|
120
|
-
}
|
|
121
|
-
else if (!isRightOf(p, e.onext)) {
|
|
122
|
-
e = e.onext;
|
|
123
|
-
}
|
|
124
|
-
else if (!isRightOf(p, e.dprev)) {
|
|
125
|
-
e = e.dprev;
|
|
126
|
-
}
|
|
127
|
-
else {
|
|
128
|
-
return [e, false];
|
|
129
|
-
}
|
|
130
|
-
}
|
|
96
|
+
this.computeDual();
|
|
97
|
+
}
|
|
98
|
+
addAll(pairs, eps) {
|
|
99
|
+
for (let p of pairs) {
|
|
100
|
+
this.add(p[0], p[1], eps, false);
|
|
131
101
|
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
isBoundary = isBoundary && t.origin.id < 3;
|
|
155
|
-
const id = this.nextVID++;
|
|
156
|
-
e.origin = {
|
|
157
|
-
pos: !isBoundary ? circumCenter2(a, b, c) : ZERO2,
|
|
158
|
-
id,
|
|
159
|
-
};
|
|
160
|
-
visitedVerts[id] = true;
|
|
161
|
-
}
|
|
162
|
-
work.push(e.sym, e.onext, e.lnext);
|
|
163
|
-
}
|
|
102
|
+
this.computeDual();
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Returns tuple of the edge related to `p` and a boolean to indicate if
|
|
106
|
+
* `p` already exists in this triangulation (true if already present).
|
|
107
|
+
*
|
|
108
|
+
* @param p - query point
|
|
109
|
+
*/
|
|
110
|
+
locate(p, eps = EPS) {
|
|
111
|
+
let e = this.first;
|
|
112
|
+
while (true) {
|
|
113
|
+
if (eqDelta2(p, e.origin.pos, eps) || eqDelta2(p, e.dest.pos, eps)) {
|
|
114
|
+
return [e, true];
|
|
115
|
+
} else if (isRightOf(p, e)) {
|
|
116
|
+
e = e.sym;
|
|
117
|
+
} else if (!isRightOf(p, e.onext)) {
|
|
118
|
+
e = e.onext;
|
|
119
|
+
} else if (!isRightOf(p, e.dprev)) {
|
|
120
|
+
e = e.dprev;
|
|
121
|
+
} else {
|
|
122
|
+
return [e, false];
|
|
123
|
+
}
|
|
164
124
|
}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
}
|
|
194
|
-
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Syncronize / update / add dual faces (i.e. Voronoi) for current
|
|
128
|
+
* primary mesh (i.e. Delaunay).
|
|
129
|
+
*/
|
|
130
|
+
computeDual() {
|
|
131
|
+
const work = [this.first.rot];
|
|
132
|
+
const visitedEdges = {};
|
|
133
|
+
const visitedVerts = {};
|
|
134
|
+
while (work.length) {
|
|
135
|
+
const e = work.pop();
|
|
136
|
+
if (visitedEdges[e.id])
|
|
137
|
+
continue;
|
|
138
|
+
visitedEdges[e.id] = true;
|
|
139
|
+
if (!e.origin || !visitedVerts[e.origin.id]) {
|
|
140
|
+
let t = e.rot;
|
|
141
|
+
const a = t.origin.pos;
|
|
142
|
+
let isBoundary = t.origin.id < 3;
|
|
143
|
+
t = t.lnext;
|
|
144
|
+
const b = t.origin.pos;
|
|
145
|
+
isBoundary = isBoundary && t.origin.id < 3;
|
|
146
|
+
t = t.lnext;
|
|
147
|
+
const c = t.origin.pos;
|
|
148
|
+
isBoundary = isBoundary && t.origin.id < 3;
|
|
149
|
+
const id = this.nextVID++;
|
|
150
|
+
e.origin = {
|
|
151
|
+
pos: !isBoundary ? circumCenter2(a, b, c) : ZERO2,
|
|
152
|
+
id
|
|
153
|
+
};
|
|
154
|
+
visitedVerts[id] = true;
|
|
155
|
+
}
|
|
156
|
+
work.push(e.sym, e.onext, e.lnext);
|
|
195
157
|
}
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
const
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
158
|
+
}
|
|
159
|
+
delaunay(bounds) {
|
|
160
|
+
const cells = [];
|
|
161
|
+
const usedEdges = defBitField(this.nextEID);
|
|
162
|
+
const bc = bounds && centroid(bounds);
|
|
163
|
+
this.traverse((eab) => {
|
|
164
|
+
if (!usedEdges.at(eab.id)) {
|
|
165
|
+
const ebc = eab.lnext;
|
|
166
|
+
const eca = ebc.lnext;
|
|
167
|
+
const va = eab.origin.pos;
|
|
168
|
+
const vb = ebc.origin.pos;
|
|
169
|
+
const vc = eca.origin.pos;
|
|
170
|
+
let verts = [va, vb, vc];
|
|
171
|
+
if (bounds && !(pointInPolygon2(va, bounds) && pointInPolygon2(vb, bounds) && pointInPolygon2(vc, bounds))) {
|
|
172
|
+
verts = sutherlandHodgeman(verts, bounds, bc);
|
|
173
|
+
if (verts.length > 2) {
|
|
174
|
+
cells.push(verts);
|
|
175
|
+
}
|
|
176
|
+
} else {
|
|
177
|
+
cells.push(verts);
|
|
178
|
+
}
|
|
179
|
+
usedEdges.setAt(eab.id);
|
|
180
|
+
usedEdges.setAt(ebc.id);
|
|
181
|
+
usedEdges.setAt(eca.id);
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
return cells;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Advanced use only. Returns Delaunay triangles as arrays of raw
|
|
188
|
+
* [thi.ng/quad-edge
|
|
189
|
+
* Edges](https://docs.thi.ng/umbrella/quad-edge/classes/Edge.html).
|
|
190
|
+
*
|
|
191
|
+
* @remarks
|
|
192
|
+
* The actual vertex position associated with each edge can be obtained via
|
|
193
|
+
* `e.origin.pos`. Each edge (and each associated {@link Vertex}) also has a
|
|
194
|
+
* unique ID, accessible via `e.id` and `e.origin.id`.
|
|
195
|
+
*/
|
|
196
|
+
delaunayQE() {
|
|
197
|
+
const cells = [];
|
|
198
|
+
const usedEdges = defBitField(this.nextEID);
|
|
199
|
+
this.traverse((eab) => {
|
|
200
|
+
if (!usedEdges.at(eab.id)) {
|
|
201
|
+
const ebc = eab.lnext;
|
|
202
|
+
const eca = ebc.lnext;
|
|
203
|
+
cells.push([eab, ebc, eca]);
|
|
204
|
+
usedEdges.setAt(eab.id);
|
|
205
|
+
usedEdges.setAt(ebc.id);
|
|
206
|
+
usedEdges.setAt(eca.id);
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
return cells;
|
|
210
|
+
}
|
|
211
|
+
voronoi(bounds) {
|
|
212
|
+
const cells = [];
|
|
213
|
+
const bc = bounds && centroid(bounds);
|
|
214
|
+
this.traverse(
|
|
215
|
+
bounds ? (e) => {
|
|
216
|
+
const first = e = e.rot;
|
|
217
|
+
let verts = [];
|
|
218
|
+
let needsClip = false;
|
|
219
|
+
let p;
|
|
220
|
+
do {
|
|
221
|
+
p = e.origin.pos;
|
|
222
|
+
verts.push(p);
|
|
223
|
+
needsClip = needsClip || !pointInPolygon2(p, bounds);
|
|
224
|
+
} while ((e = e.lnext) !== first);
|
|
225
|
+
if (needsClip) {
|
|
226
|
+
verts = sutherlandHodgeman(verts, bounds, bc);
|
|
227
|
+
if (verts.length < 3)
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
cells.push(verts);
|
|
231
|
+
} : (e) => {
|
|
232
|
+
const first = e = e.rot;
|
|
233
|
+
const verts = [];
|
|
234
|
+
do {
|
|
235
|
+
verts.push(e.origin.pos);
|
|
236
|
+
} while ((e = e.lnext) !== first);
|
|
237
|
+
cells.push(verts);
|
|
238
|
+
},
|
|
239
|
+
false
|
|
240
|
+
);
|
|
241
|
+
return cells;
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Advanced use only. Returns Voronoi cells as arrays of raw
|
|
245
|
+
* [thi.ng/quad-edge
|
|
246
|
+
* Edges](https://docs.thi.ng/umbrella/quad-edge/classes/Edge.html).
|
|
247
|
+
*
|
|
248
|
+
* @remarks
|
|
249
|
+
* The actual vertex position associated with each edge can be obtained via
|
|
250
|
+
* `e.origin.pos`. Each edge (and each associated {@link Vertex}) also has a
|
|
251
|
+
* unique ID, accessible via `e.id` and `e.origin.id`.
|
|
252
|
+
*/
|
|
253
|
+
voronoiQE() {
|
|
254
|
+
const cells = [];
|
|
255
|
+
this.traverse((e) => {
|
|
256
|
+
const first = e = e.rot;
|
|
257
|
+
const cell = [];
|
|
258
|
+
do {
|
|
259
|
+
cell.push(e);
|
|
260
|
+
} while ((e = e.lnext) !== first);
|
|
261
|
+
cells.push(cell);
|
|
262
|
+
}, false);
|
|
263
|
+
return cells;
|
|
264
|
+
}
|
|
265
|
+
edges(voronoi = false, boundsMinMax) {
|
|
266
|
+
const edges = [];
|
|
267
|
+
this.traverse(
|
|
268
|
+
(e, visitedEdges) => {
|
|
269
|
+
if (visitedEdges.at(e.sym.id))
|
|
270
|
+
return;
|
|
271
|
+
if (e.origin.id > 2 && e.dest.id > 2) {
|
|
272
|
+
const a = e.origin.pos;
|
|
273
|
+
const b = e.dest.pos;
|
|
274
|
+
if (boundsMinMax) {
|
|
275
|
+
const clip = liangBarsky2(
|
|
276
|
+
a,
|
|
277
|
+
b,
|
|
278
|
+
boundsMinMax[0],
|
|
279
|
+
boundsMinMax[1]
|
|
280
|
+
);
|
|
281
|
+
clip && edges.push([clip[0], clip[1]]);
|
|
282
|
+
} else {
|
|
283
|
+
edges.push([a, b]);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
visitedEdges.setAt(e.id);
|
|
287
|
+
},
|
|
288
|
+
true,
|
|
289
|
+
voronoi ? this.first.rot : this.first
|
|
290
|
+
);
|
|
291
|
+
return edges;
|
|
292
|
+
}
|
|
293
|
+
traverse(proc, edges = true, e = this.first) {
|
|
294
|
+
const work = [e];
|
|
295
|
+
const visitedEdges = defBitField(this.nextEID);
|
|
296
|
+
const visitedVerts = defBitField(this.nextVID);
|
|
297
|
+
while (work.length) {
|
|
298
|
+
e = work.pop();
|
|
299
|
+
if (visitedEdges.at(e.id))
|
|
300
|
+
continue;
|
|
301
|
+
visitedEdges.setAt(e.id);
|
|
302
|
+
const eoID = e.origin.id;
|
|
303
|
+
if (eoID > 2 && e.rot.origin.id > 2) {
|
|
304
|
+
if (edges || !visitedVerts.at(eoID)) {
|
|
305
|
+
visitedVerts.setAt(eoID);
|
|
306
|
+
proc(e, visitedEdges, visitedVerts);
|
|
312
307
|
}
|
|
308
|
+
}
|
|
309
|
+
work.push(e.sym, e.onext, e.lnext);
|
|
313
310
|
}
|
|
311
|
+
}
|
|
314
312
|
}
|
|
315
|
-
/** @internal */
|
|
316
313
|
const isRightOf = (p, e) => signedArea2(p, e.dest.pos, e.origin.pos) > 0;
|
|
314
|
+
export {
|
|
315
|
+
DVMesh
|
|
316
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thi.ng/geom-voronoi",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.35",
|
|
4
4
|
"description": "Fast, incremental 2D Delaunay & Voronoi mesh implementation",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "./index.js",
|
|
@@ -24,7 +24,9 @@
|
|
|
24
24
|
"author": "Karsten Schmidt (https://thi.ng)",
|
|
25
25
|
"license": "Apache-2.0",
|
|
26
26
|
"scripts": {
|
|
27
|
-
"build": "yarn
|
|
27
|
+
"build": "yarn build:esbuild && yarn build:decl",
|
|
28
|
+
"build:decl": "tsc --declaration --emitDeclarationOnly",
|
|
29
|
+
"build:esbuild": "esbuild --format=esm --platform=neutral --target=es2022 --tsconfig=tsconfig.json --outdir=. src/**/*.ts",
|
|
28
30
|
"clean": "rimraf --glob '*.js' '*.d.ts' '*.map' doc",
|
|
29
31
|
"doc": "typedoc --excludePrivate --excludeInternal --out doc src/index.ts",
|
|
30
32
|
"doc:ae": "mkdir -p .ae/doc .ae/temp && api-extractor run --local --verbose",
|
|
@@ -33,20 +35,20 @@
|
|
|
33
35
|
"test": "bun test"
|
|
34
36
|
},
|
|
35
37
|
"dependencies": {
|
|
36
|
-
"@thi.ng/api": "^8.9.
|
|
37
|
-
"@thi.ng/bitfield": "^2.3.
|
|
38
|
-
"@thi.ng/checks": "^3.4.
|
|
39
|
-
"@thi.ng/geom-clip-line": "^2.3.
|
|
40
|
-
"@thi.ng/geom-clip-poly": "^2.1.
|
|
41
|
-
"@thi.ng/geom-isec": "^2.1.
|
|
42
|
-
"@thi.ng/geom-poly-utils": "^2.3.
|
|
43
|
-
"@thi.ng/math": "^5.7.
|
|
44
|
-
"@thi.ng/quad-edge": "^3.1.
|
|
45
|
-
"@thi.ng/vectors": "^7.8.
|
|
38
|
+
"@thi.ng/api": "^8.9.12",
|
|
39
|
+
"@thi.ng/bitfield": "^2.3.10",
|
|
40
|
+
"@thi.ng/checks": "^3.4.12",
|
|
41
|
+
"@thi.ng/geom-clip-line": "^2.3.50",
|
|
42
|
+
"@thi.ng/geom-clip-poly": "^2.1.92",
|
|
43
|
+
"@thi.ng/geom-isec": "^2.1.92",
|
|
44
|
+
"@thi.ng/geom-poly-utils": "^2.3.76",
|
|
45
|
+
"@thi.ng/math": "^5.7.7",
|
|
46
|
+
"@thi.ng/quad-edge": "^3.1.43",
|
|
47
|
+
"@thi.ng/vectors": "^7.8.9"
|
|
46
48
|
},
|
|
47
49
|
"devDependencies": {
|
|
48
50
|
"@microsoft/api-extractor": "^7.38.3",
|
|
49
|
-
"
|
|
51
|
+
"esbuild": "^0.19.8",
|
|
50
52
|
"rimraf": "^5.0.5",
|
|
51
53
|
"tools": "^0.0.1",
|
|
52
54
|
"typedoc": "^0.25.4",
|
|
@@ -90,5 +92,5 @@
|
|
|
90
92
|
],
|
|
91
93
|
"year": 2016
|
|
92
94
|
},
|
|
93
|
-
"gitHead": "
|
|
95
|
+
"gitHead": "5e7bafedfc3d53bc131469a28de31dd8e5b4a3ff\n"
|
|
94
96
|
}
|