poly-extrude 0.0.7 → 0.1.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/dist/poly-extrude.js +172 -46
- package/dist/poly-extrude.js.map +1 -1
- package/dist/poly-extrude.min.js +2 -2
- package/dist/poly-extrude.mjs +171 -47
- package/index.js +3 -2
- package/package.json +47 -47
- package/readme.md +100 -0
- package/src/cylinder.js +89 -0
- package/src/polyline.js +1 -1
package/dist/poly-extrude.js
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
/*!
|
2
|
-
* poly-extrude v0.0
|
2
|
+
* poly-extrude v0.1.0
|
3
3
|
*/
|
4
4
|
(function (global, factory) {
|
5
5
|
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
|
@@ -38,10 +38,10 @@
|
|
38
38
|
|
39
39
|
|
40
40
|
invSize = Math.max(maxX - minX, maxY - minY);
|
41
|
-
invSize = invSize !== 0 ?
|
41
|
+
invSize = invSize !== 0 ? 32767 / invSize : 0;
|
42
42
|
}
|
43
43
|
|
44
|
-
earcutLinked(outerNode, triangles, dim, minX, minY, invSize);
|
44
|
+
earcutLinked(outerNode, triangles, dim, minX, minY, invSize, 0);
|
45
45
|
return triangles;
|
46
46
|
} // create a circular doubly linked list from polygon points in the specified winding order
|
47
47
|
|
@@ -105,9 +105,9 @@
|
|
105
105
|
|
106
106
|
if (invSize ? isEarHashed(ear, minX, minY, invSize) : isEar(ear)) {
|
107
107
|
// cut off the triangle
|
108
|
-
triangles.push(prev.i / dim);
|
109
|
-
triangles.push(ear.i / dim);
|
110
|
-
triangles.push(next.i / dim);
|
108
|
+
triangles.push(prev.i / dim | 0);
|
109
|
+
triangles.push(ear.i / dim | 0);
|
110
|
+
triangles.push(next.i / dim | 0);
|
111
111
|
removeNode(ear); // skipping the next vertex leads to less sliver triangles
|
112
112
|
|
113
113
|
ear = next.next;
|
@@ -141,10 +141,21 @@
|
|
141
141
|
if (area(a, b, c) >= 0) return false; // reflex, can't be an ear
|
142
142
|
// now make sure we don't have other points inside the potential ear
|
143
143
|
|
144
|
-
var
|
145
|
-
|
146
|
-
|
147
|
-
|
144
|
+
var ax = a.x,
|
145
|
+
bx = b.x,
|
146
|
+
cx = c.x,
|
147
|
+
ay = a.y,
|
148
|
+
by = b.y,
|
149
|
+
cy = c.y; // triangle bbox; min & max are calculated like this for speed
|
150
|
+
|
151
|
+
var x0 = ax < bx ? ax < cx ? ax : cx : bx < cx ? bx : cx,
|
152
|
+
y0 = ay < by ? ay < cy ? ay : cy : by < cy ? by : cy,
|
153
|
+
x1 = ax > bx ? ax > cx ? ax : cx : bx > cx ? bx : cx,
|
154
|
+
y1 = ay > by ? ay > cy ? ay : cy : by > cy ? by : cy;
|
155
|
+
var p = c.next;
|
156
|
+
|
157
|
+
while (p !== a) {
|
158
|
+
if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && pointInTriangle(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false;
|
148
159
|
p = p.next;
|
149
160
|
}
|
150
161
|
|
@@ -156,34 +167,40 @@
|
|
156
167
|
b = ear,
|
157
168
|
c = ear.next;
|
158
169
|
if (area(a, b, c) >= 0) return false; // reflex, can't be an ear
|
159
|
-
// triangle bbox; min & max are calculated like this for speed
|
160
170
|
|
161
|
-
var
|
162
|
-
|
163
|
-
|
164
|
-
|
171
|
+
var ax = a.x,
|
172
|
+
bx = b.x,
|
173
|
+
cx = c.x,
|
174
|
+
ay = a.y,
|
175
|
+
by = b.y,
|
176
|
+
cy = c.y; // triangle bbox; min & max are calculated like this for speed
|
177
|
+
|
178
|
+
var x0 = ax < bx ? ax < cx ? ax : cx : bx < cx ? bx : cx,
|
179
|
+
y0 = ay < by ? ay < cy ? ay : cy : by < cy ? by : cy,
|
180
|
+
x1 = ax > bx ? ax > cx ? ax : cx : bx > cx ? bx : cx,
|
181
|
+
y1 = ay > by ? ay > cy ? ay : cy : by > cy ? by : cy; // z-order range for the current triangle bbox;
|
165
182
|
|
166
|
-
var minZ = zOrder(
|
167
|
-
maxZ = zOrder(
|
183
|
+
var minZ = zOrder(x0, y0, minX, minY, invSize),
|
184
|
+
maxZ = zOrder(x1, y1, minX, minY, invSize);
|
168
185
|
var p = ear.prevZ,
|
169
186
|
n = ear.nextZ; // look for points inside the triangle in both directions
|
170
187
|
|
171
188
|
while (p && p.z >= minZ && n && n.z <= maxZ) {
|
172
|
-
if (p
|
189
|
+
if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c && pointInTriangle(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false;
|
173
190
|
p = p.prevZ;
|
174
|
-
if (n
|
191
|
+
if (n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c && pointInTriangle(ax, ay, bx, by, cx, cy, n.x, n.y) && area(n.prev, n, n.next) >= 0) return false;
|
175
192
|
n = n.nextZ;
|
176
193
|
} // look for remaining points in decreasing z-order
|
177
194
|
|
178
195
|
|
179
196
|
while (p && p.z >= minZ) {
|
180
|
-
if (p
|
197
|
+
if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c && pointInTriangle(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false;
|
181
198
|
p = p.prevZ;
|
182
199
|
} // look for remaining points in increasing z-order
|
183
200
|
|
184
201
|
|
185
202
|
while (n && n.z <= maxZ) {
|
186
|
-
if (n
|
203
|
+
if (n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c && pointInTriangle(ax, ay, bx, by, cx, cy, n.x, n.y) && area(n.prev, n, n.next) >= 0) return false;
|
187
204
|
n = n.nextZ;
|
188
205
|
}
|
189
206
|
|
@@ -199,9 +216,9 @@
|
|
199
216
|
b = p.next.next;
|
200
217
|
|
201
218
|
if (!equals(a, b) && intersects(a, p, p.next, b) && locallyInside(a, b) && locallyInside(b, a)) {
|
202
|
-
triangles.push(a.i / dim);
|
203
|
-
triangles.push(p.i / dim);
|
204
|
-
triangles.push(b.i / dim); // remove two nodes involved
|
219
|
+
triangles.push(a.i / dim | 0);
|
220
|
+
triangles.push(p.i / dim | 0);
|
221
|
+
triangles.push(b.i / dim | 0); // remove two nodes involved
|
205
222
|
|
206
223
|
removeNode(p);
|
207
224
|
removeNode(p.next);
|
@@ -230,8 +247,8 @@
|
|
230
247
|
a = filterPoints(a, a.next);
|
231
248
|
c = filterPoints(c, c.next); // run earcut on each half
|
232
249
|
|
233
|
-
earcutLinked(a, triangles, dim, minX, minY, invSize);
|
234
|
-
earcutLinked(c, triangles, dim, minX, minY, invSize);
|
250
|
+
earcutLinked(a, triangles, dim, minX, minY, invSize, 0);
|
251
|
+
earcutLinked(c, triangles, dim, minX, minY, invSize, 0);
|
235
252
|
return;
|
236
253
|
}
|
237
254
|
|
@@ -263,7 +280,6 @@
|
|
263
280
|
|
264
281
|
for (i = 0; i < queue.length; i++) {
|
265
282
|
outerNode = eliminateHole(queue[i], outerNode);
|
266
|
-
outerNode = filterPoints(outerNode, outerNode.next);
|
267
283
|
}
|
268
284
|
|
269
285
|
return outerNode;
|
@@ -283,10 +299,8 @@
|
|
283
299
|
|
284
300
|
var bridgeReverse = splitPolygon(bridge, hole); // filter collinear points around the cuts
|
285
301
|
|
286
|
-
|
287
|
-
filterPoints(
|
288
|
-
|
289
|
-
return outerNode === bridge ? filteredBridge : outerNode;
|
302
|
+
filterPoints(bridgeReverse, bridgeReverse.next);
|
303
|
+
return filterPoints(bridge, bridge.next);
|
290
304
|
} // David Eberly's algorithm for finding a bridge between hole and outer polygon
|
291
305
|
|
292
306
|
|
@@ -304,22 +318,15 @@
|
|
304
318
|
|
305
319
|
if (x <= hx && x > qx) {
|
306
320
|
qx = x;
|
307
|
-
|
308
|
-
if (x === hx) {
|
309
|
-
if (hy === p.y) return p;
|
310
|
-
if (hy === p.next.y) return p.next;
|
311
|
-
}
|
312
|
-
|
313
321
|
m = p.x < p.next.x ? p : p.next;
|
322
|
+
if (x === hx) return m; // hole touches outer segment; pick leftmost endpoint
|
314
323
|
}
|
315
324
|
}
|
316
325
|
|
317
326
|
p = p.next;
|
318
327
|
} while (p !== outerNode);
|
319
328
|
|
320
|
-
if (!m) return null;
|
321
|
-
if (hx === qx) return m; // hole touches outer segment; pick leftmost endpoint
|
322
|
-
// look for points inside the triangle of hole point, segment intersection and endpoint;
|
329
|
+
if (!m) return null; // look for points inside the triangle of hole point, segment intersection and endpoint;
|
323
330
|
// if there are no points found, we have a valid connection;
|
324
331
|
// otherwise choose the point of the minimum angle with the ray as connection point
|
325
332
|
|
@@ -356,7 +363,7 @@
|
|
356
363
|
var p = start;
|
357
364
|
|
358
365
|
do {
|
359
|
-
if (p.z ===
|
366
|
+
if (p.z === 0) p.z = zOrder(p.x, p.y, minX, minY, invSize);
|
360
367
|
p.prevZ = p.prev;
|
361
368
|
p.nextZ = p.next;
|
362
369
|
p = p.next;
|
@@ -428,8 +435,8 @@
|
|
428
435
|
|
429
436
|
function zOrder(x, y, minX, minY, invSize) {
|
430
437
|
// coords are transformed into non-negative 15-bit integer range
|
431
|
-
x =
|
432
|
-
y =
|
438
|
+
x = (x - minX) * invSize | 0;
|
439
|
+
y = (y - minY) * invSize | 0;
|
433
440
|
x = (x | x << 8) & 0x00FF00FF;
|
434
441
|
x = (x | x << 4) & 0x0F0F0F0F;
|
435
442
|
x = (x | x << 2) & 0x33333333;
|
@@ -456,7 +463,7 @@
|
|
456
463
|
|
457
464
|
|
458
465
|
function pointInTriangle(ax, ay, bx, by, cx, cy, px, py) {
|
459
|
-
return (cx - px) * (ay - py)
|
466
|
+
return (cx - px) * (ay - py) >= (ax - px) * (cy - py) && (ax - px) * (by - py) >= (bx - px) * (ay - py) && (bx - px) * (cy - py) >= (cx - px) * (by - py);
|
460
467
|
} // check if a diagonal between two polygon nodes is valid (lies in polygon interior)
|
461
468
|
|
462
469
|
|
@@ -589,7 +596,7 @@
|
|
589
596
|
this.prev = null;
|
590
597
|
this.next = null; // z-order curve value
|
591
598
|
|
592
|
-
this.z =
|
599
|
+
this.z = 0; // previous and next nodes in z-order
|
593
600
|
|
594
601
|
this.prevZ = null;
|
595
602
|
this.nextZ = null; // indicates whether this is a steiner point
|
@@ -1223,7 +1230,6 @@
|
|
1223
1230
|
x: 0,
|
1224
1231
|
y: 0
|
1225
1232
|
};
|
1226
|
-
|
1227
1233
|
function expandLine(line, options) {
|
1228
1234
|
var preAngle = 0;
|
1229
1235
|
var radius = options.lineWidth / 2;
|
@@ -1336,6 +1342,126 @@
|
|
1336
1342
|
return (y1 - y2) * x + (x2 - x1) * y + x1 * y2 - x2 * y1 > 0;
|
1337
1343
|
}
|
1338
1344
|
|
1345
|
+
function cylinder(point, options) {
|
1346
|
+
if (options === void 0) {
|
1347
|
+
options = {};
|
1348
|
+
}
|
1349
|
+
|
1350
|
+
options = Object.assign({}, {
|
1351
|
+
radius: 1,
|
1352
|
+
height: 2,
|
1353
|
+
radialSegments: 6
|
1354
|
+
}, options);
|
1355
|
+
var radialSegments = Math.round(Math.max(4, options.radialSegments));
|
1356
|
+
var _options = options,
|
1357
|
+
radius = _options.radius,
|
1358
|
+
height = _options.height;
|
1359
|
+
var aRad = 360 / radialSegments / 360 * Math.PI * 2;
|
1360
|
+
var circlePointsLen = radialSegments + 1;
|
1361
|
+
var points = new Float32Array(circlePointsLen * 3 * 2);
|
1362
|
+
var centerx = point[0],
|
1363
|
+
centery = point[1];
|
1364
|
+
var idx = 0,
|
1365
|
+
uIdx = 0;
|
1366
|
+
var offset = circlePointsLen * 3,
|
1367
|
+
uOffset = circlePointsLen * 2;
|
1368
|
+
var indices = [],
|
1369
|
+
uvs = [];
|
1370
|
+
|
1371
|
+
for (var i = -1; i < radialSegments; i++) {
|
1372
|
+
var rad = aRad * i;
|
1373
|
+
var x = Math.cos(rad) * radius + centerx,
|
1374
|
+
y = Math.sin(rad) * radius + centery; // bottom vertices
|
1375
|
+
|
1376
|
+
points[idx] = x;
|
1377
|
+
points[idx + 1] = y;
|
1378
|
+
points[idx + 2] = 0; // top vertices
|
1379
|
+
|
1380
|
+
points[idx + offset] = x;
|
1381
|
+
points[idx + 1 + offset] = y;
|
1382
|
+
points[idx + 2 + offset] = height;
|
1383
|
+
var u = 0,
|
1384
|
+
v = 0;
|
1385
|
+
u = 0.5 + x / radius / 2;
|
1386
|
+
v = 0.5 + y / radius / 2;
|
1387
|
+
uvs[uIdx] = u;
|
1388
|
+
uvs[uIdx + 1] = v;
|
1389
|
+
uvs[uIdx + uOffset] = u;
|
1390
|
+
uvs[uIdx + 1 + uOffset] = v;
|
1391
|
+
idx += 3;
|
1392
|
+
uIdx += 2;
|
1393
|
+
|
1394
|
+
if (i > 1) {
|
1395
|
+
// bottom indices
|
1396
|
+
indices.push(0, i - 1, i);
|
1397
|
+
}
|
1398
|
+
}
|
1399
|
+
|
1400
|
+
idx -= 3;
|
1401
|
+
points[idx] = points[0];
|
1402
|
+
points[idx + 1] = points[1];
|
1403
|
+
points[idx + 2] = points[2];
|
1404
|
+
var pointsLen = points.length;
|
1405
|
+
points[pointsLen - 3] = points[0];
|
1406
|
+
points[pointsLen - 2] = points[1];
|
1407
|
+
points[pointsLen - 1] = height;
|
1408
|
+
var indicesLen = indices.length; // top indices
|
1409
|
+
|
1410
|
+
for (var _i = 0; _i < indicesLen; _i++) {
|
1411
|
+
var index = indices[_i];
|
1412
|
+
indices.push(index + circlePointsLen);
|
1413
|
+
}
|
1414
|
+
|
1415
|
+
var sidePoints = new Float32Array((circlePointsLen * 3 * 2 - 6) * 2);
|
1416
|
+
var pIndex = -1;
|
1417
|
+
idx = circlePointsLen * 2;
|
1418
|
+
uIdx = 0;
|
1419
|
+
|
1420
|
+
for (var _i2 = 0, len = points.length / 2; _i2 < len - 3; _i2 += 3) {
|
1421
|
+
var x1 = points[_i2],
|
1422
|
+
y1 = points[_i2 + 1],
|
1423
|
+
x2 = points[_i2 + 3],
|
1424
|
+
y2 = points[_i2 + 4];
|
1425
|
+
sidePoints[++pIndex] = x1;
|
1426
|
+
sidePoints[++pIndex] = y1;
|
1427
|
+
sidePoints[++pIndex] = height;
|
1428
|
+
sidePoints[++pIndex] = x2;
|
1429
|
+
sidePoints[++pIndex] = y2;
|
1430
|
+
sidePoints[++pIndex] = height;
|
1431
|
+
sidePoints[++pIndex] = x1;
|
1432
|
+
sidePoints[++pIndex] = y1;
|
1433
|
+
sidePoints[++pIndex] = 0;
|
1434
|
+
sidePoints[++pIndex] = x2;
|
1435
|
+
sidePoints[++pIndex] = y2;
|
1436
|
+
sidePoints[++pIndex] = 0;
|
1437
|
+
var a = idx + 2,
|
1438
|
+
b = idx + 3,
|
1439
|
+
c = idx,
|
1440
|
+
d = idx + 1; // indices.push(a, c, b, c, d, b);
|
1441
|
+
|
1442
|
+
indices.push(c, a, d, a, b, d);
|
1443
|
+
idx += 4;
|
1444
|
+
var u1 = uIdx / circlePointsLen,
|
1445
|
+
u2 = (uIdx + 1) / circlePointsLen;
|
1446
|
+
uvs.push(u1, height / radius / 2, u2, height / radius / 2, u1, 0, u2, 0);
|
1447
|
+
uIdx++;
|
1448
|
+
}
|
1449
|
+
|
1450
|
+
var position = new Float32Array(points.length + sidePoints.length);
|
1451
|
+
position.set(points, 0);
|
1452
|
+
position.set(sidePoints, points.length);
|
1453
|
+
var normal = generateNormal(indices, position);
|
1454
|
+
return {
|
1455
|
+
points: points,
|
1456
|
+
indices: new Uint32Array(indices),
|
1457
|
+
position: position,
|
1458
|
+
normal: normal,
|
1459
|
+
uv: new Float32Array(uvs)
|
1460
|
+
};
|
1461
|
+
}
|
1462
|
+
|
1463
|
+
exports.cylinder = cylinder;
|
1464
|
+
exports.expandLine = expandLine;
|
1339
1465
|
exports.extrudePolygons = extrudePolygons;
|
1340
1466
|
exports.extrudePolylines = extrudePolylines;
|
1341
1467
|
|