Commit Graph

4195 Commits

Author SHA1 Message Date
Andrej730 136ae52c8e file.get_inverse: document with_attribute_indices overload
(cherry picked from commit 1b1da821f1)
2026-07-25 23:15:23 +10:00
Andrej730 b30bd5b4f2 geometry.add_boolean: fix typo in the class name
🫣🫣

(cherry picked from commit d772b24bd6)
2026-07-25 23:15:23 +10:00
Andrej730 672b0f81f4 ios pyproject: add networkx stubs as dev dependency
(cherry picked from commit 549f81a76e)
2026-07-25 23:15:23 +10:00
Andrej730 2f4bcc17a6 geom/main.py: fix ty complaint
(cherry picked from commit 8a00ce84cc)
2026-07-25 23:15:23 +10:00
Andrej730 a6a6c20a18 dev_environment.py: add shebang and make executable
(cherry picked from commit 97d1a6e488)
2026-07-25 23:15:23 +10:00
Petru Conduraru cdd54917bc Fix ci-lint: black-format selector.py
black (the version CI's psf/black@stable resolves to) flags three spots
in util/selector.py: the chained .replace() in FormatTransformer.number,
the suppress_zero_inches kwarg in format_length, and the long
`elif key in (...) and hasattr(...)` placement-key tuple in
set_element_value. Reformat all three to black's multi-line style.
Formatting only, no behavioural change (all keys preserved).

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

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
(cherry picked from commit 5a831e3d21)
2026-07-25 23:15:23 +10:00
Petru Conduraru c4609a634c util.element: read property sets inside an IfcPropertySetDefinitionSet (#6330)
get_pset and get_psets assumed RelatingPropertyDefinition is a single property
definition and read definition.Name directly. When it is an
IfcPropertySetDefinitionSet (a defined type wrapping a list of property set
definitions) that attribute access raised AttributeError, so an element whose
psets are grouped in a set returned none of them.

Unpack IfcPropertySetDefinitionSet into its members in both loops and process
each one. Single property definitions and the psets_only and qtos_only filters
are unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
(cherry picked from commit a3950ac191)
2026-07-25 23:15:23 +10:00
Petru Conduraru 6d0809c703 Selector: add rotation_x/y/z value keys #6262
Expose the Euler rotation of an element's placement in degrees through
get_element_value, alongside the existing x/y/z and easting/northing/
elevation keys. This makes element rotation exportable through ifccsv,
e.g. for placing oriented symbols in GIS.

Adopts the approach agreed in the review of the stale PR #6272 by
@TZwielehner: reuse util.shape_builder.np_matrix_to_euler and do the
degree conversion inside get_element_value.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
(cherry picked from commit d4805387ef)
2026-07-25 23:15:23 +10:00
Petru Conduraru 17146d3572 resource.assign_resource: fix typo in duplicate guard #8203
The guard that avoids re-assigning the same object to the same resource
tested is_a("IfclRelAssignsToResource") (stray "l"), so it never matched.
A repeat assignment therefore fell through and appended the related object
to RelatedObjects a second time. Corrected to "IfcRelAssignsToResource".

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
(cherry picked from commit 21ae78fbc2)
2026-07-25 23:15:23 +10:00
Petru Conduraru ff798bc989 fix(selector): round() should not crash on non-numeric values (#6776)
FormatTransformer.round() called Decimal() directly on the input value,
which raises decimal.InvalidOperation when the value is a non-numeric
string (a text property, or a value carrying a unit suffix like "12.5 m").
In a spreadsheet export this crashed the entire operation as soon as one
element carried such a value.

Now round() catches InvalidOperation and returns the value unchanged, the
same graceful-fallback convention used by add(). Numeric rounding is
unaffected.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
(cherry picked from commit 2eea7728d2)
2026-07-25 23:15:23 +10:00
Petru Conduraru 007573cea5 Support block comments in selector filter syntax (#5023)
The filter_elements selector grammar had no way to comment out part of a
query, so users had to delete and retype text to temporarily toggle a
facet. Add a /* ... */ block comment terminal that is ignored by the
lexer, and tolerate a trailing "+" so that commenting out the final
operand (e.g. "IfcWall + /* IfcSlab */") parses cleanly. Comments may
span multiple lines; a /* sequence inside a quoted string is not treated
as a comment. Only the filter grammar is affected, not get_element or
format which use "/" for regex and division.

Adds a regression test and documents the syntax.

Generated with the assistance of an AI coding tool.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
(cherry picked from commit 5c11946470)
2026-07-25 23:15:23 +10:00
Ryan Schultz d39b1c56f8 Docs: clarify immediate vs. any-depth spatial selectors
The location and parent filters both match at any depth in the spatial
hierarchy, which surprises users who want only the elements immediately
under a given container. Document that the parent query key resolves the
direct parent only (e.g. query:"parent.Name"="My Site"), add a matching
filter example, and note the immediacy on the parent value key.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
(cherry picked from commit 0b7e25a3ef)
2026-07-25 23:15:23 +10:00
Petru Conduraru c57da082a5 Make CGAL circle-segments 0-default deflection-driven (rework #8368)
Address maintainer request on #8368: instead of a deflection floor on top
of a fixed CircleSegments count, use one mode or the other. When
CircleSegments == 0 (the new default) the CGAL kernel derives the conic
segment count from MesherLinearDeflection, matching the deflection based
meshing OpenCascade already does and fixing #8051. When CircleSegments is
non zero it is used directly as a fixed, radius independent count.

CircleSegments is only read by the CGAL kernel; OpenCascade meshes by
deflection and never reads it, so the new default has no effect there.

Update the setting description and the ifcconvert / geometry-settings docs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
(cherry picked from commit 0d70812641)
2026-07-25 23:15:22 +10:00
Stephen Boddy 1132c3c385 Fix lint drift introduced by merging v0.8.0 into lint-pass
- add_stationing_referent.py: black reformat (new drift from v0.8.0).
- update_fallback_position.py: v0.8.0's changes to this file made the
  ifcopenshell.util.unit import (added in an earlier commit here) unused;
  removed per ruff.

(cherry picked from commit c4605f2a8f)
2026-07-25 23:15:22 +10:00
Stephen Boddy 7036ea5c33 Fix ty-ios type-check errors (ifcopenshell-python side)
poe ty's sequence only reaches ty-ios once ty-bonsai passes, so these
never surfaced until now:

- util/alignment.py: drop the stale `include_referent=False` kwarg from
  add_zero_length_segment() - that parameter was removed from the function's
  signature in 45ea5eb07 but this caller in a different file was missed,
  leaving a latent TypeError if this code path is ever exercised.
- ifcopenshell_wrapper.pyi: add the optional trailing `logger` parameter to
  parse_ifcxml/open/construct_iterator*, matching the real SWIG signatures
  in src/ifcwrap/*.i (all declare `Logger& logger = Logger::Root()`) that
  the hand-maintained stub never picked up.
- ifcopenshell/__init__.py: remove a stale `ty: ignore[unknown-argument]`
  comment that ty confirms is no longer suppressing anything.
- assign_cost_item_quantity.py: OPERATORS mixes 2-arg binary operators with
  the 1-arg `operator.neg` (for ast.USub), but FormulaEvaluator has no
  visit_UnaryOp so USub can never reach this lookup via visit_BinOp.
  Suppressed at the call site rather than touching the dict, since this
  looks like scaffolding for unary-minus support rather than dead code.
- Explicit submodule imports (ifcopenshell.geom / api.alignment / util.unit
  / api.aggregate / api.context / api.spatial) added where accessed but
  only reachable by accident of import order.

(cherry picked from commit d5e890bccd)
2026-07-25 23:15:22 +10:00
Richard Brice a674dc5641 Fixes bug with fallback position introduced in 206cd6bb
(cherry picked from commit ade03b171a)
2026-07-25 23:15:22 +10:00
Richard Brice 9fc01de468 Stationing referent can optionally be located relative to the basis_curve (default) or the alignment curve
(cherry picked from commit b5c1b81ede)
2026-07-25 23:15:22 +10:00
Richard Brice 26c6281cc7 Locates positioning referent on the alignment curve, not the basis curve
(cherry picked from commit 47a20f0c7c)
2026-07-25 23:15:22 +10:00
Andrej730 9001cca078 ifcwrap: exclude internal geometry pointers
Still available as `int(xxx.this)`.
2026-07-24 21:51:21 +05:00
Andrej730 018695a2a9 file.ctor: use swig shadowing 2026-07-24 21:50:49 +05:00
Andrej730 2b7f55c1a0 stub: fixes after data model changes 2026-07-24 21:50:49 +05:00
Andrej730 9a62bf3c11 stub: updates after plugins were introduced 2026-07-24 21:50:49 +05:00
Andrej730 310eaedc8e stub: group plugin search paths methods 2026-07-24 21:50:49 +05:00
Andrej730 3c381b0d00 stub: add updated get_info_cpp 2026-07-24 21:50:49 +05:00
Andrej730 4dd39ee918 downstream: stub: drop abstract_arrangement (158756e921)
And also gnore delete_same_facet_edge_pairs as it's more of an interanl API.
2026-07-24 21:50:49 +05:00
Andrej730 af32884731 downstream: stub: add logger_or_root arg type 2026-07-24 21:50:49 +05:00
Andrej730 a20c7484e5 downstream: stub: add missing arrange_polygon_settings (158756e921) 2026-07-24 21:50:49 +05:00
Andrej730 c91d6d54bc new_IfcBaseClass: use ref for safety 2026-07-24 21:50:49 +05:00
Andrej730 a954170927 downstream: ifcwrap: exclude interal geometry pointers
Still available as `int(xxx.this)`.
2026-07-24 21:50:49 +05:00
Andrej730 6fb5a619df downsteram: IfcSchema: provide arg names for register_schema, schema_by_name 2026-07-24 21:50:49 +05:00
Andrej730 849123acee downstream: ifcwrap: hide guess_file_type from Python as unused 2026-07-24 21:50:49 +05:00
Andrej730 9544641e41 downstream: stub: sync added/removed symbols 2026-07-24 21:50:49 +05:00
Andrej730 ec558dc57e stub: add logger_or_root arg type 2026-07-24 18:37:25 +05:00
Andrej730 2db5658386 ifcwrap: hide guess_file_type from Python as unused 2026-07-24 18:22:59 +05:00
Andrej730 4a20b67038 IfcSchema: provide arg names for register_schema, schema_by_name 2026-07-24 16:48:51 +05:00
dependabot[bot] a85d5cc990 Bump lxml from 4.9.1 to 6.1.0 in /src/ifcopenshell-python
Bumps [lxml](https://github.com/lxml/lxml) from 4.9.1 to 6.1.0.
- [Release notes](https://github.com/lxml/lxml/releases)
- [Changelog](https://github.com/lxml/lxml/blob/master/CHANGES.txt)
- [Commits](https://github.com/lxml/lxml/compare/lxml-4.9.1...lxml-6.1.0)

---
updated-dependencies:
- dependency-name: lxml
  dependency-version: 6.1.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-24 15:04:15 +05:00
Petru Conduraru 21122c0d28 Resolve nested complex quantity paths in the selector (#2041)
get_element_value could not reach the members of an IfcPhysicalComplexQuantity
(or IfcComplexProperty) by their natural path. util.element expands a complex
quantity into a dict whose nested members live under a "properties" sub-dict,
but the selector's dict navigation only looked at the top level, so
"Qto_Custom.Layer1.Width" returned None and IfcCsv exported nothing for it.
Only the internal "Qto_Custom.Layer1.properties.Width" path worked.

When a key is not a direct member of the value dict, descend into its
"properties" sub-dict so nested quantities/properties resolve with the
natural "Set.Complex.Nested" path. Direct keys still take priority, so the
explicit ".properties." path stays backward compatible and the regex branch
is untouched.

Verified: Qto_Custom.Layer1.Width -> 0.1 and Layer1.Height -> 2.5 (were
None), the sibling simple NetArea still resolves, the legacy .properties.
path still works, and IfcCsv now exports the nested value. test_selector.py:
38 passed (adds test_selecting_a_nested_complex_quantity).

Generated with the assistance of an AI coding tool.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-24 10:31:38 +02:00
Dion Moult 466df653b7 docs: add installation pages for bonsaiviewer and ifcviewer
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-24 17:15:09 +10:00
Petru Conduraru 82f73c29ea style.assign_representation_styles: fix crash on IfcPresentationStyleAssignment #7883
When replacing a style on an item whose previous IfcStyledItem wraps its styles
in the deprecated IfcPresentationStyleAssignment, and the assignment is not
being reused (use_style_assignment is False, e.g. an IFC4 file authored by
AVEVA E3D), the else branch called remove_same_type_styles(style_assignment)
with style_assignment still None, raising
AttributeError: 'NoneType' object has no attribute 'Styles'. Operate on style_,
the assignment found in the current iteration, instead of the accumulator.
Verified red-green with a minimal IFC4 file using IfcPresentationStyleAssignment.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-24 16:46:29 +10:00
Petru Conduraru 209c44db83 Selector: negate list comparisons as an aggregate #8129
compare() recursed into list values passing the negated comparison through,
so != meant "at least one item differs" and both = and != matched the same
elements on any multi-valued property (e.g. an enumerated property with two
values selected). Strip the negation for the per-item comparison and negate
the aggregate instead, so != means "no item equals" and stays the complement
of =. The same applies to !*=.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-24 16:24:03 +10:00
Petru Conduraru 3d7d1ff4f3 ci: drop the ColumnPSetsOfSets.ifc fixture change, conflicts upstream
Per aothms's review comment: this file's schema was already changed
independently on v0.8.0 since this branch was created, so this PR's own
edit conflicts with it. Reverting to the current upstream version of the
fixture; the bsdd.py rate-limiting fix is untouched.
2026-07-24 14:28:18 +10:00
Petru Conduraru 8c434b7167 ifcopenshell.util.element: dedupe SET-typed attributes in replace_attribute
replace_attribute() rewrites references inside aggregate attributes via
element.walk(), but never checked whether the replacement value was
already present elsewhere in the same aggregate. For an EXPRESS SET
(e.g. IfcProject.RepresentationContexts, IfcRelAggregates.RelatedObjects)
this can leave the same reference listed twice, which is invalid IFC.
LIST and BAG aggregates legitimately allow duplicates, so a blanket dedup
would be wrong; only SET-typed attributes are deduplicated, determined at
runtime from the schema declaration (IfcOpenShell#8706 review comment).

The SET/LIST/BAG check is cached per (schema, class, attribute index), and
the dedup pass itself only runs when a cheap linear pre-check finds the
replacement value already present in the aggregate, so the common case
(no duplicate produced) pays only that pre-check, not a hash-set rebuild.
Benchmarked against a 23MB (431k entities) and a 104MB (2.4M entities) IFC
model against a large SET attribute: worst case adds well under 1ms per
call; the realistic case (merging duplicate contexts, matching the PR
#8706 scenario) shows no measurable regression.

Fixes the root cause flagged in IfcOpenShell#8706 (Moult), obviating the
need for MergeDuplicateContexts' own manual aggregate-dedup pass for that
scenario.

Generated with the assistance of an AI coding tool.
2026-07-24 14:21:31 +10:00
Petru Conduraru 8fb8966094 docs: cover reading properties and quantities from an element and its type in C++ getting started
Fixes issue #3910's documentation gap. IsDefinedBy() returns
IfcRelDefinesByProperties relationship objects, not the property set
itself, and RelatingPropertyDefinition() must be used to reach the
IfcPropertySet or IfcElementQuantity. Properties can also come from an
element's type via IsTypedBy() -> RelatingType() -> HasPropertySets(),
a path that is easy to miss because it works differently. Adds a
worked, beginner-commented, compilable example covering both paths.

Generated with the assistance of an AI coding tool.
2026-07-24 06:14:34 +02:00
Petru Conduraru e23142d01a Fix #7331: derive cost item quantities from IfcSpace base quantities
assign_cost_item_quantity skipped every IfcSpatialElement, which also
swallowed IfcSpace. Spaces are legitimate quantifiable objects, so their
Qto_SpaceBaseQuantities (for example GrossFloorArea) were never picked up
and count based cost items fell back to 0. Keep skipping spatial
containers (site, building, storey) but allow IfcSpace.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 19:58:44 +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
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 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