poly-extrude 0.0.7 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|