@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.
- package/README.md +7 -0
- package/dist/ifc-creator-alignment-referents.d.ts +35 -0
- package/dist/ifc-creator-alignment-referents.d.ts.map +1 -0
- package/dist/ifc-creator-alignment-referents.js +89 -0
- package/dist/ifc-creator-alignment-referents.js.map +1 -0
- package/dist/ifc-creator-alignment-vertical.d.ts +40 -0
- package/dist/ifc-creator-alignment-vertical.d.ts.map +1 -0
- package/dist/ifc-creator-alignment-vertical.js +182 -0
- package/dist/ifc-creator-alignment-vertical.js.map +1 -0
- package/dist/ifc-creator-alignment.d.ts +45 -0
- package/dist/ifc-creator-alignment.d.ts.map +1 -0
- package/dist/ifc-creator-alignment.js +173 -0
- package/dist/ifc-creator-alignment.js.map +1 -0
- package/dist/ifc-creator-header.d.ts +2 -0
- package/dist/ifc-creator-header.d.ts.map +1 -0
- package/dist/ifc-creator-header.js +22 -0
- package/dist/ifc-creator-header.js.map +1 -0
- package/dist/ifc-creator-math.d.ts +37 -5
- package/dist/ifc-creator-math.d.ts.map +1 -1
- package/dist/ifc-creator-math.js +93 -4
- package/dist/ifc-creator-math.js.map +1 -1
- package/dist/ifc-creator-relationships.d.ts +43 -0
- package/dist/ifc-creator-relationships.d.ts.map +1 -0
- package/dist/ifc-creator-relationships.js +38 -0
- package/dist/ifc-creator-relationships.js.map +1 -0
- package/dist/ifc-creator-styles.d.ts +22 -0
- package/dist/ifc-creator-styles.d.ts.map +1 -0
- package/dist/ifc-creator-styles.js +50 -0
- package/dist/ifc-creator-styles.js.map +1 -0
- package/dist/ifc-creator-terrain.d.ts +170 -0
- package/dist/ifc-creator-terrain.d.ts.map +1 -0
- package/dist/ifc-creator-terrain.js +180 -0
- package/dist/ifc-creator-terrain.js.map +1 -0
- package/dist/ifc-creator.d.ts +21 -7
- package/dist/ifc-creator.d.ts.map +1 -1
- package/dist/ifc-creator.js +93 -97
- package/dist/ifc-creator.js.map +1 -1
- package/dist/in-store/_emit-helpers.d.ts +2 -1
- package/dist/in-store/_emit-helpers.d.ts.map +1 -1
- package/dist/in-store/_emit-helpers.js +7 -7
- package/dist/in-store/_emit-helpers.js.map +1 -1
- package/dist/in-store/anchor.d.ts +2 -0
- package/dist/in-store/anchor.d.ts.map +1 -1
- package/dist/in-store/anchor.js.map +1 -1
- package/dist/in-store/apply-style.d.ts +3 -6
- package/dist/in-store/apply-style.d.ts.map +1 -1
- package/dist/in-store/apply-style.js +3 -77
- package/dist/in-store/apply-style.js.map +1 -1
- package/dist/in-store/column.d.ts.map +1 -1
- package/dist/in-store/column.js +2 -0
- package/dist/in-store/column.js.map +1 -1
- package/dist/in-store/door.d.ts.map +1 -1
- package/dist/in-store/door.js +2 -0
- package/dist/in-store/door.js.map +1 -1
- package/dist/in-store/extract-walls.d.ts +1 -1
- package/dist/in-store/extract-walls.d.ts.map +1 -1
- package/dist/in-store/extract-walls.js +37 -55
- package/dist/in-store/extract-walls.js.map +1 -1
- package/dist/in-store/generate-spaces-all.d.ts +6 -2
- package/dist/in-store/generate-spaces-all.d.ts.map +1 -1
- package/dist/in-store/generate-spaces-all.js +33 -9
- package/dist/in-store/generate-spaces-all.js.map +1 -1
- package/dist/in-store/generate-spaces.js +1 -1
- package/dist/in-store/generate-spaces.js.map +1 -1
- package/dist/in-store/placement-frame.d.ts +8 -0
- package/dist/in-store/placement-frame.d.ts.map +1 -1
- package/dist/in-store/placement-frame.js.map +1 -1
- package/dist/in-store/plate.d.ts.map +1 -1
- package/dist/in-store/plate.js +4 -0
- package/dist/in-store/plate.js.map +1 -1
- package/dist/in-store/resolve-anchor.d.ts +4 -2
- package/dist/in-store/resolve-anchor.d.ts.map +1 -1
- package/dist/in-store/resolve-anchor.js +79 -92
- package/dist/in-store/resolve-anchor.js.map +1 -1
- package/dist/in-store/resolve-source.d.ts +2 -1
- package/dist/in-store/resolve-source.d.ts.map +1 -1
- package/dist/in-store/resolve-source.js +49 -49
- package/dist/in-store/resolve-source.js.map +1 -1
- package/dist/in-store/roof.d.ts.map +1 -1
- package/dist/in-store/roof.js +4 -0
- package/dist/in-store/roof.js.map +1 -1
- package/dist/in-store/slab.d.ts.map +1 -1
- package/dist/in-store/slab.js +4 -0
- package/dist/in-store/slab.js.map +1 -1
- package/dist/in-store/space.d.ts.map +1 -1
- package/dist/in-store/space.js +4 -0
- package/dist/in-store/space.js.map +1 -1
- package/dist/in-store/spatial-children.d.ts +52 -0
- package/dist/in-store/spatial-children.d.ts.map +1 -0
- package/dist/in-store/spatial-children.js +112 -0
- package/dist/in-store/spatial-children.js.map +1 -0
- package/dist/in-store/spatial-zone.d.ts.map +1 -1
- package/dist/in-store/spatial-zone.js +5 -5
- package/dist/in-store/spatial-zone.js.map +1 -1
- package/dist/in-store/style-entity-reader.d.ts +14 -0
- package/dist/in-store/style-entity-reader.d.ts.map +1 -0
- package/dist/in-store/style-entity-reader.js +58 -0
- package/dist/in-store/style-entity-reader.js.map +1 -0
- package/dist/in-store/wall.d.ts.map +1 -1
- package/dist/in-store/wall.js +4 -14
- package/dist/in-store/wall.js.map +1 -1
- package/dist/in-store/window.d.ts.map +1 -1
- package/dist/in-store/window.js +2 -0
- package/dist/in-store/window.js.map +1 -1
- package/dist/index.d.ts +12 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/landxml/alignment-mapping.d.ts +98 -0
- package/dist/landxml/alignment-mapping.d.ts.map +1 -0
- package/dist/landxml/alignment-mapping.js +282 -0
- package/dist/landxml/alignment-mapping.js.map +1 -0
- package/dist/landxml/alignment-record.d.ts +18 -0
- package/dist/landxml/alignment-record.d.ts.map +1 -0
- package/dist/landxml/alignment-record.js +63 -0
- package/dist/landxml/alignment-record.js.map +1 -0
- package/dist/landxml/coordinate-plausibility.d.ts +54 -0
- package/dist/landxml/coordinate-plausibility.d.ts.map +1 -0
- package/dist/landxml/coordinate-plausibility.js +59 -0
- package/dist/landxml/coordinate-plausibility.js.map +1 -0
- package/dist/landxml/landxml-to-ifc.d.ts +45 -0
- package/dist/landxml/landxml-to-ifc.d.ts.map +1 -0
- package/dist/landxml/landxml-to-ifc.js +203 -0
- package/dist/landxml/landxml-to-ifc.js.map +1 -0
- package/dist/landxml/profile-geometry.d.ts +50 -0
- package/dist/landxml/profile-geometry.d.ts.map +1 -0
- package/dist/landxml/profile-geometry.js +221 -0
- package/dist/landxml/profile-geometry.js.map +1 -0
- package/dist/landxml/profile-mapping.d.ts +36 -0
- package/dist/landxml/profile-mapping.d.ts.map +1 -0
- package/dist/landxml/profile-mapping.js +181 -0
- package/dist/landxml/profile-mapping.js.map +1 -0
- package/dist/landxml/profile-record.d.ts +46 -0
- package/dist/landxml/profile-record.d.ts.map +1 -0
- package/dist/landxml/profile-record.js +38 -0
- package/dist/landxml/profile-record.js.map +1 -0
- package/dist/landxml/refusals.d.ts +45 -0
- package/dist/landxml/refusals.d.ts.map +1 -0
- package/dist/landxml/refusals.js +141 -0
- package/dist/landxml/refusals.js.map +1 -0
- package/dist/landxml/result-types.d.ts +78 -0
- package/dist/landxml/result-types.d.ts.map +1 -0
- package/dist/landxml/result-types.js +5 -0
- package/dist/landxml/result-types.js.map +1 -0
- package/dist/landxml/source-types.d.ts +169 -0
- package/dist/landxml/source-types.d.ts.map +1 -0
- package/dist/landxml/source-types.js +5 -0
- package/dist/landxml/source-types.js.map +1 -0
- package/dist/landxml/station-equations.d.ts +69 -0
- package/dist/landxml/station-equations.d.ts.map +1 -0
- package/dist/landxml/station-equations.js +140 -0
- package/dist/landxml/station-equations.js.map +1 -0
- package/dist/landxml/writers.d.ts +33 -0
- package/dist/landxml/writers.d.ts.map +1 -0
- package/dist/landxml/writers.js +160 -0
- package/dist/landxml/writers.js.map +1 -0
- package/dist/types.d.ts +13 -2
- package/dist/types.d.ts.map +1 -1
- package/package.json +6 -6
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LandXML horizontal alignment → `IfcAlignmentHorizontalSegment` parameters
|
|
3
|
+
* (mapping spec §11).
|
|
4
|
+
*
|
|
5
|
+
* Pure numbers in, pure numbers out: no STEP is written here, so the export
|
|
6
|
+
* dialog can run the same mapping as a cheap pre-flight and the refusal it
|
|
7
|
+
* shows is the refusal the export would give.
|
|
8
|
+
*
|
|
9
|
+
* Conventions (§11.3), each of which is a place a sign error hides:
|
|
10
|
+
* - points are `(easting, northing)` in metres — LandXML authors them
|
|
11
|
+
* northing-first, and `planPoint` is the one place that swaps them;
|
|
12
|
+
* - directions are radians, counter-clockwise from +X (east);
|
|
13
|
+
* - radii are POSITIVE for a counter-clockwise (left) turn, negative for
|
|
14
|
+
* clockwise, and `0` for infinite.
|
|
15
|
+
*
|
|
16
|
+
* And the check that catches a sign error (§11.4): every segment is integrated
|
|
17
|
+
* to its end and compared with the AUTHORED end. A curve written the wrong way
|
|
18
|
+
* round lands somewhere else, and the refusal says where.
|
|
19
|
+
*/
|
|
20
|
+
import type { LandXmlIfcUnits } from './source-types.js';
|
|
21
|
+
export { isAlignmentRecord } from './alignment-record.js';
|
|
22
|
+
export type HorizontalSegmentType = 'LINE' | 'CIRCULARARC' | 'CLOTHOID';
|
|
23
|
+
/** One `IfcAlignmentHorizontalSegment`, in metres and radians. */
|
|
24
|
+
export interface HorizontalSegment {
|
|
25
|
+
sourceId: string;
|
|
26
|
+
type: HorizontalSegmentType;
|
|
27
|
+
start: readonly [number, number];
|
|
28
|
+
/** `StartDirection`: radians, counter-clockwise from +X. */
|
|
29
|
+
direction: number;
|
|
30
|
+
/** Signed: positive = counter-clockwise; 0 = infinite. */
|
|
31
|
+
startRadius: number;
|
|
32
|
+
endRadius: number;
|
|
33
|
+
length: number;
|
|
34
|
+
/** Evaluated end state — for the transition code and the terminating segment. */
|
|
35
|
+
end: readonly [number, number];
|
|
36
|
+
endDirection: number;
|
|
37
|
+
/** Signed curvature at start and end (1/R, 0 for infinite). */
|
|
38
|
+
startCurvature: number;
|
|
39
|
+
endCurvature: number;
|
|
40
|
+
}
|
|
41
|
+
export interface MappedAlignment {
|
|
42
|
+
sourceId: string;
|
|
43
|
+
name: string;
|
|
44
|
+
/** Station at distance 0, in metres. */
|
|
45
|
+
startStation: number;
|
|
46
|
+
segments: HorizontalSegment[];
|
|
47
|
+
}
|
|
48
|
+
export interface RefusedAlignment {
|
|
49
|
+
sourceId: string;
|
|
50
|
+
name: string;
|
|
51
|
+
reason: string;
|
|
52
|
+
}
|
|
53
|
+
export interface AlignmentMapping {
|
|
54
|
+
mapped: MappedAlignment[];
|
|
55
|
+
refused: RefusedAlignment[];
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Position tolerance for §11.4, in metres. LandXML coordinates are routinely
|
|
59
|
+
* authored to the millimetre and lengths/radii rounded independently of them,
|
|
60
|
+
* so a correctly-signed segment reproduces its authored end to within a few
|
|
61
|
+
* millimetres. A sign error misses by metres. One centimetre separates the two
|
|
62
|
+
* with a wide margin on both sides.
|
|
63
|
+
*/
|
|
64
|
+
export declare const ALIGNMENT_POSITION_TOLERANCE_M = 0.01;
|
|
65
|
+
/** Resolves a `pntRef` to authored coordinates, or `null`. */
|
|
66
|
+
export type PointResolver = (pntRef: string) => {
|
|
67
|
+
northing: number;
|
|
68
|
+
easting: number;
|
|
69
|
+
} | null;
|
|
70
|
+
/**
|
|
71
|
+
* Integrate position along a segment with linearly varying curvature — exact
|
|
72
|
+
* for a line, arc and clothoid, which is every type v1.1 writes. Composite
|
|
73
|
+
* Simpson on the heading `θ(s) = θ0 + κ0·s + (κ1 − κ0)·s² / (2L)`.
|
|
74
|
+
*/
|
|
75
|
+
export declare function evaluateSegment(start: readonly [number, number], direction: number, startCurvature: number, endCurvature: number, length: number, at?: number): {
|
|
76
|
+
point: [number, number];
|
|
77
|
+
direction: number;
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* Map every alignment, splitting them into written and refused (§11.2).
|
|
81
|
+
*
|
|
82
|
+
* An alignment is refused WHOLE rather than written with a gap: every station
|
|
83
|
+
* after a missing segment would be wrong.
|
|
84
|
+
*/
|
|
85
|
+
export declare function mapAlignments(alignments: readonly unknown[] | undefined, units: LandXmlIfcUnits | null, swap: boolean, resolve: PointResolver): AlignmentMapping;
|
|
86
|
+
/**
|
|
87
|
+
* A resolver over the file's `CgPoint`s, by name. A name used twice resolves
|
|
88
|
+
* to nothing: guessing which of two same-named points an alignment meant would
|
|
89
|
+
* silently move the alignment.
|
|
90
|
+
*/
|
|
91
|
+
export declare function cogoPointResolver(points: ReadonlyArray<{
|
|
92
|
+
name: string | null;
|
|
93
|
+
point: {
|
|
94
|
+
northing: number;
|
|
95
|
+
easting: number;
|
|
96
|
+
} | null;
|
|
97
|
+
}> | undefined): PointResolver;
|
|
98
|
+
//# sourceMappingURL=alignment-mapping.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"alignment-mapping.d.ts","sourceRoot":"","sources":["../../src/landxml/alignment-mapping.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAEU,eAAe,EACpC,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE1D,MAAM,MAAM,qBAAqB,GAAG,MAAM,GAAG,aAAa,GAAG,UAAU,CAAC;AAExE,kEAAkE;AAClE,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,qBAAqB,CAAC;IAC5B,KAAK,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,4DAA4D;IAC5D,SAAS,EAAE,MAAM,CAAC;IAClB,0DAA0D;IAC1D,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,iFAAiF;IACjF,GAAG,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,+DAA+D;IAC/D,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,wCAAwC;IACxC,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,iBAAiB,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,OAAO,EAAE,gBAAgB,EAAE,CAAC;CAC7B;AAED;;;;;;GAMG;AACH,eAAO,MAAM,8BAA8B,OAAO,CAAC;AAEnD,8DAA8D;AAC9D,MAAM,MAAM,aAAa,GAAG,CAAC,MAAM,EAAE,MAAM,KAAK;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC;AAgD7F;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EACjG,MAAM,EAAE,MAAM,EAAE,EAAE,GAAE,MAAe,GAClC;IAAE,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAehD;AAiKD;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,UAAU,EAAE,SAAS,OAAO,EAAE,GAAG,SAAS,EAAE,KAAK,EAAE,eAAe,GAAG,IAAI,EAAE,IAAI,EAAE,OAAO,EACxF,OAAO,EAAE,aAAa,GACrB,gBAAgB,CAmBlB;AAmBD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,aAAa,CAAC;IAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,KAAK,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAA;CAAE,CAAC,GAAG,SAAS,GAC9G,aAAa,CAOf"}
|
|
@@ -0,0 +1,282 @@
|
|
|
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 { alignmentRecordProblem } from './alignment-record.js';
|
|
5
|
+
export { isAlignmentRecord } from './alignment-record.js';
|
|
6
|
+
/**
|
|
7
|
+
* Position tolerance for §11.4, in metres. LandXML coordinates are routinely
|
|
8
|
+
* authored to the millimetre and lengths/radii rounded independently of them,
|
|
9
|
+
* so a correctly-signed segment reproduces its authored end to within a few
|
|
10
|
+
* millimetres. A sign error misses by metres. One centimetre separates the two
|
|
11
|
+
* with a wide margin on both sides.
|
|
12
|
+
*/
|
|
13
|
+
export const ALIGNMENT_POSITION_TOLERANCE_M = 0.01;
|
|
14
|
+
class Refusal extends Error {
|
|
15
|
+
}
|
|
16
|
+
function refuse(message) {
|
|
17
|
+
throw new Refusal(message);
|
|
18
|
+
}
|
|
19
|
+
/** Authored northing-first → `(easting, northing)` metres; the one swap for alignments. */
|
|
20
|
+
function planPoint(location, units, swap, resolve, what) {
|
|
21
|
+
let point;
|
|
22
|
+
if (location.kind === 'coordinates') {
|
|
23
|
+
point = location.point;
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
point = resolve(location.pntRef);
|
|
27
|
+
if (!point)
|
|
28
|
+
refuse(`${what} references point '${location.pntRef}', which the file does not define uniquely`);
|
|
29
|
+
}
|
|
30
|
+
if (!Number.isFinite(point.northing) || !Number.isFinite(point.easting))
|
|
31
|
+
refuse(`${what} has a non-finite coordinate`);
|
|
32
|
+
const scale = units.linearScaleToMeters;
|
|
33
|
+
// `swap` is the operator's confirmed override for an easting-first producer
|
|
34
|
+
// (§2.2); it reverses this function's own swap.
|
|
35
|
+
return swap
|
|
36
|
+
? [point.northing * scale, point.easting * scale]
|
|
37
|
+
: [point.easting * scale, point.northing * scale];
|
|
38
|
+
}
|
|
39
|
+
function distance(a, b) {
|
|
40
|
+
return Math.hypot(b[0] - a[0], b[1] - a[1]);
|
|
41
|
+
}
|
|
42
|
+
/** Normalise to (-π, π]. */
|
|
43
|
+
function wrap(angle) {
|
|
44
|
+
let a = angle % (2 * Math.PI);
|
|
45
|
+
if (a <= -Math.PI)
|
|
46
|
+
a += 2 * Math.PI;
|
|
47
|
+
if (a > Math.PI)
|
|
48
|
+
a -= 2 * Math.PI;
|
|
49
|
+
return a;
|
|
50
|
+
}
|
|
51
|
+
function signFor(rotation) {
|
|
52
|
+
return rotation === 'counter_clockwise' ? 1 : -1;
|
|
53
|
+
}
|
|
54
|
+
function curvatureOf(radius) {
|
|
55
|
+
return radius === 0 ? 0 : 1 / radius;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Integrate position along a segment with linearly varying curvature — exact
|
|
59
|
+
* for a line, arc and clothoid, which is every type v1.1 writes. Composite
|
|
60
|
+
* Simpson on the heading `θ(s) = θ0 + κ0·s + (κ1 − κ0)·s² / (2L)`.
|
|
61
|
+
*/
|
|
62
|
+
export function evaluateSegment(start, direction, startCurvature, endCurvature, length, at = length) {
|
|
63
|
+
const heading = (s) => direction + startCurvature * s + (length === 0 ? 0 : ((endCurvature - startCurvature) * s * s) / (2 * length));
|
|
64
|
+
if (at === 0)
|
|
65
|
+
return { point: [start[0], start[1]], direction };
|
|
66
|
+
const steps = Math.min(4096, Math.max(64, 2 * Math.ceil(at)));
|
|
67
|
+
const h = at / steps;
|
|
68
|
+
let x = 0;
|
|
69
|
+
let y = 0;
|
|
70
|
+
for (let i = 0; i <= steps; i += 1) {
|
|
71
|
+
const weight = i === 0 || i === steps ? 1 : i % 2 === 1 ? 4 : 2;
|
|
72
|
+
const theta = heading(i * h);
|
|
73
|
+
x += weight * Math.cos(theta);
|
|
74
|
+
y += weight * Math.sin(theta);
|
|
75
|
+
}
|
|
76
|
+
return { point: [start[0] + (x * h) / 3, start[1] + (y * h) / 3], direction: heading(at) };
|
|
77
|
+
}
|
|
78
|
+
function radiusValue(radius, units, what) {
|
|
79
|
+
if (radius === undefined)
|
|
80
|
+
refuse(`${what} declares no radius`);
|
|
81
|
+
if (radius === 'infinite')
|
|
82
|
+
return 0;
|
|
83
|
+
if (!Number.isFinite(radius) || radius <= 0)
|
|
84
|
+
refuse(`${what} has an invalid radius (${String(radius)})`);
|
|
85
|
+
return radius * units.linearScaleToMeters;
|
|
86
|
+
}
|
|
87
|
+
function mapPrimitive(primitive, sourceId, units, swap, resolve, label) {
|
|
88
|
+
const point = (location, role) => planPoint(location, units, swap, resolve, `${label} ${role}`);
|
|
89
|
+
switch (primitive.kind) {
|
|
90
|
+
case 'line': {
|
|
91
|
+
const start = point(primitive.start, 'start');
|
|
92
|
+
const end = point(primitive.end, 'end');
|
|
93
|
+
const length = distance(start, end);
|
|
94
|
+
if (length === 0)
|
|
95
|
+
refuse(`${label} is a zero-length line`);
|
|
96
|
+
return {
|
|
97
|
+
segment: {
|
|
98
|
+
sourceId, type: 'LINE', start, direction: Math.atan2(end[1] - start[1], end[0] - start[0]),
|
|
99
|
+
startRadius: 0, endRadius: 0, length, startCurvature: 0, endCurvature: 0,
|
|
100
|
+
},
|
|
101
|
+
authoredEnd: end,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
case 'curve': {
|
|
105
|
+
const start = point(primitive.start, 'start');
|
|
106
|
+
const center = point(primitive.center, 'center');
|
|
107
|
+
const end = point(primitive.end, 'end');
|
|
108
|
+
const radius = distance(center, start);
|
|
109
|
+
if (radius === 0)
|
|
110
|
+
refuse(`${label} has its center on its start point`);
|
|
111
|
+
const sign = signFor(primitive.rotation);
|
|
112
|
+
const radial = Math.atan2(start[1] - center[1], start[0] - center[0]);
|
|
113
|
+
// The tangent is the radial direction turned a quarter towards travel:
|
|
114
|
+
// +90° for a counter-clockwise arc, −90° for clockwise.
|
|
115
|
+
const direction = radial + (sign * Math.PI) / 2;
|
|
116
|
+
const endRadial = Math.atan2(end[1] - center[1], end[0] - center[0]);
|
|
117
|
+
// Sweep in the direction of travel, in (0, 2π].
|
|
118
|
+
let sweep = sign * (endRadial - radial);
|
|
119
|
+
sweep = ((sweep % (2 * Math.PI)) + 2 * Math.PI) % (2 * Math.PI);
|
|
120
|
+
if (sweep === 0)
|
|
121
|
+
sweep = 2 * Math.PI;
|
|
122
|
+
const signedRadius = sign * radius;
|
|
123
|
+
const length = radius * sweep;
|
|
124
|
+
// The end-point check CANNOT catch a flipped `rot` on an arc: start,
|
|
125
|
+
// centre and end describe one circle, and the other rotation is simply
|
|
126
|
+
// the other arc of it — ending at the same point. The authored length is
|
|
127
|
+
// what tells a 90° arc from its 270° complement, so when LandXML states
|
|
128
|
+
// one it must agree.
|
|
129
|
+
if (primitive.declaredLength !== null) {
|
|
130
|
+
const declared = primitive.declaredLength * units.linearScaleToMeters;
|
|
131
|
+
if (Math.abs(declared - length) > ALIGNMENT_POSITION_TOLERANCE_M) {
|
|
132
|
+
refuse(`${label} is ${length.toFixed(3)} m long going ${primitive.rotation.replace('_', '-')}, but declares `
|
|
133
|
+
+ `${declared.toFixed(3)} m — its rotation may be the other way round`);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return {
|
|
137
|
+
segment: {
|
|
138
|
+
sourceId, type: 'CIRCULARARC', start, direction, startRadius: signedRadius, endRadius: signedRadius,
|
|
139
|
+
length, startCurvature: 1 / signedRadius, endCurvature: 1 / signedRadius,
|
|
140
|
+
},
|
|
141
|
+
authoredEnd: end,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
case 'spiral': {
|
|
145
|
+
if (primitive.spiType !== 'clothoid') {
|
|
146
|
+
refuse(`${label} is a '${primitive.spiType}' spiral; only clothoid spirals have a mapping`);
|
|
147
|
+
}
|
|
148
|
+
const start = point(primitive.start, 'start');
|
|
149
|
+
const pi = point(primitive.pi, 'PI');
|
|
150
|
+
const end = point(primitive.end, 'end');
|
|
151
|
+
const length = primitive.declaredLength * units.linearScaleToMeters;
|
|
152
|
+
if (!Number.isFinite(length) || length <= 0)
|
|
153
|
+
refuse(`${label} has an invalid length`);
|
|
154
|
+
// The tangent at the start points at the spiral's PI.
|
|
155
|
+
const direction = Math.atan2(pi[1] - start[1], pi[0] - start[0]);
|
|
156
|
+
// An authored `rot` wins; without one the turn is read from the PI.
|
|
157
|
+
const cross = (pi[0] - start[0]) * (end[1] - pi[1]) - (pi[1] - start[1]) * (end[0] - pi[0]);
|
|
158
|
+
const rotation = primitive.rotation
|
|
159
|
+
?? (cross > 0 ? 'counter_clockwise' : cross < 0 ? 'clockwise' : refuse(`${label} does not turn`));
|
|
160
|
+
const sign = signFor(rotation);
|
|
161
|
+
// `|| 0` folds the `-0` a clockwise infinite radius would produce.
|
|
162
|
+
const startRadius = sign * radiusValue(primitive.radiusStart, units, `${label} start`) || 0;
|
|
163
|
+
const endRadius = sign * radiusValue(primitive.radiusEnd, units, `${label} end`) || 0;
|
|
164
|
+
if (startRadius === endRadius)
|
|
165
|
+
refuse(`${label} has equal start and end radius — not a transition`);
|
|
166
|
+
return {
|
|
167
|
+
segment: {
|
|
168
|
+
sourceId, type: 'CLOTHOID', start, direction, startRadius, endRadius, length,
|
|
169
|
+
startCurvature: curvatureOf(startRadius), endCurvature: curvatureOf(endRadius),
|
|
170
|
+
},
|
|
171
|
+
authoredEnd: end,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
case 'unsupported_spiral':
|
|
175
|
+
return refuse(`${label} is a '${primitive.spiType}' spiral; only clothoid spirals have a mapping`);
|
|
176
|
+
case 'irregular_line':
|
|
177
|
+
return refuse(`${label} is an IrregularLine, which has no IfcAlignmentHorizontalSegment type`);
|
|
178
|
+
default:
|
|
179
|
+
return refuse(`${label} has an unrecognised geometry type`);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
function mapOne(alignment, units, swap, resolve) {
|
|
183
|
+
const ordered = [...(alignment.segments ?? [])].sort((a, b) => a.ordinal - b.ordinal);
|
|
184
|
+
if (ordered.length === 0)
|
|
185
|
+
refuse('it has no horizontal geometry');
|
|
186
|
+
const segments = [];
|
|
187
|
+
let previousAuthoredEnd = null;
|
|
188
|
+
let previousEvaluatedEnd = null;
|
|
189
|
+
ordered.forEach((entry, index) => {
|
|
190
|
+
const label = `segment ${index + 1}`;
|
|
191
|
+
const { segment, authoredEnd } = mapPrimitive(entry.primitive, entry.sourceId, units, swap, resolve, label);
|
|
192
|
+
// Continuity with the previous segment's AUTHORED end (§11.4): a gap is a
|
|
193
|
+
// wrong alignment, not a short one.
|
|
194
|
+
if (previousAuthoredEnd) {
|
|
195
|
+
const gap = distance(previousAuthoredEnd, segment.start);
|
|
196
|
+
if (gap > ALIGNMENT_POSITION_TOLERANCE_M) {
|
|
197
|
+
refuse(`${label} starts ${gap.toFixed(3)} m from where segment ${index} ends`);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
// The written curve joins the previous segment's EVALUATED end, not its
|
|
201
|
+
// authored one: each is within tolerance of the authored point, so the
|
|
202
|
+
// two can still be up to twice it apart. The writer only labels a join
|
|
203
|
+
// continuous within the tolerance, so check the join it will see.
|
|
204
|
+
if (previousEvaluatedEnd) {
|
|
205
|
+
const join = distance(previousEvaluatedEnd, segment.start);
|
|
206
|
+
if (join > ALIGNMENT_POSITION_TOLERANCE_M) {
|
|
207
|
+
refuse(`${label} starts ${join.toFixed(3)} m from where segment ${index}'s parameters end`);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
// The sign check: integrate the parameters and land on the authored end.
|
|
211
|
+
const evaluated = evaluateSegment(segment.start, segment.direction, segment.startCurvature, segment.endCurvature, segment.length);
|
|
212
|
+
const miss = distance(evaluated.point, authoredEnd);
|
|
213
|
+
if (miss > ALIGNMENT_POSITION_TOLERANCE_M) {
|
|
214
|
+
refuse(`${label}'s parameters end ${miss.toFixed(3)} m from its authored end point`);
|
|
215
|
+
}
|
|
216
|
+
segments.push({ ...segment, end: evaluated.point, endDirection: wrap(evaluated.direction) });
|
|
217
|
+
previousAuthoredEnd = authoredEnd;
|
|
218
|
+
previousEvaluatedEnd = evaluated.point;
|
|
219
|
+
});
|
|
220
|
+
return {
|
|
221
|
+
sourceId: alignment.sourceId,
|
|
222
|
+
name: alignment.name,
|
|
223
|
+
startStation: alignment.staStart * units.linearScaleToMeters,
|
|
224
|
+
segments,
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Map every alignment, splitting them into written and refused (§11.2).
|
|
229
|
+
*
|
|
230
|
+
* An alignment is refused WHOLE rather than written with a gap: every station
|
|
231
|
+
* after a missing segment would be wrong.
|
|
232
|
+
*/
|
|
233
|
+
export function mapAlignments(alignments, units, swap, resolve) {
|
|
234
|
+
const result = { mapped: [], refused: [] };
|
|
235
|
+
(alignments ?? []).forEach((candidate, index) => {
|
|
236
|
+
const problem = alignmentRecordProblem(candidate);
|
|
237
|
+
if (problem !== null) {
|
|
238
|
+
// Named by its own id and name when the header carries them, so a
|
|
239
|
+
// malformed segment is refused under the alignment it belongs to.
|
|
240
|
+
const header = candidate;
|
|
241
|
+
const named = typeof header?.sourceId === 'string' && typeof header.name === 'string';
|
|
242
|
+
result.refused.push({
|
|
243
|
+
sourceId: named ? header.sourceId : `alignment[${index}]`,
|
|
244
|
+
name: named ? header.name || header.sourceId : `alignment ${index + 1}`,
|
|
245
|
+
reason: problem,
|
|
246
|
+
});
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
mapOneInto(result, candidate, units, swap, resolve);
|
|
250
|
+
});
|
|
251
|
+
return result;
|
|
252
|
+
}
|
|
253
|
+
function mapOneInto(result, alignment, units, swap, resolve) {
|
|
254
|
+
const name = alignment.name || alignment.sourceId;
|
|
255
|
+
if (units === null) {
|
|
256
|
+
result.refused.push({ sourceId: alignment.sourceId, name, reason: 'the file declares no units' });
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
try {
|
|
260
|
+
result.mapped.push(mapOne(alignment, units, swap, resolve));
|
|
261
|
+
}
|
|
262
|
+
catch (error) {
|
|
263
|
+
if (!(error instanceof Refusal))
|
|
264
|
+
throw error;
|
|
265
|
+
result.refused.push({ sourceId: alignment.sourceId, name, reason: error.message });
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* A resolver over the file's `CgPoint`s, by name. A name used twice resolves
|
|
270
|
+
* to nothing: guessing which of two same-named points an alignment meant would
|
|
271
|
+
* silently move the alignment.
|
|
272
|
+
*/
|
|
273
|
+
export function cogoPointResolver(points) {
|
|
274
|
+
const byName = new Map();
|
|
275
|
+
for (const entry of points ?? []) {
|
|
276
|
+
if (!entry.name || !entry.point)
|
|
277
|
+
continue;
|
|
278
|
+
byName.set(entry.name, byName.has(entry.name) ? null : entry.point);
|
|
279
|
+
}
|
|
280
|
+
return (pntRef) => byName.get(pntRef) ?? null;
|
|
281
|
+
}
|
|
282
|
+
//# sourceMappingURL=alignment-mapping.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"alignment-mapping.js","sourceRoot":"","sources":["../../src/landxml/alignment-mapping.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Run-time shape check for `LandXmlIfcSource.alignments`, which is `unknown[]`
|
|
3
|
+
* (narrowing a published input type is a breaking change, #5370 review).
|
|
4
|
+
*
|
|
5
|
+
* The check goes all the way down to each location: a record whose header is
|
|
6
|
+
* fine but whose segment is `{}` used to pass, and the mapper then threw a
|
|
7
|
+
* `TypeError` out of the pre-flight and the export instead of refusing that
|
|
8
|
+
* alignment by name.
|
|
9
|
+
*/
|
|
10
|
+
import type { LandXmlIfcAlignment } from './source-types.js';
|
|
11
|
+
/**
|
|
12
|
+
* Why this record is not a `LandXmlIfcAlignment`, or `null` when it is. The
|
|
13
|
+
* reason names the first malformed segment, so a refusal says where to look.
|
|
14
|
+
*/
|
|
15
|
+
export declare function alignmentRecordProblem(value: unknown): string | null;
|
|
16
|
+
/** Is this record shaped like a `LandXmlIfcAlignment`, down to every location? */
|
|
17
|
+
export declare function isAlignmentRecord(value: unknown): value is LandXmlIfcAlignment;
|
|
18
|
+
//# sourceMappingURL=alignment-record.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"alignment-record.d.ts","sourceRoot":"","sources":["../../src/landxml/alignment-record.ts"],"names":[],"mappings":"AAIA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AA2C7D;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAYpE;AAED,kFAAkF;AAClF,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,mBAAmB,CAE9E"}
|
|
@@ -0,0 +1,63 @@
|
|
|
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
|
+
/** A length must be finite: `NaN` fails every `>` comparison, so it would pass the length checks unseen. */
|
|
7
|
+
const isLength = (value) => typeof value === 'number' && Number.isFinite(value);
|
|
8
|
+
const isOptionalLength = (value) => value === null || isLength(value);
|
|
9
|
+
const isRotation = (value) => value === 'clockwise' || value === 'counter_clockwise';
|
|
10
|
+
const isRadius = (value) => value === undefined || value === 'infinite' || isNumber(value);
|
|
11
|
+
function isLocation(value) {
|
|
12
|
+
if (!isObject(value))
|
|
13
|
+
return false;
|
|
14
|
+
if (value.kind === 'point_reference')
|
|
15
|
+
return typeof value.pntRef === 'string';
|
|
16
|
+
return value.kind === 'coordinates' && isObject(value.point)
|
|
17
|
+
&& isNumber(value.point.northing) && isNumber(value.point.easting);
|
|
18
|
+
}
|
|
19
|
+
function isPrimitive(value) {
|
|
20
|
+
if (!isObject(value))
|
|
21
|
+
return false;
|
|
22
|
+
switch (value.kind) {
|
|
23
|
+
case 'line':
|
|
24
|
+
case 'irregular_line':
|
|
25
|
+
return isLocation(value.start) && isLocation(value.end) && isOptionalLength(value.declaredLength);
|
|
26
|
+
case 'curve':
|
|
27
|
+
return isLocation(value.start) && isLocation(value.center) && isLocation(value.end)
|
|
28
|
+
&& isRotation(value.rotation) && isOptionalLength(value.radius) && isOptionalLength(value.declaredLength);
|
|
29
|
+
case 'spiral':
|
|
30
|
+
case 'unsupported_spiral':
|
|
31
|
+
return isLocation(value.start) && isLocation(value.pi) && isLocation(value.end)
|
|
32
|
+
&& typeof value.spiType === 'string' && isRadius(value.radiusStart) && isRadius(value.radiusEnd)
|
|
33
|
+
&& (value.rotation === undefined || isRotation(value.rotation)) && isLength(value.declaredLength);
|
|
34
|
+
default:
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function isSegment(value) {
|
|
39
|
+
return isObject(value) && typeof value.sourceId === 'string' && isNumber(value.ordinal)
|
|
40
|
+
&& isPrimitive(value.primitive);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Why this record is not a `LandXmlIfcAlignment`, or `null` when it is. The
|
|
44
|
+
* reason names the first malformed segment, so a refusal says where to look.
|
|
45
|
+
*/
|
|
46
|
+
export function alignmentRecordProblem(value) {
|
|
47
|
+
if (!isObject(value)
|
|
48
|
+
|| typeof value.sourceId !== 'string'
|
|
49
|
+
|| typeof value.name !== 'string'
|
|
50
|
+
|| !(typeof value.staStart === 'number' && Number.isFinite(value.staStart))
|
|
51
|
+
|| !Array.isArray(value.segments)) {
|
|
52
|
+
return 'it is not an alignment record (it needs a sourceId, a name, a numeric staStart and a segments list)';
|
|
53
|
+
}
|
|
54
|
+
const bad = value.segments.findIndex((segment) => !isSegment(segment));
|
|
55
|
+
return bad === -1
|
|
56
|
+
? null
|
|
57
|
+
: `its segment ${bad + 1} is not a line, curve or spiral record with plan locations for each of its points`;
|
|
58
|
+
}
|
|
59
|
+
/** Is this record shaped like a `LandXmlIfcAlignment`, down to every location? */
|
|
60
|
+
export function isAlignmentRecord(value) {
|
|
61
|
+
return alignmentRecordProblem(value) === null;
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=alignment-record.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"alignment-record.js","sourceRoot":"","sources":["../../src/landxml/alignment-record.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The northing/easting transposition check (§2.2, §9.1 of the mapping spec).
|
|
3
|
+
*
|
|
4
|
+
* LandXML `<P>`/`<CgPoint>` element text is *northing easting elevation*. A
|
|
5
|
+
* producer that writes it easting-first is a real, observed defect, and it is
|
|
6
|
+
* silent by construction: a transpose is a reflection, so the surface is still
|
|
7
|
+
* well-formed, still renders, and passes every count-based assertion. It is
|
|
8
|
+
* simply in the wrong place.
|
|
9
|
+
*
|
|
10
|
+
* This warns. It never refuses and never corrects:
|
|
11
|
+
*
|
|
12
|
+
* - A bounds test is a *plausibility* argument, not a proof. Refusing on it
|
|
13
|
+
* would block legitimate data at the edge of a zone.
|
|
14
|
+
* - Auto-correcting would silently move a correct dataset, which is the same
|
|
15
|
+
* class of failure it is meant to catch, in the opposite direction.
|
|
16
|
+
*
|
|
17
|
+
* It also never infers from magnitude alone. Without declared bounds there is
|
|
18
|
+
* no test — `checkCoordinateOrder` returns `null` and the caller says so.
|
|
19
|
+
*/
|
|
20
|
+
import type { LandXmlIfcWarning } from './result-types.js';
|
|
21
|
+
/** Inclusive metre bounds for a projected CRS's two horizontal axes. */
|
|
22
|
+
export interface CrsPlausibilityBounds {
|
|
23
|
+
easting: readonly [number, number];
|
|
24
|
+
northing: readonly [number, number];
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Bounds shared by every Transverse-Mercator-family projected CRS (UTM zones,
|
|
28
|
+
* national TM grids such as SWEREF99 TM).
|
|
29
|
+
*
|
|
30
|
+
* The false easting is 500 000 m and a zone is ±500 km wide, so an easting
|
|
31
|
+
* lives in roughly 0…1 000 000 m; a northing runs the length of the hemisphere,
|
|
32
|
+
* to ~10 000 000 m. That asymmetry is the whole discriminating power of the
|
|
33
|
+
* test, and it is a property of the projection family rather than of any one
|
|
34
|
+
* EPSG code — which is why this needs no EPSG table and why §4.2's rule that
|
|
35
|
+
* the exporter must not start resolving EPSG codes is not violated.
|
|
36
|
+
*
|
|
37
|
+
* Callers opt in by passing this; nothing here sniffs a CRS name for 'UTM'.
|
|
38
|
+
*/
|
|
39
|
+
export declare const TRANSVERSE_MERCATOR_BOUNDS: CrsPlausibilityBounds;
|
|
40
|
+
/**
|
|
41
|
+
* Test the coordinates as they are about to be written, in metres.
|
|
42
|
+
*
|
|
43
|
+
* Returns a warning only when the pair is implausible as written **and**
|
|
44
|
+
* swapping the two axes would make it plausible. Both halves matter: the first
|
|
45
|
+
* alone fires on any out-of-zone data, which is a different problem and not one
|
|
46
|
+
* this check can diagnose; the second is what makes the message's claim — that
|
|
47
|
+
* the source may be written easting-first — an inference the evidence supports.
|
|
48
|
+
*
|
|
49
|
+
* @param samples `(easting, northing)` metre pairs in the order they will be
|
|
50
|
+
* written to `IfcCartesianPointList3D`, i.e. already converted from LandXML's
|
|
51
|
+
* northing-first authored order.
|
|
52
|
+
*/
|
|
53
|
+
export declare function checkCoordinateOrder(samples: Iterable<readonly [number, number]>, bounds: CrsPlausibilityBounds, crsName: string): LandXmlIfcWarning | null;
|
|
54
|
+
//# sourceMappingURL=coordinate-plausibility.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coordinate-plausibility.d.ts","sourceRoot":"","sources":["../../src/landxml/coordinate-plausibility.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAE3D,wEAAwE;AACxE,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,QAAQ,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACrC;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,0BAA0B,EAAE,qBAGxC,CAAC;AAMF;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,QAAQ,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAC5C,MAAM,EAAE,qBAAqB,EAC7B,OAAO,EAAE,MAAM,GACd,iBAAiB,GAAG,IAAI,CAoB1B"}
|
|
@@ -0,0 +1,59 @@
|
|
|
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
|
+
* Bounds shared by every Transverse-Mercator-family projected CRS (UTM zones,
|
|
6
|
+
* national TM grids such as SWEREF99 TM).
|
|
7
|
+
*
|
|
8
|
+
* The false easting is 500 000 m and a zone is ±500 km wide, so an easting
|
|
9
|
+
* lives in roughly 0…1 000 000 m; a northing runs the length of the hemisphere,
|
|
10
|
+
* to ~10 000 000 m. That asymmetry is the whole discriminating power of the
|
|
11
|
+
* test, and it is a property of the projection family rather than of any one
|
|
12
|
+
* EPSG code — which is why this needs no EPSG table and why §4.2's rule that
|
|
13
|
+
* the exporter must not start resolving EPSG codes is not violated.
|
|
14
|
+
*
|
|
15
|
+
* Callers opt in by passing this; nothing here sniffs a CRS name for 'UTM'.
|
|
16
|
+
*/
|
|
17
|
+
export const TRANSVERSE_MERCATOR_BOUNDS = {
|
|
18
|
+
easting: [0, 1_000_000],
|
|
19
|
+
northing: [0, 10_000_000],
|
|
20
|
+
};
|
|
21
|
+
function within(value, [low, high]) {
|
|
22
|
+
return value >= low && value <= high;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Test the coordinates as they are about to be written, in metres.
|
|
26
|
+
*
|
|
27
|
+
* Returns a warning only when the pair is implausible as written **and**
|
|
28
|
+
* swapping the two axes would make it plausible. Both halves matter: the first
|
|
29
|
+
* alone fires on any out-of-zone data, which is a different problem and not one
|
|
30
|
+
* this check can diagnose; the second is what makes the message's claim — that
|
|
31
|
+
* the source may be written easting-first — an inference the evidence supports.
|
|
32
|
+
*
|
|
33
|
+
* @param samples `(easting, northing)` metre pairs in the order they will be
|
|
34
|
+
* written to `IfcCartesianPointList3D`, i.e. already converted from LandXML's
|
|
35
|
+
* northing-first authored order.
|
|
36
|
+
*/
|
|
37
|
+
export function checkCoordinateOrder(samples, bounds, crsName) {
|
|
38
|
+
for (const [easting, northing] of samples) {
|
|
39
|
+
if (!Number.isFinite(easting) || !Number.isFinite(northing))
|
|
40
|
+
continue;
|
|
41
|
+
const plausibleAsWritten = within(easting, bounds.easting) && within(northing, bounds.northing);
|
|
42
|
+
if (plausibleAsWritten)
|
|
43
|
+
continue;
|
|
44
|
+
const plausibleSwapped = within(northing, bounds.easting) && within(easting, bounds.northing);
|
|
45
|
+
if (!plausibleSwapped)
|
|
46
|
+
continue;
|
|
47
|
+
return {
|
|
48
|
+
code: 'LXIFC-COORD-ORDER',
|
|
49
|
+
message: `Coordinate order looks transposed. Easting ${easting} is outside ${crsName}'s easting range `
|
|
50
|
+
+ `[${bounds.easting[0]}, ${bounds.easting[1]}], but would be a valid northing — and northing `
|
|
51
|
+
+ `${northing} would be a valid easting. LandXML point text is northing-first; a producer that `
|
|
52
|
+
+ 'writes it easting-first yields a mirrored surface that still renders and still passes every '
|
|
53
|
+
+ 'count check. Verify the source before relying on this export, or re-export it with the '
|
|
54
|
+
+ 'coordinate-order override if you know the producer is at fault.',
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=coordinate-plausibility.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coordinate-plausibility.js","sourceRoot":"","sources":["../../src/landxml/coordinate-plausibility.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AA8B/D;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAA0B;IAC/D,OAAO,EAAE,CAAC,CAAC,EAAE,SAAS,CAAC;IACvB,QAAQ,EAAE,CAAC,CAAC,EAAE,UAAU,CAAC;CAC1B,CAAC;AAEF,SAAS,MAAM,CAAC,KAAa,EAAE,CAAC,GAAG,EAAE,IAAI,CAA4B;IACnE,OAAO,KAAK,IAAI,GAAG,IAAI,KAAK,IAAI,IAAI,CAAC;AACvC,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,oBAAoB,CAClC,OAA4C,EAC5C,MAA6B,EAC7B,OAAe;IAEf,KAAK,MAAM,CAAC,OAAO,EAAE,QAAQ,CAAC,IAAI,OAAO,EAAE,CAAC;QAC1C,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC;YAAE,SAAS;QACtE,MAAM,kBAAkB,GAAG,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;QAChG,IAAI,kBAAkB;YAAE,SAAS;QACjC,MAAM,gBAAgB,GAAG,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC9F,IAAI,CAAC,gBAAgB;YAAE,SAAS;QAEhC,OAAO;YACL,IAAI,EAAE,mBAAmB;YACzB,OAAO,EACL,8CAA8C,OAAO,eAAe,OAAO,mBAAmB;kBAC5F,IAAI,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,kDAAkD;kBAC7F,GAAG,QAAQ,mFAAmF;kBAC9F,8FAA8F;kBAC9F,yFAAyF;kBACzF,iEAAiE;SACtE,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|