@ifc-lite/flow-nodes 0.3.1 → 0.5.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 +1 -0
- package/dist/aps-client.d.ts +55 -0
- package/dist/aps-client.d.ts.map +1 -0
- package/dist/aps-client.js +194 -0
- package/dist/aps-client.js.map +1 -0
- package/dist/aps-nodes.d.ts +3 -0
- package/dist/aps-nodes.d.ts.map +1 -0
- package/dist/aps-nodes.js +192 -0
- package/dist/aps-nodes.js.map +1 -0
- package/dist/aps-table.d.ts +24 -0
- package/dist/aps-table.d.ts.map +1 -0
- package/dist/aps-table.js +123 -0
- package/dist/aps-table.js.map +1 -0
- package/dist/base64.d.ts +8 -0
- package/dist/base64.d.ts.map +1 -0
- package/dist/base64.js +59 -0
- package/dist/base64.js.map +1 -0
- package/dist/bcf-client.d.ts +36 -0
- package/dist/bcf-client.d.ts.map +1 -0
- package/dist/bcf-client.js +108 -0
- package/dist/bcf-client.js.map +1 -0
- package/dist/bcf-nodes.d.ts +3 -0
- package/dist/bcf-nodes.d.ts.map +1 -0
- package/dist/bcf-nodes.js +181 -0
- package/dist/bcf-nodes.js.map +1 -0
- package/dist/documents-fetch.d.ts +23 -0
- package/dist/documents-fetch.d.ts.map +1 -0
- package/dist/documents-fetch.js +48 -0
- package/dist/documents-fetch.js.map +1 -0
- package/dist/documents-nodes.d.ts +5 -0
- package/dist/documents-nodes.d.ts.map +1 -0
- package/dist/documents-nodes.js +167 -0
- package/dist/documents-nodes.js.map +1 -0
- package/dist/host.d.ts +28 -0
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js.map +1 -1
- package/dist/http-request-node.d.ts +9 -0
- package/dist/http-request-node.d.ts.map +1 -0
- package/dist/http-request-node.js +109 -0
- package/dist/http-request-node.js.map +1 -0
- package/dist/index.d.ts +20 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +34 -5
- package/dist/index.js.map +1 -1
- package/dist/model-nodes.d.ts.map +1 -1
- package/dist/model-nodes.js +11 -6
- package/dist/model-nodes.js.map +1 -1
- package/dist/open-model-node.d.ts +3 -0
- package/dist/open-model-node.d.ts.map +1 -0
- package/dist/open-model-node.js +47 -0
- package/dist/open-model-node.js.map +1 -0
- package/dist/script-node.d.ts.map +1 -1
- package/dist/script-node.js +55 -21
- package/dist/script-node.js.map +1 -1
- package/dist/secrets.d.ts +88 -0
- package/dist/secrets.d.ts.map +1 -0
- package/dist/secrets.js +202 -0
- package/dist/secrets.js.map +1 -0
- package/dist/speckle/client.d.ts +52 -0
- package/dist/speckle/client.d.ts.map +1 -0
- package/dist/speckle/client.js +153 -0
- package/dist/speckle/client.js.map +1 -0
- package/dist/speckle/geometry.d.ts +37 -0
- package/dist/speckle/geometry.d.ts.map +1 -0
- package/dist/speckle/geometry.js +126 -0
- package/dist/speckle/geometry.js.map +1 -0
- package/dist/speckle/mapping.d.ts +62 -0
- package/dist/speckle/mapping.d.ts.map +1 -0
- package/dist/speckle/mapping.js +208 -0
- package/dist/speckle/mapping.js.map +1 -0
- package/dist/speckle/parameters.d.ts +49 -0
- package/dist/speckle/parameters.d.ts.map +1 -0
- package/dist/speckle/parameters.js +95 -0
- package/dist/speckle/parameters.js.map +1 -0
- package/dist/speckle/refusals.d.ts +45 -0
- package/dist/speckle/refusals.d.ts.map +1 -0
- package/dist/speckle/refusals.js +40 -0
- package/dist/speckle/refusals.js.map +1 -0
- package/dist/speckle/units.d.ts +13 -0
- package/dist/speckle/units.d.ts.map +1 -0
- package/dist/speckle/units.js +59 -0
- package/dist/speckle/units.js.map +1 -0
- package/dist/speckle/url.d.ts +35 -0
- package/dist/speckle/url.d.ts.map +1 -0
- package/dist/speckle/url.js +48 -0
- package/dist/speckle/url.js.map +1 -0
- package/dist/speckle-receive-node.d.ts +9 -0
- package/dist/speckle-receive-node.d.ts.map +1 -0
- package/dist/speckle-receive-node.js +180 -0
- package/dist/speckle-receive-node.js.map +1 -0
- package/dist/xlsx-nodes.d.ts.map +1 -1
- package/dist/xlsx-nodes.js +1 -40
- package/dist/xlsx-nodes.js.map +1 -1
- package/package.json +11 -9
|
@@ -0,0 +1,153 @@
|
|
|
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
|
+
* The Speckle wire protocol, spoken ONLY through `coreNetworkRequest` (the
|
|
6
|
+
* gated, https-only, exact-host-grant request function every flow node
|
|
7
|
+
* uses). Nothing here calls `fetch`: the transport comes from the host, and
|
|
8
|
+
* the grant check runs before any byte moves.
|
|
9
|
+
*
|
|
10
|
+
* Three requests, the same three Speckle's own object loader makes:
|
|
11
|
+
*
|
|
12
|
+
* POST /graphql version → `referencedObject` (root object id)
|
|
13
|
+
* GET /objects/<project>/<object>/single the root object alone
|
|
14
|
+
* POST /api/getobjects/<project> a batch of objects by id, one `id\tjson` per line
|
|
15
|
+
*
|
|
16
|
+
* The walk is lazy and iterative: a round fetches only the ids the previous
|
|
17
|
+
* round referenced and has not yet seen, so display meshes and their data
|
|
18
|
+
* chunks (the bulk of any commit) are never downloaded — `speckle.receive`
|
|
19
|
+
* does not write them (see `mapping.ts`). A visited set stops cycles and
|
|
20
|
+
* revisits, and `maxObjects` bounds the total, failing loudly when reached.
|
|
21
|
+
*/
|
|
22
|
+
import { coreNetworkRequest, NetworkDeniedError } from '@ifc-lite/sandbox';
|
|
23
|
+
/** Keys whose values are display geometry: never followed, never fetched. */
|
|
24
|
+
export const DISPLAY_KEYS = new Set(['displayValue', '@displayValue', 'displayMesh', '@displayMesh']);
|
|
25
|
+
const BATCH_SIZE = 500;
|
|
26
|
+
function headers(opts, extra) {
|
|
27
|
+
const h = { ...extra };
|
|
28
|
+
if (opts.token && opts.token.length > 0)
|
|
29
|
+
h.Authorization = `Bearer ${opts.token}`;
|
|
30
|
+
return h;
|
|
31
|
+
}
|
|
32
|
+
async function request(opts, url, method, extra, body) {
|
|
33
|
+
let res;
|
|
34
|
+
try {
|
|
35
|
+
res = await coreNetworkRequest({ url, method, headers: headers(opts, extra), body, timeoutMs: opts.timeoutMs, maxBytes: opts.maxBytes, signal: opts.signal }, opts.grants, opts.transport);
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
if (err instanceof NetworkDeniedError)
|
|
39
|
+
throw new Error(`speckle.receive: ${err.message}`);
|
|
40
|
+
throw err;
|
|
41
|
+
}
|
|
42
|
+
if (res.status === 401 || res.status === 403) {
|
|
43
|
+
throw new Error(`speckle.receive: ${method} ${url} was refused (${res.status}); the project is private or the token lacks access`);
|
|
44
|
+
}
|
|
45
|
+
if (res.status < 200 || res.status >= 300)
|
|
46
|
+
throw new Error(`speckle.receive: ${method} ${url} failed with status ${res.status}`);
|
|
47
|
+
if (res.truncated)
|
|
48
|
+
throw new Error(`speckle.receive: the response from ${url} exceeded maxBytes (${opts.maxBytes}); raise maxBytes to receive this model`);
|
|
49
|
+
return res.body;
|
|
50
|
+
}
|
|
51
|
+
function parseJson(text, what) {
|
|
52
|
+
try {
|
|
53
|
+
return JSON.parse(text);
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
throw new Error(`speckle.receive: ${what} is not valid JSON`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
const VERSION_QUERY = 'query ($projectId: String!, $versionId: String!) { project(id: $projectId) { version(id: $versionId) { id referencedObject } } }';
|
|
60
|
+
const LATEST_QUERY = 'query ($projectId: String!, $modelId: String!) { project(id: $projectId) { model(id: $modelId) { versions(limit: 1) { items { id referencedObject } } } } }';
|
|
61
|
+
/** The root object id a target points at, and the version it came from (if any). */
|
|
62
|
+
export async function resolveRoot(opts, target) {
|
|
63
|
+
if (target.kind === 'object')
|
|
64
|
+
return { objectId: target.objectId };
|
|
65
|
+
const pinned = target.versionId !== undefined;
|
|
66
|
+
const body = JSON.stringify(pinned
|
|
67
|
+
? { query: VERSION_QUERY, variables: { projectId: target.projectId, versionId: target.versionId } }
|
|
68
|
+
: { query: LATEST_QUERY, variables: { projectId: target.projectId, modelId: target.modelId } });
|
|
69
|
+
const text = await request(opts, `${target.server}/graphql`, 'POST', { 'Content-Type': 'application/json', Accept: 'application/json' }, body);
|
|
70
|
+
const res = parseJson(text, 'the GraphQL response');
|
|
71
|
+
if (res.errors && res.errors.length > 0) {
|
|
72
|
+
throw new Error(`speckle.receive: the server answered the version query with an error: ${res.errors.map((e) => e.message ?? '?').join('; ')}`);
|
|
73
|
+
}
|
|
74
|
+
const version = pinned ? res.data?.project?.version : res.data?.project?.model?.versions?.items?.[0];
|
|
75
|
+
if (!version) {
|
|
76
|
+
throw new Error(pinned ? `speckle.receive: version ${target.versionId} was not found in project ${target.projectId}` : `speckle.receive: model ${target.modelId} has no versions`);
|
|
77
|
+
}
|
|
78
|
+
if (typeof version.referencedObject !== 'string' || version.referencedObject.length === 0) {
|
|
79
|
+
throw new Error(`speckle.receive: version ${version.id} carries no referencedObject`);
|
|
80
|
+
}
|
|
81
|
+
return { objectId: version.referencedObject, versionId: version.id };
|
|
82
|
+
}
|
|
83
|
+
/** Every `referencedId` in an object's own JSON tree, except under display keys. */
|
|
84
|
+
export function referencedIds(value, out = new Set()) {
|
|
85
|
+
const stack = [value];
|
|
86
|
+
while (stack.length > 0) {
|
|
87
|
+
const v = stack.pop();
|
|
88
|
+
if (Array.isArray(v)) {
|
|
89
|
+
for (const x of v)
|
|
90
|
+
stack.push(x);
|
|
91
|
+
}
|
|
92
|
+
else if (v !== null && typeof v === 'object') {
|
|
93
|
+
const o = v;
|
|
94
|
+
if (typeof o.referencedId === 'string')
|
|
95
|
+
out.add(o.referencedId);
|
|
96
|
+
for (const [k, child] of Object.entries(o)) {
|
|
97
|
+
if (k === '__closure' || DISPLAY_KEYS.has(k))
|
|
98
|
+
continue;
|
|
99
|
+
if (child !== null && typeof child === 'object')
|
|
100
|
+
stack.push(child);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return out;
|
|
105
|
+
}
|
|
106
|
+
function asObject(value, what) {
|
|
107
|
+
if (value === null || typeof value !== 'object' || Array.isArray(value) || typeof value.id !== 'string') {
|
|
108
|
+
throw new Error(`speckle.receive: ${what} is not a Speckle object`);
|
|
109
|
+
}
|
|
110
|
+
return value;
|
|
111
|
+
}
|
|
112
|
+
async function fetchBatch(opts, target, ids) {
|
|
113
|
+
const text = await request(opts, `${target.server}/api/getobjects/${encodeURIComponent(target.projectId)}`, 'POST', { 'Content-Type': 'application/json', Accept: 'text/plain' }, JSON.stringify({ objects: JSON.stringify(ids) }));
|
|
114
|
+
const out = [];
|
|
115
|
+
for (const line of text.split('\n')) {
|
|
116
|
+
if (line.trim().length === 0)
|
|
117
|
+
continue;
|
|
118
|
+
const tab = line.indexOf('\t');
|
|
119
|
+
out.push(asObject(parseJson(tab >= 0 ? line.slice(tab + 1) : line, `object line "${line.slice(0, 40)}"`), 'a batch line'));
|
|
120
|
+
}
|
|
121
|
+
return out;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Fetch the root object and everything it references (display geometry
|
|
125
|
+
* excepted), keyed by id. Throws when an id the graph references is not
|
|
126
|
+
* returned by the server, or when `maxObjects` is reached.
|
|
127
|
+
*/
|
|
128
|
+
export async function fetchObjectGraph(opts, target, rootId) {
|
|
129
|
+
const objects = new Map();
|
|
130
|
+
const rootText = await request(opts, `${target.server}/objects/${encodeURIComponent(target.projectId)}/${encodeURIComponent(rootId)}/single`, 'GET', { Accept: 'text/plain' });
|
|
131
|
+
const root = asObject(parseJson(rootText, `root object ${rootId}`), `root object ${rootId}`);
|
|
132
|
+
objects.set(rootId, root);
|
|
133
|
+
let frontier = [...referencedIds(root)].filter((id) => !objects.has(id));
|
|
134
|
+
while (frontier.length > 0) {
|
|
135
|
+
if (objects.size + frontier.length > opts.maxObjects) {
|
|
136
|
+
throw new Error(`speckle.receive: the model references more than maxObjects (${opts.maxObjects}) objects; raise maxObjects to receive it`);
|
|
137
|
+
}
|
|
138
|
+
const next = new Set();
|
|
139
|
+
for (let i = 0; i < frontier.length; i += BATCH_SIZE) {
|
|
140
|
+
const ids = frontier.slice(i, i + BATCH_SIZE);
|
|
141
|
+
for (const obj of await fetchBatch(opts, target, ids))
|
|
142
|
+
objects.set(obj.id, obj);
|
|
143
|
+
const missing = ids.filter((id) => !objects.has(id));
|
|
144
|
+
if (missing.length > 0)
|
|
145
|
+
throw new Error(`speckle.receive: the server did not return ${missing.length} referenced object(s), e.g. ${missing[0]}`);
|
|
146
|
+
for (const id of ids)
|
|
147
|
+
referencedIds(objects.get(id), next);
|
|
148
|
+
}
|
|
149
|
+
frontier = [...next].filter((id) => !objects.has(id));
|
|
150
|
+
}
|
|
151
|
+
return objects;
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/speckle/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reading Speckle geometry primitives into metres: points, straight lines,
|
|
3
|
+
* and polygonal outlines. Anything that is not exactly one of those (an
|
|
4
|
+
* arc, a NURBS curve, a gap between polycurve segments) is reported as
|
|
5
|
+
* `undefined` with a reason, so the caller refuses the element rather than
|
|
6
|
+
* approximating its shape.
|
|
7
|
+
*/
|
|
8
|
+
import type { SpeckleObject } from './client.js';
|
|
9
|
+
export type Vec3 = [number, number, number];
|
|
10
|
+
export type Resolver = (value: unknown) => Record<string, unknown> | undefined;
|
|
11
|
+
/** Resolve a detached `{ speckle_type: 'reference', referencedId }` against the fetched graph; inline objects pass through. */
|
|
12
|
+
export declare function resolverFor(objects: ReadonlyMap<string, SpeckleObject>): Resolver;
|
|
13
|
+
/** `speckle_type` is a `:`-joined inheritance chain; true when `base` is one of its links. */
|
|
14
|
+
export declare function isA(obj: Record<string, unknown> | undefined, base: string): boolean;
|
|
15
|
+
/** The most-derived link of the chain, the name refusals use. */
|
|
16
|
+
export declare function leafType(obj: Record<string, unknown>): string;
|
|
17
|
+
/** A Speckle point in metres; its own `units` win over the owner's. */
|
|
18
|
+
export declare function pointOf(resolve: Resolver, value: unknown, ownerUnits: unknown): Vec3 | undefined;
|
|
19
|
+
/** Start/end of an `Objects.Geometry.Line`, in metres. */
|
|
20
|
+
export declare function lineOf(resolve: Resolver, value: unknown, ownerUnits: unknown): {
|
|
21
|
+
start: Vec3;
|
|
22
|
+
end: Vec3;
|
|
23
|
+
} | {
|
|
24
|
+
reason: string;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* The vertices of a closed, planar-horizontal outline (a `Polycurve` of
|
|
28
|
+
* `Line` segments, or a closed `Polyline`), in metres, without the closing
|
|
29
|
+
* duplicate. Everything else — arcs, open or gapped outlines, outlines whose
|
|
30
|
+
* vertices do not share one elevation — returns a reason.
|
|
31
|
+
*/
|
|
32
|
+
export declare function outlineOf(resolve: Resolver, value: unknown, ownerUnits: unknown): {
|
|
33
|
+
points: Vec3[];
|
|
34
|
+
} | {
|
|
35
|
+
reason: string;
|
|
36
|
+
};
|
|
37
|
+
//# sourceMappingURL=geometry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"geometry.d.ts","sourceRoot":"","sources":["../../src/speckle/geometry.ts"],"names":[],"mappings":"AAIA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAGjD,MAAM,MAAM,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AAC5C,MAAM,MAAM,QAAQ,GAAG,CAAC,KAAK,EAAE,OAAO,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;AAE/E,+HAA+H;AAC/H,wBAAgB,WAAW,CAAC,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,aAAa,CAAC,GAAG,QAAQ,CAOjF;AAED,8FAA8F;AAC9F,wBAAgB,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAEnF;AAED,iEAAiE;AACjE,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAK7D;AAOD,uEAAuE;AACvE,wBAAgB,OAAO,CAAC,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,GAAG,IAAI,GAAG,SAAS,CAMhG;AAED,0DAA0D;AAC1D,wBAAgB,MAAM,CAAC,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,GAAG;IAAE,KAAK,EAAE,IAAI,CAAC;IAAC,GAAG,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAS9H;AAuBD;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,GAAG;IAAE,MAAM,EAAE,IAAI,EAAE,CAAA;CAAE,GAAG;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAgCzH"}
|
|
@@ -0,0 +1,126 @@
|
|
|
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 { lengthScale } from './units.js';
|
|
5
|
+
/** Resolve a detached `{ speckle_type: 'reference', referencedId }` against the fetched graph; inline objects pass through. */
|
|
6
|
+
export function resolverFor(objects) {
|
|
7
|
+
return (value) => {
|
|
8
|
+
if (value === null || typeof value !== 'object' || Array.isArray(value))
|
|
9
|
+
return undefined;
|
|
10
|
+
const o = value;
|
|
11
|
+
if (typeof o.referencedId === 'string')
|
|
12
|
+
return objects.get(o.referencedId);
|
|
13
|
+
return o;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
/** `speckle_type` is a `:`-joined inheritance chain; true when `base` is one of its links. */
|
|
17
|
+
export function isA(obj, base) {
|
|
18
|
+
return typeof obj?.speckle_type === 'string' && obj.speckle_type.split(':').includes(base);
|
|
19
|
+
}
|
|
20
|
+
/** The most-derived link of the chain, the name refusals use. */
|
|
21
|
+
export function leafType(obj) {
|
|
22
|
+
const t = typeof obj.speckle_type === 'string' ? obj.speckle_type : 'Base';
|
|
23
|
+
const chain = t.split(':');
|
|
24
|
+
const leaf = chain[chain.length - 1];
|
|
25
|
+
return leaf.slice(leaf.lastIndexOf('.') + 1);
|
|
26
|
+
}
|
|
27
|
+
/** `a Line`, `an Arc`. */
|
|
28
|
+
const withArticle = (word) => `${/^[AEIOU]/i.test(word) ? 'an' : 'a'} ${word}`;
|
|
29
|
+
const finite = (v) => typeof v === 'number' && Number.isFinite(v);
|
|
30
|
+
/** A Speckle point in metres; its own `units` win over the owner's. */
|
|
31
|
+
export function pointOf(resolve, value, ownerUnits) {
|
|
32
|
+
const p = resolve(value);
|
|
33
|
+
if (!p || !finite(p.x) || !finite(p.y) || !finite(p.z))
|
|
34
|
+
return undefined;
|
|
35
|
+
const s = lengthScale(p.units) ?? lengthScale(ownerUnits);
|
|
36
|
+
if (s === undefined)
|
|
37
|
+
return undefined;
|
|
38
|
+
return [p.x * s, p.y * s, p.z * s];
|
|
39
|
+
}
|
|
40
|
+
/** Start/end of an `Objects.Geometry.Line`, in metres. */
|
|
41
|
+
export function lineOf(resolve, value, ownerUnits) {
|
|
42
|
+
const line = resolve(value);
|
|
43
|
+
if (!line)
|
|
44
|
+
return { reason: 'has no location line' };
|
|
45
|
+
if (!isA(line, 'Objects.Geometry.Line'))
|
|
46
|
+
return { reason: `has ${withArticle(leafType(line))} location, not a straight line` };
|
|
47
|
+
const units = line.units ?? ownerUnits;
|
|
48
|
+
const start = pointOf(resolve, line.start, units);
|
|
49
|
+
const end = pointOf(resolve, line.end, units);
|
|
50
|
+
if (!start || !end)
|
|
51
|
+
return { reason: 'has a location line without numeric points in a length unit' };
|
|
52
|
+
return { start, end };
|
|
53
|
+
}
|
|
54
|
+
/** A flat number list, possibly chunked into `DataChunk` references. */
|
|
55
|
+
function numbers(resolve, value) {
|
|
56
|
+
if (!Array.isArray(value))
|
|
57
|
+
return undefined;
|
|
58
|
+
const out = [];
|
|
59
|
+
for (const item of value) {
|
|
60
|
+
if (finite(item))
|
|
61
|
+
out.push(item);
|
|
62
|
+
else {
|
|
63
|
+
const chunk = resolve(item);
|
|
64
|
+
if (!chunk || !Array.isArray(chunk.data) || !chunk.data.every(finite))
|
|
65
|
+
return undefined;
|
|
66
|
+
out.push(...chunk.data);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return out;
|
|
70
|
+
}
|
|
71
|
+
const TOL = 1e-4; // metres: 0.1 mm
|
|
72
|
+
function near(a, b) {
|
|
73
|
+
return Math.abs(a[0] - b[0]) <= TOL && Math.abs(a[1] - b[1]) <= TOL && Math.abs(a[2] - b[2]) <= TOL;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* The vertices of a closed, planar-horizontal outline (a `Polycurve` of
|
|
77
|
+
* `Line` segments, or a closed `Polyline`), in metres, without the closing
|
|
78
|
+
* duplicate. Everything else — arcs, open or gapped outlines, outlines whose
|
|
79
|
+
* vertices do not share one elevation — returns a reason.
|
|
80
|
+
*/
|
|
81
|
+
export function outlineOf(resolve, value, ownerUnits) {
|
|
82
|
+
const curve = resolve(value);
|
|
83
|
+
if (!curve)
|
|
84
|
+
return { reason: 'has no outline' };
|
|
85
|
+
const units = curve.units ?? ownerUnits;
|
|
86
|
+
let points = [];
|
|
87
|
+
if (isA(curve, 'Objects.Geometry.Polycurve')) {
|
|
88
|
+
const segments = Array.isArray(curve.segments) ? curve.segments : [];
|
|
89
|
+
for (const [i, seg] of segments.entries()) {
|
|
90
|
+
const line = lineOf(resolve, seg, units);
|
|
91
|
+
if ('reason' in line) {
|
|
92
|
+
const s = resolve(seg);
|
|
93
|
+
return { reason: `has an outline with ${withArticle(s ? leafType(s) : 'missing')} segment, not only straight lines` };
|
|
94
|
+
}
|
|
95
|
+
if (i > 0 && !near(points[points.length - 1], line.start))
|
|
96
|
+
return { reason: 'has an outline with a gap between segments' };
|
|
97
|
+
if (i === 0)
|
|
98
|
+
points.push(line.start);
|
|
99
|
+
points.push(line.end);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
else if (isA(curve, 'Objects.Geometry.Polyline')) {
|
|
103
|
+
const flat = numbers(resolve, curve.value);
|
|
104
|
+
const s = lengthScale(units);
|
|
105
|
+
if (!flat || flat.length % 3 !== 0 || s === undefined)
|
|
106
|
+
return { reason: 'has a polyline outline without numeric coordinates in a length unit' };
|
|
107
|
+
for (let i = 0; i < flat.length; i += 3)
|
|
108
|
+
points.push([flat[i] * s, flat[i + 1] * s, flat[i + 2] * s]);
|
|
109
|
+
if (curve.closed !== true && !(points.length > 1 && near(points[0], points[points.length - 1])))
|
|
110
|
+
return { reason: 'has an open polyline outline' };
|
|
111
|
+
if (curve.closed === true)
|
|
112
|
+
points.push(points[0]);
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
return { reason: `has ${withArticle(leafType(curve))} outline, not line segments` };
|
|
116
|
+
}
|
|
117
|
+
if (points.length < 2 || !near(points[0], points[points.length - 1]))
|
|
118
|
+
return { reason: 'has an outline that does not close' };
|
|
119
|
+
points = points.slice(0, -1);
|
|
120
|
+
if (points.length < 3)
|
|
121
|
+
return { reason: 'has an outline with fewer than three vertices' };
|
|
122
|
+
if (points.some((p) => Math.abs(p[2] - points[0][2]) > TOL))
|
|
123
|
+
return { reason: 'has an outline that is not horizontal (sloped)' };
|
|
124
|
+
return { points };
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=geometry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"geometry.js","sourceRoot":"","sources":["../../src/speckle/geometry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Speckle object graph → planned IFC elements (mapping v1). Pure: no I/O,
|
|
3
|
+
* no model access. See docs/architecture/speckle-mapping.md for the table.
|
|
4
|
+
*
|
|
5
|
+
* Objects.BuiltElements.Wall → IfcWall (straight location line, height, WALL_ATTR_WIDTH_PARAM)
|
|
6
|
+
* Objects.BuiltElements.Floor → IfcSlab (flat polygonal outline, FLOOR_ATTR_THICKNESS_PARAM)
|
|
7
|
+
* Objects.BuiltElements.Roof → IfcRoof (flat polygonal footprint, ROOF_ATTR_THICKNESS_PARAM)
|
|
8
|
+
* Objects.BuiltElements.Column → IfcColumn (vertical, unrotated location line, `b` × `h`)
|
|
9
|
+
* Objects.BuiltElements.Beam → IfcBeam (straight location line, `b` × `h`)
|
|
10
|
+
*
|
|
11
|
+
* The body is rebuilt parametrically through the same `bim.store.add*`
|
|
12
|
+
* builders `model.addElement` uses; `bim.store` has no tessellated-body
|
|
13
|
+
* writer, so display meshes are counted and reported, never written.
|
|
14
|
+
* Coordinates are made relative to the element's own Speckle level and
|
|
15
|
+
* written into the one target storey.
|
|
16
|
+
*
|
|
17
|
+
* The walk is iterative with a global visited set (the output for an id is
|
|
18
|
+
* a pure function of that id, so revisits are skipped, not re-counted).
|
|
19
|
+
*/
|
|
20
|
+
import type { AddBeamInStoreParams, AddColumnInStoreParams, AddRoofPolygonParams, AddSlabPolygonParams, AddWallInStoreParams } from '@ifc-lite/sdk';
|
|
21
|
+
import type { SpeckleObject } from './client.js';
|
|
22
|
+
import { type ParamValue } from './parameters.js';
|
|
23
|
+
import { RefusalLog, type SpeckleRefusal } from './refusals.js';
|
|
24
|
+
export declare const PSET_SOURCE = "Speckle_Source";
|
|
25
|
+
export declare const PSET_TYPE = "Speckle_TypeParameters";
|
|
26
|
+
export declare const PSET_INSTANCE = "Speckle_InstanceParameters";
|
|
27
|
+
export type PlannedElement = {
|
|
28
|
+
/** Stable identity across versions: the Revit `applicationId`, else the Speckle id. */
|
|
29
|
+
readonly key: string;
|
|
30
|
+
readonly speckleType: string;
|
|
31
|
+
readonly speckleId: string;
|
|
32
|
+
readonly psets: Readonly<Record<string, Readonly<Record<string, ParamValue>>>>;
|
|
33
|
+
readonly displayMeshes: number;
|
|
34
|
+
readonly skippedEntries: number;
|
|
35
|
+
} & ({
|
|
36
|
+
readonly kind: 'wall';
|
|
37
|
+
readonly params: AddWallInStoreParams;
|
|
38
|
+
} | {
|
|
39
|
+
readonly kind: 'slab';
|
|
40
|
+
readonly params: AddSlabPolygonParams;
|
|
41
|
+
} | {
|
|
42
|
+
readonly kind: 'roof';
|
|
43
|
+
readonly params: AddRoofPolygonParams;
|
|
44
|
+
} | {
|
|
45
|
+
readonly kind: 'column';
|
|
46
|
+
readonly params: AddColumnInStoreParams;
|
|
47
|
+
} | {
|
|
48
|
+
readonly kind: 'beam';
|
|
49
|
+
readonly params: AddBeamInStoreParams;
|
|
50
|
+
});
|
|
51
|
+
export interface MappingOptions {
|
|
52
|
+
/** Only elements on this Speckle level (by name); empty = every level. */
|
|
53
|
+
readonly level?: string;
|
|
54
|
+
}
|
|
55
|
+
export interface MappingResult {
|
|
56
|
+
readonly planned: PlannedElement[];
|
|
57
|
+
readonly refusals: RefusalLog;
|
|
58
|
+
}
|
|
59
|
+
/** Walk the fetched graph from its root and plan every mappable element. */
|
|
60
|
+
export declare function mapSpeckleGraph(objects: ReadonlyMap<string, SpeckleObject>, rootId: string, opts?: MappingOptions): MappingResult;
|
|
61
|
+
export type { SpeckleRefusal };
|
|
62
|
+
//# sourceMappingURL=mapping.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mapping.d.ts","sourceRoot":"","sources":["../../src/speckle/mapping.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACpJ,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAGjD,OAAO,EAAuC,KAAK,UAAU,EAAyB,MAAM,iBAAiB,CAAC;AAC9G,OAAO,EAAE,UAAU,EAAE,KAAK,cAAc,EAA6B,MAAM,eAAe,CAAC;AAG3F,eAAO,MAAM,WAAW,mBAAmB,CAAC;AAC5C,eAAO,MAAM,SAAS,2BAA2B,CAAC;AAClD,eAAO,MAAM,aAAa,+BAA+B,CAAC;AAI1D,MAAM,MAAM,cAAc,GAAG;IAC3B,uFAAuF;IACvF,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/E,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CACjC,GAAG,CACA;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,oBAAoB,CAAA;CAAE,GAChE;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,oBAAoB,CAAA;CAAE,GAChE;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,oBAAoB,CAAA;CAAE,GAChE;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,sBAAsB,CAAA;CAAE,GACpE;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,oBAAoB,CAAA;CAAE,CACnE,CAAC;AAEF,MAAM,WAAW,cAAc;IAC7B,0EAA0E;IAC1E,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,OAAO,EAAE,cAAc,EAAE,CAAC;IACnC,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC;CAC/B;AAiKD,4EAA4E;AAC5E,wBAAgB,eAAe,CAAC,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,GAAE,cAAmB,GAAG,aAAa,CAwBrI;AAED,YAAY,EAAE,cAAc,EAAE,CAAC"}
|
|
@@ -0,0 +1,208 @@
|
|
|
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 { DISPLAY_KEYS } from './client.js';
|
|
5
|
+
import { isA, leafType, lineOf, outlineOf, resolverFor } from './geometry.js';
|
|
6
|
+
import { dimension, psetRows, readParameters } from './parameters.js';
|
|
7
|
+
import { RefusalLog } from './refusals.js';
|
|
8
|
+
import { lengthScale } from './units.js';
|
|
9
|
+
export const PSET_SOURCE = 'Speckle_Source';
|
|
10
|
+
export const PSET_TYPE = 'Speckle_TypeParameters';
|
|
11
|
+
export const PSET_INSTANCE = 'Speckle_InstanceParameters';
|
|
12
|
+
const KINDS = [
|
|
13
|
+
['Objects.BuiltElements.Wall', 'wall'],
|
|
14
|
+
['Objects.BuiltElements.Floor', 'slab'],
|
|
15
|
+
['Objects.BuiltElements.Roof', 'roof'],
|
|
16
|
+
['Objects.BuiltElements.Column', 'column'],
|
|
17
|
+
['Objects.BuiltElements.Beam', 'beam'],
|
|
18
|
+
];
|
|
19
|
+
const kindOf = (o) => KINDS.find(([base]) => isA(o, base))?.[1];
|
|
20
|
+
function isContainer(o) {
|
|
21
|
+
const t = typeof o.speckle_type === 'string' ? o.speckle_type : 'Base';
|
|
22
|
+
return t === 'Base' || isA(o, 'Speckle.Core.Models.Collections.Collection') || t.startsWith('Objects.Organization.');
|
|
23
|
+
}
|
|
24
|
+
/** Child slots a container is walked through: `elements` and dynamic `@`-detached members. */
|
|
25
|
+
function childSlots(o) {
|
|
26
|
+
const out = [];
|
|
27
|
+
for (const [k, v] of Object.entries(o)) {
|
|
28
|
+
if (DISPLAY_KEYS.has(k) || (k !== 'elements' && !k.startsWith('@')))
|
|
29
|
+
continue;
|
|
30
|
+
if (Array.isArray(v))
|
|
31
|
+
out.push(...v);
|
|
32
|
+
else if (v !== null && typeof v === 'object')
|
|
33
|
+
out.push(v);
|
|
34
|
+
}
|
|
35
|
+
return out;
|
|
36
|
+
}
|
|
37
|
+
/** Display geometry under every key the client skips; a bare object counts as one. */
|
|
38
|
+
function displayCount(o) {
|
|
39
|
+
let n = 0;
|
|
40
|
+
for (const key of DISPLAY_KEYS) {
|
|
41
|
+
const v = o[key];
|
|
42
|
+
if (Array.isArray(v))
|
|
43
|
+
n += v.length;
|
|
44
|
+
else if (v !== null && typeof v === 'object')
|
|
45
|
+
n += 1;
|
|
46
|
+
}
|
|
47
|
+
return n;
|
|
48
|
+
}
|
|
49
|
+
class Refused extends Error {
|
|
50
|
+
reason;
|
|
51
|
+
constructor(reason, detail) {
|
|
52
|
+
super(detail);
|
|
53
|
+
this.reason = reason;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
const TOL = 1e-4;
|
|
57
|
+
const str = (v) => (typeof v === 'string' && v.length > 0 ? v : v === null || v === undefined ? undefined : String(v));
|
|
58
|
+
const xy = (p) => [p[0], p[1]];
|
|
59
|
+
function required(params, internal, label) {
|
|
60
|
+
const d = dimension(params, internal);
|
|
61
|
+
if ('reason' in d)
|
|
62
|
+
throw new Refused('missing-dimension', `${d.reason} (${label})`);
|
|
63
|
+
return d.value;
|
|
64
|
+
}
|
|
65
|
+
function line(resolve, o) {
|
|
66
|
+
const l = lineOf(resolve, o.baseLine, o.units);
|
|
67
|
+
if ('reason' in l)
|
|
68
|
+
throw new Refused('geometry', l.reason);
|
|
69
|
+
return l;
|
|
70
|
+
}
|
|
71
|
+
function flatOutline(resolve, o) {
|
|
72
|
+
if (typeof o.slope === 'number' && Math.abs(o.slope) > 1e-9)
|
|
73
|
+
throw new Refused('geometry', 'is sloped; v1 writes flat slabs and roofs only');
|
|
74
|
+
if (Array.isArray(o.voids) && o.voids.length > 0)
|
|
75
|
+
throw new Refused('openings', 'has openings (voids), which a v1 extrusion would fill in');
|
|
76
|
+
const outline = outlineOf(resolve, o.outline, o.units);
|
|
77
|
+
if ('reason' in outline)
|
|
78
|
+
throw new Refused('geometry', outline.reason);
|
|
79
|
+
return outline.points;
|
|
80
|
+
}
|
|
81
|
+
function plan(resolve, o, kind, params, elevation) {
|
|
82
|
+
const header = {
|
|
83
|
+
Name: [str(o.family), str(o.type)].filter((s) => s !== undefined).join(': ') || leafType(o),
|
|
84
|
+
ObjectType: str(o.type),
|
|
85
|
+
Tag: str(o.elementId),
|
|
86
|
+
};
|
|
87
|
+
const local = (p) => [p[0], p[1], p[2] - elevation];
|
|
88
|
+
switch (kind) {
|
|
89
|
+
case 'wall': {
|
|
90
|
+
const { start, end } = line(resolve, o);
|
|
91
|
+
if (Math.abs(start[2] - end[2]) > TOL)
|
|
92
|
+
throw new Refused('geometry', 'has a location line that is not horizontal');
|
|
93
|
+
const height = typeof o.height === 'number' && o.height > 0 ? o.height * (lengthScale(o.units) ?? Number.NaN) : Number.NaN;
|
|
94
|
+
if (!Number.isFinite(height))
|
|
95
|
+
throw new Refused('missing-dimension', 'no positive height');
|
|
96
|
+
return { kind, params: { ...header, Start: local(start), End: local(end), Height: height, Thickness: required(params, 'WALL_ATTR_WIDTH_PARAM', 'Width') } };
|
|
97
|
+
}
|
|
98
|
+
case 'slab': {
|
|
99
|
+
const points = flatOutline(resolve, o);
|
|
100
|
+
const thickness = required(params, 'FLOOR_ATTR_THICKNESS_PARAM', 'Thickness');
|
|
101
|
+
// A Revit floor's outline is its top face at the level: the slab hangs below it.
|
|
102
|
+
return { kind, params: { ...header, Profile: 'polygon', OuterCurve: points.map(xy), Position: [0, 0, points[0][2] - elevation - thickness], Thickness: thickness } };
|
|
103
|
+
}
|
|
104
|
+
case 'roof': {
|
|
105
|
+
if (isA(o, 'Objects.BuiltElements.Revit.RevitRoof.RevitExtrusionRoof'))
|
|
106
|
+
throw new Refused('geometry', 'is an extrusion roof (a profile swept along a path)');
|
|
107
|
+
const points = flatOutline(resolve, o);
|
|
108
|
+
const thickness = required(params, 'ROOF_ATTR_THICKNESS_PARAM', 'Thickness');
|
|
109
|
+
return { kind, params: { ...header, Profile: 'polygon', OuterCurve: points.map(xy), Position: [0, 0, points[0][2] - elevation], Thickness: thickness } };
|
|
110
|
+
}
|
|
111
|
+
case 'column': {
|
|
112
|
+
const { start, end } = line(resolve, o);
|
|
113
|
+
if (Math.abs(start[0] - end[0]) > TOL || Math.abs(start[1] - end[1]) > TOL)
|
|
114
|
+
throw new Refused('geometry', 'is slanted; v1 writes vertical columns only');
|
|
115
|
+
if (typeof o.rotation === 'number' && Math.abs(o.rotation) > 1e-9)
|
|
116
|
+
throw new Refused('geometry', 'is rotated about its axis, which the column writer cannot express');
|
|
117
|
+
const base = start[2] <= end[2] ? start : end;
|
|
118
|
+
const height = Math.abs(end[2] - start[2]);
|
|
119
|
+
if (height <= TOL)
|
|
120
|
+
throw new Refused('missing-dimension', 'no height (zero-length location line)');
|
|
121
|
+
return { kind, params: { ...header, Position: local(base), Height: height, Width: required(params, 'b', 'b'), Depth: required(params, 'h', 'h') } };
|
|
122
|
+
}
|
|
123
|
+
case 'beam': {
|
|
124
|
+
const { start, end } = line(resolve, o);
|
|
125
|
+
return { kind, params: { ...header, Start: local(start), End: local(end), Width: required(params, 'b', 'b'), Height: required(params, 'h', 'h') } };
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
function sourcePset(o, levelName) {
|
|
130
|
+
const rows = { SpeckleId: o.id, SpeckleType: String(o.speckle_type) };
|
|
131
|
+
const add = (k, v) => {
|
|
132
|
+
const s = str(v);
|
|
133
|
+
if (s !== undefined)
|
|
134
|
+
rows[k] = s;
|
|
135
|
+
};
|
|
136
|
+
add('ApplicationId', o.applicationId);
|
|
137
|
+
add('Category', o.category);
|
|
138
|
+
add('Family', o.family);
|
|
139
|
+
add('Type', o.type);
|
|
140
|
+
add('ElementId', o.elementId);
|
|
141
|
+
add('Level', levelName);
|
|
142
|
+
add('SourceUnits', o.units);
|
|
143
|
+
return rows;
|
|
144
|
+
}
|
|
145
|
+
function mapElement(resolve, o, kind, opts, log, planned) {
|
|
146
|
+
const type = leafType(o);
|
|
147
|
+
const level = resolve(o.level);
|
|
148
|
+
const levelName = str(level?.name);
|
|
149
|
+
if (opts.level && levelName !== opts.level) {
|
|
150
|
+
log.add(type, 'other-level', `on level "${levelName ?? '(none)'}", not the requested level "${opts.level}"`, o.id);
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
const scale = lengthScale(o.units);
|
|
154
|
+
if (scale === undefined) {
|
|
155
|
+
log.add(type, 'no-units', `units "${String(o.units ?? '(none)')}" is not a length unit`, o.id);
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
const elevation = typeof level?.elevation === 'number' ? level.elevation * (lengthScale(level.units) ?? scale) : 0;
|
|
159
|
+
const { parameters, skipped } = readParameters(resolve, o);
|
|
160
|
+
try {
|
|
161
|
+
const p = plan(resolve, o, kind, parameters, elevation);
|
|
162
|
+
planned.push({
|
|
163
|
+
...p,
|
|
164
|
+
key: str(o.applicationId) ?? o.id,
|
|
165
|
+
speckleType: type,
|
|
166
|
+
speckleId: o.id,
|
|
167
|
+
psets: { [PSET_SOURCE]: sourcePset(o, levelName), [PSET_TYPE]: psetRows(parameters, 'type'), [PSET_INSTANCE]: psetRows(parameters, 'instance') },
|
|
168
|
+
displayMeshes: displayCount(o),
|
|
169
|
+
skippedEntries: skipped,
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
catch (err) {
|
|
173
|
+
if (!(err instanceof Refused))
|
|
174
|
+
throw err;
|
|
175
|
+
log.add(type, err.reason, err.message, o.id);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
/** Walk the fetched graph from its root and plan every mappable element. */
|
|
179
|
+
export function mapSpeckleGraph(objects, rootId, opts = {}) {
|
|
180
|
+
const resolve = resolverFor(objects);
|
|
181
|
+
const log = new RefusalLog();
|
|
182
|
+
const planned = [];
|
|
183
|
+
const root = objects.get(rootId);
|
|
184
|
+
if (!root)
|
|
185
|
+
throw new Error(`speckle.receive: root object ${rootId} was not fetched`);
|
|
186
|
+
const seen = new Set();
|
|
187
|
+
const stack = [root];
|
|
188
|
+
while (stack.length > 0) {
|
|
189
|
+
const o = resolve(stack.pop());
|
|
190
|
+
if (!o || typeof o.id !== 'string' || seen.has(o.id))
|
|
191
|
+
continue;
|
|
192
|
+
seen.add(o.id);
|
|
193
|
+
const kind = kindOf(o);
|
|
194
|
+
if (kind)
|
|
195
|
+
mapElement(resolve, o, kind, opts, log, planned);
|
|
196
|
+
else if (!isContainer(o)) {
|
|
197
|
+
log.add(leafType(o), 'unmapped-type', 'has no v1 mapping', o.id);
|
|
198
|
+
continue;
|
|
199
|
+
}
|
|
200
|
+
// Containers, and hosted elements under a mapped one (a stacked wall's
|
|
201
|
+
// layers, a wall's doors), are walked in document order.
|
|
202
|
+
const children = kind ? (Array.isArray(o.elements) ? o.elements : []) : childSlots(o);
|
|
203
|
+
for (let i = children.length - 1; i >= 0; i--)
|
|
204
|
+
stack.push(children[i]);
|
|
205
|
+
}
|
|
206
|
+
return { planned, refusals: log };
|
|
207
|
+
}
|
|
208
|
+
//# sourceMappingURL=mapping.js.map
|