@bldrs-ai/conway 1.470.1390 → 1.471.1405
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/compiled/examples/browser-bundled.cjs +1 -1
- package/compiled/examples/cli-bundled.cjs +1 -1
- package/compiled/examples/cli-step-bundled.cjs +1 -1
- package/compiled/examples/validator-bundled.cjs +1 -1
- package/compiled/src/scripts/model_report_displacement.test.d.ts +2 -0
- package/compiled/src/scripts/model_report_displacement.test.d.ts.map +1 -0
- package/compiled/src/scripts/model_report_displacement.test.js +104 -0
- package/compiled/src/version/version.js +1 -1
- package/compiled/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
|
@@ -30,7 +30,7 @@ var import_node_process = require("node:process");
|
|
|
30
30
|
var readline = __toESM(require("node:readline"), 1);
|
|
31
31
|
|
|
32
32
|
// compiled/src/version/version.js
|
|
33
|
-
var versionString = "Conway v1.
|
|
33
|
+
var versionString = "Conway v1.471.1405";
|
|
34
34
|
|
|
35
35
|
// compiled/dependencies/conway-geom/interface/conway_geometry.js
|
|
36
36
|
var wasmType = "";
|
|
@@ -14965,7 +14965,7 @@ ${t5.join("\n")}` : "";
|
|
|
14965
14965
|
var import_process = require("process");
|
|
14966
14966
|
|
|
14967
14967
|
// compiled/src/version/version.js
|
|
14968
|
-
var versionString = "Conway v1.
|
|
14968
|
+
var versionString = "Conway v1.471.1405";
|
|
14969
14969
|
|
|
14970
14970
|
// compiled/dependencies/conway-geom/interface/conway_geometry.js
|
|
14971
14971
|
function pThreadsAllowed() {
|
|
@@ -15943,7 +15943,7 @@ var ParsingBuffer = class {
|
|
|
15943
15943
|
};
|
|
15944
15944
|
|
|
15945
15945
|
// compiled/src/version/version.js
|
|
15946
|
-
var versionString = "Conway v1.
|
|
15946
|
+
var versionString = "Conway v1.471.1405";
|
|
15947
15947
|
|
|
15948
15948
|
// compiled/dependencies/conway-geom/interface/conway_geometry.js
|
|
15949
15949
|
function pThreadsAllowed() {
|
|
@@ -944,7 +944,7 @@ var EntityTypesIfcCount = 909;
|
|
|
944
944
|
var entity_types_ifc_gen_default = EntityTypesIfc;
|
|
945
945
|
|
|
946
946
|
// compiled/src/version/version.js
|
|
947
|
-
var versionString = "Conway v1.
|
|
947
|
+
var versionString = "Conway v1.471.1405";
|
|
948
948
|
|
|
949
949
|
// compiled/dependencies/conway-geom/interface/conway_geometry.js
|
|
950
950
|
var wasmType = "";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model_report_displacement.test.d.ts","sourceRoot":"","sources":["../../../src/scripts/model_report_displacement.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { describe, expect, test } from '@jest/globals';
|
|
2
|
+
// @ts-expect-error -- an untyped .mjs helper beside the CLI it serves.
|
|
3
|
+
import { localCentre, placeCentre, robustCentre } from '../../../scripts/debug/displacement.mjs';
|
|
4
|
+
/* eslint-disable no-magic-numbers -- these are synthetic coordinates and
|
|
5
|
+
distances chosen to mirror the real model in conway#456. Naming each one
|
|
6
|
+
would obscure the shape the cases exist to express: a tight cluster near
|
|
7
|
+
the site origin plus one part flung far away. */
|
|
8
|
+
/**
|
|
9
|
+
* The scoring behind model_report.mjs's `displacement` stage (conway#456).
|
|
10
|
+
*
|
|
11
|
+
* The stage answers "which parts are flung away from where they belong",
|
|
12
|
+
* which the `mesh` stage cannot: `mesh` measures extent in MESH-LOCAL
|
|
13
|
+
* coordinates, so on an export that writes geometry directly in site
|
|
14
|
+
* coordinates every honest part looks displaced by its distance from the
|
|
15
|
+
* file origin.
|
|
16
|
+
*
|
|
17
|
+
* These cases use synthetic centres rather than a model, because the
|
|
18
|
+
* motivating file is 256 MB and private. What is worth pinning is the
|
|
19
|
+
* scoring, and the scoring is pure — which is why it lives in
|
|
20
|
+
* displacement.mjs rather than in the CLI script, whose module body runs
|
|
21
|
+
* the whole tool on import.
|
|
22
|
+
*/
|
|
23
|
+
/**
|
|
24
|
+
* Column-major 4x4 translation, matching the walk tuple's layout.
|
|
25
|
+
*
|
|
26
|
+
* @param x Translation along x.
|
|
27
|
+
* @param y Translation along y.
|
|
28
|
+
* @param z Translation along z.
|
|
29
|
+
* @return The 16-element matrix.
|
|
30
|
+
*/
|
|
31
|
+
function translation(x, y, z) {
|
|
32
|
+
return [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, x, y, z, 1];
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* A stub geometry over a fixed point list.
|
|
36
|
+
*
|
|
37
|
+
* @param points One [x, y, z] per vertex.
|
|
38
|
+
* @return Something with the getPoint() shape worldCentre reads.
|
|
39
|
+
*/
|
|
40
|
+
function geometryOf(points) {
|
|
41
|
+
return {
|
|
42
|
+
getPoint: (i) => ({ x: points[i][0], y: points[i][1], z: points[i][2] }),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
describe('displacement scoring', () => {
|
|
46
|
+
test('the robust centre ignores outliers rather than chasing them', () => {
|
|
47
|
+
// Nine parts clustered near the site origin, one flung far away — the
|
|
48
|
+
// shape of the motivating model, scaled down.
|
|
49
|
+
const centres = [
|
|
50
|
+
...Array.from({ length: 9 }, (_, i) => [578 + i, 763, 3]),
|
|
51
|
+
[-751, 1075, 1377],
|
|
52
|
+
];
|
|
53
|
+
const centre = robustCentre(centres);
|
|
54
|
+
// A MEAN would sit ~130 units off in x and ~137 in z, dragged by the
|
|
55
|
+
// single outlier; every honest part would then score as displaced and
|
|
56
|
+
// the outlier's own score would shrink. That inversion is the reason
|
|
57
|
+
// this is a median.
|
|
58
|
+
expect(centre[0]).toBeGreaterThan(577);
|
|
59
|
+
expect(centre[0]).toBeLessThan(587);
|
|
60
|
+
expect(centre[2]).toBeCloseTo(3, 6);
|
|
61
|
+
const distances = centres.map((each) => Math.hypot(each[0] - centre[0], each[1] - centre[1], each[2] - centre[2]));
|
|
62
|
+
const cluster = distances.slice(0, 9);
|
|
63
|
+
const outlier = distances[9];
|
|
64
|
+
// The signal the stage's `factor x median` threshold consumes: the
|
|
65
|
+
// outlier has to clear 8x the median by a wide margin, or it would be
|
|
66
|
+
// reported as ordinary.
|
|
67
|
+
const median = [...cluster].sort((a, b) => a - b)[Math.floor(cluster.length / 2)];
|
|
68
|
+
expect(outlier).toBeGreaterThan(median * 8);
|
|
69
|
+
});
|
|
70
|
+
test('a mesh centre is placed by its transform, not left local', () => {
|
|
71
|
+
// The defect this stage exists to fix in one assertion: identical local
|
|
72
|
+
// geometry at two different placements must score differently. Reading
|
|
73
|
+
// local coordinates would make these indistinguishable.
|
|
74
|
+
const unitBox = [[-1, -1, -1], [1, 1, 1]];
|
|
75
|
+
const local = localCentre(geometryOf(unitBox), 2);
|
|
76
|
+
const atOrigin = placeCentre(local, translation(0, 0, 0));
|
|
77
|
+
const farAway = placeCentre(local, translation(1000, 0, 0));
|
|
78
|
+
expect(atOrigin).toEqual([0, 0, 0]);
|
|
79
|
+
expect(farAway).toEqual([1000, 0, 0]);
|
|
80
|
+
});
|
|
81
|
+
test('an undefined transform means identity, not a skipped mesh', () => {
|
|
82
|
+
expect(placeCentre(localCentre(geometryOf([[2, 4, 6], [4, 8, 12]]), 2), undefined))
|
|
83
|
+
.toEqual([3, 6, 9]);
|
|
84
|
+
});
|
|
85
|
+
test('a wrong walk-tuple index throws rather than scoring NaN', () => {
|
|
86
|
+
// conway#456 names the transform as walked[1]; it is walked[0].
|
|
87
|
+
// Following the issue verbatim handed this an object, every
|
|
88
|
+
// multiplication produced NaN, Stage.record silently discarded every
|
|
89
|
+
// non-finite value, and the stage reported "N calls, 0 measured" — a
|
|
90
|
+
// clean-looking result manufactured by a bug. That is hazard 1 from the
|
|
91
|
+
// script's own header, so it has to be loud.
|
|
92
|
+
const notATransform = { someObject: true };
|
|
93
|
+
expect(() => placeCentre([0, 0, 0], notATransform)).toThrow(/walk tuple index/);
|
|
94
|
+
});
|
|
95
|
+
test('non-finite vertex data yields no centre rather than a NaN score', () => {
|
|
96
|
+
expect(localCentre(geometryOf([[0, 0, 0], [NaN, 0, 0]]), 2)).toBeUndefined();
|
|
97
|
+
});
|
|
98
|
+
test('a right-shaped transform holding NaN drops the mesh, and does not throw', () => {
|
|
99
|
+
// Data, not a programming error: one unusable placement must not take
|
|
100
|
+
// down the whole run and discard the other stages' reports.
|
|
101
|
+
const nanTransform = translation(NaN, 0, 0);
|
|
102
|
+
expect(placeCentre([1, 1, 1], nanTransform)).toBeUndefined();
|
|
103
|
+
});
|
|
104
|
+
});
|
|
@@ -5,5 +5,5 @@
|
|
|
5
5
|
// only the first segment (major) is meaningful and is the one CI carries forward.
|
|
6
6
|
// Must stay in `vN.N.N` shape: the CI stamp regex, scripts/updateVersion.mjs, and
|
|
7
7
|
// statistics.ts all match `v\d+\.\d+\.\d+`.
|
|
8
|
-
const versionString = 'Conway v1.
|
|
8
|
+
const versionString = 'Conway v1.471.1405';
|
|
9
9
|
export { versionString };
|