poly-extrude 0.16.0 → 0.17.1

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/readme.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Extrude polygons/polylines. Born in [maptalks.three](https://github.com/maptalks/maptalks.three) project<br>
4
4
 
5
- ## Examples
5
+ <!-- ## Examples
6
6
 
7
7
  [![](./gallery/building.png)](https://deyihu.github.io/poly-extrude/test/building.html)
8
8
 
@@ -21,6 +21,8 @@ Extrude polygons/polylines. Born in [maptalks.three](https://github.com/maptalks
21
21
  [![](./gallery/tube.png)](https://deyihu.github.io/poly-extrude/test/tube.html)<br>
22
22
  [![](./gallery/terrain.png)](https://deyihu.github.io/poly-extrude/test/terrain.html)<br>
23
23
 
24
+ [shape demo ](https://deyihu.github.io/poly-extrude/test/shape.html)<br> -->
25
+
24
26
  ## Install
25
27
 
26
28
  ### NPM
@@ -39,7 +41,9 @@ npm i poly-extrude
39
41
 
40
42
  ```js
41
43
  import {
44
+ polygons,
42
45
  extrudePolygons,
46
+ extrudePolygonsOnPath,
43
47
  extrudePolylines,
44
48
  cylinder,
45
49
  expandPaths,
@@ -105,6 +109,7 @@ npm i poly-extrude
105
109
 
106
110
  ## API
107
111
 
112
+
108
113
  ![](./img/extrudePolygons.png)
109
114
 
110
115
  ### `extrudePolygons(polygons, options)`
@@ -125,6 +130,49 @@ npm i poly-extrude
125
130
  } = result;
126
131
  //do something
127
132
  ```
133
+ [building](https://deyihu.github.io/poly-extrude/test/building.html)
134
+ [buildings](https://deyihu.github.io/poly-extrude/test/buildings.html)
135
+ [china](https://deyihu.github.io/poly-extrude/test/china.html)
136
+ [muti polygon](https://deyihu.github.io/poly-extrude/test/multi-polygon.html)
137
+ [ny buildings](https://deyihu.github.io/poly-extrude/test/ny-building.html)
138
+ [custom shape](https://deyihu.github.io/poly-extrude/test/shape.html)
139
+
140
+ ___
141
+
142
+ ![](./img/extrudepolygonsonpath.png)
143
+
144
+ ### `extrudePolygonsOnPath(polygons, options)`
145
+
146
+ * `polygons`
147
+ * `options.extrudePath` is line
148
+ * `options.openEnd`
149
+ * `options.openEndUV`
150
+
151
+ ```js
152
+ const result = extrudePolygonsOnPath(polygons, {
153
+ extrudePath: [
154
+ [0, 0],
155
+ [100, 0]
156
+ ]
157
+ });
158
+ const {
159
+ positon,
160
+ normal,
161
+ uv,
162
+ indices
163
+ } = result;
164
+ //do something
165
+ ```
166
+
167
+ [base demo](https://deyihu.github.io/poly-extrude/test/polygon-on-path.html)
168
+ [with holes demo](https://deyihu.github.io/poly-extrude/test/polygon-on-path-hole.html)
169
+ [with holes by custom shape](https://deyihu.github.io/poly-extrude/test/polygon-on-path-hole1.html)
170
+ [extrude along spring](https://deyihu.github.io/poly-extrude/test/polygon-on-path-spring.html)
171
+ [extrude taihu lake](https://deyihu.github.io/poly-extrude/test/polygon-on-path-taihu.html)
172
+
173
+
174
+ ___
175
+
128
176
 
129
177
  ![](./img/extrudePolylines.png)
130
178
 
@@ -136,8 +184,6 @@ npm i poly-extrude
136
184
  * `options.bottomStickGround` Is the bottom attached to the ground
137
185
  * `options.pathUV` generate Path UV
138
186
 
139
- [extrudePolylines pathUV demo](https://deyihu.github.io/poly-extrude/test/line-pathuv.html)
140
-
141
187
  ```js
142
188
  const result = extrudePolylines(polylines, {
143
189
  depth: 2,
@@ -151,6 +197,21 @@ npm i poly-extrude
151
197
  } = result;
152
198
  //do something
153
199
  ```
200
+ [line](https://deyihu.github.io/poly-extrude/test/line.html)
201
+ [line uv](https://deyihu.github.io/poly-extrude/test/line-uv.html)
202
+ [line pathUV](https://deyihu.github.io/poly-extrude/test/line-pathuv.html)
203
+ [brige](https://deyihu.github.io/poly-extrude/test/brige.html)
204
+ [brige bottomStickGround](https://deyihu.github.io/poly-extrude/test/brige-bottomStickGround.html)
205
+ [extrude brige](https://deyihu.github.io/poly-extrude/test/extrudepolyline-brige.html)
206
+ [spring](https://deyihu.github.io/poly-extrude/test/spring.html)
207
+ [wall](https://deyihu.github.io/poly-extrude/test/wall.html)
208
+ [street](https://deyihu.github.io/poly-extrude/test/street.html)
209
+
210
+
211
+
212
+
213
+ ___
214
+
154
215
 
155
216
  ![](./img/cylinder.png)
156
217
 
@@ -179,6 +240,10 @@ const {
179
240
  } = result;
180
241
  //do something
181
242
  ```
243
+ [cylinder](https://deyihu.github.io/poly-extrude/test/cylinder.html)
244
+ ___
245
+
246
+
182
247
 
183
248
  ![](./img/expandPaths.png)
184
249
 
@@ -205,6 +270,12 @@ const {
205
270
  //do something
206
271
  ```
207
272
 
273
+ [paths](https://deyihu.github.io/poly-extrude/test/expand-path.html)
274
+ [street paths](https://deyihu.github.io/poly-extrude/test/expand-path-street.html)
275
+ [brige paths](https://deyihu.github.io/poly-extrude/test/expand-paths-brige.html)
276
+ ___
277
+
278
+
208
279
  ![](./img/extrudeSlopes.png)
209
280
 
210
281
  ### `extrudeSlopes(lines, options)`
@@ -217,7 +288,6 @@ const {
217
288
  * `options.bottomStickGround` Is the bottom attached to the ground
218
289
  * `options.pathUV` generate Path UV
219
290
 
220
- [extrudeSlopes pathUV demo](https://deyihu.github.io/poly-extrude/test/slope-pathuv.html)
221
291
 
222
292
  ```js
223
293
  const result = extrudeSlopes(polylines, {
@@ -239,6 +309,10 @@ const {
239
309
  //do something
240
310
  ```
241
311
 
312
+ [slope](https://deyihu.github.io/poly-extrude/test/slope.html)
313
+ [extrudeSlopes pathUV demo](https://deyihu.github.io/poly-extrude/test/slope-pathuv.html)
314
+ ___
315
+
242
316
  ![](./img/expandTubes.png)
243
317
 
244
318
  ### `expandTubes(lines, options)`
@@ -265,6 +339,9 @@ const {
265
339
  //do something
266
340
  ```
267
341
 
342
+ [tube](https://deyihu.github.io/poly-extrude/test/tube.html)
343
+ ___
344
+
268
345
  ![](./img/plane.png)
269
346
 
270
347
  ### `plane(width, height,devideW,devideH)`
@@ -274,8 +351,6 @@ const {
274
351
  * `devideW`
275
352
  * `devideH`
276
353
 
277
- [plane demo](https://deyihu.github.io/poly-extrude/test/plane.html)
278
- [custom terrain demo](https://deyihu.github.io/poly-extrude/test/terrain.html)
279
354
 
280
355
  ```js
281
356
  const result = plane(100, 100, 10, 10);
@@ -289,3 +364,29 @@ const {
289
364
  } = result;
290
365
  //do something
291
366
  ```
367
+
368
+ [plane demo](https://deyihu.github.io/poly-extrude/test/plane.html)
369
+ [custom terrain demo](https://deyihu.github.io/poly-extrude/test/terrain.html)
370
+
371
+ ___
372
+
373
+ ![](./img/polygons.png)
374
+
375
+ ### `polygons(polygons, options)`
376
+
377
+ * `polygons`
378
+
379
+ ```js
380
+ const result = polygons(polygons, {
381
+
382
+ });
383
+ const {
384
+ positon,
385
+ normal,
386
+ uv,
387
+ indices
388
+ } = result;
389
+ //do something
390
+ ```
391
+
392
+ [polygons demo](https://deyihu.github.io/poly-extrude/test/simplepolygon.html)
package/src/index.ts CHANGED
@@ -1,13 +1,16 @@
1
- import { extrudePolygons } from './polygon';
1
+ import { extrudePolygons, polygons } from './polygon';
2
2
  import { extrudePolylines, expandLine, leftOnLine, extrudeSlopes } from './polyline';
3
3
  import { cylinder } from './cylinder';
4
4
  import { expandPaths } from './path';
5
5
  import { expandTubes } from './tube';
6
6
  import { plane } from './plane';
7
+ import { extrudePolygonsOnPath } from './polygonpath';
7
8
  import { isClockwise, merge } from './util';
8
9
  export {
9
10
  isClockwise, merge,
10
11
  extrudePolygons, extrudePolylines,
11
12
  extrudeSlopes, expandLine, leftOnLine,
12
- cylinder, expandPaths, expandTubes, plane
13
+ cylinder, expandPaths, expandTubes, plane,
14
+ extrudePolygonsOnPath,
15
+ polygons
13
16
  };
package/src/polygon.ts CHANGED
@@ -1,6 +1,6 @@
1
1
 
2
2
  import earcut from 'earcut';
3
- import { generateNormal, generateSideWallUV, isClockwise, merge } from './util';
3
+ import { generateNormal, generateSideWallUV, isClockwise, merge, isClosedRing, validateRing, calPolygonPointsCount, validatePolygon } from './util';
4
4
  import { PolylineType, PolygonType, ResultType } from './type';
5
5
 
6
6
  type PolygonsOptions = {
@@ -16,20 +16,7 @@ type PolygonsResult = ResultType & {
16
16
  export function extrudePolygons(polygons: Array<PolygonType>, options?: PolygonsOptions): PolygonsResult {
17
17
  options = Object.assign({}, { depth: 2, top: true }, options);
18
18
  const results = polygons.map(polygon => {
19
- for (let i = 0, len = polygon.length; i < len; i++) {
20
- const ring = polygon[i];
21
- validateRing(ring);
22
- if (i === 0) {
23
- if (!isClockwise(ring)) {
24
- polygon[i] = ring.reverse();
25
- }
26
- } else if (isClockwise(ring)) {
27
- polygon[i] = ring.reverse();
28
- }
29
- if (isClosedRing(ring)) {
30
- ring.splice(ring.length - 1, 1);
31
- }
32
- }
19
+ validatePolygon(polygon);
33
20
  const result = flatVertices(polygon, options) as Record<string, any>;
34
21
  result.polygon = polygon;
35
22
  const triangles = earcut(result.flatVertices, result.holes, 2);
@@ -119,16 +106,6 @@ function generateSides(result, options) {
119
106
  }
120
107
  }
121
108
 
122
- function calPolygonPointsCount(polygon) {
123
- let count = 0;
124
- let i = 0;
125
- const len = polygon.length;
126
- while (i < len) {
127
- count += (polygon[i].length);
128
- i++;
129
- }
130
- return count;
131
- }
132
109
 
133
110
  function flatVertices(polygon, options) {
134
111
  const count = calPolygonPointsCount(polygon);
@@ -183,14 +160,55 @@ function flatVertices(polygon, options) {
183
160
 
184
161
  }
185
162
 
186
- function validateRing(ring: PolylineType) {
187
- if (!isClosedRing(ring)) {
188
- ring.push(ring[0]);
163
+
164
+ function simplePolygon(polygon, options = {}) {
165
+ const flatVertices = [], holes = [];
166
+ let pIndex = -1, aIndex = -1, uvIndex = -1;
167
+ const points = [], uv = [];
168
+ for (let i = 0, len = polygon.length; i < len; i++) {
169
+ const ring = polygon[i];
170
+ if (i > 0) {
171
+ holes.push(flatVertices.length / 2);
172
+ }
173
+ for (let j = 0, len1 = ring.length; j < len1; j++) {
174
+ const c = ring[j];
175
+ flatVertices[++pIndex] = c[0];
176
+ flatVertices[++pIndex] = c[1];
177
+
178
+ points[++aIndex] = c[0];
179
+ points[++aIndex] = c[1];
180
+ points[++aIndex] = c[2] || 0;
181
+
182
+ uv[++uvIndex] = c[0];
183
+ uv[++uvIndex] = c[1];
184
+ }
185
+ }
186
+ const triangles = earcut(flatVertices, holes, 2);
187
+ const normal = generateNormal(triangles, points);
188
+ return {
189
+ normal,
190
+ uv,
191
+ points,
192
+ indices: triangles
189
193
  }
190
194
  }
191
195
 
192
- function isClosedRing(ring: PolylineType) {
193
- const len = ring.length;
194
- const [x1, y1] = ring[0], [x2, y2] = ring[len - 1];
195
- return (x1 === x2 && y1 === y2);
196
+ export function polygons(polygons, options = {}): PolygonsResult {
197
+ const results = polygons.map(polygon => {
198
+ validatePolygon(polygon);
199
+
200
+ const result = simplePolygon(polygon, options) as Record<string, any>;
201
+ result.polygon = polygon;
202
+ result.position = new Float32Array(result.points);
203
+ result.indices = new Uint32Array(result.indices);
204
+ result.uv = new Float32Array(result.uv);
205
+ result.normal = new Float32Array(result.normal);
206
+ return result;
207
+ });
208
+ const result = merge(results as Array<ResultType>) as PolygonsResult;
209
+ result.polygons = polygons;
210
+ return result;
211
+
212
+
213
+
196
214
  }
@@ -0,0 +1,315 @@
1
+ import { Vector3 } from './math/Vector3';
2
+ import { PathPoint } from './path/PathPoint';
3
+ import { PathPointList } from './path/PathPointList';
4
+ import { PolygonType, PolylineType, ResultType } from './type';
5
+ import { generateNormal, isClockwise, line2Vectors, merge, validateRing, isClosedRing, calPolygonPointsCount, getPolygonsBBOX, mergeArray } from './util';
6
+ import earcut from 'earcut';
7
+ const UP = new Vector3(0, 0, 1);
8
+ const normalDir = new Vector3();
9
+
10
+ type PolygonsOnPathOptions = {
11
+ extrudePath: PolylineType;
12
+ openEnd?: boolean;
13
+ openEndUV?: boolean;
14
+
15
+ }
16
+
17
+ type PolygonsOnPathResult = ResultType & {
18
+ polygons: Array<PolygonType>;
19
+ }
20
+
21
+
22
+ type Point = [number, number];
23
+
24
+ export function extrudePolygonsOnPath(polygons: Array<PolygonType>, options?: PolygonsOnPathOptions) {
25
+ options = Object.assign({}, { openEnd: false, openEndUV: true }, options);
26
+ const { extrudePath, openEnd } = options;
27
+ if (!extrudePath || !Array.isArray(extrudePath) || extrudePath.length < 2) {
28
+ console.error('extrudePath is error:', extrudePath);
29
+ return null;
30
+ }
31
+ const bbox = getPolygonsBBOX(polygons);
32
+ const [minx, miny, maxx, maxy] = bbox;
33
+ const center = [(minx + maxx) / 2, (miny + maxy) / 2] as Point;
34
+
35
+ const points = line2Vectors(extrudePath);
36
+ const pathPointList = new PathPointList();
37
+ //@ts-ignore
38
+ pathPointList.set(points, 0, options.cornerSplit, UP);
39
+
40
+ const results = polygons.map(polygon => {
41
+ for (let i = 0, len = polygon.length; i < len; i++) {
42
+ const ring = polygon[i];
43
+ validateRing(ring);
44
+ if (i === 0) {
45
+ if (!isClockwise(ring)) {
46
+ polygon[i] = ring.reverse();
47
+ }
48
+ } else if (isClockwise(ring)) {
49
+ polygon[i] = ring.reverse();
50
+ }
51
+ }
52
+
53
+ const result = generatePolygonOnPathVertexData(pathPointList, polygon, center) as Record<string, any>;
54
+ if (!openEnd) {
55
+ generateStartAndEnd(result, polygon, options);
56
+ }
57
+ result.polygon = polygon;
58
+ result.position = new Float32Array(result.points);
59
+ result.indices = new Uint32Array(result.indices);
60
+ result.uv = new Float32Array(result.uv);
61
+ result.normal = new Float32Array(result.normal);
62
+ return result;
63
+ });
64
+ const result = merge(results as Array<ResultType>) as PolygonsOnPathResult;
65
+ result.polygons = polygons;
66
+ return result;
67
+ }
68
+
69
+
70
+ function getAngle(c1: Point, c2: Point) {
71
+ const [x1, y1] = c1;
72
+ const [x2, y2] = c2;
73
+ const dy = y2 - y1;
74
+ const dx = x2 - x1;
75
+ return Math.atan2(dy, dx);
76
+ }
77
+
78
+
79
+ function transformPolygon(polygon: PolygonType, center: Point) {
80
+ const [cx, cy] = center;
81
+ const list = [];
82
+ polygon.forEach((ring, rIndex) => {
83
+ const data = [];
84
+ let totalDistance = 0;
85
+ let tempPoint;
86
+ for (let i = 0, len = ring.length; i < len; i++) {
87
+ const p = ring[i];
88
+ const x1 = p[0], y1 = p[1];
89
+ const offsetx = x1 - cx, offsety = y1 - cy;
90
+ let distance = 0;
91
+ if (i > 0) {
92
+ const x2 = tempPoint[0], y2 = tempPoint[1];
93
+ const dx = x2 - x1, dy = y2 - y1;
94
+ distance = Math.sqrt(dx * dx + dy * dy) + totalDistance;
95
+ totalDistance = distance;
96
+ }
97
+ data[i] = {
98
+ // dx,
99
+ // dy,
100
+ // dz: 0,
101
+ distance,
102
+ radius: Math.sqrt(offsetx * offsetx + offsety * offsety),
103
+ angle: -getAngle(center, p as Point)
104
+ }
105
+ tempPoint = p;
106
+ }
107
+ list[rIndex] = {
108
+ ring: data,
109
+ ringLen: totalDistance
110
+ };
111
+ });
112
+ return list;
113
+ }
114
+
115
+ const TEMP_VECTOR3 = new Vector3(0, 0, 0);
116
+ // Vertex Data Generate Functions
117
+ // code copy from https://github.com/shawn0326/three.path/blob/master/src/PathGeometry.js
118
+ function generatePolygonOnPathVertexData(pathPointList, polygon: PolygonType, center: Point) {
119
+ const tpolygon = transformPolygon(polygon, center);
120
+ // let count = 0;
121
+ // modify data
122
+ const points: number[] = [];
123
+ const normal: number[] = [];
124
+ const uv: number[] = [];
125
+ // const uv2 = [];
126
+ const indices: number[] = [];
127
+ let verticesCount = 0;
128
+
129
+ let pIndex = -1;
130
+ let nIndex = -1;
131
+ let uIndex = -1;
132
+ let iIndex = -1;
133
+
134
+ const startPoints = [], endPoints = [];
135
+
136
+ function addVertices(pathPoint, ring, ringLen, first, end) {
137
+ const uvDist = pathPoint.dist / ringLen;
138
+ const radialSegments = ring.length;
139
+ // const startRad = ring[0].angle;
140
+
141
+ for (let i = 0; i < radialSegments; i++) {
142
+ const item = ring[i];
143
+ if (!item) {
144
+ continue;
145
+ }
146
+ const isLast = i === radialSegments - 1;
147
+ const angle = item.angle;
148
+ const radius = item.radius;
149
+ const distance = item.distance;
150
+ normalDir.copy(pathPoint.up).applyAxisAngle(pathPoint.dir, angle).normalize();
151
+ const v = TEMP_VECTOR3.copy(pathPoint.up);
152
+ v.applyAxisAngle(pathPoint.dir, angle);
153
+ v.x *= radius;
154
+ v.y *= radius;
155
+ v.z *= radius;
156
+
157
+ points[++pIndex] = pathPoint.pos.x + v.x;
158
+ points[++pIndex] = pathPoint.pos.y + v.y;
159
+ points[++pIndex] = pathPoint.pos.z + v.z;
160
+
161
+ // if (i === 0 || i === radialSegments - 1) {
162
+ // console.log(i, radialSegments, v.x, v.y, v.z);
163
+ // }
164
+
165
+
166
+ normal[++nIndex] = normalDir.x;
167
+ normal[++nIndex] = normalDir.y;
168
+ normal[++nIndex] = normalDir.z;
169
+
170
+ uv[++uIndex] = uvDist;
171
+ uv[++uIndex] = distance / ringLen;
172
+
173
+ verticesCount++;
174
+
175
+ if (first && !isLast) {
176
+ let index = startPoints.length - 1;
177
+ startPoints[++index] = pathPoint.pos.x + v.x;
178
+ startPoints[++index] = pathPoint.pos.y + v.y;
179
+ startPoints[++index] = pathPoint.pos.z + v.z;
180
+ }
181
+ if (end && !isLast) {
182
+ let index = endPoints.length - 1;
183
+ endPoints[++index] = pathPoint.pos.x + v.x;
184
+ endPoints[++index] = pathPoint.pos.y + v.y;
185
+ endPoints[++index] = pathPoint.pos.z + v.z;
186
+ }
187
+ }
188
+
189
+ if (!first) {
190
+ const begin1 = verticesCount - (radialSegments) * 2;
191
+ const begin2 = verticesCount - (radialSegments);
192
+
193
+ for (let i = 0; i < radialSegments; i++) {
194
+ indices[++iIndex] = begin2 + i;
195
+ indices[++iIndex] = begin1 + i;
196
+ indices[++iIndex] = begin1 + i + 1;
197
+ indices[++iIndex] = begin2 + i;
198
+ indices[++iIndex] = begin1 + i + 1;
199
+ indices[++iIndex] = begin2 + i + 1;
200
+ }
201
+ }
202
+ }
203
+
204
+ const polygonLen = tpolygon[0].ringLen;
205
+ tpolygon.forEach(item => {
206
+ for (let i = 0; i < pathPointList.count; i++) {
207
+ const pathPoint = pathPointList.array[i];
208
+ const { ring, ringLen } = item;
209
+ addVertices(pathPoint, ring, ringLen, i === 0, i === pathPointList.count - 1);
210
+
211
+ }
212
+ });
213
+
214
+
215
+ return {
216
+ points,
217
+ normal,
218
+ uv,
219
+ // uv2,
220
+ indices,
221
+ startPoints,
222
+ endPoints,
223
+ polygonLen
224
+ // count
225
+ };
226
+ }
227
+
228
+
229
+ function generateStartAndEnd(result, polygon, options) {
230
+ const { openEndUV } = options;
231
+ for (let i = 0, len = polygon.length; i < len; i++) {
232
+ const ring = polygon[i];
233
+ if (isClosedRing(ring)) {
234
+ ring.splice(ring.length - 1, 1);
235
+ }
236
+ }
237
+ const pointCount = calPolygonPointsCount(polygon);
238
+
239
+ const flatVertices = [], holes = [];
240
+ let pIndex = -1;
241
+ for (let i = 0, len = polygon.length; i < len; i++) {
242
+ const ring = polygon[i];
243
+ if (i > 0) {
244
+ holes.push(flatVertices.length / 2);
245
+ }
246
+ for (let j = 0, len1 = ring.length; j < len1; j++) {
247
+ const c = ring[j];
248
+ flatVertices[++pIndex] = c[0];
249
+ flatVertices[++pIndex] = c[1];
250
+ }
251
+ }
252
+ const triangles = earcut(flatVertices, holes, 2);
253
+ const { points, normal, uv, indices, startPoints, endPoints, polygonLen } = result;
254
+
255
+ pIndex = 0;
256
+ let uIndex = 0;
257
+ const aPoints1 = [], auv1 = [], aPoints2 = [], auv2 = [];
258
+
259
+
260
+ for (let i = 0; i < pointCount; i++) {
261
+ const idx = i * 3;
262
+ const x = startPoints[idx];
263
+ const y = startPoints[idx + 1];
264
+ const z = startPoints[idx + 2];
265
+
266
+ aPoints1[pIndex] = x;
267
+ aPoints1[pIndex + 1] = y;
268
+ aPoints1[pIndex + 2] = z;
269
+ if (openEndUV) {
270
+ auv1[uIndex] = y / polygonLen;
271
+ auv1[uIndex + 1] = z / polygonLen;
272
+ } else {
273
+ auv1[uIndex] = 0;
274
+ auv1[uIndex + 1] = 0;
275
+ }
276
+
277
+ const x1 = endPoints[idx];
278
+ const y1 = endPoints[idx + 1];
279
+ const z1 = endPoints[idx + 2];
280
+
281
+ aPoints2[pIndex] = x1;
282
+ aPoints2[pIndex + 1] = y1;
283
+ aPoints2[pIndex + 2] = z1;
284
+ if (openEndUV) {
285
+ auv2[uIndex] = y1 / polygonLen;
286
+ auv2[uIndex + 1] = z1 / polygonLen;
287
+ } else {
288
+ auv2[uIndex] = 0;
289
+ auv2[uIndex + 1] = 0;
290
+ }
291
+
292
+ pIndex += 3;
293
+ uIndex += 2;
294
+
295
+ }
296
+
297
+ const indexOffset = points.length / 3;
298
+ const indexs = [];
299
+ for (let i = 0, len = triangles.length; i < len; i++) {
300
+ indexs[i] = triangles[i] + indexOffset;
301
+ indexs[i + len] = triangles[i] + indexOffset + pointCount;
302
+ }
303
+
304
+ const anormal1 = generateNormal(triangles, aPoints1) as any;
305
+ const anormal2 = generateNormal(triangles, aPoints2) as any;
306
+ mergeArray(points, aPoints1);
307
+ mergeArray(points, aPoints2);
308
+ mergeArray(uv, auv1);
309
+ mergeArray(uv, auv2);
310
+ mergeArray(normal, anormal1);
311
+ mergeArray(normal, anormal2);
312
+ mergeArray(indices, indexs);
313
+ }
314
+
315
+