@ifc-lite/create 2.8.0 → 3.1.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.
Files changed (159) hide show
  1. package/README.md +7 -0
  2. package/dist/ifc-creator-alignment-referents.d.ts +35 -0
  3. package/dist/ifc-creator-alignment-referents.d.ts.map +1 -0
  4. package/dist/ifc-creator-alignment-referents.js +89 -0
  5. package/dist/ifc-creator-alignment-referents.js.map +1 -0
  6. package/dist/ifc-creator-alignment-vertical.d.ts +40 -0
  7. package/dist/ifc-creator-alignment-vertical.d.ts.map +1 -0
  8. package/dist/ifc-creator-alignment-vertical.js +182 -0
  9. package/dist/ifc-creator-alignment-vertical.js.map +1 -0
  10. package/dist/ifc-creator-alignment.d.ts +45 -0
  11. package/dist/ifc-creator-alignment.d.ts.map +1 -0
  12. package/dist/ifc-creator-alignment.js +173 -0
  13. package/dist/ifc-creator-alignment.js.map +1 -0
  14. package/dist/ifc-creator-header.d.ts +2 -0
  15. package/dist/ifc-creator-header.d.ts.map +1 -0
  16. package/dist/ifc-creator-header.js +22 -0
  17. package/dist/ifc-creator-header.js.map +1 -0
  18. package/dist/ifc-creator-math.d.ts +37 -5
  19. package/dist/ifc-creator-math.d.ts.map +1 -1
  20. package/dist/ifc-creator-math.js +93 -4
  21. package/dist/ifc-creator-math.js.map +1 -1
  22. package/dist/ifc-creator-relationships.d.ts +43 -0
  23. package/dist/ifc-creator-relationships.d.ts.map +1 -0
  24. package/dist/ifc-creator-relationships.js +38 -0
  25. package/dist/ifc-creator-relationships.js.map +1 -0
  26. package/dist/ifc-creator-styles.d.ts +22 -0
  27. package/dist/ifc-creator-styles.d.ts.map +1 -0
  28. package/dist/ifc-creator-styles.js +50 -0
  29. package/dist/ifc-creator-styles.js.map +1 -0
  30. package/dist/ifc-creator-terrain.d.ts +170 -0
  31. package/dist/ifc-creator-terrain.d.ts.map +1 -0
  32. package/dist/ifc-creator-terrain.js +180 -0
  33. package/dist/ifc-creator-terrain.js.map +1 -0
  34. package/dist/ifc-creator.d.ts +21 -7
  35. package/dist/ifc-creator.d.ts.map +1 -1
  36. package/dist/ifc-creator.js +93 -97
  37. package/dist/ifc-creator.js.map +1 -1
  38. package/dist/in-store/_emit-helpers.d.ts +2 -1
  39. package/dist/in-store/_emit-helpers.d.ts.map +1 -1
  40. package/dist/in-store/_emit-helpers.js +7 -7
  41. package/dist/in-store/_emit-helpers.js.map +1 -1
  42. package/dist/in-store/anchor.d.ts +2 -0
  43. package/dist/in-store/anchor.d.ts.map +1 -1
  44. package/dist/in-store/anchor.js.map +1 -1
  45. package/dist/in-store/apply-style.d.ts +3 -6
  46. package/dist/in-store/apply-style.d.ts.map +1 -1
  47. package/dist/in-store/apply-style.js +3 -77
  48. package/dist/in-store/apply-style.js.map +1 -1
  49. package/dist/in-store/column.d.ts.map +1 -1
  50. package/dist/in-store/column.js +2 -0
  51. package/dist/in-store/column.js.map +1 -1
  52. package/dist/in-store/door.d.ts.map +1 -1
  53. package/dist/in-store/door.js +2 -0
  54. package/dist/in-store/door.js.map +1 -1
  55. package/dist/in-store/extract-walls.d.ts +1 -1
  56. package/dist/in-store/extract-walls.d.ts.map +1 -1
  57. package/dist/in-store/extract-walls.js +37 -55
  58. package/dist/in-store/extract-walls.js.map +1 -1
  59. package/dist/in-store/generate-spaces-all.d.ts +6 -2
  60. package/dist/in-store/generate-spaces-all.d.ts.map +1 -1
  61. package/dist/in-store/generate-spaces-all.js +33 -9
  62. package/dist/in-store/generate-spaces-all.js.map +1 -1
  63. package/dist/in-store/generate-spaces.js +1 -1
  64. package/dist/in-store/generate-spaces.js.map +1 -1
  65. package/dist/in-store/placement-frame.d.ts +8 -0
  66. package/dist/in-store/placement-frame.d.ts.map +1 -1
  67. package/dist/in-store/placement-frame.js.map +1 -1
  68. package/dist/in-store/plate.d.ts.map +1 -1
  69. package/dist/in-store/plate.js +4 -0
  70. package/dist/in-store/plate.js.map +1 -1
  71. package/dist/in-store/resolve-anchor.d.ts +4 -2
  72. package/dist/in-store/resolve-anchor.d.ts.map +1 -1
  73. package/dist/in-store/resolve-anchor.js +79 -92
  74. package/dist/in-store/resolve-anchor.js.map +1 -1
  75. package/dist/in-store/resolve-source.d.ts +2 -1
  76. package/dist/in-store/resolve-source.d.ts.map +1 -1
  77. package/dist/in-store/resolve-source.js +49 -49
  78. package/dist/in-store/resolve-source.js.map +1 -1
  79. package/dist/in-store/roof.d.ts.map +1 -1
  80. package/dist/in-store/roof.js +4 -0
  81. package/dist/in-store/roof.js.map +1 -1
  82. package/dist/in-store/slab.d.ts.map +1 -1
  83. package/dist/in-store/slab.js +4 -0
  84. package/dist/in-store/slab.js.map +1 -1
  85. package/dist/in-store/space.d.ts.map +1 -1
  86. package/dist/in-store/space.js +4 -0
  87. package/dist/in-store/space.js.map +1 -1
  88. package/dist/in-store/spatial-children.d.ts +52 -0
  89. package/dist/in-store/spatial-children.d.ts.map +1 -0
  90. package/dist/in-store/spatial-children.js +112 -0
  91. package/dist/in-store/spatial-children.js.map +1 -0
  92. package/dist/in-store/spatial-zone.d.ts.map +1 -1
  93. package/dist/in-store/spatial-zone.js +5 -5
  94. package/dist/in-store/spatial-zone.js.map +1 -1
  95. package/dist/in-store/style-entity-reader.d.ts +14 -0
  96. package/dist/in-store/style-entity-reader.d.ts.map +1 -0
  97. package/dist/in-store/style-entity-reader.js +58 -0
  98. package/dist/in-store/style-entity-reader.js.map +1 -0
  99. package/dist/in-store/wall.d.ts.map +1 -1
  100. package/dist/in-store/wall.js +4 -14
  101. package/dist/in-store/wall.js.map +1 -1
  102. package/dist/in-store/window.d.ts.map +1 -1
  103. package/dist/in-store/window.js +2 -0
  104. package/dist/in-store/window.js.map +1 -1
  105. package/dist/index.d.ts +12 -1
  106. package/dist/index.d.ts.map +1 -1
  107. package/dist/index.js +5 -0
  108. package/dist/index.js.map +1 -1
  109. package/dist/landxml/alignment-mapping.d.ts +98 -0
  110. package/dist/landxml/alignment-mapping.d.ts.map +1 -0
  111. package/dist/landxml/alignment-mapping.js +282 -0
  112. package/dist/landxml/alignment-mapping.js.map +1 -0
  113. package/dist/landxml/alignment-record.d.ts +18 -0
  114. package/dist/landxml/alignment-record.d.ts.map +1 -0
  115. package/dist/landxml/alignment-record.js +63 -0
  116. package/dist/landxml/alignment-record.js.map +1 -0
  117. package/dist/landxml/coordinate-plausibility.d.ts +54 -0
  118. package/dist/landxml/coordinate-plausibility.d.ts.map +1 -0
  119. package/dist/landxml/coordinate-plausibility.js +59 -0
  120. package/dist/landxml/coordinate-plausibility.js.map +1 -0
  121. package/dist/landxml/landxml-to-ifc.d.ts +45 -0
  122. package/dist/landxml/landxml-to-ifc.d.ts.map +1 -0
  123. package/dist/landxml/landxml-to-ifc.js +203 -0
  124. package/dist/landxml/landxml-to-ifc.js.map +1 -0
  125. package/dist/landxml/profile-geometry.d.ts +50 -0
  126. package/dist/landxml/profile-geometry.d.ts.map +1 -0
  127. package/dist/landxml/profile-geometry.js +221 -0
  128. package/dist/landxml/profile-geometry.js.map +1 -0
  129. package/dist/landxml/profile-mapping.d.ts +36 -0
  130. package/dist/landxml/profile-mapping.d.ts.map +1 -0
  131. package/dist/landxml/profile-mapping.js +181 -0
  132. package/dist/landxml/profile-mapping.js.map +1 -0
  133. package/dist/landxml/profile-record.d.ts +46 -0
  134. package/dist/landxml/profile-record.d.ts.map +1 -0
  135. package/dist/landxml/profile-record.js +38 -0
  136. package/dist/landxml/profile-record.js.map +1 -0
  137. package/dist/landxml/refusals.d.ts +45 -0
  138. package/dist/landxml/refusals.d.ts.map +1 -0
  139. package/dist/landxml/refusals.js +141 -0
  140. package/dist/landxml/refusals.js.map +1 -0
  141. package/dist/landxml/result-types.d.ts +78 -0
  142. package/dist/landxml/result-types.d.ts.map +1 -0
  143. package/dist/landxml/result-types.js +5 -0
  144. package/dist/landxml/result-types.js.map +1 -0
  145. package/dist/landxml/source-types.d.ts +169 -0
  146. package/dist/landxml/source-types.d.ts.map +1 -0
  147. package/dist/landxml/source-types.js +5 -0
  148. package/dist/landxml/source-types.js.map +1 -0
  149. package/dist/landxml/station-equations.d.ts +69 -0
  150. package/dist/landxml/station-equations.d.ts.map +1 -0
  151. package/dist/landxml/station-equations.js +140 -0
  152. package/dist/landxml/station-equations.js.map +1 -0
  153. package/dist/landxml/writers.d.ts +33 -0
  154. package/dist/landxml/writers.d.ts.map +1 -0
  155. package/dist/landxml/writers.js +160 -0
  156. package/dist/landxml/writers.js.map +1 -0
  157. package/dist/types.d.ts +13 -2
  158. package/dist/types.d.ts.map +1 -1
  159. package/package.json +6 -6
