Commit Graph

20408 Commits

Author SHA1 Message Date
Petru Conduraru 6085894433 Fix #8570: populate ifc5d IfcOpenShell QTO formulas for IfcSpace
The headless "IfcOpenShell" calculator had all Qto_SpaceBaseQuantities
formulas set to null for IfcSpace in both IFC4QtoBaseQuantities.json and
IFC4X3QtoBaseQuantities.json, so qto.py's `if not formula: continue`
skipped every quantity, no geometry task was queued, and spaces never
appeared in results (elements_quantified: 0). The Blender calculator
already computes these; they were just never ported to the
ifcopenshell.util.shape-backed calculator.

Map the eight computable quantities to existing util.shape functions,
mirroring the Blender calculator semantics (no new shape.py code):
GrossFloorArea=gross_get_footprint_area, NetFloorArea=net_get_footprint_area,
GrossCeilingArea=gross_get_top_area, NetCeilingArea=net_get_top_area,
GrossPerimeter=gross_get_footprint_perimeter, GrossVolume=gross_get_volume,
NetVolume=net_get_volume, Height=net_get_z.

Left null (matching the Blender ruleset, not guessed): GrossWallArea,
NetWallArea, NetPerimeter (Blender stub), and FinishFloor/CeilingHeight
(Blender derives these from sibling IfcCovering decomposition geometry,
which this per-element calculator architecture can't reach).

Verified on IFC4 (4x3 space extruded 2.5m): before -> {} / elements_quantified 0;
after -> GrossFloorArea 12, GrossPerimeter 14, Height 2.5, GrossVolume 30,
etc. - all exact matches to the extrusion. IFC4X3 formulas are identical
and the formula->function resolution is schema-agnostic.

Scope: fixes the IfcSpace case (the issue title). The 12 other all-null
classes noted in the issue (IfcDoor, IfcSite, IfcRailing, ...) are left as
follow-up.

This change was made with the assistance of an AI tool.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 19:55:02 +02:00
Petru Conduraru c61ebe3876 Fix IfcCovering Qto_CoveringBaseQuantities mismatch between calculators (#6728)
The ifc5d IfcOpenShell (geometry-based) Qto engine computed
Qto_CoveringBaseQuantities using axis-agnostic heuristics:

- GrossArea/NetArea: gross_get_max_side_area / net_get_max_side_area,
  the largest of the X/Y/Z projected side areas.
- Width: gross_get_min_xyz, the smallest of the X/Y/Z dimensions.

The Blender Qto engine instead already used
EPset_Parametric.LayerSetDirection (AXIS2 for wall-like coverings,
AXIS3 for floor/ceiling-like coverings) to pick the correct axis via
get_covering_gross_area/get_covering_net_area/get_covering_width in
bonsai/bim/module/qto/calculator.py.

For any covering whose length isn't the largest dimension (e.g. a
short wall-covering strip, or a small covering patch), the two
engines' heuristics can pick different faces/axes entirely, giving
different Width/Area values for the same element - this is what was
reported in #6728.

Fix: give the IfcOpenShell engine the same layer-set-direction
awareness. Added IfcOpenShell.get_covering_parametric_axis/
get_covering_area/get_covering_width (dispatched as internal
functions, like the existing get_weight/get_segment_length), and
wired gross_get_covering_area/net_get_covering_area/
gross_get_covering_width into the IfcCovering rules in
IFC4QtoBaseQuantities.json and IFC4X3QtoBaseQuantities.json.

The AXIS2 area/width formulas (get_side_area, net_get_y) intentionally
match the simpler formulas already used for Qto_WallBaseQuantities in
this same rule set (net_get_side_area/net_get_y), rather than
replicating the Blender engine's more elaborate get_lateral_area/
get_width (min(X,Y)) helpers, consistent with how the two engines
already diverge for regular walls without being considered a bug.

Verified with a standalone script driving ifc5d.qto.IfcOpenShell
directly against synthetic AXIS2/AXIS3 IfcCovering geometry: for
typical proportions old and new formulas agree, and for
disproportionate coverings (thin dimension not the smallest/largest)
the old formulas picked the wrong axis while the new ones correctly
track the covering's LayerSetDirection, matching the Blender engine.
Did not verify through the full Blender/Bonsai UI, as it would have
required registering the addon in the machine's shared Blender
profile, which is unsafe while other agents may have it loaded.

Generated with the assistance of an AI coding tool.
2026-07-23 19:51:03 +02:00
carlopav 305f8c6003 cost: don't leave copied cost items in the copied schedule (#8851)
copy_cost_item appends the copy to the inverse relationships of the
original cost item, which for a root cost item includes the source
schedule's IfcRelAssignsToControl. copy_cost_schedule then assigned that
same cost item to the new schedule as well, so the copies showed up in
both schedules and deleting them from one removed them from the other.

Unassign the copy from the source schedule before assigning it to the
new one.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 15:04:38 +02:00
Petru Conduraru 98a25eca96 Bonsai: wire Shift+Q quantity take off hotkey into Spatial tool
Fixes #4443. The Wall/Slab/other authoring tools (BimTool subclasses)
already bind Shift+Q to bim.perform_quantity_take_off via hotkey_S_Q,
but the Spatial tool has its own separate keymap/operator
(bim.spatial_hotkey) that never registered a Q entry, forcing users to
switch tools just to (re)calculate quantities for a selected element.
Added the same Shift+Q keymap entry and a matching hotkey_S_Q handler
to the Spatial tool, mirroring BimTool's existing behavior exactly
(including the same selected-objects guard).

The other part of the request, a bulk "calculate all quantities"
entry point, already exists today: bim.perform_quantity_take_off
computes quantities for every IfcElement when no objects are
selected, exposed via the Scene > Quantity Take-off panel regardless
of which workspace tool is active, so no change was needed there.

AI-generated, reviewed and tested by BIMvoice.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-23 07:19:04 +02:00
Petru Conduraru 99c370b755 Bonsai: allow nesting element type objects together (#2283)
can_nest() only permitted IfcElement-to-IfcElement pairs, so nesting
two IfcElementType objects (e.g. an IfcElementAssemblyType nesting a
component IfcDoorType) was silently rejected. IfcRelNests.RelatingObject/
RelatedObjects are typed as the general IfcObjectDefinition in the
schema, so type-to-type nesting is schema legal, IfcOpenShell's core
nest.assign_object API already handles it generically, and the Nest
UI panel is driven purely by ifcopenshell.util.element.get_nest/
get_components (IFC data queries, not Blender collection structure),
so once the relationship exists it displays correctly with no other
changes needed.

Extended is_compatible_class to also accept a same-kind IfcTypeProduct
pair. Mixing an occurrence element with a type is intentionally still
rejected, that isn't a real modeling pattern.

Verified live in headless Blender: type-to-type nesting now creates
a real IfcRelNests and the Nest panel's own data functions reflect
it correctly; mixing an occurrence with a type is still rejected;
existing element-to-element nesting is unaffected.

Generated with the assistance of an AI coding tool.
2026-07-23 07:19:04 +02:00
Petru Conduraru f3cb7aea61 ifc5d: wire up GrossFootprintArea/NetFootprintArea for IfcWall QTO
Root cause: the IfcOpenShell-geometry-engine calculator ruleset
(IFC4QtoBaseQuantities.json and IFC4X3QtoBaseQuantities.json) left
IfcWall's GrossFootprintArea/NetFootprintArea mapped to null, so
these two quantities were silently omitted from Qto_WallBaseQuantities
whenever that ruleset was used. The generic gross_get_footprint_area
and net_get_footprint_area formulas already exist and are already
wired up for IfcSlab in the same files, so this was a missing mapping,
not a missing implementation.

Fixes #7029.

Generated with the assistance of an AI coding tool.
2026-07-23 07:16:01 +02:00
Andrej730 4cd9d4b53a drawing: update use of settings after introduction of plugins 2026-07-22 19:01:51 +05:00
Andrej730 3536bcf46d entity_instance: switch to use of declaration as a property
Fixes most of the bonsai tests.
2026-07-22 19:01:51 +05:00
Andrej730 c2badadfc4 cmake: skip compiled extensions when installing ifcwrap sources 2026-07-22 19:01:51 +05:00
Andrej730 037908f08e dev_environment.py: add --skip-binaries flag 2026-07-22 19:01:50 +05:00
Andrej730 1e4b4b5557 test_getting_elements_by_profile: fix test 2026-07-22 19:01:50 +05:00
Andrej730 5786d1e4bd test_global_id_updated: fix expected message (a07f56db6) 2026-07-22 19:01:50 +05:00
Andrej730 1bc5134578 ifcopenshell: fix stale reference to _file 2026-07-22 19:01:50 +05:00
Andrej730 298e4cfd8d instance_streamer: migrate to snake case 2026-07-22 19:01:50 +05:00
Andrej730 e98a3a5c2c test_create_shape: fix use of renamed OutputFormat 2026-07-22 19:01:50 +05:00
Andrej730 ab38f4f7f6 Consider new geometry settings 2026-07-22 19:01:50 +05:00
Andrej730 01cfbe6948 Consider new serializer settings 2026-07-22 19:01:50 +05:00
Andrej730 872efac4d2 parse_ifcxml: drop the use of the removed method 2026-07-22 19:01:50 +05:00
Andrej730 32f2dfd294 downstream: logger: reuse logger_or_root, dedupe optional-logger-arg pattern 2026-07-22 19:01:50 +05:00
Andrej730 d45174066f downstream: logger: use Logger* instead of Logger& to propagate signature using swig 2026-07-22 19:01:50 +05:00
Andrej730 e50bace056 stub: drop serializer classes
Superseded by generic `create_geometry_serializer`
2026-07-22 19:01:50 +05:00
Andrej730 5f0f4669f2 Fix using logger.Root instead of logger.root 2026-07-22 19:01:50 +05:00
Andrej730 c4e411c735 Drop use of removed entity_instance.wrapped_data 2026-07-22 19:01:50 +05:00
Andrej730 f733502757 Replace removed get_info_2 2026-07-22 19:01:50 +05:00
Andrej730 6ff35f4a00 IfcParseWrapper: use swig feature to override base classes
Needed to make all attributes be resolvable statically.
2026-07-22 19:01:50 +05:00
Andrej730 e6a7f7513d entity_instance: comparison operators to support non-entity types 2026-07-22 19:01:50 +05:00
Andrej730 6f643bad0c entity_instance: fix using get_info before it's defined 2026-07-22 19:01:50 +05:00
Andrej730 4275b23a27 ifcviewer: fatal_error on missing patchelf instead of warning 2026-07-22 19:01:50 +05:00
Andrej730 3efb2c2d5f Fix ruff complaints 2026-07-22 19:01:49 +05:00
Andrej730 ba3801718f downstream: surveyor: drop never used dead code
Surveyor test was failing because `get_z_rotation` and `set_z_rotation` were not implemented.
The code was added in 230cbe1fd8, but it was never used.
2026-07-22 19:01:49 +05:00
Andrej730 147119d5f6 downstream: bsdd: raise informative HTTPError
Previously we were just passing `.json()` which allowed too many request
error slip in to later occur as missing attributes on the dictionaries.
2026-07-22 18:51:53 +05:00
Andrej730 ecbd8941de downstream: bsdd: warn about include_class_properties deprecation
See https://github.com/buildingSMART/bSDD/issues/149
2026-07-22 18:51:53 +05:00
Andrej730 9296fd8d1f downstream: misc: add Blender 5.2 offset for Quick Favorites user_menus 2026-07-22 18:49:38 +05:00
Andrej730 dc1d35ce8b downstream: bonsai tests: fix test_failed_to_load_returns_only_base_keys (fdb2947) 2026-07-22 18:41:30 +05:00
Andrej730 113643c916 dev_environment.py: add --skip-binaries flag 2026-07-22 18:36:24 +05:00
Andrej730 16c1d2ece3 downstream: core.drawing: deduplicate code, fix test
Core test was trying to access actual ifc data (`ifc.get().by_type("IfcGroup")` and was failing.
2026-07-22 18:36:08 +05:00
Andrej730 f0e6cfecc1 cmake: skip compiled extensions when installing ifcwrap sources 2026-07-22 18:31:48 +05:00
Andrej730 036c74e901 downstream: dev_environment.py: detect Python 3.13 on any Blender 5.1+ 2026-07-22 17:59:38 +05:00
Andrej730 4972556eb9 downstream: ColumnPSetsOfSets.ifc: restore original schema
It seems it was switched to ifc2x3 by accident.
Related - a7738ee 6c590bf00
2026-07-22 17:26:30 +05:00
Andrej730 7338736898 ColumnPSetsOfSets.ifc: restore original schema
It seems it was switched to ifc2x3 by accident.
Related - a7738ee 6c590bf00
2026-07-22 17:24:40 +05:00
Andrej730 8f5b744cea downstream: util.schema: fix geometry_classes_introduced_after using wrong IFC4X3 schema
It was passing `IFC4X3` directly to `schema_by_name` which is expecting
schema identifier (e.g. IFC4X3_ADD2, not IFC4X3 allowed by `IFC_SCHEMA`
- IFC4X3 is one of the IFC4X3 iterations while it was in development,
not the final one).

Noticed by tests failing:
FAILED
test/util/test_schema.py::TestGeometryClassesIntroducedAfter::test_ifc4x3_to_ifc2x3_is_superset_of_ifc4_to_ifc2x3
- RuntimeError: No schema named IFC4X3
FAILED
test/util/test_schema.py::TestGeometryClassesIntroducedAfter::test_ifc4_to_ifc4x3_is_empty
- RuntimeError: No schema named IFC4X3
2026-07-22 16:26:49 +05:00
Andrej730 e9e2f89649 Revert "Sync ifcopenshell_wrapper.pyi with sync_stub.py"
This reverts commit b61f809731.

This commit was probably using not updated build, currently latest build is e333c1c and can confirm that it has `logger_or_root` added and `delete_same_facet_edge_pairs` removed.
2026-07-22 15:19:16 +05:00
Andrej730 20b1d98178 downstream: express: drop Python 2 fallbacks 2026-07-22 14:52:28 +05:00
Andrej730 c5634d5160 downstream: express: fix use of non-existent ifcexpressparser
`express.bnf` arg wasn't handled since d506ad77b
`ifcexpressparser` waa moved inside `ifcopenshell-python` awhile ago too
2026-07-22 14:52:28 +05:00
Andrej730 89663b716a downstream: pyparsing: fix using deprecated aliases
Deprecated since pyparsing 3.0 and produce runtime warnings. New
function work exactly the same, except their name is pep8 compatible.
2026-07-22 14:52:28 +05:00
Andrej730 9da1b9e02b downstream: express_parser: fix non-idempotent results 2026-07-22 14:52:28 +05:00
Andrej730 94a7ca6ac5 downstream: express: clean up trailing spaces 2026-07-22 14:52:28 +05:00
Andrej730 90c395bde4 downstream: express: update transpiled express rules using latest Python's AST
AST parser has changed a bit and there are some minor differences in the
.py output. Updating files just to avoid seeing these diffs when
rerunning rule compiler.
2026-07-22 14:52:28 +05:00
Andrej730 9e6179e671 downstream: rule_compiler: fix error running on Python 3.14
Example error:
```
    ast.Str(s=node.attr),
    ^^^^^^^
AttributeError: module 'ast' has no attribute 'Str'
```

`ast.Str` was deprecated since 3.8 and was removed in 3.14, see
https://docs.python.org/3/whatsnew/3.14.html#id9
2026-07-22 14:52:28 +05:00
Stephen Boddy a16ea85610 downstream: Remove unused imports flagged by ruff
Fixes 23 unused-import violations, mostly in the alignment API module.
2026-07-22 12:32:05 +05:00