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.mjs
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
/*!
|
2
|
-
* poly-extrude v0.0
|
2
|
+
* poly-extrude v0.1.0
|
3
3
|
*/
|
4
4
|
var earcut$2 = {exports: {}};
|
5
5
|
|
@@ -32,10 +32,10 @@ function earcut(data, holeIndices, dim) {
|
|
32
32
|
|
33
33
|
|
34
34
|
invSize = Math.max(maxX - minX, maxY - minY);
|
35
|
-
invSize = invSize !== 0 ?
|
35
|
+
invSize = invSize !== 0 ? 32767 / invSize : 0;
|
36
36
|
}
|
37
37
|
|
38
|
-
earcutLinked(outerNode, triangles, dim, minX, minY, invSize);
|
38
|
+
earcutLinked(outerNode, triangles, dim, minX, minY, invSize, 0);
|
39
39
|
return triangles;
|
40
40
|
} // create a circular doubly linked list from polygon points in the specified winding order
|
41
41
|
|
@@ -99,9 +99,9 @@ function earcutLinked(ear, triangles, dim, minX, minY, invSize, pass) {
|
|
99
99
|
|
100
100
|
if (invSize ? isEarHashed(ear, minX, minY, invSize) : isEar(ear)) {
|
101
101
|
// cut off the triangle
|
102
|
-
triangles.push(prev.i / dim);
|
103
|
-
triangles.push(ear.i / dim);
|
104
|
-
triangles.push(next.i / dim);
|
102
|
+
triangles.push(prev.i / dim | 0);
|
103
|
+
triangles.push(ear.i / dim | 0);
|
104
|
+
triangles.push(next.i / dim | 0);
|
105
105
|
removeNode(ear); // skipping the next vertex leads to less sliver triangles
|
106
106
|
|
107
107
|
ear = next.next;
|
@@ -135,10 +135,21 @@ function isEar(ear) {
|
|
135
135
|
if (area(a, b, c) >= 0) return false; // reflex, can't be an ear
|
136
136
|
// now make sure we don't have other points inside the potential ear
|
137
137
|
|
138
|
-
var
|
139
|
-
|
140
|
-
|
141
|
-
|
138
|
+
var ax = a.x,
|
139
|
+
bx = b.x,
|
140
|
+
cx = c.x,
|
141
|
+
ay = a.y,
|
142
|
+
by = b.y,
|
143
|
+
cy = c.y; // triangle bbox; min & max are calculated like this for speed
|
144
|
+
|
145
|
+
var x0 = ax < bx ? ax < cx ? ax : cx : bx < cx ? bx : cx,
|
146
|
+
y0 = ay < by ? ay < cy ? ay : cy : by < cy ? by : cy,
|
147
|
+
x1 = ax > bx ? ax > cx ? ax : cx : bx > cx ? bx : cx,
|
148
|
+
y1 = ay > by ? ay > cy ? ay : cy : by > cy ? by : cy;
|
149
|
+
var p = c.next;
|
150
|
+
|
151
|
+
while (p !== a) {
|
152
|
+
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;
|
142
153
|
p = p.next;
|
143
154
|
}
|
144
155
|
|
@@ -150,34 +161,40 @@ function isEarHashed(ear, minX, minY, invSize) {
|
|
150
161
|
b = ear,
|
151
162
|
c = ear.next;
|
152
163
|
if (area(a, b, c) >= 0) return false; // reflex, can't be an ear
|
153
|
-
// triangle bbox; min & max are calculated like this for speed
|
154
164
|
|
155
|
-
var
|
156
|
-
|
157
|
-
|
158
|
-
|
165
|
+
var ax = a.x,
|
166
|
+
bx = b.x,
|
167
|
+
cx = c.x,
|
168
|
+
ay = a.y,
|
169
|
+
by = b.y,
|
170
|
+
cy = c.y; // triangle bbox; min & max are calculated like this for speed
|
171
|
+
|
172
|
+
var x0 = ax < bx ? ax < cx ? ax : cx : bx < cx ? bx : cx,
|
173
|
+
y0 = ay < by ? ay < cy ? ay : cy : by < cy ? by : cy,
|
174
|
+
x1 = ax > bx ? ax > cx ? ax : cx : bx > cx ? bx : cx,
|
175
|
+
y1 = ay > by ? ay > cy ? ay : cy : by > cy ? by : cy; // z-order range for the current triangle bbox;
|
159
176
|
|
160
|
-
var minZ = zOrder(
|
161
|
-
maxZ = zOrder(
|
177
|
+
var minZ = zOrder(x0, y0, minX, minY, invSize),
|
178
|
+
maxZ = zOrder(x1, y1, minX, minY, invSize);
|
162
179
|
var p = ear.prevZ,
|
163
180
|
n = ear.nextZ; // look for points inside the triangle in both directions
|
164
181
|
|
165
182
|
while (p && p.z >= minZ && n && n.z <= maxZ) {
|
166
|
-
if (p
|
183
|
+
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;
|
167
184
|
p = p.prevZ;
|
168
|
-
if (n
|
185
|
+
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;
|
169
186
|
n = n.nextZ;
|
170
187
|
} // look for remaining points in decreasing z-order
|
171
188
|
|
172
189
|
|
173
190
|
while (p && p.z >= minZ) {
|
174
|
-
if (p
|
191
|
+
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;
|
175
192
|
p = p.prevZ;
|
176
193
|
} // look for remaining points in increasing z-order
|
177
194
|
|
178
195
|
|
179
196
|
while (n && n.z <= maxZ) {
|
180
|
-
if (n
|
197
|
+
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;
|
181
198
|
n = n.nextZ;
|
182
199
|
}
|
183
200
|
|
@@ -193,9 +210,9 @@ function cureLocalIntersections(start, triangles, dim) {
|
|
193
210
|
b = p.next.next;
|
194
211
|
|
195
212
|
if (!equals(a, b) && intersects(a, p, p.next, b) && locallyInside(a, b) && locallyInside(b, a)) {
|
196
|
-
triangles.push(a.i / dim);
|
197
|
-
triangles.push(p.i / dim);
|
198
|
-
triangles.push(b.i / dim); // remove two nodes involved
|
213
|
+
triangles.push(a.i / dim | 0);
|
214
|
+
triangles.push(p.i / dim | 0);
|
215
|
+
triangles.push(b.i / dim | 0); // remove two nodes involved
|
199
216
|
|
200
217
|
removeNode(p);
|
201
218
|
removeNode(p.next);
|
@@ -224,8 +241,8 @@ function splitEarcut(start, triangles, dim, minX, minY, invSize) {
|
|
224
241
|
a = filterPoints(a, a.next);
|
225
242
|
c = filterPoints(c, c.next); // run earcut on each half
|
226
243
|
|
227
|
-
earcutLinked(a, triangles, dim, minX, minY, invSize);
|
228
|
-
earcutLinked(c, triangles, dim, minX, minY, invSize);
|
244
|
+
earcutLinked(a, triangles, dim, minX, minY, invSize, 0);
|
245
|
+
earcutLinked(c, triangles, dim, minX, minY, invSize, 0);
|
229
246
|
return;
|
230
247
|
}
|
231
248
|
|
@@ -257,7 +274,6 @@ function eliminateHoles(data, holeIndices, outerNode, dim) {
|
|
257
274
|
|
258
275
|
for (i = 0; i < queue.length; i++) {
|
259
276
|
outerNode = eliminateHole(queue[i], outerNode);
|
260
|
-
outerNode = filterPoints(outerNode, outerNode.next);
|
261
277
|
}
|
262
278
|
|
263
279
|
return outerNode;
|
@@ -277,10 +293,8 @@ function eliminateHole(hole, outerNode) {
|
|
277
293
|
|
278
294
|
var bridgeReverse = splitPolygon(bridge, hole); // filter collinear points around the cuts
|
279
295
|
|
280
|
-
|
281
|
-
filterPoints(
|
282
|
-
|
283
|
-
return outerNode === bridge ? filteredBridge : outerNode;
|
296
|
+
filterPoints(bridgeReverse, bridgeReverse.next);
|
297
|
+
return filterPoints(bridge, bridge.next);
|
284
298
|
} // David Eberly's algorithm for finding a bridge between hole and outer polygon
|
285
299
|
|
286
300
|
|
@@ -298,22 +312,15 @@ function findHoleBridge(hole, outerNode) {
|
|
298
312
|
|
299
313
|
if (x <= hx && x > qx) {
|
300
314
|
qx = x;
|
301
|
-
|
302
|
-
if (x === hx) {
|
303
|
-
if (hy === p.y) return p;
|
304
|
-
if (hy === p.next.y) return p.next;
|
305
|
-
}
|
306
|
-
|
307
315
|
m = p.x < p.next.x ? p : p.next;
|
316
|
+
if (x === hx) return m; // hole touches outer segment; pick leftmost endpoint
|
308
317
|
}
|
309
318
|
}
|
310
319
|
|
311
320
|
p = p.next;
|
312
321
|
} while (p !== outerNode);
|
313
322
|
|
314
|
-
if (!m) return null;
|
315
|
-
if (hx === qx) return m; // hole touches outer segment; pick leftmost endpoint
|
316
|
-
// look for points inside the triangle of hole point, segment intersection and endpoint;
|
323
|
+
if (!m) return null; // look for points inside the triangle of hole point, segment intersection and endpoint;
|
317
324
|
// if there are no points found, we have a valid connection;
|
318
325
|
// otherwise choose the point of the minimum angle with the ray as connection point
|
319
326
|
|
@@ -350,7 +357,7 @@ function indexCurve(start, minX, minY, invSize) {
|
|
350
357
|
var p = start;
|
351
358
|
|
352
359
|
do {
|
353
|
-
if (p.z ===
|
360
|
+
if (p.z === 0) p.z = zOrder(p.x, p.y, minX, minY, invSize);
|
354
361
|
p.prevZ = p.prev;
|
355
362
|
p.nextZ = p.next;
|
356
363
|
p = p.next;
|
@@ -422,8 +429,8 @@ function sortLinked(list) {
|
|
422
429
|
|
423
430
|
function zOrder(x, y, minX, minY, invSize) {
|
424
431
|
// coords are transformed into non-negative 15-bit integer range
|
425
|
-
x =
|
426
|
-
y =
|
432
|
+
x = (x - minX) * invSize | 0;
|
433
|
+
y = (y - minY) * invSize | 0;
|
427
434
|
x = (x | x << 8) & 0x00FF00FF;
|
428
435
|
x = (x | x << 4) & 0x0F0F0F0F;
|
429
436
|
x = (x | x << 2) & 0x33333333;
|
@@ -450,7 +457,7 @@ function getLeftmost(start) {
|
|
450
457
|
|
451
458
|
|
452
459
|
function pointInTriangle(ax, ay, bx, by, cx, cy, px, py) {
|
453
|
-
return (cx - px) * (ay - py)
|
460
|
+
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);
|
454
461
|
} // check if a diagonal between two polygon nodes is valid (lies in polygon interior)
|
455
462
|
|
456
463
|
|
@@ -583,7 +590,7 @@ function Node(i, x, y) {
|
|
583
590
|
this.prev = null;
|
584
591
|
this.next = null; // z-order curve value
|
585
592
|
|
586
|
-
this.z =
|
593
|
+
this.z = 0; // previous and next nodes in z-order
|
587
594
|
|
588
595
|
this.prevZ = null;
|
589
596
|
this.nextZ = null; // indicates whether this is a steiner point
|
@@ -1217,7 +1224,6 @@ var TEMPV1 = {
|
|
1217
1224
|
x: 0,
|
1218
1225
|
y: 0
|
1219
1226
|
};
|
1220
|
-
|
1221
1227
|
function expandLine(line, options) {
|
1222
1228
|
var preAngle = 0;
|
1223
1229
|
var radius = options.lineWidth / 2;
|
@@ -1330,4 +1336,122 @@ function leftOnLine(p, p1, p2) {
|
|
1330
1336
|
return (y1 - y2) * x + (x2 - x1) * y + x1 * y2 - x2 * y1 > 0;
|
1331
1337
|
}
|
1332
1338
|
|
1333
|
-
|
1339
|
+
function cylinder(point, options) {
|
1340
|
+
if (options === void 0) {
|
1341
|
+
options = {};
|
1342
|
+
}
|
1343
|
+
|
1344
|
+
options = Object.assign({}, {
|
1345
|
+
radius: 1,
|
1346
|
+
height: 2,
|
1347
|
+
radialSegments: 6
|
1348
|
+
}, options);
|
1349
|
+
var radialSegments = Math.round(Math.max(4, options.radialSegments));
|
1350
|
+
var _options = options,
|
1351
|
+
radius = _options.radius,
|
1352
|
+
height = _options.height;
|
1353
|
+
var aRad = 360 / radialSegments / 360 * Math.PI * 2;
|
1354
|
+
var circlePointsLen = radialSegments + 1;
|
1355
|
+
var points = new Float32Array(circlePointsLen * 3 * 2);
|
1356
|
+
var centerx = point[0],
|
1357
|
+
centery = point[1];
|
1358
|
+
var idx = 0,
|
1359
|
+
uIdx = 0;
|
1360
|
+
var offset = circlePointsLen * 3,
|
1361
|
+
uOffset = circlePointsLen * 2;
|
1362
|
+
var indices = [],
|
1363
|
+
uvs = [];
|
1364
|
+
|
1365
|
+
for (var i = -1; i < radialSegments; i++) {
|
1366
|
+
var rad = aRad * i;
|
1367
|
+
var x = Math.cos(rad) * radius + centerx,
|
1368
|
+
y = Math.sin(rad) * radius + centery; // bottom vertices
|
1369
|
+
|
1370
|
+
points[idx] = x;
|
1371
|
+
points[idx + 1] = y;
|
1372
|
+
points[idx + 2] = 0; // top vertices
|
1373
|
+
|
1374
|
+
points[idx + offset] = x;
|
1375
|
+
points[idx + 1 + offset] = y;
|
1376
|
+
points[idx + 2 + offset] = height;
|
1377
|
+
var u = 0,
|
1378
|
+
v = 0;
|
1379
|
+
u = 0.5 + x / radius / 2;
|
1380
|
+
v = 0.5 + y / radius / 2;
|
1381
|
+
uvs[uIdx] = u;
|
1382
|
+
uvs[uIdx + 1] = v;
|
1383
|
+
uvs[uIdx + uOffset] = u;
|
1384
|
+
uvs[uIdx + 1 + uOffset] = v;
|
1385
|
+
idx += 3;
|
1386
|
+
uIdx += 2;
|
1387
|
+
|
1388
|
+
if (i > 1) {
|
1389
|
+
// bottom indices
|
1390
|
+
indices.push(0, i - 1, i);
|
1391
|
+
}
|
1392
|
+
}
|
1393
|
+
|
1394
|
+
idx -= 3;
|
1395
|
+
points[idx] = points[0];
|
1396
|
+
points[idx + 1] = points[1];
|
1397
|
+
points[idx + 2] = points[2];
|
1398
|
+
var pointsLen = points.length;
|
1399
|
+
points[pointsLen - 3] = points[0];
|
1400
|
+
points[pointsLen - 2] = points[1];
|
1401
|
+
points[pointsLen - 1] = height;
|
1402
|
+
var indicesLen = indices.length; // top indices
|
1403
|
+
|
1404
|
+
for (var _i = 0; _i < indicesLen; _i++) {
|
1405
|
+
var index = indices[_i];
|
1406
|
+
indices.push(index + circlePointsLen);
|
1407
|
+
}
|
1408
|
+
|
1409
|
+
var sidePoints = new Float32Array((circlePointsLen * 3 * 2 - 6) * 2);
|
1410
|
+
var pIndex = -1;
|
1411
|
+
idx = circlePointsLen * 2;
|
1412
|
+
uIdx = 0;
|
1413
|
+
|
1414
|
+
for (var _i2 = 0, len = points.length / 2; _i2 < len - 3; _i2 += 3) {
|
1415
|
+
var x1 = points[_i2],
|
1416
|
+
y1 = points[_i2 + 1],
|
1417
|
+
x2 = points[_i2 + 3],
|
1418
|
+
y2 = points[_i2 + 4];
|
1419
|
+
sidePoints[++pIndex] = x1;
|
1420
|
+
sidePoints[++pIndex] = y1;
|
1421
|
+
sidePoints[++pIndex] = height;
|
1422
|
+
sidePoints[++pIndex] = x2;
|
1423
|
+
sidePoints[++pIndex] = y2;
|
1424
|
+
sidePoints[++pIndex] = height;
|
1425
|
+
sidePoints[++pIndex] = x1;
|
1426
|
+
sidePoints[++pIndex] = y1;
|
1427
|
+
sidePoints[++pIndex] = 0;
|
1428
|
+
sidePoints[++pIndex] = x2;
|
1429
|
+
sidePoints[++pIndex] = y2;
|
1430
|
+
sidePoints[++pIndex] = 0;
|
1431
|
+
var a = idx + 2,
|
1432
|
+
b = idx + 3,
|
1433
|
+
c = idx,
|
1434
|
+
d = idx + 1; // indices.push(a, c, b, c, d, b);
|
1435
|
+
|
1436
|
+
indices.push(c, a, d, a, b, d);
|
1437
|
+
idx += 4;
|
1438
|
+
var u1 = uIdx / circlePointsLen,
|
1439
|
+
u2 = (uIdx + 1) / circlePointsLen;
|
1440
|
+
uvs.push(u1, height / radius / 2, u2, height / radius / 2, u1, 0, u2, 0);
|
1441
|
+
uIdx++;
|
1442
|
+
}
|
1443
|
+
|
1444
|
+
var position = new Float32Array(points.length + sidePoints.length);
|
1445
|
+
position.set(points, 0);
|
1446
|
+
position.set(sidePoints, points.length);
|
1447
|
+
var normal = generateNormal(indices, position);
|
1448
|
+
return {
|
1449
|
+
points: points,
|
1450
|
+
indices: new Uint32Array(indices),
|
1451
|
+
position: position,
|
1452
|
+
normal: normal,
|
1453
|
+
uv: new Float32Array(uvs)
|
1454
|
+
};
|
1455
|
+
}
|
1456
|
+
|
1457
|
+
export { cylinder, expandLine, extrudePolygons, extrudePolylines };
|
package/index.js
CHANGED
@@ -1,3 +1,4 @@
|
|
1
1
|
import { extrudePolygons } from './src/polygon';
|
2
|
-
import { extrudePolylines } from './src/polyline';
|
3
|
-
|
2
|
+
import { extrudePolylines, expandLine } from './src/polyline';
|
3
|
+
import { cylinder } from './src/cylinder';
|
4
|
+
export { extrudePolygons, extrudePolylines, expandLine, cylinder };
|
package/package.json
CHANGED
@@ -1,47 +1,47 @@
|
|
1
|
-
{
|
2
|
-
"name": "poly-extrude",
|
3
|
-
"version": "0.0
|
4
|
-
"description": "",
|
5
|
-
"main": "dist/poly-extrude.js",
|
6
|
-
"module": "dist/poly-extrude.mjs",
|
7
|
-
"scripts": {
|
8
|
-
"test": "echo \"Error: no test specified\" && exit 1",
|
9
|
-
"lint": "eslint src/**/*.js",
|
10
|
-
"build": "npm run lint && cross-env NODE_ENV=dev rollup -c"
|
11
|
-
},
|
12
|
-
"repository": {
|
13
|
-
"type": "git",
|
14
|
-
"url": "git+https://github.com/deyihu/poly-extrude.git"
|
15
|
-
},
|
16
|
-
"author": "",
|
17
|
-
"license": "ISC",
|
18
|
-
"bugs": {
|
19
|
-
"url": "https://github.com/deyihu/poly-extrude/issues"
|
20
|
-
},
|
21
|
-
"homepage": "https://github.com/deyihu/poly-extrude#readme",
|
22
|
-
"devDependencies": {
|
23
|
-
"@babel/core": "^7.17.5",
|
24
|
-
"@babel/preset-env": "^7.16.11",
|
25
|
-
"@rollup/plugin-babel": "^5.3.0",
|
26
|
-
"@rollup/plugin-commonjs": "^21.0.1",
|
27
|
-
"@rollup/plugin-json": "^4.1.0",
|
28
|
-
"@rollup/plugin-node-resolve": "^13.1.3",
|
29
|
-
"cross-env": "^5.1.4",
|
30
|
-
"eslint": "^6.2.2",
|
31
|
-
"eslint-config-standard": "^14.1.0",
|
32
|
-
"eslint-plugin-import": "^2.18.2",
|
33
|
-
"eslint-plugin-node": "^10.0.0",
|
34
|
-
"eslint-plugin-promise": "^4.2.1",
|
35
|
-
"eslint-plugin-standard": "^4.0.1",
|
36
|
-
"rollup": "^2.64.0",
|
37
|
-
"rollup-plugin-terser": "^7.0.2"
|
38
|
-
},
|
39
|
-
"dependencies": {
|
40
|
-
"earcut": "^2.2.
|
41
|
-
},
|
42
|
-
"files": [
|
43
|
-
"dist/",
|
44
|
-
"src/",
|
45
|
-
"index.js"
|
46
|
-
]
|
47
|
-
}
|
1
|
+
{
|
2
|
+
"name": "poly-extrude",
|
3
|
+
"version": "0.1.0",
|
4
|
+
"description": "",
|
5
|
+
"main": "dist/poly-extrude.js",
|
6
|
+
"module": "dist/poly-extrude.mjs",
|
7
|
+
"scripts": {
|
8
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
9
|
+
"lint": "eslint src/**/*.js",
|
10
|
+
"build": "npm run lint && cross-env NODE_ENV=dev rollup -c"
|
11
|
+
},
|
12
|
+
"repository": {
|
13
|
+
"type": "git",
|
14
|
+
"url": "git+https://github.com/deyihu/poly-extrude.git"
|
15
|
+
},
|
16
|
+
"author": "",
|
17
|
+
"license": "ISC",
|
18
|
+
"bugs": {
|
19
|
+
"url": "https://github.com/deyihu/poly-extrude/issues"
|
20
|
+
},
|
21
|
+
"homepage": "https://github.com/deyihu/poly-extrude#readme",
|
22
|
+
"devDependencies": {
|
23
|
+
"@babel/core": "^7.17.5",
|
24
|
+
"@babel/preset-env": "^7.16.11",
|
25
|
+
"@rollup/plugin-babel": "^5.3.0",
|
26
|
+
"@rollup/plugin-commonjs": "^21.0.1",
|
27
|
+
"@rollup/plugin-json": "^4.1.0",
|
28
|
+
"@rollup/plugin-node-resolve": "^13.1.3",
|
29
|
+
"cross-env": "^5.1.4",
|
30
|
+
"eslint": "^6.2.2",
|
31
|
+
"eslint-config-standard": "^14.1.0",
|
32
|
+
"eslint-plugin-import": "^2.18.2",
|
33
|
+
"eslint-plugin-node": "^10.0.0",
|
34
|
+
"eslint-plugin-promise": "^4.2.1",
|
35
|
+
"eslint-plugin-standard": "^4.0.1",
|
36
|
+
"rollup": "^2.64.0",
|
37
|
+
"rollup-plugin-terser": "^7.0.2"
|
38
|
+
},
|
39
|
+
"dependencies": {
|
40
|
+
"earcut": "^2.2.4"
|
41
|
+
},
|
42
|
+
"files": [
|
43
|
+
"dist/",
|
44
|
+
"src/",
|
45
|
+
"index.js"
|
46
|
+
]
|
47
|
+
}
|
package/readme.md
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
# poly-extrude
|
2
|
+
|
3
|
+
Extrude polygons/polylines. Born in [maptalks.three](https://github.com/maptalks/maptalks.three) project<br>
|
4
|
+
[building](https://deyihu.github.io/poly-extrude/test/building.html)<br>
|
5
|
+
![](./gallery/building.png)<br>
|
6
|
+
[buildings](https://deyihu.github.io/poly-extrude/test/buildings.html)<br>
|
7
|
+
![](./gallery/buildings.png)<br>
|
8
|
+
[multi-polygon](https://deyihu.github.io/poly-extrude/test/multi-polygon.html)<br>
|
9
|
+
![](./gallery/multi-polygon.png)<br>
|
10
|
+
[street](https://deyihu.github.io/poly-extrude/test/street.html)<br>
|
11
|
+
![](./gallery/street.png)<br>
|
12
|
+
[line-uv](https://deyihu.github.io/poly-extrude/test/line-uv.html)<br>
|
13
|
+
![](./gallery/line-uv.png)
|
14
|
+
|
15
|
+
## install
|
16
|
+
|
17
|
+
```sh
|
18
|
+
npm i poly-extrude
|
19
|
+
|
20
|
+
# or
|
21
|
+
|
22
|
+
yarn add poly-extrude
|
23
|
+
|
24
|
+
# or
|
25
|
+
|
26
|
+
pnpm i poly-extrude
|
27
|
+
```
|
28
|
+
|
29
|
+
## API
|
30
|
+
|
31
|
+
### ESM
|
32
|
+
|
33
|
+
```js
|
34
|
+
import {extrudePolygons,extrudePolylines} from 'poly-extrude';
|
35
|
+
const polygons=[
|
36
|
+
//polygon
|
37
|
+
[
|
38
|
+
//outring
|
39
|
+
[[x,y],[x,y],...........],
|
40
|
+
//holes
|
41
|
+
[[x,y],[x,y],...........],
|
42
|
+
........
|
43
|
+
|
44
|
+
],
|
45
|
+
//other polygons
|
46
|
+
......
|
47
|
+
]
|
48
|
+
|
49
|
+
const result = extrudePolygons(polygons,{depth:2});
|
50
|
+
const {positon,normal,uv,indices}=result;
|
51
|
+
//do something
|
52
|
+
|
53
|
+
const polylines=[
|
54
|
+
// polyline
|
55
|
+
[[x,y],[x,y],...........],
|
56
|
+
//polyline
|
57
|
+
[[x,y],[x,y],...........],
|
58
|
+
];
|
59
|
+
|
60
|
+
const result = extrudePolylines(polylines,{depth:2,lineWidth:2});
|
61
|
+
const {positon,normal,uv,indices}=result;
|
62
|
+
//do something
|
63
|
+
```
|
64
|
+
|
65
|
+
### CDN
|
66
|
+
|
67
|
+
```html
|
68
|
+
<script src="https://unpkg.com/poly-extrude/dist/poly-extrude.js"></script>
|
69
|
+
|
70
|
+
<script>
|
71
|
+
const polygons=[
|
72
|
+
//polygon
|
73
|
+
[
|
74
|
+
//outring
|
75
|
+
[[x,y],[x,y],...........],
|
76
|
+
//holes
|
77
|
+
[[x,y],[x,y],...........],
|
78
|
+
........
|
79
|
+
|
80
|
+
],
|
81
|
+
//other polygons
|
82
|
+
......
|
83
|
+
]
|
84
|
+
|
85
|
+
const result = polyextrude.extrudePolygons(polygons,{depth:2})
|
86
|
+
const {positon,normal,uv,indices}=result;
|
87
|
+
//do something
|
88
|
+
|
89
|
+
const polylines=[
|
90
|
+
// polyline
|
91
|
+
[[x,y],[x,y],...........],
|
92
|
+
//polyline
|
93
|
+
[[x,y],[x,y],...........],
|
94
|
+
];
|
95
|
+
|
96
|
+
const result = polyextrude.extrudePolylines(polylines,{depth:2,lineWidth:2});
|
97
|
+
const {positon,normal,uv,indices}=result;
|
98
|
+
//do something
|
99
|
+
</script>
|
100
|
+
```
|
package/src/cylinder.js
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
import { generateNormal } from './util';
|
2
|
+
|
3
|
+
export function cylinder(point, options = {}) {
|
4
|
+
options = Object.assign({}, { radius: 1, height: 2, radialSegments: 6 }, options);
|
5
|
+
const radialSegments = Math.round(Math.max(4, options.radialSegments));
|
6
|
+
const { radius, height } = options;
|
7
|
+
const aRad = 360 / radialSegments / 360 * Math.PI * 2;
|
8
|
+
const circlePointsLen = (radialSegments + 1);
|
9
|
+
const points = new Float32Array(circlePointsLen * 3 * 2);
|
10
|
+
const [centerx, centery] = point;
|
11
|
+
let idx = 0, uIdx = 0;
|
12
|
+
const offset = circlePointsLen * 3, uOffset = circlePointsLen * 2;
|
13
|
+
const indices = [], uvs = [];
|
14
|
+
for (let i = -1; i < radialSegments; i++) {
|
15
|
+
const rad = aRad * i;
|
16
|
+
const x = Math.cos(rad) * radius + centerx, y = Math.sin(rad) * radius + centery;
|
17
|
+
// bottom vertices
|
18
|
+
points[idx] = x;
|
19
|
+
points[idx + 1] = y;
|
20
|
+
points[idx + 2] = 0;
|
21
|
+
|
22
|
+
// top vertices
|
23
|
+
points[idx + offset] = x;
|
24
|
+
points[idx + 1 + offset] = y;
|
25
|
+
points[idx + 2 + offset] = height;
|
26
|
+
|
27
|
+
let u = 0, v = 0;
|
28
|
+
u = 0.5 + x / radius / 2;
|
29
|
+
v = 0.5 + y / radius / 2;
|
30
|
+
uvs[uIdx] = u;
|
31
|
+
uvs[uIdx + 1] = v;
|
32
|
+
uvs[uIdx + uOffset] = u;
|
33
|
+
uvs[uIdx + 1 + uOffset] = v;
|
34
|
+
|
35
|
+
idx += 3;
|
36
|
+
uIdx += 2;
|
37
|
+
if (i > 1) {
|
38
|
+
// bottom indices
|
39
|
+
indices.push(0, i - 1, i);
|
40
|
+
}
|
41
|
+
}
|
42
|
+
idx -= 3;
|
43
|
+
points[idx] = points[0];
|
44
|
+
points[idx + 1] = points[1];
|
45
|
+
points[idx + 2] = points[2];
|
46
|
+
const pointsLen = points.length;
|
47
|
+
points[pointsLen - 3] = points[0];
|
48
|
+
points[pointsLen - 2] = points[1];
|
49
|
+
points[pointsLen - 1] = height;
|
50
|
+
|
51
|
+
const indicesLen = indices.length;
|
52
|
+
// top indices
|
53
|
+
for (let i = 0; i < indicesLen; i++) {
|
54
|
+
const index = indices[i];
|
55
|
+
indices.push(index + circlePointsLen);
|
56
|
+
}
|
57
|
+
|
58
|
+
const sidePoints = new Float32Array((circlePointsLen * 3 * 2 - 6) * 2);
|
59
|
+
let pIndex = -1;
|
60
|
+
idx = circlePointsLen * 2;
|
61
|
+
uIdx = 0;
|
62
|
+
for (let i = 0, len = points.length / 2; i < len - 3; i += 3) {
|
63
|
+
const x1 = points[i], y1 = points[i + 1], x2 = points[i + 3], y2 = points[i + 4];
|
64
|
+
sidePoints[++pIndex] = x1;
|
65
|
+
sidePoints[++pIndex] = y1;
|
66
|
+
sidePoints[++pIndex] = height;
|
67
|
+
sidePoints[++pIndex] = x2;
|
68
|
+
sidePoints[++pIndex] = y2;
|
69
|
+
sidePoints[++pIndex] = height;
|
70
|
+
sidePoints[++pIndex] = x1;
|
71
|
+
sidePoints[++pIndex] = y1;
|
72
|
+
sidePoints[++pIndex] = 0;
|
73
|
+
sidePoints[++pIndex] = x2;
|
74
|
+
sidePoints[++pIndex] = y2;
|
75
|
+
sidePoints[++pIndex] = 0;
|
76
|
+
const a = idx + 2, b = idx + 3, c = idx, d = idx + 1;
|
77
|
+
// indices.push(a, c, b, c, d, b);
|
78
|
+
indices.push(c, a, d, a, b, d);
|
79
|
+
idx += 4;
|
80
|
+
const u1 = uIdx / circlePointsLen, u2 = (uIdx + 1) / circlePointsLen;
|
81
|
+
uvs.push(u1, height / radius / 2, u2, height / radius / 2, u1, 0, u2, 0);
|
82
|
+
uIdx++;
|
83
|
+
}
|
84
|
+
const position = new Float32Array(points.length + sidePoints.length);
|
85
|
+
position.set(points, 0);
|
86
|
+
position.set(sidePoints, points.length);
|
87
|
+
const normal = generateNormal(indices, position);
|
88
|
+
return { points, indices: new Uint32Array(indices), position, normal, uv: new Float32Array(uvs) };
|
89
|
+
}
|
package/src/polyline.js
CHANGED
@@ -121,7 +121,7 @@ function generateSides(result, options) {
|
|
121
121
|
|
122
122
|
const TEMPV1 = { x: 0, y: 0 }, TEMPV2 = { x: 0, y: 0 };
|
123
123
|
|
124
|
-
function expandLine(line, options) {
|
124
|
+
export function expandLine(line, options) {
|
125
125
|
let preAngle = 0;
|
126
126
|
const radius = options.lineWidth / 2;
|
127
127
|
const points = [], leftPoints = [], rightPoints = [];
|