landxml 0.6.1 → 0.6.3

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 CHANGED
@@ -1,5 +1,17 @@
1
1
  # landxml
2
2
 
3
+ ## 0.6.3
4
+
5
+ ### Patch Changes
6
+
7
+ - e25e54b: bugfix: Parsing large LandXMLs now correctly parses on web workers
8
+
9
+ ## 0.6.2
10
+
11
+ ### Patch Changes
12
+
13
+ - 0ce99bd: optimized surface outline identification
14
+
3
15
  ## 0.6.1
4
16
 
5
17
  ### Patch Changes
package/dist/index.js CHANGED
@@ -150,26 +150,43 @@ var import_xml_js = __toESM(require("xml-js"));
150
150
  var surfaceDefWorker = (0, import_easy_web_worker.createEasyWebWorker)(
151
151
  ({ onMessage }) => {
152
152
  onMessage((message) => {
153
- const { isPoint, arr, idMap } = message.payload;
154
- if (isPoint) {
155
- message.resolve(
156
- arr.map((pt) => [pt.attr.id, pt.content.split(" ").map(Number)]).map((v) => [v[0], [v[1][1], v[1][0], v[1][2]]])
157
- );
158
- } else {
159
- message.resolve(
160
- arr.flatMap((f) => {
161
- var _a;
162
- if (typeof f === "string")
163
- return [f.split(" ").map((id) => idMap == null ? void 0 : idMap.indexOf(id))];
164
- if (((_a = f == null ? void 0 : f.attr) == null ? void 0 : _a.i) === "1")
165
- return [];
166
- return [f.content.split(" ").map((id) => idMap == null ? void 0 : idMap.indexOf(id))];
167
- })
168
- );
153
+ try {
154
+ const { task } = message.payload;
155
+ if (task === "parse-surface-points") {
156
+ const { points } = message.payload;
157
+ message.resolve(
158
+ points.map((pt) => [pt.attr.id, pt.content.split(" ").map(Number)]).map((v) => [v[0], [v[1][1], v[1][0], v[1][2]]])
159
+ );
160
+ } else if (task === "parse-surface-faces") {
161
+ const { faces, idMap } = message.payload;
162
+ message.resolve(
163
+ faces.flatMap((f) => {
164
+ var _a;
165
+ if (typeof f === "string")
166
+ return [f.split(" ").map((id) => idMap == null ? void 0 : idMap.indexOf(id))];
167
+ if (((_a = f == null ? void 0 : f.attr) == null ? void 0 : _a.i) === "1")
168
+ return [];
169
+ return [f.content.split(" ").map((id) => idMap == null ? void 0 : idMap.indexOf(id))];
170
+ })
171
+ );
172
+ } else if (task === "find-neighboring-faces") {
173
+ const { faces, range: { start, end } } = message.payload;
174
+ const faceNeighbors = [];
175
+ for (let i = start; i < end; i++) {
176
+ const sourceFace = faces[i];
177
+ const neighborA = faces.findIndex((f, j) => f.findIndex((v) => v === sourceFace[0]) >= 0 && f.findIndex((v) => v === sourceFace[1]) >= 0 && j !== i);
178
+ const neighborB = faces.findIndex((f, j) => f.findIndex((v) => v === sourceFace[1]) >= 0 && f.findIndex((v) => v === sourceFace[2]) >= 0 && j !== i);
179
+ const neighborC = faces.findIndex((f, j) => f.findIndex((v) => v === sourceFace[0]) >= 0 && f.findIndex((v) => v === sourceFace[2]) >= 0 && j !== i);
180
+ faceNeighbors.push([neighborA, neighborB, neighborC]);
181
+ }
182
+ message.resolve(faceNeighbors);
183
+ }
184
+ } catch (e) {
185
+ message.reject(e);
169
186
  }
170
187
  });
171
188
  },
172
- { maxWorkers: 10 }
189
+ { maxWorkers: 16 }
173
190
  );
174
191
  var parseXML = (xmlString) => __async(void 0, null, function* () {
175
192
  return new Promise((resolve, reject) => __async(void 0, null, function* () {
@@ -197,21 +214,22 @@ var parseXML = (xmlString) => __async(void 0, null, function* () {
197
214
  const Faces = surface.Definition.Faces.F;
198
215
  let ptsIdArray = [];
199
216
  let faces = [];
217
+ let faceNeighbors = [];
200
218
  if (Pnts.length > 1e4) {
201
219
  const sliceIndexes = [...Array(20).keys()].map((i) => Math.round(Pnts.length / 20 * i));
202
220
  ptsIdArray = (yield Promise.all(
203
221
  sliceIndexes.map(
204
222
  (v, i, a) => new Promise((resolve3, reject3) => __async(void 0, null, function* () {
205
223
  const pts = yield surfaceDefWorker.send({
206
- isPoint: true,
207
- arr: Pnts.slice(a[i], a[i + 1] || Pnts.length)
224
+ task: "parse-surface-points",
225
+ points: Pnts.slice(a[i], a[i + 1] || Pnts.length)
208
226
  });
209
227
  resolve3(pts);
210
228
  }))
211
229
  )
212
230
  )).reduce((prev, curr) => [...prev, ...curr], []);
213
231
  } else {
214
- ptsIdArray = yield surfaceDefWorker.send({ arr: Pnts, isPoint: true });
232
+ ptsIdArray = yield surfaceDefWorker.send({ task: "parse-surface-points", points: Pnts });
215
233
  }
216
234
  const points = ptsIdArray.map((v) => v[1]);
217
235
  const pointsIdMap = ptsIdArray.map((v) => v[0]);
@@ -221,8 +239,8 @@ var parseXML = (xmlString) => __async(void 0, null, function* () {
221
239
  sliceIndexes.map(
222
240
  (v, i, a) => new Promise((resolve3, reject3) => __async(void 0, null, function* () {
223
241
  const fcs = yield surfaceDefWorker.send({
224
- isPoint: false,
225
- arr: Faces.slice(a[i], a[i + 1] || Faces.length),
242
+ task: "parse-surface-faces",
243
+ faces: Faces.slice(a[i], a[i + 1] || Faces.length),
226
244
  idMap: pointsIdMap
227
245
  });
228
246
  resolve3(fcs);
@@ -230,7 +248,38 @@ var parseXML = (xmlString) => __async(void 0, null, function* () {
230
248
  )
231
249
  )).reduce((prev, curr) => [...prev, ...curr], []);
232
250
  } else {
233
- faces = yield surfaceDefWorker.send({ arr: Faces, isPoint: false, idMap: pointsIdMap });
251
+ faces = yield surfaceDefWorker.send({
252
+ task: "parse-surface-faces",
253
+ faces: Faces,
254
+ idMap: pointsIdMap
255
+ });
256
+ }
257
+ if (Faces.length > 1e4) {
258
+ const sliceIndexes = [...Array(20).keys()].map((i) => Math.round((faces.length - 1) / 20 * i));
259
+ faceNeighbors = (yield Promise.all(
260
+ sliceIndexes.map(
261
+ (v, i, a) => new Promise((resolve3, reject3) => __async(void 0, null, function* () {
262
+ const fcs = yield surfaceDefWorker.send({
263
+ task: "find-neighboring-faces",
264
+ faces,
265
+ range: {
266
+ start: a[i],
267
+ end: a[i + 1] || faces.length
268
+ }
269
+ });
270
+ resolve3(fcs);
271
+ }))
272
+ )
273
+ )).reduce((prev, curr) => [...prev, ...curr], []);
274
+ } else {
275
+ faceNeighbors = yield surfaceDefWorker.send({
276
+ task: "find-neighboring-faces",
277
+ faces,
278
+ range: {
279
+ start: 0,
280
+ end: faces.length - 1
281
+ }
282
+ });
234
283
  }
235
284
  resolve2({
236
285
  sourceFile,
@@ -240,7 +289,8 @@ var parseXML = (xmlString) => __async(void 0, null, function* () {
240
289
  wktString,
241
290
  surfaceDefinition: {
242
291
  points,
243
- faces
292
+ faces,
293
+ faceNeighbors
244
294
  }
245
295
  });
246
296
  }));
@@ -478,39 +528,21 @@ var get_contours_default = getContours;
478
528
 
479
529
  // src/private/get-outline.ts
480
530
  var getOutline = (surface) => {
481
- const triangleVertexIdEdgePairs = [];
482
- let i = -1;
483
- let pairs = [];
484
- surface.surfaceDefinition.faces.forEach((f) => {
485
- pairs = [];
486
- [
487
- [f[0], f[1]],
488
- [f[1], f[2]],
489
- [f[2], f[0]]
490
- ].forEach(([a, b]) => {
491
- if (a < b) {
492
- pairs.push(`${a};${b}`);
493
- } else {
494
- pairs.push(`${b};${a}`);
495
- }
496
- });
497
- pairs.forEach((pair) => {
498
- i = triangleVertexIdEdgePairs.indexOf(pair);
499
- if (i >= 0) {
500
- triangleVertexIdEdgePairs.splice(i, 1);
501
- } else {
502
- triangleVertexIdEdgePairs.push(pair);
503
- }
504
- });
531
+ const vertexIndexPairEdges = [];
532
+ surface.surfaceDefinition.faces.forEach((f, i) => {
533
+ const neighbors = surface.surfaceDefinition.faceNeighbors[i];
534
+ if (neighbors[0] === -1)
535
+ vertexIndexPairEdges.push([f[0], f[1]]);
536
+ if (neighbors[1] === -1)
537
+ vertexIndexPairEdges.push([f[1], f[2]]);
538
+ if (neighbors[2] === -1)
539
+ vertexIndexPairEdges.push([f[0], f[2]]);
505
540
  });
506
541
  const edges = [];
507
- triangleVertexIdEdgePairs.map((pair) => {
508
- const [v1, v2] = pair.split(";").map((v) => {
509
- var _a;
510
- return (_a = surface.surfaceDefinition.points[parseInt(v, 10)]) == null ? void 0 : _a.slice(0, 2);
511
- });
512
- if (v1 && v2)
513
- edges.push([v1, v2]);
542
+ vertexIndexPairEdges.map((pair) => {
543
+ const [v1, v2] = pair.map((vertexIndex) => surface.surfaceDefinition.points[vertexIndex]);
544
+ if (typeof v1 !== "undefined" && typeof v2 !== "undefined")
545
+ edges.push([v1.slice(0, 2), v2.slice(0, 2)]);
514
546
  });
515
547
  return constructGeojson([{ elevation: 0, polylines: linesToPolyLines(edges) }]);
516
548
  };
package/dist/index.mjs CHANGED
@@ -115,26 +115,43 @@ import convert from "xml-js";
115
115
  var surfaceDefWorker = createEasyWebWorker(
116
116
  ({ onMessage }) => {
117
117
  onMessage((message) => {
118
- const { isPoint, arr, idMap } = message.payload;
119
- if (isPoint) {
120
- message.resolve(
121
- arr.map((pt) => [pt.attr.id, pt.content.split(" ").map(Number)]).map((v) => [v[0], [v[1][1], v[1][0], v[1][2]]])
122
- );
123
- } else {
124
- message.resolve(
125
- arr.flatMap((f) => {
126
- var _a;
127
- if (typeof f === "string")
128
- return [f.split(" ").map((id) => idMap == null ? void 0 : idMap.indexOf(id))];
129
- if (((_a = f == null ? void 0 : f.attr) == null ? void 0 : _a.i) === "1")
130
- return [];
131
- return [f.content.split(" ").map((id) => idMap == null ? void 0 : idMap.indexOf(id))];
132
- })
133
- );
118
+ try {
119
+ const { task } = message.payload;
120
+ if (task === "parse-surface-points") {
121
+ const { points } = message.payload;
122
+ message.resolve(
123
+ points.map((pt) => [pt.attr.id, pt.content.split(" ").map(Number)]).map((v) => [v[0], [v[1][1], v[1][0], v[1][2]]])
124
+ );
125
+ } else if (task === "parse-surface-faces") {
126
+ const { faces, idMap } = message.payload;
127
+ message.resolve(
128
+ faces.flatMap((f) => {
129
+ var _a;
130
+ if (typeof f === "string")
131
+ return [f.split(" ").map((id) => idMap == null ? void 0 : idMap.indexOf(id))];
132
+ if (((_a = f == null ? void 0 : f.attr) == null ? void 0 : _a.i) === "1")
133
+ return [];
134
+ return [f.content.split(" ").map((id) => idMap == null ? void 0 : idMap.indexOf(id))];
135
+ })
136
+ );
137
+ } else if (task === "find-neighboring-faces") {
138
+ const { faces, range: { start, end } } = message.payload;
139
+ const faceNeighbors = [];
140
+ for (let i = start; i < end; i++) {
141
+ const sourceFace = faces[i];
142
+ const neighborA = faces.findIndex((f, j) => f.findIndex((v) => v === sourceFace[0]) >= 0 && f.findIndex((v) => v === sourceFace[1]) >= 0 && j !== i);
143
+ const neighborB = faces.findIndex((f, j) => f.findIndex((v) => v === sourceFace[1]) >= 0 && f.findIndex((v) => v === sourceFace[2]) >= 0 && j !== i);
144
+ const neighborC = faces.findIndex((f, j) => f.findIndex((v) => v === sourceFace[0]) >= 0 && f.findIndex((v) => v === sourceFace[2]) >= 0 && j !== i);
145
+ faceNeighbors.push([neighborA, neighborB, neighborC]);
146
+ }
147
+ message.resolve(faceNeighbors);
148
+ }
149
+ } catch (e) {
150
+ message.reject(e);
134
151
  }
135
152
  });
136
153
  },
137
- { maxWorkers: 10 }
154
+ { maxWorkers: 16 }
138
155
  );
139
156
  var parseXML = (xmlString) => __async(void 0, null, function* () {
140
157
  return new Promise((resolve, reject) => __async(void 0, null, function* () {
@@ -162,21 +179,22 @@ var parseXML = (xmlString) => __async(void 0, null, function* () {
162
179
  const Faces = surface.Definition.Faces.F;
163
180
  let ptsIdArray = [];
164
181
  let faces = [];
182
+ let faceNeighbors = [];
165
183
  if (Pnts.length > 1e4) {
166
184
  const sliceIndexes = [...Array(20).keys()].map((i) => Math.round(Pnts.length / 20 * i));
167
185
  ptsIdArray = (yield Promise.all(
168
186
  sliceIndexes.map(
169
187
  (v, i, a) => new Promise((resolve3, reject3) => __async(void 0, null, function* () {
170
188
  const pts = yield surfaceDefWorker.send({
171
- isPoint: true,
172
- arr: Pnts.slice(a[i], a[i + 1] || Pnts.length)
189
+ task: "parse-surface-points",
190
+ points: Pnts.slice(a[i], a[i + 1] || Pnts.length)
173
191
  });
174
192
  resolve3(pts);
175
193
  }))
176
194
  )
177
195
  )).reduce((prev, curr) => [...prev, ...curr], []);
178
196
  } else {
179
- ptsIdArray = yield surfaceDefWorker.send({ arr: Pnts, isPoint: true });
197
+ ptsIdArray = yield surfaceDefWorker.send({ task: "parse-surface-points", points: Pnts });
180
198
  }
181
199
  const points = ptsIdArray.map((v) => v[1]);
182
200
  const pointsIdMap = ptsIdArray.map((v) => v[0]);
@@ -186,8 +204,8 @@ var parseXML = (xmlString) => __async(void 0, null, function* () {
186
204
  sliceIndexes.map(
187
205
  (v, i, a) => new Promise((resolve3, reject3) => __async(void 0, null, function* () {
188
206
  const fcs = yield surfaceDefWorker.send({
189
- isPoint: false,
190
- arr: Faces.slice(a[i], a[i + 1] || Faces.length),
207
+ task: "parse-surface-faces",
208
+ faces: Faces.slice(a[i], a[i + 1] || Faces.length),
191
209
  idMap: pointsIdMap
192
210
  });
193
211
  resolve3(fcs);
@@ -195,7 +213,38 @@ var parseXML = (xmlString) => __async(void 0, null, function* () {
195
213
  )
196
214
  )).reduce((prev, curr) => [...prev, ...curr], []);
197
215
  } else {
198
- faces = yield surfaceDefWorker.send({ arr: Faces, isPoint: false, idMap: pointsIdMap });
216
+ faces = yield surfaceDefWorker.send({
217
+ task: "parse-surface-faces",
218
+ faces: Faces,
219
+ idMap: pointsIdMap
220
+ });
221
+ }
222
+ if (Faces.length > 1e4) {
223
+ const sliceIndexes = [...Array(20).keys()].map((i) => Math.round((faces.length - 1) / 20 * i));
224
+ faceNeighbors = (yield Promise.all(
225
+ sliceIndexes.map(
226
+ (v, i, a) => new Promise((resolve3, reject3) => __async(void 0, null, function* () {
227
+ const fcs = yield surfaceDefWorker.send({
228
+ task: "find-neighboring-faces",
229
+ faces,
230
+ range: {
231
+ start: a[i],
232
+ end: a[i + 1] || faces.length
233
+ }
234
+ });
235
+ resolve3(fcs);
236
+ }))
237
+ )
238
+ )).reduce((prev, curr) => [...prev, ...curr], []);
239
+ } else {
240
+ faceNeighbors = yield surfaceDefWorker.send({
241
+ task: "find-neighboring-faces",
242
+ faces,
243
+ range: {
244
+ start: 0,
245
+ end: faces.length - 1
246
+ }
247
+ });
199
248
  }
200
249
  resolve2({
201
250
  sourceFile,
@@ -205,7 +254,8 @@ var parseXML = (xmlString) => __async(void 0, null, function* () {
205
254
  wktString,
206
255
  surfaceDefinition: {
207
256
  points,
208
- faces
257
+ faces,
258
+ faceNeighbors
209
259
  }
210
260
  });
211
261
  }));
@@ -443,39 +493,21 @@ var get_contours_default = getContours;
443
493
 
444
494
  // src/private/get-outline.ts
445
495
  var getOutline = (surface) => {
446
- const triangleVertexIdEdgePairs = [];
447
- let i = -1;
448
- let pairs = [];
449
- surface.surfaceDefinition.faces.forEach((f) => {
450
- pairs = [];
451
- [
452
- [f[0], f[1]],
453
- [f[1], f[2]],
454
- [f[2], f[0]]
455
- ].forEach(([a, b]) => {
456
- if (a < b) {
457
- pairs.push(`${a};${b}`);
458
- } else {
459
- pairs.push(`${b};${a}`);
460
- }
461
- });
462
- pairs.forEach((pair) => {
463
- i = triangleVertexIdEdgePairs.indexOf(pair);
464
- if (i >= 0) {
465
- triangleVertexIdEdgePairs.splice(i, 1);
466
- } else {
467
- triangleVertexIdEdgePairs.push(pair);
468
- }
469
- });
496
+ const vertexIndexPairEdges = [];
497
+ surface.surfaceDefinition.faces.forEach((f, i) => {
498
+ const neighbors = surface.surfaceDefinition.faceNeighbors[i];
499
+ if (neighbors[0] === -1)
500
+ vertexIndexPairEdges.push([f[0], f[1]]);
501
+ if (neighbors[1] === -1)
502
+ vertexIndexPairEdges.push([f[1], f[2]]);
503
+ if (neighbors[2] === -1)
504
+ vertexIndexPairEdges.push([f[0], f[2]]);
470
505
  });
471
506
  const edges = [];
472
- triangleVertexIdEdgePairs.map((pair) => {
473
- const [v1, v2] = pair.split(";").map((v) => {
474
- var _a;
475
- return (_a = surface.surfaceDefinition.points[parseInt(v, 10)]) == null ? void 0 : _a.slice(0, 2);
476
- });
477
- if (v1 && v2)
478
- edges.push([v1, v2]);
507
+ vertexIndexPairEdges.map((pair) => {
508
+ const [v1, v2] = pair.map((vertexIndex) => surface.surfaceDefinition.points[vertexIndex]);
509
+ if (typeof v1 !== "undefined" && typeof v2 !== "undefined")
510
+ edges.push([v1.slice(0, 2), v2.slice(0, 2)]);
479
511
  });
480
512
  return constructGeojson([{ elevation: 0, polylines: linesToPolyLines(edges) }]);
481
513
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "landxml",
3
- "version": "0.6.1",
3
+ "version": "0.6.3",
4
4
  "description": "Parse LandXML surfaces on the modern web.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",