@@ -0,0 +1,181 @@
1
+ /* This Source Code Form is subject to the terms of the Mozilla Public
2
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
+ /**
5
+ * Which LandXML profiles become an `IfcAlignmentVertical`, and which are
6
+ * refused by name (mapping spec §12.2).
7
+ *
8
+ * Like `alignment-mapping.ts`, no STEP is written here, so the export dialog's
9
+ * pre-flight and the export itself give the same answer. The geometry lives in
10
+ * `profile-geometry.ts`; this module decides linkage and runs the mapping.
11
+ */
12
+ import { ALIGNMENT_POSITION_TOLERANCE_M, isAlignmentRecord } from './alignment-mapping.js';
13
+ import { ProfileRefusal, assembleProfile, checkProfile, curveSegments, refuseProfile, } from './profile-geometry.js';
14
+ import { profileRecordProblem } from './profile-record.js';
15
+ import { distancesForStation } from './station-equations.js';
16
+ function mapDesignProfile(profile, distanceOf, horizontalLength, units) {
17
+ if (profile.pvis.length < 2)
18
+ refuseProfile('it has fewer than two PVIs, so it has no grade');
19
+ const vertices = profile.pvis.map((pvi, index) => {
20
+ if (pvi.elevation === null || !Number.isFinite(pvi.elevation) || !Number.isFinite(pvi.station)) {
21
+ refuseProfile(`its PVI ${index + 1} has no finite station and elevation`);
22
+ }
23
+ return {
24
+ sourceId: pvi.sourceId,
25
+ distAlong: distanceOf(pvi.station, `its PVI ${index + 1}`),
26
+ height: pvi.elevation * units.elevationScaleToMeters,
27
+ };
28
+ });
29
+ vertices.slice(1).forEach((vertex, index) => {
30
+ if (vertex.distAlong <= vertices[index].distAlong)
31
+ refuseProfile(`its PVI ${index + 2} does not advance in station`);
32
+ });
33
+ const start = vertices[0].distAlong;
34
+ const end = vertices[vertices.length - 1].distAlong;
35
+ if (start < -ALIGNMENT_POSITION_TOLERANCE_M || end > horizontalLength + ALIGNMENT_POSITION_TOLERANCE_M) {
36
+ refuseProfile(`it runs from ${start.toFixed(3)} m to ${end.toFixed(3)} m along an alignment ${horizontalLength.toFixed(3)} m long`);
37
+ }
38
+ const gradeOf = (a, b) => (b.height - a.height) / (b.distAlong - a.distAlong);
39
+ const curves = vertices.map(() => []);
40
+ const seen = new Set();
41
+ profile.verticalCurves.forEach((curve, curveIndex) => {
42
+ const label = `vertical curve ${curveIndex + 1}`;
43
+ // The parser records a curve's PVI in `pvis` with the same station and
44
+ // elevation — the same pairing `rust/landxml`'s profile evaluator uses.
45
+ const index = profile.pvis.findIndex((pvi) => pvi.station === curve.station && pvi.elevation === curve.elevation);
46
+ if (index <= 0 || index >= vertices.length - 1) {
47
+ refuseProfile(`${label} is not at an interior PVI, so it has no grade on both sides`);
48
+ }
49
+ if (seen.has(index))
50
+ refuseProfile(`PVI ${index + 1} carries more than one vertical curve`);
51
+ seen.add(index);
52
+ const before = vertices[index - 1];
53
+ const pvi = vertices[index];
54
+ const after = vertices[index + 1];
55
+ curves[index] = curveSegments(curve, pvi, gradeOf(before, pvi), gradeOf(pvi, after), units, label);
56
+ });
57
+ const segments = assembleProfile(profile.sourceId, vertices, curves);
58
+ checkProfile(segments, vertices, curves);
59
+ return segments;
60
+ }
61
+ /**
62
+ * Map every profile onto the alignments `alignmentMapping` writes, and refuse
63
+ * the rest by name (§12.2). `alignments` is the source's raw list — a
64
+ * profile's link is checked against it, not only against the written ones, so
65
+ * a profile of a refused alignment says so rather than reading as unlinked.
66
+ */
67
+ export function mapProfiles(profiles, alignments, alignmentMapping, units, stationing = new Map()) {
68
+ const result = { mapped: [], refused: [] };
69
+ const records = (alignments ?? []).filter(isAlignmentRecord);
70
+ const written = new Map(alignmentMapping.mapped.map((alignment) => [alignment.sourceId, alignment]));
71
+ const designCount = new Map();
72
+ const valid = [];
73
+ (profiles ?? []).forEach((candidate, index) => {
74
+ const problem = profileRecordProblem(candidate);
75
+ if (problem === null) {
76
+ valid.push(candidate);
77
+ return;
78
+ }
79
+ const header = candidate;
80
+ const named = typeof header?.sourceId === 'string' && typeof header.name === 'string';
81
+ result.refused.push({
82
+ sourceId: named ? header.sourceId : `profile[${index}]`,
83
+ name: named ? header.name || header.sourceId : `profile ${index + 1}`,
84
+ reason: problem,
85
+ });
86
+ });
87
+ // A profile is linked when its alignment exists and, if that alignment
88
+ // lists its profiles, lists this one. Only LINKED design profiles compete
89
+ // for the alignment's one vertical layout: an unlinked sibling is refused
90
+ // on its own and must not make the linked one look ambiguous (#5930 review).
91
+ const alignmentOf = (profile) => records.find((record) => record.sourceId === profile.parentAlignmentSourceId);
92
+ const isLinked = (profile) => {
93
+ const alignment = alignmentOf(profile);
94
+ const listed = alignment?.profileSourceIds ?? [];
95
+ return alignment !== undefined && (listed.length === 0 || listed.includes(profile.sourceId));
96
+ };
97
+ for (const profile of valid) {
98
+ if (profile.kind === 'design' && isLinked(profile)) {
99
+ designCount.set(profile.parentAlignmentSourceId, (designCount.get(profile.parentAlignmentSourceId) ?? 0) + 1);
100
+ }
101
+ }
102
+ for (const profile of valid) {
103
+ const refuse = (reason) => {
104
+ result.refused.push({ sourceId: profile.sourceId, name: profile.name || profile.sourceId, reason });
105
+ };
106
+ const alignment = alignmentOf(profile);
107
+ // An empty `profileSourceIds` declares nothing; a non-empty one must agree.
108
+ if (!alignment || !isLinked(profile)) {
109
+ refuse('it is not linked to any alignment in the file');
110
+ continue;
111
+ }
112
+ const alignmentName = alignment.name || alignment.sourceId;
113
+ const mapped = written.get(alignment.sourceId);
114
+ if (!mapped || units === null) {
115
+ refuse(`its alignment '${alignmentName}' is not written, so there is no horizontal to measure it along`);
116
+ continue;
117
+ }
118
+ if (profile.kind === 'sampled') {
119
+ refuse('it is a sampled ground profile (ProfSurf), not a design vertical layout');
120
+ continue;
121
+ }
122
+ const designs = designCount.get(alignment.sourceId) ?? 0;
123
+ if (designs > 1) {
124
+ refuse(`its alignment '${alignmentName}' has ${designs} design profiles, and IFC nests one vertical layout under an alignment; choosing one would be a guess`);
125
+ continue;
126
+ }
127
+ const horizontalLength = mapped.segments.reduce((total, segment) => total + segment.length, 0);
128
+ const distanceOf = profileDistances(alignment, mapped.startStation, horizontalLength, units, stationing);
129
+ if (typeof distanceOf === 'string') {
130
+ refuse(distanceOf);
131
+ continue;
132
+ }
133
+ try {
134
+ result.mapped.push({
135
+ sourceId: profile.sourceId,
136
+ name: profile.name,
137
+ alignmentSourceId: alignment.sourceId,
138
+ segments: mapDesignProfile(profile, distanceOf, horizontalLength, units),
139
+ });
140
+ }
141
+ catch (error) {
142
+ if (!(error instanceof ProfileRefusal))
143
+ throw error;
144
+ refuse(error.message);
145
+ }
146
+ }
147
+ return result;
148
+ }
149
+ /**
150
+ * How a profile's stations become distances along its alignment (§14.5).
151
+ *
152
+ * Without station equations, linearly from the start station. With written
153
+ * ones, through the displayed stationing they define: a PVI station must occur
154
+ * at exactly one place along the alignment, and one in a forward jump's gap or
155
+ * displayed twice after a backward jump is refused by name, never guessed. When
156
+ * the alignment's equations were themselves refused (§14.2) there is no
157
+ * stationing to read the profile against, so it is refused as a whole.
158
+ */
159
+ function profileDistances(alignment, startStation, length, units, stationing) {
160
+ const scale = units.linearScaleToMeters;
161
+ if ((alignment.stationEquations?.length ?? 0) === 0) {
162
+ return (station) => station * scale - startStation;
163
+ }
164
+ const alignmentName = alignment.name || alignment.sourceId;
165
+ const mapping = stationing.get(alignment.sourceId);
166
+ if (!mapping || mapping.refusal !== null) {
167
+ return `its alignment '${alignmentName}' has station equations that are not written, so its stations cannot be placed along it`;
168
+ }
169
+ return (station, label) => {
170
+ const places = distancesForStation(station * scale, startStation, mapping.equations, length);
171
+ if (places.length === 0) {
172
+ refuseProfile(`${label} is at station ${station}, which falls in a station-equation gap of '${alignmentName}'`);
173
+ }
174
+ if (places.length > 1) {
175
+ refuseProfile(`${label} is at station ${station}, which '${alignmentName}' displays at ${places.length} places `
176
+ + `(${places.map((place) => `${place.toFixed(3)} m`).join(', ')}); choosing one would be a guess`);
177
+ }
178
+ return places[0];
179
+ };
180
+ }
181
+ //# sourceMappingURL=profile-mapping.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile-mapping.js","sourceRoot":"","sources":["../../src/landxml/profile-mapping.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * The shape of one `LandXmlIfcSource.profiles` record, and its run-time check
3
+ * (mapping spec §12).
4
+ *
5
+ * `profiles` stays `unknown[]` on the source (narrowing a published input type
6
+ * is a breaking change, #5370 review), so every record is checked here before
7
+ * the mapper reads it — exactly as `alignment-record.ts` does for alignments.
8
+ * A record that fails is refused by name, never read into.
9
+ *
10
+ * The shapes mirror the viewer's `LandXmlProfile` field for field, so the
11
+ * viewer's parsed document satisfies them without a translation layer.
12
+ */
13
+ /** One `PVI` (or sampled station/elevation pair), in the file's declared units. */
14
+ export interface LandXmlIfcProfilePoint {
15
+ sourceId: string;
16
+ /** A STATION, not a distance along: `staStart` has not been subtracted. */
17
+ station: number;
18
+ elevation: number | null;
19
+ }
20
+ /**
21
+ * A `ParaCurve`, `UnsymParaCurve` or `CircCurve`, anchored at its PVI. The
22
+ * parser also records that PVI in `pvis`, with the same station and elevation.
23
+ */
24
+ export interface LandXmlIfcVerticalCurve {
25
+ sourceId: string;
26
+ kind: 'parabolic' | 'unsymmetrical_parabolic' | 'circular';
27
+ station: number;
28
+ elevation: number | null;
29
+ length: number | null;
30
+ lengthIn: number | null;
31
+ lengthOut: number | null;
32
+ radius: number | null;
33
+ }
34
+ /** A `ProfAlign` (`kind: 'design'`) or `ProfSurf` (`kind: 'sampled'`) under an alignment. */
35
+ export interface LandXmlIfcProfile {
36
+ sourceId: string;
37
+ parentAlignmentSourceId: string;
38
+ name: string;
39
+ kind: 'design' | 'sampled';
40
+ /** Authored order. */
41
+ pvis: readonly LandXmlIfcProfilePoint[];
42
+ verticalCurves: readonly LandXmlIfcVerticalCurve[];
43
+ }
44
+ /** Why this record is not a `LandXmlIfcProfile`, or `null` when it is. */
45
+ export declare function profileRecordProblem(value: unknown): string | null;
46
+ //# sourceMappingURL=profile-record.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile-record.d.ts","sourceRoot":"","sources":["../../src/landxml/profile-record.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;GAWG;AAEH,mFAAmF;AACnF,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,2EAA2E;IAC3E,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED;;;GAGG;AACH,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,WAAW,GAAG,yBAAyB,GAAG,UAAU,CAAC;IAC3D,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED,6FAA6F;AAC7F,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,uBAAuB,EAAE,MAAM,CAAC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC3B,sBAAsB;IACtB,IAAI,EAAE,SAAS,sBAAsB,EAAE,CAAC;IACxC,cAAc,EAAE,SAAS,uBAAuB,EAAE,CAAC;CACpD;AAqBD,0EAA0E;AAC1E,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAgBlE"}
@@ -0,0 +1,38 @@
1
+ /* This Source Code Form is subject to the terms of the Mozilla Public
2
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
+ const isObject = (value) => typeof value === 'object' && value !== null;
5
+ const isNumber = (value) => typeof value === 'number';
6
+ const isOptionalNumber = (value) => value === null || isNumber(value);
7
+ function isPoint(value) {
8
+ return isObject(value) && typeof value.sourceId === 'string' && isNumber(value.station)
9
+ && isOptionalNumber(value.elevation);
10
+ }
11
+ function isCurve(value) {
12
+ return isObject(value) && typeof value.sourceId === 'string'
13
+ && (value.kind === 'parabolic' || value.kind === 'unsymmetrical_parabolic' || value.kind === 'circular')
14
+ && isNumber(value.station) && isOptionalNumber(value.elevation)
15
+ && isOptionalNumber(value.length) && isOptionalNumber(value.lengthIn)
16
+ && isOptionalNumber(value.lengthOut) && isOptionalNumber(value.radius);
17
+ }
18
+ /** Why this record is not a `LandXmlIfcProfile`, or `null` when it is. */
19
+ export function profileRecordProblem(value) {
20
+ if (!isObject(value)
21
+ || typeof value.sourceId !== 'string'
22
+ || typeof value.parentAlignmentSourceId !== 'string'
23
+ || typeof value.name !== 'string'
24
+ || (value.kind !== 'design' && value.kind !== 'sampled')
25
+ || !Array.isArray(value.pvis)
26
+ || !Array.isArray(value.verticalCurves)) {
27
+ return 'it is not a profile record (it needs a sourceId, a parentAlignmentSourceId, a name, a design or '
28
+ + 'sampled kind, and PVI and vertical-curve lists)';
29
+ }
30
+ const badPoint = value.pvis.findIndex((point) => !isPoint(point));
31
+ if (badPoint !== -1)
32
+ return `its PVI ${badPoint + 1} is not a station/elevation record`;
33
+ const badCurve = value.verticalCurves.findIndex((curve) => !isCurve(curve));
34
+ if (badCurve !== -1)
35
+ return `its vertical curve ${badCurve + 1} is not a ParaCurve, UnsymParaCurve or CircCurve record`;
36
+ return null;
37
+ }
38
+ //# sourceMappingURL=profile-record.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile-record.js","sourceRoot":"","sources":["../../src/landxml/profile-record.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAmD/D,MAAM,QAAQ,GAAG,CAAC,KAAc,EAAmB,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC;AAClG,MAAM,QAAQ,GAAG,CAAC,KAAc,EAAW,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC;AACxE,MAAM,gBAAgB,GAAG,CAAC,KAAc,EAAW,EAAE,CAAC,KAAK,KAAK,IAAI,IAAI,QAAQ,CAAC,KAAK,CAAC,CAAC;AAExF,SAAS,OAAO,CAAC,KAAc;IAC7B,OAAO,QAAQ,CAAC,KAAK,CAAC,IAAI,OAAO,KAAK,CAAC,QAAQ,KAAK,QAAQ,IAAI,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC;WAClF,gBAAgB,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;AACzC,CAAC;AAED,SAAS,OAAO,CAAC,KAAc;IAC7B,OAAO,QAAQ,CAAC,KAAK,CAAC,IAAI,OAAO,KAAK,CAAC,QAAQ,KAAK,QAAQ;WACvD,CAAC,KAAK,CAAC,IAAI,KAAK,WAAW,IAAI,KAAK,CAAC,IAAI,KAAK,yBAAyB,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,CAAC;WACrG,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,gBAAgB,CAAC,KAAK,CAAC,SAAS,CAAC;WAC5D,gBAAgB,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,gBAAgB,CAAC,KAAK,CAAC,QAAQ,CAAC;WAClE,gBAAgB,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,gBAAgB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;AAC3E,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,oBAAoB,CAAC,KAAc;IACjD,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;WACf,OAAO,KAAK,CAAC,QAAQ,KAAK,QAAQ;WAClC,OAAO,KAAK,CAAC,uBAAuB,KAAK,QAAQ;WACjD,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ;WAC9B,CAAC,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC;WACrD,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC;WAC1B,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE,CAAC;QAC1C,OAAO,kGAAkG;cACrG,iDAAiD,CAAC;IACxD,CAAC;IACD,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;IAClE,IAAI,QAAQ,KAAK,CAAC,CAAC;QAAE,OAAO,WAAW,QAAQ,GAAG,CAAC,oCAAoC,CAAC;IACxF,MAAM,QAAQ,GAAG,KAAK,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;IAC5E,IAAI,QAAQ,KAAK,CAAC,CAAC;QAAE,OAAO,sBAAsB,QAAQ,GAAG,CAAC,yDAAyD,CAAC;IACxH,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Enumerate the LandXML record families a source carries that v1 does not map.
3
+ *
4
+ * §5 of the mapping spec: named, never silently dropped. The point of counting
5
+ * them is that "this file has 14 alignments and none of them are in your IFC"
6
+ * is actionable, while a missing record is not even noticeable.
7
+ */
8
+ import type { LandXmlIfcSource, LandXmlIfcSurface } from './source-types.js';
9
+ import type { LandXmlRefusal } from './result-types.js';
10
+ import { type AlignmentMapping, type RefusedAlignment } from './alignment-mapping.js';
11
+ import { type ProfileMapping, type RefusedProfile } from './profile-mapping.js';
12
+ import { type StationEquationMapping } from './station-equations.js';
13
+ /**
14
+ * A surface v1 can write: a rendered TIN with vertices and at least one
15
+ * VISIBLE face. A surface whose every face is an authored `<F i="true">` draws
16
+ * nothing, so it is refused by name like any other non-rendered surface rather
17
+ * than vanishing from an otherwise successful export.
18
+ */
19
+ export declare function isMappableSurface(surface: LandXmlIfcSurface): boolean;
20
+ /**
21
+ * Every out-of-scope family the source actually contains, with its count.
22
+ *
23
+ * A family with zero records is absent from the list rather than present with
24
+ * `count: 0` — a refusal the user cannot act on is noise, and "0 parcels were
25
+ * not exported" is exactly that.
26
+ */
27
+ /** The alignment mapping for a source, computed the one way both the plan and the export use. */
28
+ export declare function alignmentMappingOf(source: LandXmlIfcSource): AlignmentMapping;
29
+ export declare function collectRefusals(source: LandXmlIfcSource, alignmentMapping?: AlignmentMapping, profileMapping?: ProfileMapping, stationing?: ReadonlyMap<string, StationEquationMapping>): LandXmlRefusal[];
30
+ /**
31
+ * Name each refused alignment and why. A count alone ("2 alignments") leaves
32
+ * the operator unable to tell a spiral type from a gap from a sign problem.
33
+ */
34
+ export declare function alignmentRefusalMessage(refused: readonly RefusedAlignment[]): string;
35
+ /** Name each refused profile and why (§12.6), as alignments are. */
36
+ export declare function profileRefusalMessage(refused: readonly RefusedProfile[]): string;
37
+ /**
38
+ * The sentence shown when nothing in the source is mappable.
39
+ *
40
+ * It names what the file *does* hold. A bare "nothing to export" leaves the
41
+ * operator to guess whether the file is empty, unsupported, or broken — and
42
+ * for the alignment-only files §9.4 is about, the answer is none of those.
43
+ */
44
+ export declare function refusalReason(refusals: readonly LandXmlRefusal[]): string;
45
+ //# sourceMappingURL=refusals.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"refusals.d.ts","sourceRoot":"","sources":["../../src/landxml/refusals.ts"],"names":[],"mappings":"AAIA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAuB,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAClG,OAAO,KAAK,EAAE,cAAc,EAAwB,MAAM,mBAAmB,CAAC;AAC9E,OAAO,EACgD,KAAK,gBAAgB,EAAE,KAAK,gBAAgB,EAClG,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAe,KAAK,cAAc,EAAE,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC7F,OAAO,EAAsB,KAAK,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAmCzF;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAIrE;AAED;;;;;;GAMG;AACH,iGAAiG;AACjG,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,gBAAgB,GAAG,gBAAgB,CAE7E;AAED,wBAAgB,eAAe,CAC7B,MAAM,EAAE,gBAAgB,EAAE,gBAAgB,GAAE,gBAA6C,EACzF,cAAc,GAAE,cAEf,EACD,UAAU,GAAE,WAAW,CAAC,MAAM,EAAE,sBAAsB,CAAgD,GACrG,cAAc,EAAE,CA2ClB;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,SAAS,gBAAgB,EAAE,GAAG,MAAM,CAOpF;AAED,oEAAoE;AACpE,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,SAAS,cAAc,EAAE,GAAG,MAAM,CAKhF;AAcD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,SAAS,cAAc,EAAE,GAAG,MAAM,CAOzE"}
@@ -0,0 +1,141 @@
1
+ /* This Source Code Form is subject to the terms of the Mozilla Public
2
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
+ import { cogoPointResolver, isAlignmentRecord, mapAlignments, } from './alignment-mapping.js';
5
+ import { mapProfiles } from './profile-mapping.js';
6
+ import { stationEquationsOf } from './station-equations.js';
7
+ /**
8
+ * Why each family is out of scope, in the operator's terms.
9
+ *
10
+ * Kept as one table rather than inline strings so the export dialog, the
11
+ * provenance property set and the refusal report cannot drift apart on what
12
+ * the same family is called.
13
+ */
14
+ const FAMILY_REASONS = {
15
+ alignments: 'an alignment is written only when every horizontal segment is a line, circular arc or clothoid that reproduces its authored end point; one that does not is refused whole, because a gap would make every later station wrong',
16
+ profiles: 'a profile is written, as IfcAlignmentVertical, only when it is the one design profile of a written alignment and its grades and vertical curves reproduce every authored PVI; one that does not is refused whole',
17
+ 'cross-sections': 'cross sections have no v1 mapping — they are sampled along an alignment, which v1 does not carry',
18
+ roadways: 'roadways have no v1 mapping — they compose alignments and surfaces, and v1 carries only the surfaces',
19
+ parcels: 'parcel boundaries have no v1 mapping',
20
+ monuments: 'survey monuments have no v1 mapping; only CgPoints become IfcAnnotation/.SURVEY.',
21
+ 'plan-features': 'plan features have no v1 mapping',
22
+ 'pipe-networks': 'pipe networks, structures and pipes have no v1 mapping',
23
+ 'surface-boundaries': 'surface boundary polylines are not written; only the triangulated surface itself is',
24
+ 'surface-breaklines': 'surface breaklines are not written; only the triangulated surface itself is',
25
+ 'surface-contours': 'surface contour lines are not written; only the triangulated surface itself is',
26
+ 'non-rendered-surfaces': 'surfaces that carry no numeric, renderable triangulation (or whose every face is hidden) cannot become an IfcTriangulatedIrregularNetwork',
27
+ 'unlocated-cgpoints': 'CgPoints that carry only a point reference and no coordinates of their own have nothing to place',
28
+ 'station-equations': "an alignment's station equations are written all or none, because a dropped one would make every later station wrong; the alignment is still written, with its start station only",
29
+ cant: 'cant (rail superelevation) has no mapping; the alignment is written with its horizontal layout only',
30
+ superelevation: 'road superelevation has no mapping; the alignment is written with its horizontal layout only',
31
+ };
32
+ function countAcrossSurfaces(surfaces, pick) {
33
+ return surfaces.reduce((total, surface) => total + (pick(surface)?.length ?? 0), 0);
34
+ }
35
+ /**
36
+ * A surface v1 can write: a rendered TIN with vertices and at least one
37
+ * VISIBLE face. A surface whose every face is an authored `<F i="true">` draws
38
+ * nothing, so it is refused by name like any other non-rendered surface rather
39
+ * than vanishing from an otherwise successful export.
40
+ */
41
+ export function isMappableSurface(surface) {
42
+ return surface.renderState === 'rendered'
43
+ && surface.points.length > 0
44
+ && surface.faces.some((_, ordinal) => surface.faceVisibility?.[ordinal] !== false);
45
+ }
46
+ /**
47
+ * Every out-of-scope family the source actually contains, with its count.
48
+ *
49
+ * A family with zero records is absent from the list rather than present with
50
+ * `count: 0` — a refusal the user cannot act on is noise, and "0 parcels were
51
+ * not exported" is exactly that.
52
+ */
53
+ /** The alignment mapping for a source, computed the one way both the plan and the export use. */
54
+ export function alignmentMappingOf(source) {
55
+ return mapAlignments(source.alignments, source.units, false, cogoPointResolver(source.plan?.cogoPoints));
56
+ }
57
+ export function collectRefusals(source, alignmentMapping = alignmentMappingOf(source), profileMapping = mapProfiles(source.profiles, source.alignments, alignmentMapping, source.units, stationEquationsOf(source, alignmentMapping)), stationing = stationEquationsOf(source, alignmentMapping)) {
58
+ // Only the alignments that are WRITTEN carry these on into the IFC; a
59
+ // refused alignment takes its station equations and cant with it, and
60
+ // counting them twice would misstate what is missing.
61
+ const written = new Set(alignmentMapping.mapped.map((alignment) => alignment.sourceId));
62
+ const writtenAlignments = (source.alignments ?? [])
63
+ .filter(isAlignmentRecord)
64
+ .filter((alignment) => written.has(alignment.sourceId));
65
+ const counts = [
66
+ ['alignments', alignmentMapping.refused.length],
67
+ // Written as IfcReferents (§14) unless refused, all or none, per alignment.
68
+ ['station-equations', writtenAlignments.reduce((n, a) => n + (stationing.get(a.sourceId)?.refusal ? (a.stationEquations?.length ?? 0) : 0), 0)],
69
+ ['cant', writtenAlignments.filter((a) => a.cant || (a.cantStations?.length ?? 0) > 0).length],
70
+ ['superelevation', writtenAlignments.reduce((n, a) => n + (a.superelevations?.length ?? 0), 0)],
71
+ ['profiles', profileMapping.refused.length],
72
+ ['cross-sections', (source.crossSections?.length ?? 0) + (source.crossSectionSurfaces?.length ?? 0)],
73
+ ['roadways', source.roadways?.length ?? 0],
74
+ ['parcels', source.plan?.parcels?.length ?? 0],
75
+ ['monuments', source.plan?.monuments?.length ?? 0],
76
+ ['plan-features', source.plan?.planFeatures?.length ?? 0],
77
+ ['pipe-networks', source.pipeNetworks?.networks?.length ?? 0],
78
+ ['surface-boundaries', countAcrossSurfaces(source.surfaces, (s) => s.boundaries)],
79
+ ['surface-breaklines', countAcrossSurfaces(source.surfaces, (s) => s.breaklines)],
80
+ ['surface-contours', countAcrossSurfaces(source.surfaces, (s) => s.contours)],
81
+ ['non-rendered-surfaces', source.surfaces.filter((s) => !isMappableSurface(s)).length],
82
+ ['unlocated-cgpoints', (source.plan?.cogoPoints ?? []).filter((point) => point.point === null).length],
83
+ ];
84
+ return counts
85
+ .filter(([, count]) => count > 0)
86
+ .map(([family, count]) => ({
87
+ family,
88
+ count,
89
+ message: family === 'alignments'
90
+ ? alignmentRefusalMessage(alignmentMapping.refused)
91
+ : family === 'profiles'
92
+ ? profileRefusalMessage(profileMapping.refused)
93
+ : family === 'station-equations'
94
+ ? stationEquationRefusalMessage(count, writtenAlignments, stationing)
95
+ : `${count} ${family.replace(/-/g, ' ')} record${count === 1 ? '' : 's'} will not be included: ${FAMILY_REASONS[family]}.`,
96
+ }));
97
+ }
98
+ /**
99
+ * Name each refused alignment and why. A count alone ("2 alignments") leaves
100
+ * the operator unable to tell a spiral type from a gap from a sign problem.
101
+ */
102
+ export function alignmentRefusalMessage(refused) {
103
+ // Every one is named: an alignment left out as "and N more" is one the
104
+ // operator cannot find or fix (#5370 review).
105
+ const count = refused.length;
106
+ const named = refused.map((entry) => `'${entry.name}': ${entry.reason}`);
107
+ return `${count} alignment record${count === 1 ? '' : 's'} will not be included (${named.join('; ')}). `
108
+ + `${FAMILY_REASONS.alignments}.`;
109
+ }
110
+ /** Name each refused profile and why (§12.6), as alignments are. */
111
+ export function profileRefusalMessage(refused) {
112
+ const count = refused.length;
113
+ const named = refused.map((entry) => `'${entry.name}': ${entry.reason}`);
114
+ return `${count} profile record${count === 1 ? '' : 's'} will not be included (${named.join('; ')}). `
115
+ + `${FAMILY_REASONS.profiles}.`;
116
+ }
117
+ /** Name each alignment whose station equations were refused, and why (§14.2). */
118
+ function stationEquationRefusalMessage(count, alignments, stationing) {
119
+ const named = alignments.flatMap((alignment) => {
120
+ const reason = stationing.get(alignment.sourceId)?.refusal;
121
+ return reason ? [`'${alignment.name || alignment.sourceId}': ${reason}`] : [];
122
+ });
123
+ return `${count} station equation record${count === 1 ? '' : 's'} will not be included (${named.join('; ')}). `
124
+ + `${FAMILY_REASONS['station-equations']}.`;
125
+ }
126
+ /**
127
+ * The sentence shown when nothing in the source is mappable.
128
+ *
129
+ * It names what the file *does* hold. A bare "nothing to export" leaves the
130
+ * operator to guess whether the file is empty, unsupported, or broken — and
131
+ * for the alignment-only files §9.4 is about, the answer is none of those.
132
+ */
133
+ export function refusalReason(refusals) {
134
+ if (refusals.length === 0) {
135
+ return 'This LandXML file carries no triangulated surface, no CgPoints and no alignment, so there is nothing the IFC mapping can write.';
136
+ }
137
+ const families = refusals.map((refusal) => `${refusal.count} ${refusal.family.replace(/-/g, ' ')}`).join(', ');
138
+ return `This LandXML file carries no record the IFC mapping covers. It contains ${families}, `
139
+ + 'none of which has a v1 mapping. Export the original LandXML file instead.';
140
+ }
141
+ //# sourceMappingURL=refusals.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"refusals.js","sourceRoot":"","sources":["../../src/landxml/refusals.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,78 @@
1
+ /**
2
+ * What a LandXML→IFC conversion returns.
3
+ *
4
+ * The result is a discriminated union rather than a string plus an error
5
+ * channel, because §6 of the mapping makes refusal a first-class outcome: a
6
+ * source with no in-scope record must refuse outright, not hand back a valid,
7
+ * empty, useless IFC. A caller cannot reach `content` without having seen
8
+ * which of the two happened.
9
+ */
10
+ import type { LandXmlIfcUnits } from './source-types.js';
11
+ /**
12
+ * A LandXML record family the v1 mapping does not cover (§5).
13
+ *
14
+ * Named, never silently dropped — the family names are the vocabulary the
15
+ * export dialog shows the user before they commit.
16
+ */
17
+ export type LandXmlRefusedFamily = 'alignments' | 'profiles' | 'cross-sections' | 'roadways' | 'parcels' | 'monuments' | 'plan-features' | 'pipe-networks' | 'surface-boundaries' | 'surface-breaklines' | 'surface-contours' | 'non-rendered-surfaces' | 'unlocated-cgpoints' | 'station-equations' | 'cant' | 'superelevation';
18
+ export interface LandXmlRefusal {
19
+ family: LandXmlRefusedFamily;
20
+ /** How many records of this family the source holds. Always ≥ 1. */
21
+ count: number;
22
+ /** One sentence, addressed to the operator, saying what is left out and why. */
23
+ message: string;
24
+ }
25
+ /** A condition worth surfacing that does not stop the export (§9.1). */
26
+ export interface LandXmlIfcWarning {
27
+ /** Stable code so the UI can style or suppress by kind, never by text. */
28
+ code: 'LXIFC-COORD-ORDER' | 'LXIFC-ASSUMED-UNIT' | 'LXIFC-NO-CRS' | 'LXIFC-COORD-SWAPPED';
29
+ message: string;
30
+ }
31
+ export interface LandXmlIfcCoverage {
32
+ /** TIN surfaces written as `IfcGeographicElement`/`.TERRAIN.`. */
33
+ surfaces: number;
34
+ /** `<CgPoint>` records written as `IfcAnnotation`/`.SURVEY.`. */
35
+ surveyPoints: number;
36
+ /** Vertices across all written surfaces. */
37
+ vertices: number;
38
+ /** Triangles across all written surfaces. */
39
+ triangles: number;
40
+ /**
41
+ * Horizontal alignments written as `IfcAlignment` (§11). `landXmlToIfc`
42
+ * always sets it; it is optional only so that adding it is not a breaking
43
+ * change to an interface v1.0 may already have published (#5370 review) —
44
+ * read it as `coverage.alignments ?? 0`.
45
+ */
46
+ alignments?: number;
47
+ /**
48
+ * Design profiles written as `IfcAlignmentVertical` (§12). Optional for the
49
+ * same reason as `alignments`: read it as `coverage.profiles ?? 0`.
50
+ */
51
+ profiles?: number;
52
+ }
53
+ /** What the produced file records about where it came from (§7). */
54
+ export interface LandXmlIfcProvenance {
55
+ sourceFileName: string | null;
56
+ sourceHash: string | null;
57
+ mappingVersion: string;
58
+ landXmlSchema: string;
59
+ units: LandXmlIfcUnits | null;
60
+ assumedLinearUnit: string | null;
61
+ coordinateOrderSwapped: boolean;
62
+ refusedFamilies: readonly LandXmlRefusedFamily[];
63
+ }
64
+ export type LandXmlIfcResult = {
65
+ status: 'exported';
66
+ content: string;
67
+ coverage: LandXmlIfcCoverage;
68
+ provenance: LandXmlIfcProvenance;
69
+ refusals: readonly LandXmlRefusal[];
70
+ warnings: readonly LandXmlIfcWarning[];
71
+ } | {
72
+ status: 'refused';
73
+ /** Why nothing could be written, naming what the source does contain. */
74
+ reason: string;
75
+ refusals: readonly LandXmlRefusal[];
76
+ warnings: readonly LandXmlIfcWarning[];
77
+ };
78
+ //# sourceMappingURL=result-types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"result-types.d.ts","sourceRoot":"","sources":["../../src/landxml/result-types.ts"],"names":[],"mappings":"AAIA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEzD;;;;;GAKG;AACH,MAAM,MAAM,oBAAoB,GAC5B,YAAY,GACZ,UAAU,GACV,gBAAgB,GAChB,UAAU,GACV,SAAS,GACT,WAAW,GACX,eAAe,GACf,eAAe,GACf,oBAAoB,GACpB,oBAAoB,GACpB,kBAAkB,GAClB,uBAAuB,GACvB,oBAAoB,GACpB,mBAAmB,GACnB,MAAM,GACN,gBAAgB,CAAC;AAErB,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,oBAAoB,CAAC;IAC7B,oEAAoE;IACpE,KAAK,EAAE,MAAM,CAAC;IACd,gFAAgF;IAChF,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wEAAwE;AACxE,MAAM,WAAW,iBAAiB;IAChC,0EAA0E;IAC1E,IAAI,EAAE,mBAAmB,GAAG,oBAAoB,GAAG,cAAc,GAAG,qBAAqB,CAAC;IAC1F,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,kEAAkE;IAClE,QAAQ,EAAE,MAAM,CAAC;IACjB,iEAAiE;IACjE,YAAY,EAAE,MAAM,CAAC;IACrB,4CAA4C;IAC5C,QAAQ,EAAE,MAAM,CAAC;IACjB,6CAA6C;IAC7C,SAAS,EAAE,MAAM,CAAC;IAClB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,oEAAoE;AACpE,MAAM,WAAW,oBAAoB;IACnC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,eAAe,GAAG,IAAI,CAAC;IAC9B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,sBAAsB,EAAE,OAAO,CAAC;IAChC,eAAe,EAAE,SAAS,oBAAoB,EAAE,CAAC;CAClD;AAED,MAAM,MAAM,gBAAgB,GACxB;IACA,MAAM,EAAE,UAAU,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,UAAU,EAAE,oBAAoB,CAAC;IACjC,QAAQ,EAAE,SAAS,cAAc,EAAE,CAAC;IACpC,QAAQ,EAAE,SAAS,iBAAiB,EAAE,CAAC;CACxC,GACC;IACA,MAAM,EAAE,SAAS,CAAC;IAClB,yEAAyE;IACzE,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,SAAS,cAAc,EAAE,CAAC;IACpC,QAAQ,EAAE,SAAS,iBAAiB,EAAE,CAAC;CACxC,CAAC"}
@@ -0,0 +1,5 @@
1
+ /* This Source Code Form is subject to the terms of the Mozilla Public
2
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
+ export {};
5
+ //# sourceMappingURL=result-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"result-types.js","sourceRoot":"","sources":["../../src/landxml/result-types.ts"],"names":[],"mappings":"AAAA;;+DAE+D"}