mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-16 02:24:30 +00:00
Bonsai: include/exclude filter pair for linked models
A single selector query cannot express set differences (the grammar only unions groups, and the parent facet cannot negate), so links now carry an Exclude query beside the include, mirroring the drawing Include/Exclude pattern: final set = include (or the default set when empty) minus exclude. Applied in LoadLinkedProject and per link in create_drawing so prints match the viewport. The cache key hashes both strings when an exclude exists - keying on the query alone would let same-include/different-exclude links serve each other's geometry. Include-only filters keep the pre-exclude hash and empty filters the legacy names, so existing caches stay valid. Persistence in IfcDocumentReference.Description stays backwards compatible: a plain include is stored as-is, an exclude promotes the value to a small JSON blob, and non-JSON decodes as a legacy include. The Exclude field appears in Link IFC and the Reload Link dialog (carried through the file browser round trip, SKIP_SAVE like the rest). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -105,6 +105,32 @@ no `Description` — custom queries are not restorable there (accepted).
|
||||
clearing tolerates a missing blend (a reload with a brand-new query points at a
|
||||
not-yet-existing filename).
|
||||
|
||||
### Include/Exclude filter pair
|
||||
|
||||
The selector grammar's only cross-group combiner is `+` (union) and the `parent`
|
||||
facet cannot express "not under X" (its `!=`/regex paths also match by GlobalId, so
|
||||
negation removes everything with any parent), which makes set differences like
|
||||
"group members minus the slabs under aggregate X" structurally inexpressible in one
|
||||
query string. Links therefore carry an **Exclude** query beside the include —
|
||||
mirroring `EPset_Drawing`'s Include/Exclude pattern: final set = include (or the
|
||||
default set when empty) − exclude, applied in `LoadLinkedProject` and per link in
|
||||
`create_drawing`.
|
||||
|
||||
- **Cache key**: `get_link_cache_paths` hashes `md5(query + "\0" + exclude)` when an
|
||||
exclude exists; include-only filters keep the pre-exclude `md5(query)` so existing
|
||||
caches stay valid; empty filter keeps legacy un-suffixed names. Keying on query
|
||||
alone would let same-include/different-exclude links silently serve each other's
|
||||
geometry.
|
||||
- **Persistence**: `encode_link_filter`/`decode_link_filter` — a plain include is
|
||||
stored in `Description` as-is (backwards compatible); an exclude promotes the
|
||||
value to `{"include": …, "exclude": …}` JSON. Decode treats non-JSON as a legacy
|
||||
include string.
|
||||
- Exclude applies on top of the **default** element set too, so
|
||||
"everything except X" needs no explicit include.
|
||||
- Verified headless: `query=""`/`exclude="IfcDoor"` loads only the window;
|
||||
same file with a different filter gets its own cache; both filters survive
|
||||
save → reopen → reload.
|
||||
|
||||
### External styles + layerset slicing in the linked loader
|
||||
|
||||
`LoadLinkedProject.get_external_material(style_id)` resolves a style id → appended
|
||||
|
||||
Reference in New Issue
Block a user