landxml 0.7.1 → 0.8.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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # landxml
2
2
 
3
+ ## 0.8.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 6a4a531: Modified "auto" behavior on LandXML files with multiple surfaces to create a combined center (rather than each surface its own cetner)
8
+
3
9
  ## 0.7.1
4
10
 
5
11
  ### Patch Changes
package/README.md CHANGED
@@ -19,8 +19,6 @@ Easily transform LandXML surfaces into GeoJSON contours or GLB 3D models for use
19
19
  npm install landxml
20
20
  ```
21
21
 
22
- ---
23
-
24
22
  ## Examples
25
23
 
26
24
  ### Get contours and a GLB model together (recommended)
@@ -36,7 +34,7 @@ const surfaces = await toGlbAndContours(
36
34
  landXmlString,
37
35
  2, // contour interval (LandXML units)
38
36
  true, // generate outline
39
- "auto", // GLB centre: "auto" | "origin" | [x, y]
37
+ "auto", // GLB center: "auto" | "origin" | [x, y]
40
38
  );
41
39
 
42
40
  const { glb, center, geojson, wktString, download } = surfaces[0];
@@ -59,7 +57,7 @@ const landXmlString = `<?xml version="1.0"?>...<LandXML>...</LandXML>`;
59
57
 
60
58
  const surfaces = await toGeojsonContours(
61
59
  landXmlString,
62
- 2, // contour interval (metres)
60
+ 2, // contour interval (LandXML units)
63
61
  true, // include surface outline as a z=0 feature
64
62
  );
65
63
 
@@ -186,3 +184,13 @@ Returns `Promise<{ name, description, sourceFile, timeStamp, glb, center, downlo
186
184
  | `keepOriginalGeometry` | `boolean` | `true` | Store original coordinates under `feature.properties._rawGeometry` |
187
185
 
188
186
  Returns the mutated `FeatureCollection` with updated coordinates.
187
+
188
+ ---
189
+
190
+ ## Multi-surface center behaviour
191
+
192
+ When a LandXML file contains multiple surfaces and `center` is set to `"auto"` (the default), the package computes a **single shared median center** across all surfaces' points. Every GLB produced in that call is offset by the same origin, so the surfaces remain correctly positioned relative to each other in your 3D scene. This happens automatically — no extra configuration is needed.
193
+
194
+ If you need each surface to be individually centered (e.g. you are processing them in isolation), pass an explicit `[x, y]` pair instead.
195
+
196
+ ---
package/dist/index.d.mts CHANGED
@@ -3,7 +3,9 @@ import { FeatureCollection, LineString } from 'geojson';
3
3
 
4
4
  /**
5
5
  * @param landXmlString
6
- * @param center 3D models don't work well when they're far from origin (coordinate `[0,0,0]`), therefore by default your center is moved to the median of x and y axis of your surface
6
+ * @param center 3D models don't work well when they're far from origin (coordinate `[0,0,0]`), therefore by default your center is moved to the median of x and y axis of your surface.
7
+ * When processing multiple surfaces with `"auto"`, a **single shared center** is computed
8
+ * from all surfaces combined so they remain correctly positioned relative to each other.
7
9
  * @param surfaceId Surface name or index if your LandXML contains multiple surfaces. By default all surfaces are converted and returns an array of glb Uint8Array
8
10
  * @returns {Object[]} glbs - Array of processed glbs (will also return an array when just one surface has been processed)
9
11
  * @returns {string} glbs[].name - Name of surface as defined in LandXML
@@ -11,7 +13,7 @@ import { FeatureCollection, LineString } from 'geojson';
11
13
  * @returns {string} glbs[].sourceFile - Source file of where the LandXML was generated from.
12
14
  * @returns {string} glbs[].timeStamp - Timestamp of when the surface was exported into LandXML
13
15
  * @returns {Uint8Array} glbs[].glb - Uint8Array binary data of glb
14
- * @returns {[number, number]} glbs[].center - Offset center of the processed glb
16
+ * @returns {[number, number]} glbs[].center - Shared offset center applied to all GLBs
15
17
  * @returns {function(): void} glbs[].download - Convenient way to download the GLB, within the filename the new center will be appended.
16
18
  */
17
19
  declare const toGlb: (landXmlString: string, center?: "auto" | "origin" | [
@@ -67,7 +69,7 @@ type GlbAndContoursResult = {
67
69
  wktString?: string;
68
70
  /** Binary GLB data */
69
71
  glb: Uint8Array;
70
- /** XY center used to offset the GLB model from origin */
72
+ /** Shared XY center used to offset all GLB models from origin */
71
73
  center: [x: number, y: number];
72
74
  /** Convenience download trigger (browser only) */
73
75
  download: () => void;
@@ -84,12 +86,16 @@ type GlbAndContoursResult = {
84
86
  * Use this instead of calling `toGlb` + `toGeojsonContours` separately when
85
87
  * you need both outputs, as it eliminates all redundant work.
86
88
  *
89
+ * When processing multiple surfaces with `center: "auto"`, a **single shared
90
+ * center** is computed from all surfaces combined, so every GLB is offset by
91
+ * the same origin and surfaces remain correctly positioned relative to each other.
92
+ *
87
93
  * @param landXmlString Raw LandXML string
88
94
  * @param contourInterval Vertical interval between contour lines (default 2)
89
95
  * @param generateOutline When true, the outline of each surface is appended to
90
96
  * the GeoJSON as a z=0 feature (default true)
91
- * @param center GLB origin strategy: "auto" (median XY), "origin" ([0,0]),
92
- * or an explicit [x, y] pair (default "auto")
97
+ * @param center GLB origin strategy: "auto" (combined median XY of all surfaces),
98
+ * "origin" ([0,0]), or an explicit [x, y] pair (default "auto")
93
99
  * @param surfaceId Surface name or 0-based index to process a single
94
100
  * surface; -1 processes all surfaces (default -1)
95
101
  */
package/dist/index.d.ts CHANGED
@@ -3,7 +3,9 @@ import { FeatureCollection, LineString } from 'geojson';
3
3
 
4
4
  /**
5
5
  * @param landXmlString
6
- * @param center 3D models don't work well when they're far from origin (coordinate `[0,0,0]`), therefore by default your center is moved to the median of x and y axis of your surface
6
+ * @param center 3D models don't work well when they're far from origin (coordinate `[0,0,0]`), therefore by default your center is moved to the median of x and y axis of your surface.
7
+ * When processing multiple surfaces with `"auto"`, a **single shared center** is computed
8
+ * from all surfaces combined so they remain correctly positioned relative to each other.
7
9
  * @param surfaceId Surface name or index if your LandXML contains multiple surfaces. By default all surfaces are converted and returns an array of glb Uint8Array
8
10
  * @returns {Object[]} glbs - Array of processed glbs (will also return an array when just one surface has been processed)
9
11
  * @returns {string} glbs[].name - Name of surface as defined in LandXML
@@ -11,7 +13,7 @@ import { FeatureCollection, LineString } from 'geojson';
11
13
  * @returns {string} glbs[].sourceFile - Source file of where the LandXML was generated from.
12
14
  * @returns {string} glbs[].timeStamp - Timestamp of when the surface was exported into LandXML
13
15
  * @returns {Uint8Array} glbs[].glb - Uint8Array binary data of glb
14
- * @returns {[number, number]} glbs[].center - Offset center of the processed glb
16
+ * @returns {[number, number]} glbs[].center - Shared offset center applied to all GLBs
15
17
  * @returns {function(): void} glbs[].download - Convenient way to download the GLB, within the filename the new center will be appended.
16
18
  */
17
19
  declare const toGlb: (landXmlString: string, center?: "auto" | "origin" | [
@@ -67,7 +69,7 @@ type GlbAndContoursResult = {
67
69
  wktString?: string;
68
70
  /** Binary GLB data */
69
71
  glb: Uint8Array;
70
- /** XY center used to offset the GLB model from origin */
72
+ /** Shared XY center used to offset all GLB models from origin */
71
73
  center: [x: number, y: number];
72
74
  /** Convenience download trigger (browser only) */
73
75
  download: () => void;
@@ -84,12 +86,16 @@ type GlbAndContoursResult = {
84
86
  * Use this instead of calling `toGlb` + `toGeojsonContours` separately when
85
87
  * you need both outputs, as it eliminates all redundant work.
86
88
  *
89
+ * When processing multiple surfaces with `center: "auto"`, a **single shared
90
+ * center** is computed from all surfaces combined, so every GLB is offset by
91
+ * the same origin and surfaces remain correctly positioned relative to each other.
92
+ *
87
93
  * @param landXmlString Raw LandXML string
88
94
  * @param contourInterval Vertical interval between contour lines (default 2)
89
95
  * @param generateOutline When true, the outline of each surface is appended to
90
96
  * the GeoJSON as a z=0 feature (default true)
91
- * @param center GLB origin strategy: "auto" (median XY), "origin" ([0,0]),
92
- * or an explicit [x, y] pair (default "auto")
97
+ * @param center GLB origin strategy: "auto" (combined median XY of all surfaces),
98
+ * "origin" ([0,0]), or an explicit [x, y] pair (default "auto")
93
99
  * @param surfaceId Surface name or 0-based index to process a single
94
100
  * surface; -1 processes all surfaces (default -1)
95
101
  */
package/dist/index.js CHANGED
@@ -287,19 +287,27 @@ var parse_xml_default = parseXML;
287
287
 
288
288
  // src/public/to-glb.ts
289
289
  var toGlb = (landXmlString, center = "auto", surfaceId = -1) => __async(null, null, function* () {
290
- const requestedCenter = center == "origin" ? [0, 0] : center === "auto" ? void 0 : center;
291
290
  let requestedParsedSurfaces = filter_by_surfaceId_default(yield parse_xml_default(landXmlString), surfaceId);
291
+ let resolvedCenter;
292
+ if (center === "origin") {
293
+ resolvedCenter = [0, 0];
294
+ } else if (center === "auto") {
295
+ const allPoints = requestedParsedSurfaces.flatMap((s) => s.surfaceDefinition.points);
296
+ resolvedCenter = findXYAxisMedians(allPoints);
297
+ } else {
298
+ resolvedCenter = center;
299
+ }
292
300
  const glbs = yield Promise.all(
293
301
  requestedParsedSurfaces.map(
294
302
  (surface) => new Promise((resolve, reject) => __async(null, null, function* () {
295
303
  try {
296
- const { glb, center: center2 } = yield get_glb_default(surface, requestedCenter);
304
+ const { glb } = yield get_glb_default(surface, resolvedCenter);
297
305
  const _a = surface, { surfaceDefinition } = _a, rest = __objRest(_a, ["surfaceDefinition"]);
298
306
  resolve(__spreadProps(__spreadValues({}, rest), {
299
307
  glb,
300
- center: center2,
308
+ center: resolvedCenter,
301
309
  download: () => {
302
- download_glb_default(glb, surface.name.replace(/\.xml$/, `${JSON.stringify(center2)}.glb`));
310
+ download_glb_default(glb, surface.name.replace(/\.xml$/, `${JSON.stringify(resolvedCenter)}.glb`));
303
311
  }
304
312
  }));
305
313
  } catch (e) {
@@ -590,13 +598,21 @@ var reproject_geojson_default = reprojectGeoJson;
590
598
 
591
599
  // src/public/to-glb-and-contours.ts
592
600
  var toGlbAndContours = (landXmlString, contourInterval = 2, generateOutline = true, center = "auto", surfaceId = -1) => __async(null, null, function* () {
593
- const requestedCenter = center === "origin" ? [0, 0] : center === "auto" ? void 0 : center;
594
601
  const requestedParsedSurfaces = filter_by_surfaceId_default(yield parse_xml_default(landXmlString), surfaceId);
602
+ let resolvedCenter;
603
+ if (center === "origin") {
604
+ resolvedCenter = [0, 0];
605
+ } else if (center === "auto") {
606
+ const allPoints = requestedParsedSurfaces.flatMap((s) => s.surfaceDefinition.points);
607
+ resolvedCenter = findXYAxisMedians(allPoints);
608
+ } else {
609
+ resolvedCenter = center;
610
+ }
595
611
  const results = yield Promise.all(
596
612
  requestedParsedSurfaces.map((surface) => __async(null, null, function* () {
597
613
  const precomputed = precomputeSurfaceData(surface);
598
- const [{ glb, center: resolvedCenter }, geojson] = yield Promise.all([
599
- get_glb_default(surface, requestedCenter),
614
+ const [{ glb }, geojson] = yield Promise.all([
615
+ get_glb_default(surface, resolvedCenter),
600
616
  get_contours_default(surface, contourInterval, precomputed)
601
617
  ]);
602
618
  if (generateOutline) {
package/dist/index.mjs CHANGED
@@ -250,19 +250,27 @@ var parse_xml_default = parseXML;
250
250
 
251
251
  // src/public/to-glb.ts
252
252
  var toGlb = (landXmlString, center = "auto", surfaceId = -1) => __async(null, null, function* () {
253
- const requestedCenter = center == "origin" ? [0, 0] : center === "auto" ? void 0 : center;
254
253
  let requestedParsedSurfaces = filter_by_surfaceId_default(yield parse_xml_default(landXmlString), surfaceId);
254
+ let resolvedCenter;
255
+ if (center === "origin") {
256
+ resolvedCenter = [0, 0];
257
+ } else if (center === "auto") {
258
+ const allPoints = requestedParsedSurfaces.flatMap((s) => s.surfaceDefinition.points);
259
+ resolvedCenter = findXYAxisMedians(allPoints);
260
+ } else {
261
+ resolvedCenter = center;
262
+ }
255
263
  const glbs = yield Promise.all(
256
264
  requestedParsedSurfaces.map(
257
265
  (surface) => new Promise((resolve, reject) => __async(null, null, function* () {
258
266
  try {
259
- const { glb, center: center2 } = yield get_glb_default(surface, requestedCenter);
267
+ const { glb } = yield get_glb_default(surface, resolvedCenter);
260
268
  const _a = surface, { surfaceDefinition } = _a, rest = __objRest(_a, ["surfaceDefinition"]);
261
269
  resolve(__spreadProps(__spreadValues({}, rest), {
262
270
  glb,
263
- center: center2,
271
+ center: resolvedCenter,
264
272
  download: () => {
265
- download_glb_default(glb, surface.name.replace(/\.xml$/, `${JSON.stringify(center2)}.glb`));
273
+ download_glb_default(glb, surface.name.replace(/\.xml$/, `${JSON.stringify(resolvedCenter)}.glb`));
266
274
  }
267
275
  }));
268
276
  } catch (e) {
@@ -553,13 +561,21 @@ var reproject_geojson_default = reprojectGeoJson;
553
561
 
554
562
  // src/public/to-glb-and-contours.ts
555
563
  var toGlbAndContours = (landXmlString, contourInterval = 2, generateOutline = true, center = "auto", surfaceId = -1) => __async(null, null, function* () {
556
- const requestedCenter = center === "origin" ? [0, 0] : center === "auto" ? void 0 : center;
557
564
  const requestedParsedSurfaces = filter_by_surfaceId_default(yield parse_xml_default(landXmlString), surfaceId);
565
+ let resolvedCenter;
566
+ if (center === "origin") {
567
+ resolvedCenter = [0, 0];
568
+ } else if (center === "auto") {
569
+ const allPoints = requestedParsedSurfaces.flatMap((s) => s.surfaceDefinition.points);
570
+ resolvedCenter = findXYAxisMedians(allPoints);
571
+ } else {
572
+ resolvedCenter = center;
573
+ }
558
574
  const results = yield Promise.all(
559
575
  requestedParsedSurfaces.map((surface) => __async(null, null, function* () {
560
576
  const precomputed = precomputeSurfaceData(surface);
561
- const [{ glb, center: resolvedCenter }, geojson] = yield Promise.all([
562
- get_glb_default(surface, requestedCenter),
577
+ const [{ glb }, geojson] = yield Promise.all([
578
+ get_glb_default(surface, resolvedCenter),
563
579
  get_contours_default(surface, contourInterval, precomputed)
564
580
  ]);
565
581
  if (generateOutline) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "landxml",
3
- "version": "0.7.1",
3
+ "version": "0.8.0",
4
4
  "description": "Parse LandXML surfaces on the modern web.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",