Commit Graph

19278 Commits

Author SHA1 Message Date
Stephen Boddy 96e2efebc8 Route boolean-op kernel logging through the injected Logger
src/ifcgeom/kernels/opencascade/boolean_utils.cpp, OpenCascadeKernel.cpp,
and boolean_result.cpp logged diagnostics (including the "Processed
fully in 2D" family of messages) through the global Logger::Root()
singleton. IfcConvert's main() constructs its own Logger and wires it
to --log-file via SetOutput(), then threads that instance through
Converter/kernel constructors as logger_ (see AbstractKernel). Since
Logger::Root() is never itself configured with an output stream, every
Notice/Warning/Message call through it was silently dropped instead of
reaching the log file - Logger::Message's log1_/log2_ null checks just
no-op.

This made src/ifcopenshell-python/test/test_wall_opening.py fail: it
asserts on specific log messages that the underlying boolean-op code
was still emitting correctly, just to nowhere. The geometry itself was
never wrong.

Add a Logger*, defaulting to null, to boolean_settings (with a log()
accessor falling back to Logger::Root() for the few remaining
call sites with no injected logger available), thread it through
eliminate_narrow_operands and boolean_subtraction_2d_using_builder,
and have OpenCascadeKernel/boolean_result.cpp populate it from their
inherited logger_ member instead of relying on the global singleton.

Generated with the assistance of an AI coding tool.
2026-07-18 15:03:32 +01:00
Stephen Boddy d188e3beaf Allow process/resource type assignment via Type-suffix convention
The class-pairing validation added in 10ee5aef4f rejects any type
assignment whose class isn't in the buildingSMART implementer
agreement map. That map only covers physical product occurrence/type
pairs (IfcWallType -> IfcWall, etc); IfcTypeProcess and IfcTypeResource
subtypes such as IfcTaskType, IfcProcedureType and the resource types
have no entry, so previously-valid assignments like
IfcTaskType -> IfcTask were rejected with "allowed occurrence
classes: <none>".

These classes still follow the schema's universal Type-suffix naming
convention, so derive the pairing the same way the existing
ApplicableOccurrence fallback does: strip "Type" from the relating
type's class name and accept it only if the schema actually declares
that entity. This can only add pairings implied by the type's own
class name, so it cannot loosen the existing rejection of genuine
mismatches (e.g. IfcWallType -> IfcWindow).

Generated with the assistance of an AI coding tool.
2026-07-18 15:03:32 +01:00
Stephen Boddy 93c0290131 Minor tweak to the default lining weights
The crease and sharp weighting seemed flipped to my sensibilities, so
now crease is heavier than sharp. I also added a commented out block
for debug colours in case someone wants to quickly use bright colours
to diagnose future problems.
2026-07-18 01:33:15 +01:00
Stephen Boddy f3a7a35acf Expose SVG edge classification settings in drawing UI
Add UseEdgeClassification, RenderCreases, ValleyAngleMinDegrees,
RenderSharp, RidgeAngleMinDegrees, and RenderFlush to EPset_Drawing,
following the existing HasUnderlay/DPI/PerspectiveShiftX pattern.
The master toggle defaults off, preserving current linework output;
the three dependent controls only show in the panel once it's on.

Removes the previous dormant, transient operator-redo properties for
the ridge/valley thresholds and flush-edge toggle, which were never
persisted per-drawing or exposed in any panel, replacing them with
the persistent camera properties read in setup_serialiser().

Generated with the assistance of an AI coding tool.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 01:33:15 +01:00
Stephen Boddy 183e4c47f7 Add SVG edge classification on/off + render settings
Add svg-use-edge-classification (default off, preserving today's
linework), svg-render-crease-edges, and svg-render-sharp-edges
settings, gating the existing 5-class classification feature so it
can be disabled entirely (falling back to the pre-classification
whole-shape output) or have individual classes suppressed.

Also fixes a bug uncovered while wiring this into Bonsai: ready(),
where geometry_settings() actually gets read into the serializer,
was only ever invoked explicitly by IfcConvert's CLI driver and
isn't exposed to Python. Every Svg* setting -- including the three
from previous rounds -- silently stayed at its hardcoded constructor
default when the serializer was constructed directly through the
Python bindings, as Bonsai does. Fixed by calling ready() from
SvgSerializer's own constructor, safe since it only reads
geometry_settings() with no other side effects, and settings are
always finalized before construction in every call path.

Generated with the assistance of an AI coding tool.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 01:33:15 +01:00
Stephen Boddy 2ac92f01e4 Fix missing silhouette on curved analytic column/pile faces
Circular-profile IfcColumn/IfcPile elements produce a genuine
analytic cylindrical BRep face (via BRepPrimAPI_MakePrism), not a
tessellated facet. The edge classification/extraction pipeline is
edge-identity-based end to end, but a smooth surface's silhouette is
synthesized by HLR on the fly and has no corresponding pre-existing
edge to bucket, so it was silently dropped once any edge in the
product had been classified. Add a face-level pass that includes any
non-planar face directly in the outline bucket, giving HLR's
per-face OutLine reconstruction a face identity to correlate
against. Purely additive: diffing the whole test scene's output
before and after shows only the two previously-missing tangent
lines appear, nothing else changes.

Generated with the assistance of an AI coding tool.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 01:33:15 +01:00
Stephen Boddy 2e9e75c7bd Fix Issue 4: gate the back-facing crease flip by threshold
Re-enable the view-relative sign flip for folds seen through an
opening (e.g. a box with a face removed), reverted in the previous
commit after it corrupted unrelated geometry. The earlier revert's
diagnosis was slightly off: bucket reassignment can't affect HLR's
own visibility computation, so the corruption was actually an
asymmetric-threshold artifact -- an unconditional flip re-tested
small, correctly-flush deviations against the much smaller valley
threshold instead of the ridge one. Gating the flip so it only
reinterprets folds that already clear their own pre-flip threshold
fixes the box case while leaving every other test object's
classification unchanged (verified against the full test scene).

Generated with the assistance of an AI coding tool.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 01:33:15 +01:00
Stephen Boddy 8857396a1f Fix SVG edge classification sign/threshold bugs
Fixes three bugs in classify_edge_from_faces() found via real-world
testing against a dedicated stress-test scene (icosphere, Suzanne,
cylinders/cones at various orientations, a dihedral-angle sweep rig):

- The outline (silhouette) test used a bare sign comparison, so a face
  at or near exactly edge-on to the camera could land on the wrong
  side of zero and fall through to angle-based classification instead
  of being drawn as outline. Now uses a tolerance band around zero,
  matching an equivalent check already used elsewhere in this file.
- The signed deviation-from-flat formula was inverted (180 - angle
  instead of angle), so small, genuinely near-flat facet angles came
  out with a large computed deviation and always classified as
  sharp/crease, never flush. This is why thresholds appeared to have
  no effect. Also replaced the edge/wire-orientation-based convexity
  sign (unreliable on real BRep topology, verified wrong against a
  known fully-convex icosphere) with a simpler position-based test.
- A specific edge that was previously missing entirely (not just
  misclassified) reappears correctly as a side effect of the outline
  fix above; no separate change was needed for it.

A fourth issue (folds viewed through an opening, e.g. a box missing a
face, should read as crease rather than sharp) was attempted via a
back-facing sign flip, but reverted: it broke the fixes above broadly,
since "both faces back-facing" isn't a rare look-through-a-hole case
once HLR has already filtered to visible edges only. Documented in a
code comment for whoever picks this up next.

Generated with the assistance of an AI coding tool.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 01:33:15 +01:00
Stephen Boddy f0970b90b0 Classify projection edges in SVG elevations
Adds boundary/outline/sharp/crease/flush classification of HLR
projection edges in SvgSerializer, so CSS can style silhouettes,
ridges, and valleys differently instead of drawing every edge
identically (fixes the "ugly faceted sphere" problem from #3668).

Classification happens pre-HLR on the original solid's real face
topology (three prior attempts tried to classify HLR's own output,
which carries no face topology at all and can't be correlated back
by edge identity). Each class's visible portion is then extracted via
HLRBRep_HLRToShape::VCompound(S)/OutLineVCompound(S), the same
per-shape filtering mechanism already used for per-product
segmentation, applied per class instead. Classes are tagged directly
on individual <path> elements so Bonsai's merge_linework_and_add_metadata
group-level class rewrite in operator.py never touches them.

New settings: svg-ridge-angle-min-degrees, svg-valley-angle-min-degrees,
svg-emit-flush-edges (ConversionSettings.h), wired through Bonsai's
CreateDrawing operator and exposed via its redo panel.

Refs #3668.

Generated with the assistance of an AI coding tool.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 01:33:15 +01:00
Andrej730 71a598e63a ifcopenshell.file: small wording fix 2026-07-17 21:55:22 +05:00
Andrej730 3d8115ebc5 ifcopenshell.file: drop workarounds for older builds
Introduced in aeed371 and it's been a while.
2026-07-17 21:55:22 +05:00
Ryan Schultz b5a0f1fc74 Bonsai: allow cross-family class reassignment for spatial elements with geometry (#8665)
The Reassign Class operator refused to reassign an element to a different
IFC product family unless it was an IfcElement <-> IfcElementType swap, so a
piece of geometry mistakenly hosted on IfcSite could not be turned into
IfcFurniture even though root.reassign_class handles it fine.

Loosen the guard: only block the case that actually matters - a spatial
element (IfcSpatialElement / IfcSpatialStructureElement for IFC2X3) with no
geometry, which would be a real containment-hierarchy container rather than
a stray modelled object. Everything else reassigns freely.

Closes #8664

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 18:57:11 -05:00
Petru Conduraru 25441bd816 Bonsai: make 'has openings' representation error actionable (#8108)
When converting a wall representation to a parametric extrusion via the
Representation Utilities buttons, an element that has openings would report
"has openings - representation cannot be updated" and stop, without telling
the user there is an ALT+click path that bakes the openings into the new
representation. Point the message at that path so the error is actionable.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 21:35:46 +02:00
Petru Conduraru 65811ac7c9 Bonsai: place auto-generated opening boundaries at their real position (#8237) (#8311)
* Bonsai: place auto-generated opening boundaries at their real position #8237

auto_generate_boundaries (single-space mode) built each opening/filling boundary
from the opening's LOCAL geometry (get_vertices) but first did
mat.translation = (0, 0, 0) on its placement matrix. Because the vertices are
local, that placement translation is exactly what carries the opening to its
real location, so zeroing it collapsed every window/door boundary onto the
origin. This is why the auto path misplaced window boundaries while the
single-element path (create_element_boundary) placed them correctly, as
@MDHering observed with the two modes. Keep the full placement matrix.

Verified on the reporter's file: the opening's real placement is (0.1, 1.5, 1.0);
a vertex went from (0.6, 0, 0) under the old code to (0.7, 1.5, 1.0) with the fix,
i.e. moved by exactly the (0.1, 1.5, 1.0) that was being discarded.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Remove superfluous comment from #8237 fix

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: CyrilWaechter <cyril@biminsight.ch>
2026-07-16 20:17:02 +02:00
Andrej730 d9d1824886 test-package: drop stale comment
This information is already documented in maintanence.rst.
2026-07-16 19:03:35 +05:00
Andrej730 16e5f18553 Bump build 3e7b739 -> 821cf7b
Just to test everything is working with the changes from the last month.
2026-07-16 18:59:44 +05:00
Andrej730 b7a9b7bc5a test-package: assert BUILD_COMMIT is a 7-char short SHA 2026-07-16 18:56:44 +05:00
Andrej730 e14397058d test-package: verify build URLs with HEAD requests instead of scraping listing page 2026-07-16 18:53:54 +05:00
Andrej730 f0117c60b3 stub: sync added/removed symbols 2026-07-16 18:09:32 +05:00
Andrej730 0e5223a30d stub: add missing arrange_polygon_settings (158756e921) 2026-07-16 18:00:55 +05:00
Andrej730 bc41ff78f4 stub: drop abstract_arrangement (158756e921)
And also gnore delete_same_facet_edge_pairs as it's more of an interanl API.
2026-07-16 18:00:47 +05:00
Andrej730 9123d8c183 stub: add missing entity.inverse_attributes 2026-07-16 17:35:52 +05:00
Andrej730 9213b31235 logger: reuse logger_or_root, dedupe optional-logger-arg pattern 2026-07-16 17:28:24 +05:00
Andrej730 2155e3206f logger: use Logger* instead of Logger& to propagate signature using swig
See the comment in IfcLogger.h explaining this.
2026-07-16 17:28:24 +05:00
Andrej730 9e0c6cf524 util.schema: dedupe inline schema resolution logic 2026-07-16 17:28:23 +05:00
Andrej730 d5dc069b2f 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-16 17:28:23 +05:00
Andrej730 821cf7b671 ifcparse: replace std::to_chars to fix mac build (ee2b357d7) 2026-07-16 11:57:37 +05:00
Andrej730 8718db63da pyproject: flip ty rules to error-by-default, review all new rules added since version bump 2026-07-15 19:20:17 +05:00
Andrej730 71c6950a59 ifcclash: fix use of undefined clash["position"]
It's an artifact from the old hppfcl clasher dropped in 18c38b312
2026-07-15 19:20:17 +05:00
Andrej730 5a8aa0a659 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-15 19:20:17 +05:00
Andrej730 f4526d152f bsdd: warn about include_class_properties deprecation
See https://github.com/buildingSMART/bSDD/issues/149
2026-07-15 19:20:17 +05:00
Andrej730 a7a7edfd27 bsdd: fix test_get_class_relations
`classRelations` doesn't exist on `ClassPropertiesContractV1`, probably was just a typo.
2026-07-15 19:20:17 +05:00
Andrej730 78712ead98 misc: more readable poll error for import_quick_favorites 2026-07-14 19:57:31 +05:00
Andrej730 6efb8a4373 misc: add Blender 5.2 offset for Quick Favorites user_menus 2026-07-14 19:57:31 +05:00
Andrej730 9e25c12b16 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-14 19:57:31 +05:00
Andrej730 0968d06780 Deduplicate code by reusing tool.document 2026-07-14 19:57:31 +05:00
Andrej730 3a8619726b 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-14 19:57:31 +05:00
Andrej730 1b1da821f1 file.get_inverse: document with_attribute_indices overload 2026-07-14 19:29:34 +05:00
Andrej730 d772b24bd6 geometry.add_boolean: fix typo in the class name
🫣🫣
2026-07-14 19:29:34 +05:00
Andrej730 549f81a76e ios pyproject: add networkx stubs as dev dependency 2026-07-14 19:29:34 +05:00
Andrej730 e5c7206a37 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-14 19:29:34 +05:00
Andrej730 5b968d5c75 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-14 19:29:34 +05:00
Andrej730 6075187720 express_parser: fix non-idempotent results 2026-07-14 18:42:12 +05:00
Andrej730 92528d84cd express: clean up trailing spaces 2026-07-14 18:42:12 +05:00
Andrej730 3955718145 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-14 18:42:12 +05:00
Andrej730 501246cd0b 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-14 18:42:12 +05:00
Andrej730 fb8b2ee878 bonsai pyproject: move pytest deps to requirements-dev.txt 2026-07-14 18:42:05 +05:00
Andrej730 8a00ce84cc geom/main.py: fix ty complaint 2026-07-14 14:56:06 +05:00
Andrej730 4032bbbd17 entity_instance.py: fix oveloads signatures (f93d79dc)
Without `/` overload implies that it also accepts kw args, while the implementation signature doesn't support them.
2026-07-14 14:56:06 +05:00
Andrej730 3e9ef82448 maintenance.rst: move pyver matrix to bundled Python version section 2026-07-14 14:56:06 +05:00