Queries
Positive-only queries that report what the engine measured, without asserting an expected value.
A query reports a measurement instead of comparing it with an expectation; a negated query is an invalid-claim error. passed carries the measurement in evidence; refused means the evidence the query reads is missing or cannot decide, under the common refusals and the codes below. A query asserts nothing, so it never fails.
client.query({ capability, subject, payload }) resolves to a Geo; query_geo(subject, capability, payload) returns a Geo whose passed means status passed. Neither throws for the three outcomes. client.query admits the subjects of create and rejects those of createModelLoader, so this page uses the native loader throughout. Payload keys keep the camelCase field names in both languages (maxRecords).
plate and gear are the site's demo models; the rest are repository fixtures: tessellated, a STEP box whose faces carry no surface; housingShaft, a housing and a shaft that share material; nist, a NIST AP242 test case with semantic PMI. Python adds y_up_plate, the demo plate admitted y-up through engine.; no loader in geospec@beta admits one. Refusal codes add to the common refusals.
import { readFile } from 'node:fs/promises';
import { createGeoSpecAssertionClient } from 'geospec/assertion-client';
import { createGeoSpecNativeModelLoader } from 'geospec/runner/native';
import { Engine } from 'geospec-engine/node';
const engine = new Engine();
const loadModel = createGeoSpecNativeModelLoader({
engine,
readSource: async (source) => new Uint8Array(await readFile(source as string)),
});
const client = createGeoSpecAssertionClient({ engine });
const plate = await loadModel({ source: 'plate-with-through-bore.step', format: 'step' });
const gear = await loadModel({ source: 'involute-gear.glb', format: 'glb', sourceUnit: 'mm' });
const tessellated = await loadModel({
source: 'packages/geospec-engine/native/occt/rust/tests/fixtures/read-profile/box-tessellated-only.step',
format: 'step',
});
const housingShaft = await loadModel({
source: 'packages/geospec-engine/native/occt/rust/tests/fixtures/component-interference/original.step',
format: 'step',
});
const nist = await loadModel({
source: 'packages/geospec-engine/fixtures/interop/nist-pmi/nist_ctc_05_asme1_ap242-e1.stp',
format: 'stp',
});from pathlib import Path
from geospec import GeoSpecEngine, GeoSpecRegex, load_model, query_geo
with GeoSpecEngine(model_root=".") as engine:
plate = load_model(file="plate-with-through-bore.step", format="step")
gear = load_model(file="involute-gear.glb", format="glb", source_unit="mm")
tessellated = load_model(
file="packages/geospec-engine/native/occt/rust/tests/fixtures/read-profile/box-tessellated-only.step",
format="step",
)
housing_shaft = load_model(
file="packages/geospec-engine/native/occt/rust/tests/fixtures/component-interference/original.step",
format="step",
)
nist = load_model(
file="packages/geospec-engine/fixtures/interop/nist-pmi/nist_ctc_05_asme1_ap242-e1.stp",
format="stp",
)
y_up_plate = engine.ingest_subject(
Path("plate-with-through-bore.step").read_bytes(),
format="step", coordinate_system="y-up", source_unit="auto", output_unit="mm",
)analyze Brep
Reports a STEP subject's exact BRep facts: bounds, validity, topology counts, mass properties and the face, hole, chamfer and fillet inventories.
Signature
client.query({ capability: 'analyzeBrep', subject: part }): Promise<GeoSpecCanonicalClaimReport>query_geo(part, "analyzeBrep") -> GeoSpecAssertionReportFields
None.
Admitted geometry
- STEP with exact BRep faces.
- An incomplete hole or edge-treatment inventory is a warning in the evidence.
Refusal codes
GEOSPEC_: the subject has no BRep, such as a mesh or glTF subject.BREP_ EVIDENCE_ UNAVAILABLE
Examples
// passed: plate, evidence.brep lists 7 faces and a 10 mm through hole along z
await client.query({ capability: 'analyzeBrep', subject: plate });
// refused (GEOSPEC_UNSUPPORTED_EVIDENCE): tessellated, its faces carry no surface
await client.query({ capability: 'analyzeBrep', subject: tessellated });# passed: plate, evidence["brep"] lists 7 faces and a 10 mm through hole along z
query_geo(plate, "analyzeBrep")
# refused (GEOSPEC_UNSUPPORTED_EVIDENCE): tessellated, its faces carry no surface
query_geo(tessellated, "analyzeBrep")analyze Mesh
Reports the mesh the engine measures: counts, per-triangle rows, quality findings, watertightness and bounds per primitive.
Signature
client.query({ capability: 'analyzeMesh', subject: part }): Promise<GeoSpecCanonicalClaimReport>query_geo(part, "analyzeMesh") -> GeoSpecAssertionReportFields
None.
Admitted geometry
- Mesh and glTF/GLB: the admitted triangles.
- STEP: the engine's own tessellation, so a STEP subject whose faces carry no surface is admitted.
Refusal codes
GEOSPEC_: the subject has no mesh record, such as a rational plate, or was admitted in a y-up frame.UNSUPPORTED_ EVIDENCE GEOSPEC_: the watertight analysis inside the report needs more working memory thanANALYSIS_ LIMIT maxMeshBytesallows.
Examples
// passed: gear, 1872 vertices, 624 triangles, watertight, signedVolume 911.53 mm³
await client.query({ capability: 'analyzeMesh', subject: gear });The refused case is Python only: no loader in geospec@beta admits y_up_plate.
# passed: gear, 1872 vertices, 624 triangles, watertight, signedVolume 911.53 mm³
query_geo(gear, "analyzeMesh")
# refused (GEOSPEC_UNSUPPORTED_EVIDENCE): y_up_plate, a y-up subject answers minimumDistance only
query_geo(y_up_plate, "analyzeMesh")inspect Geometry
Resolves selectors and reports each match: occurrences and bodies with bounds and centre, planes with normal and offset, axes with direction and radius.
Signature
client.query({ capability: 'inspectGeometry', subject: part, payload: { selectors, evidence? } }): Promise<GeoSpecCanonicalClaimReport>query_geo(part, "inspectGeometry", {"selectors": [...], "evidence": [...]}) -> GeoSpecAssertionReportFields
| Field | Type | Default | Meaning |
|---|---|---|---|
selectors | array of selectors | required | Names, RegExp (GeoSpecRegex in Python) or catalog objects |
evidence | array of 'bounds', 'facts', 'frames' | none | Recorded in the claim; does not narrow the report |
The selectors are those of to; payload is typed unknown, so every catalog form compiles here.
Admitted geometry
- STEP: occurrences, faces, axes and planes, from the exact BRep.
- glTF/GLB: bodies, by
{ kind: 'body', of: 'cubeA#0' }. - One selector that cannot resolve refuses the whole query, and the report lists no matches.
Refusal codes
GEOSPEC_: a selector reads evidence the subject does not carry, such as a face, axis or plane selector on a glTF subject.SELECTOR_ UNSUPPORTED_ EVIDENCE GEOSPEC_,SELECTOR_ UNMATCHED GEOSPEC_: a selector resolves to no entity, or to more than its cardinality allows.SELECTOR_ AMBIGUOUS
Examples
// passed: housingShaft, housing and shaft, each with bounds and centre
await client.query({
capability: 'inspectGeometry',
subject: housingShaft,
payload: { selectors: [{ kind: 'occurrence', name: /.*/, expect: 'many' }] },
});
// refused (GEOSPEC_UNSUPPORTED_EVIDENCE): tessellated, its faces carry no surface
await client.query({ capability: 'inspectGeometry', subject: tessellated, payload: { selectors: ['box'] } });# passed: housing_shaft, housing and shaft, each with bounds and centre
query_geo(housing_shaft, "inspectGeometry", {"selectors": [dict(kind="occurrence", name=GeoSpecRegex(".*"), expect="many")]})
# refused (GEOSPEC_UNSUPPORTED_EVIDENCE): tessellated, its faces carry no surface
query_geo(tessellated, "inspectGeometry", {"selectors": ["box"]})analyze Mesh Overlap
Reports each component pair's shared volume, without comparing it with an allowance.
Signature
client.query({ capability: 'analyzeMeshOverlap', subject: part, payload: { pairs?, tolerance? } }): Promise<GeoSpecCanonicalClaimReport>query_geo(part, "analyzeMeshOverlap", {"pairs": [...], "tolerance": ...}) -> GeoSpecAssertionReportFields
| Field | Type | Default | Meaning |
|---|---|---|---|
pairs | array of { left, right } | every pair | Pairs to measure |
tolerance | number, 0 or more, mm | 0.001 | Widens the candidate bounds check; a pair below its cube is omitted |
The payload object is required: {} measures every pair. Components and selectors follow to.
Admitted geometry
- STEP: an exact Boolean intersection of each candidate pair's leaf solids; the evidence says it is not an allowance check.
- glTF/GLB: a polyhedral Boolean observation with no error bound; an omitted pair is not shown to be zero.
Refusal codes
GEOSPEC_: fewer than two components.COMPONENT_ PARTITION_ INCONCLUSIVE GEOSPEC_,EXACT_ COMPONENT_ INVALID GEOSPEC_: a candidate component is not a valid closed solid, so its overlap cannot be measured.MANIFOLD_ COMPONENT_ INVALID GEOSPEC_: aSELECTOR_ UNMATCHED pairsentry matches no pair of distinct components.MATCHER_TIMEOUT: one pair's Boolean work exceeds the budget; the diagnostic names the pair and its cost, 210 units forhousingandshaft.GEOSPEC_: the component partition or the overlap observation needs more thanANALYSIS_ LIMIT maxMeshBytesormaxMeshEntriesallows.
Examples
// passed: housingShaft, intersectionVolume 380.81 mm³ for housing and shaft
await client.query({ capability: 'analyzeMeshOverlap', subject: housingShaft, payload: {} });
// refused (GEOSPEC_SELECTOR_UNMATCHED): housingShaft, no component is named nut
await client.query({
capability: 'analyzeMeshOverlap',
subject: housingShaft,
payload: { pairs: [{ left: 'housing', right: 'nut' }] },
});# passed: housing_shaft, intersectionVolume 380.81 mm³ for housing and shaft
query_geo(housing_shaft, "analyzeMeshOverlap", {})
# refused (GEOSPEC_SELECTOR_UNMATCHED): housing_shaft, no component is named nut
query_geo(housing_shaft, "analyzeMeshOverlap", {"pairs": [dict(left="housing", right="nut")]})query Pmi
Reports a STEP file's product manufacturing information (PMI) records and the faces they refer to, as an inventory; it does not interpret or check tolerances.
Signature
client.query({ capability: 'queryPmi', subject: part, payload: { maxRecords?, maxOutputBytes? } }): Promise<GeoSpecCanonicalClaimReport>query_geo(part, "queryPmi", {"maxRecords": ..., "maxOutputBytes": ...}) -> GeoSpecAssertionReportFields
| Field | Type | Default | Meaning |
|---|---|---|---|
maxRecords | integer, 1 to 1,024 | 1024 | Record limit |
maxOutputBytes | integer, 1 to 1,048,576 | 1048576 | Byte limit |
Admitted geometry
- STEP whose source is within 8 MiB. A file with no PMI, such as the plate, answers
passedwith an empty inventory. - The query reads no face geometry, so a STEP subject whose faces carry no surface is admitted.
Refusal codes
GEOSPEC_: the subject is not STEP;UNSUPPORTED_ EVIDENCE details.isapplicability. condition retained-step-source.GEOSPEC_: the inventory exceedsANALYSIS_ LIMIT maxRecordsormaxOutputBytes, as the NIST case does withmaxRecords: 1, and nothing truncated is returned; or the source exceeds 8 MiB, a capacity the inventory profile fixes, or the engine'smaxMeshBytes. The message names the limit and what the query needed, anddetailscarrylimitandrequired.
Examples
// passed: nist, 94 records with inventory status 'semantic'
await client.query({ capability: 'queryPmi', subject: nist });
// refused (GEOSPEC_UNSUPPORTED_EVIDENCE): gear, a GLB mesh carries no STEP source
await client.query({ capability: 'queryPmi', subject: gear });
// refused (GEOSPEC_ANALYSIS_LIMIT): nist with maxRecords 1, the inventory needs 2 records
await client.query({ capability: 'queryPmi', subject: nist, payload: { maxRecords: 1 } });# passed: nist, 94 records with inventory status "semantic"
query_geo(nist, "queryPmi")
# refused (GEOSPEC_UNSUPPORTED_EVIDENCE): gear, a GLB mesh carries no STEP source
query_geo(gear, "queryPmi")
# refused (GEOSPEC_ANALYSIS_LIMIT): nist with maxRecords 1, the inventory needs 2 records
query_geo(nist, "queryPmi", {"maxRecords": 1})minimum Distance
Reports the exact minimum distance between two occurrences of a STEP assembly, with a closest point on each.
Signature
client.query({ capability: 'minimumDistance', subject: part, payload: { pair: [{ occurrencePath }, { occurrencePath }] } }): Promise<MinimumDistanceResult>query_geo(part, "minimumDistance", {"pair": [{"occurrencePath": ...}, {"occurrencePath": ...}]}) -> GeoSpecAssertionReportFields
| Field | Type | Default | Meaning |
|---|---|---|---|
pair | two { occurrencePath: string } items | required | Two distinct occurrence paths |
Returns
type MinimumDistanceResult =
| { status: 'complete'; fact: MinimumDistanceFact }
| { status: 'refused'; code: 'unsupported-evidence' | 'invalid-selection' | 'work-limit'; message: string }
| { status: 'interrupted'; code: 'cancelled' | 'executor-exited' | 'deadline' | 'engine-error'; message: string };
type MinimumDistanceFact = {
distance: number;
points: [[number, number, number], [number, number, number]];
occurrences: [string, string];
unit: 'mm';
coordinateSystem: 'z-up';
source: 'ap242';
assurance: 'exact-brep';
subjectHash: string;
algorithmProfile: 'geospec-minimum-distance-v1';
};The report: passed carries the same fact in result[, and refused keeps the engine's code in diagnostics.
refused maps the engine's GEOSPEC_ to unsupported-evidence, GEOSPEC_ to invalid-selection and MATCHER_TIMEOUT to work-limit; interrupted is a stop, not a verdict.
Admitted geometry
- An AP242 STEP subject with exact BRep faces, every length unit in millimetres.
- The one capability a y-up STEP subject answers; its points are reported z-up.
Refusal codes
GEOSPEC_: the subject is not STEP, the file is not AP242, or a length unit is not millimetres.UNSUPPORTED_ EVIDENCE GEOSPEC_: a path names no occurrence, or more than one.INVALID_ SELECTION
Examples
// passed: housingShaft, fact.distance 0 with coincident points; housing and shaft share material
await client.query({
capability: 'minimumDistance',
subject: housingShaft,
payload: { pair: [{ occurrencePath: 'housing' }, { occurrencePath: 'shaft' }] },
});
// refused (GEOSPEC_INVALID_SELECTION): housingShaft, no occurrence is named nut
await client.query({
capability: 'minimumDistance',
subject: housingShaft,
payload: { pair: [{ occurrencePath: 'housing' }, { occurrencePath: 'nut' }] },
});# passed: housing_shaft, fact distance 0 with coincident points; housing and shaft share material
query_geo(housing_shaft, "minimumDistance", {"pair": [{"occurrencePath": "housing"}, {"occurrencePath": "shaft"}]})
# refused (GEOSPEC_INVALID_SELECTION): housing_shaft, no occurrence is named nut
query_geo(housing_shaft, "minimumDistance", {"pair": [{"occurrencePath": "housing"}, {"occurrencePath": "nut"}]})