@team-geospan/structuresio 0.0.4 → 0.0.5

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.
Files changed (2) hide show
  1. package/lib/geojson.js +52 -43
  2. package/package.json +1 -1
package/lib/geojson.js CHANGED
@@ -22,56 +22,65 @@
22
22
  import { isCollection } from "./helpers";
23
23
 
24
24
  /**
25
- * toCoordinateArray converts the surface topology to a GeoJSON style
26
- * Polygon geometry coordinates array.
27
- *
28
- * This is written to be as clear and testable as possible.
29
- * There are likely more efficient ways to loop through this loop,
30
- * but this version works and is relatively easy to read.
31
- *
25
+ * simplifyRing converts a single surface ring and coverts it to a list
26
+ * of points.
32
27
  */
33
- export const toCoordinateArray = (surface, edges, points) => {
34
- // the "edges" array is structued similar to a simple features polygon.
35
- // [outer ring, inner ring, inner ring]
36
- // And each ring is composed of [edgeId, edgeId, edgeId]
37
- // edges contains points [pointId, pointId]
38
- const coords = surface.edges.map((edgeIds) => {
39
- const edgePoints = [];
40
- edgeIds.forEach((edgeId, edgeIdx) => {
41
- const edge = edges[edgeId];
42
- // copy the points to ensure the origin edge is not mutated.
43
- const nextPoints = [...edge.points];
44
- if (edgeIdx === 0) {
45
- // determine whether to start the line with the first segment reversed
46
- const testPoints = edges[edgeIds[1]].points;
47
- if (nextPoints[0] === testPoints[0]) {
48
- // flip it
49
- nextPoints.reverse();
50
- }
51
- } else {
52
- // keep the line contiguous, flip the next set of points
53
- // when the lastPoint in the line does not match the
54
- // first point of the next edge.
55
- const lastPoint = edgePoints[edgePoints.length - 1];
56
- if (nextPoints[0] !== lastPoint) {
57
- nextPoints.reverse();
58
- }
28
+ export const simplifyRing = (ringEdges) => {
29
+ if (ringEdges.length === 0) {
30
+ return [];
31
+ }
32
+
33
+ let edges = structuredClone(ringEdges);
34
+ const sortedList = [];
35
+
36
+ sortedList.push(edges.shift());
37
+
38
+ // ensure the iterations of the while loop do not exceed
39
+ // O(n^2), the input edge structure is likely degenerate.
40
+ let maxIter = edges.length * edges.length;
41
+ while (maxIter > 0 && edges.length > 0) {
42
+ for (let i = 0, len = edges.length; i < len; i++) {
43
+ const edge = edges[i];
44
+ const len = sortedList.length - 1;
45
+ if (sortedList[len][1] === edge[0]) {
46
+ sortedList.push(edge);
47
+ edges = edges.slice(0, i).concat(edges.slice(i + 1));
48
+ break;
49
+ } else if (sortedList[len][1] === edge[edge.length - 1]) {
50
+ sortedList.push(edge.reverse());
51
+ edges = edges.slice(0, i).concat(edges.slice(i + 1));
52
+ break;
59
53
  }
60
- // use slice(1) to prevent duplicate points.
61
- nextPoints.slice(1).forEach((p) => edgePoints.push(p));
62
- });
63
- // ensure the polygon is closed.
64
- if (edgePoints[0] !== edgePoints[edgePoints.length - 1]) {
65
- edgePoints.push(edgePoints[0]);
66
54
  }
67
- // convert all the point ids into [x, y, z] coordinates.
68
- return edgePoints.map((ptId) => points[ptId].coordinates);
55
+ maxIter--;
56
+ }
57
+
58
+ // flatten the list
59
+ const asPoints = sortedList.map((edge) => edge[0]);
60
+ // ensure the polygon is closed
61
+ asPoints.push(sortedList[0][0]);
62
+ return asPoints;
63
+ };
64
+
65
+ // surfaceRings returns a list of point ids based on the surfaces edges
66
+ const surfaceRings = (surfaceId, { surfaces, edges }) => {
67
+ return surfaces[surfaceId].edges.map((ring) => {
68
+ return ring.map((edgeId) => {
69
+ return edges[edgeId].points;
70
+ });
69
71
  });
70
- return coords;
71
72
  };
72
73
 
73
74
  const structureToPolygonFeature = ({ surfaces, points, edges }) => {
74
75
  const features = Object.keys(surfaces).map((surfaceId) => {
76
+ const rings = surfaceRings(surfaceId, { surfaces, edges }).map((ring) =>
77
+ simplifyRing(ring),
78
+ );
79
+ // convert all the rings into coordinates
80
+ const coordinates = rings.map((ring) =>
81
+ ring.map((pointId) => points[pointId].coordinates),
82
+ );
83
+
75
84
  return {
76
85
  type: "Feature",
77
86
  properties: {
@@ -81,7 +90,7 @@ const structureToPolygonFeature = ({ surfaces, points, edges }) => {
81
90
  },
82
91
  geometry: {
83
92
  type: "Polygon",
84
- coordinates: toCoordinateArray(surfaces[surfaceId], edges, points),
93
+ coordinates,
85
94
  },
86
95
  };
87
96
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@team-geospan/structuresio",
3
- "version": "0.0.4",
3
+ "version": "0.0.5",
4
4
  "description": "Collection of utilities for working with StructuresJSON",
5
5
  "type": "module",
6
6
  "exports": {