Commit Graph

22358 Commits

Author SHA1 Message Date
Andrej730 c23fd446d0 build-all: ifcopenshell-shared 2026-08-04 21:15:28 +05:00
Andrej730 6c750b0fdb build-all: fix opencollada patch to support it being buildable as shared 2026-08-04 14:24:32 +05:00
Andrej730 6d21801e53 build-all: fix shared build failing because opencollada is always built as static 2026-08-04 14:24:32 +05:00
Andrej730 6c049e6d6b build-all: use colors in logs for readibility 2026-08-04 14:24:32 +05:00
Andrej730 108acf1cd0 build_rocky: rely on uv for providing Python 2026-08-04 14:24:32 +05:00
Andrej730 cf7a484ce1 black . 2026-08-04 14:24:32 +05:00
Dion Moult 6aeaba0e3d p62ifc: carry across what the P6 export actually says
Level of Effort activities were skipped outright. They are now imported as
IfcTask with PredefinedType ATTENDANCE, the nearest thing IFC has to support
work that spans what it hangs off. Their dates stay derivable: the SS/FS and FF
predecessors P6 computes the span from are ordinary relationships and are
written out like any other. Skipping them also dropped 970 relationships that
happened to touch one.

User defined fields and activity codes now land as P6_UDF and
P6_ActivityCodes property sets. Separate sets because they are separate
concepts in P6, and not IfcClassificationReference for the codes because they
are orthogonal facets rather than a hierarchy. A code's description goes on
IfcProperty.Description so the short value and the readable one both survive.
UDF types come from the root declarations, since that is the only place the
data type is known, and are written sparsely.

Task times are now transcribed rather than recalculated. edit_task_time exists
to keep a schedule self-consistent while somebody edits it, so it snaps dates
off non-working days and derives durations across the calendar: reasonable for
an editor, wrong for a transcription where P6 has already run the critical path
and its answer is authoritative. On one 4,181 activity programme it moved 3,534
start dates and disagreed with P6's own duration on 3,206 activities. Actual
dates, early and late dates, float and completion are now carried too, none of
which were written before.

WBS children are created in P6's SequenceNumber order rather than document
order. IfcRelNests keeps an ordered list, so this is all it takes for a reader
to recover the breakdown as the planner arranged it, and sorting any other way
shows a programme nobody recognises.

Also: the project name was read without the namespace map, so every schedule
came out called "Unnamed".
2026-08-04 15:35:30 +10:00
Dion Moult 409373d882 Assign / unassign sequence should be specific to sequence type
I previously incorrectly believed that sequence types are mutually exclusive. E.g. you can have max 1 relationship between two tasks. Now after looking at more schedules I realise it's logically allowed to have more than one sequence relationship. For example simultaneous SS + FF.
2026-08-04 13:01:23 +10:00
Dion Moult e678012c71 ifcpatch: run FixArchiCADToRevitSpaces headlessly
The recipe loaded the model into Blender purely to reach its geometry
engine, so it could only run inside Bonsai and needed a filepath instead
of a file. It is now a plain BasePatcher.

The three fixes Revit needs are unchanged. To lower each space onto its
storey we take the storey elevation from util.placement and the space
placement from util.shape, instead of from Blender object matrices. To
convert to an extruded area solid we triangulate the space with
ifcopenshell.geom, union its downwards facing triangles with shapely to
get the footprint and its voids, and rebuild the body with
util.shape_builder.

Unioning every downwards facing face, rather than only the vertices
sitting at z=0, means stepped and clipped spaces keep their full
footprint, columns poking through a room become profile voids, and
disjoint footprints extrude as one item each. Spaces that cannot be
patched are logged and skipped rather than aborting the run, and a
storey above the top of a space falls back to the space's own height
instead of asking for a negative extrusion depth.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-04 12:16:46 +10:00
Dion Moult 0b8875669e Let the viewport composite over what is behind it
Background colour gains a meaningful alpha. Below 1 the viewport composites
over whatever the host has stacked behind it rather than painting a colour
of its own; at 0 it clears to nothing, so the model draws over another 3D
view, a map, or ordinary page content. There is no depth interaction -- the
layer behind is strictly behind and cannot occlude the model.

Honouring the alpha needs a premultiplied surface. configureSurface asks for
one only when the platform advertises it, the same way it picks a present
mode, and falls back to Auto otherwise -- this machine's Vulkan surface
offers opaque compositing only, so hardcoding premultiplied would have
requested a mode it does not support. The clear follows that choice: scaled
by alpha when premultiplied, held at 1 when not, since scaling would
otherwise just darken the colour for an alpha nobody reads.

ViewportWindow::setBackgroundColor now forwards to core rather than writing
through a reference proxy, dropping one more member from the friend
declaration it is meant to shrink. The screenshot QImage is tagged
premultiplied to match what the main pass leaves in the buffer.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-04 10:55:57 +10:00
Dion Moult c9f269a0e5 Draw a silhouette outline around the selection
The renderer tints the selection blue, which says nothing about an object
that is already blue. Add a halo drawn just outside the selected objects
instead: a fixed colour against the background, so it reads whatever the
element is painted.

The mask pass reuses the main shader module and pipeline layout and shares
the main depth buffer read-only, so the halo follows the selection as
visible -- an occluded object contributes nothing. A separable dilation
widens the mask into inner and outer rings, composited after the edge pass
so the edge multiply does not darken it.

On by default; IfcViewer.setSelectionOutline(false) gets the tint alone.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-04 10:55:57 +10:00
Andrej730 83a7836081 stub: document use_attribute_value_derived 2026-08-03 20:04:29 +05:00
Andrej730 cdf107e579 validate fixtures: validate expected error count 2026-08-03 19:51:10 +05:00
Andrej730 c1c94b9362 validate: document supported Path type 2026-08-03 18:44:06 +05:00
Andrej730 cb52013a5d validate: color output for readibility 2026-08-03 18:38:06 +05:00
Andrej730 de4ad60df3 validate: at the end print number of errors found 2026-08-03 18:24:59 +05:00
Andrej730 2fe177885e Drop unused log_entry_type named tuple (31cf1127a) 2026-08-03 18:24:47 +05:00
Andrej730 f457048285 rules fixtures: check number of expected failures 2026-08-03 17:51:26 +05:00
Andrej730 0e9ef70971 rules fixtures: append comment indicating fixture origin 2026-08-03 16:54:52 +05:00
Andrej730 ea0be33aa1 ifcopenshell.validate: typing for json logger statements 2026-08-03 16:54:52 +05:00
Andrej730 44ce7c7e8a rules fixture: nornallize headers
- to avoid some diffs on regeneration
- some fixtures had problems with the header, so `fail` for them wasn't
really testing the intended case, because small issues in the header
would make fixture fail regardless
2026-08-03 16:54:22 +05:00
Andrej730 e57c326ad1 rule fixtures: update fixture and generation script to match 4404470d9
IFCBSPLINECURVE is abstract and causing fail to fail even if point
dimensions wouldn't be checked.
2026-08-03 16:54:22 +05:00
Andrej730 5964160d67 rule fixtures: add missing generation scripts 2026-08-03 16:54:22 +05:00
Andrej730 26ab77bdf6 rule fixtures: script to regenerate all fixtures 2026-08-03 16:54:22 +05:00
Andrej730 7b2f4ad1cb rule fixture: update generation script to match a7e925b 2026-08-03 16:54:22 +05:00
Andrej730 8f67b905eb Fix ifcopenshell.file calls in rules fixtures, use simpler schema postfix 2026-08-03 16:54:22 +05:00
Andrej730 6edea83137 file.good - document return type 2026-08-03 16:54:22 +05:00
Andrej730 b1f388311c Return support for creating uninitialized files from Python
Created a new method to avoid complicating `ifcopenshell.file` ctor signature.
2026-08-03 16:54:22 +05:00
Andrej730 26b412cff6 Fix uses of ifcopenshell.file 2026-08-03 13:18:15 +05:00
Andrej730 a86667d063 Drop ignored delete_same_facet_edge_pairs from stub 2026-08-03 12:44:16 +05:00
Andrej730 b6fb5e6cdc IfcParseWrapper: ignore internal spf_header::assign 2026-08-03 12:44:00 +05:00
Andrej730 aaa763ad21 Drop revenants from previously used linters 2026-08-03 12:22:31 +05:00
Andrej730 bfd9eeb9a1 Drop unused requirements.txt
Introduced in 47cad88, but it seems it was always documentation-only and then it was also covered elsewhere.
2026-08-03 12:11:49 +05:00
Andrej730 a655ef6cd2 Drop Python 2 workaround 2026-08-03 11:52:48 +05:00
Thomas Krijnen 1cd78f487f also ignore __ne__ 2026-08-02 03:18:33 +02:00
Thomas Krijnen 1c6e2aa301 run black 2026-08-02 03:12:46 +02:00
Thomas Krijnen 064ce00826 import Any 2026-08-01 14:16:12 +02:00
Thomas Krijnen 98ce2a1b46 Move __eq__ impl back to the mixin and fix test_rules.py test 2026-08-01 13:16:51 +02:00
Thomas Krijnen 6abeb459a2 Mark v0.8.0 as merged 2026-08-01 10:50:58 +02:00
dependabot[bot] c4d402eb21 build(deps): bump actions/setup-python from 6 to 7
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 6 to 7.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v6...v7)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-01 10:50:34 +02:00
Bartok 4ea05f79c3 docs: add Eigen to Linux install deps
Linux "basic dependencies" omitted libeigen3-dev even though
ifcgeom requires Eigen3 (find_package Eigen3 REQUIRED) and the
cmake snippet already passes -DEIGEN_DIR=/usr/include/eigen3.
macOS Homebrew line already installs eigen.

Closes #6903

Generated with the assistance of an AI coding tool.
2026-08-01 10:50:34 +02:00
Petru Conduraru 6b917ba36d Fix test_rules.py filtering by sys.argv, which empties the corpus under pytest
test_file's parametrize list was filtered with `sys.argv[1] in
os.path.basename(fn)`, reading the raw process argv instead of a
pytest-native option. Under a bare `pytest` invocation sys.argv[1] is
pytest's own first CLI token, never a match, so the 138-fixture EXPRESS
rule corpus in test/fixtures/rules collapses to an empty parametrize and
pytest reports it as a single skipped test rather than an error. Under
CI's actual invocation (pytest -p no:pytest-blender -n $NPROCS test ...)
sys.argv[1] is "-p", which happens to substring-match 47 of the 138
fixtures, so CI has been silently running a coincidental 34% slice of
the corpus with no signal anything was wrong.

Replaced the module-level list comprehension with a pytest_generate_tests
hook plus a --rule CLI option (added via a new test/conftest.py). This
runs the full corpus by default under any pytest invocation, still
allows filtering to one rule for local debugging via --rule, and no
longer collides with pytest's own argv.

Verified all 138 fixtures collect and pass under the fixed harness
(63 fail- fixtures each raise a violation, 75 pass- fixtures raise none).

Generated with the assistance of an AI coding tool.
2026-08-01 10:50:30 +02:00
Petru Conduraru fa1b70883f ifcmcp: pin mcp below 2.0 to fix broken FastMCP import
mcp 2.0.0 (unpinned in CI and in the ifcmcp[mcp] extra) renamed
mcp.server.fastmcp.FastMCP to mcp.server.mcpserver.MCPServer, which
ifcmcp does not support yet. server.py caught the resulting
ModuleNotFoundError with a bare except Exception and silently
reported it as FastMCP not installed, masking the real breakage
until the ifcmcp test suite failed in CI.

Pinned mcp to >=1.0,<2 in both ci.yml and ifcmcp's pyproject.toml
mcp extra, confirmed the full ifcmcp test suite (70 tests) passes
against mcp 1.29.0, and confirmed the genuinely-not-installed path
still raises the expected ImportError. Also narrowed the except
clause to ImportError only so an unrelated future bug in that
import block surfaces instead of being swallowed as "not installed".

Generated with the assistance of an AI coding tool.
2026-08-01 10:49:17 +02:00
Petru Conduraru 913f9f2262 ifcopenshell.template: fix timestring ignoring an explicit timestamp of 0
create(timestamp=0) computed the FILE_NAME timestring with
`d.get("timestamp") or time.time()`, which treats 0 (a legitimate
epoch timestamp) as unset because 0 is falsy. The header ended up
with the current wall-clock time in FILE_NAME while IFCOWNERHISTORY
correctly stored CreationDate=0, an inconsistent pair of dates in
the same file. Switched to an explicit None check so an explicit
timestamp of 0 is honoured the same way any other explicit
timestamp is.

Generated with the assistance of an AI coding tool.
2026-08-01 10:49:17 +02:00
yekose 34da3950e3 ifcgeom: add a profile_point overload taking a plain double
The profile mapping builds its points as

    profile_helper(m4, {
        {{-x, -y}, {f2}},
        ...

where `f2` is a `double` and profile_point's second member is a
`boost::optional<double>`. In recent Boost (somewhere between 1.85 and 1.91)
optional's converting constructor became explicit, and an explicit constructor
cannot be used in copy-initialization — which is what a braced element is. So
every one of these call sites stops compiling:

  MSVC 19.4x:  error C2664: cannot convert argument 2 from
               'initializer list' to 'const std::vector<profile_point>&'
  clang-cl 22: error: chosen constructor is explicit in copy-initialization

Twelve translation units are affected (IfcCShapeProfileDef,
IfcIShapeProfileDef, IfcLShapeProfileDef, IfcTShapeProfileDef,
IfcUShapeProfileDef, IfcZShapeProfileDef, IfcAsymmetricIShapeProfileDef,
IfcCraneRailAShapeProfileDef, IfcRectangleProfileDef,
IfcRectangleHollowProfileDef, IfcRoundedRectangleProfileDef,
IfcTrapeziumProfileDef), roughly 100 call sites in total.

Adding one overload that takes the double directly fixes all of them without
touching a single call site, and changes nothing for existing code: the
optional overload still wins wherever an optional is passed.

Verified by building schemas 2x3;4;4x3_add2 with MSVC 2022 against Boost
1.91 and OCCT 7.9.3 — IfcParse, IfcGeom, the schema mappings and
geometry_kernel_opencascade all archive cleanly. Without this, the same build
against Boost 1.85 succeeds, which is what identified Boost as the variable.
2026-08-01 10:49:17 +02:00
CyrilWaechter 24f7629fad Fix space regen doubling Z location
Removing translate_obj_to_z_location from the existing-IfcSpace
regeneration branch. The ShapeBuilder rewrite (d8de62308) builds
geometry in local space preserving obj.matrix_world, making the
translate call redundant — it adds z on top of the already-correct
location.z, producing 2*z.

Add test_regenerate_space_preserves_z_location to cover the
regeneration path with a non-zero Z elevation.

Generated with the assistance of an AI coding tool.
2026-08-01 10:49:17 +02:00
dependabot[bot] a11ebdf8c4 build(deps): bump actions/setup-python from 6 to 7
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 6 to 7.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v6...v7)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
bonsai-0.8.6-alpha2607311157
2026-07-31 13:57:34 +02:00
Bartok b997726564 docs: add Eigen to Linux install deps
Linux "basic dependencies" omitted libeigen3-dev even though
ifcgeom requires Eigen3 (find_package Eigen3 REQUIRED) and the
cmake snippet already passes -DEIGEN_DIR=/usr/include/eigen3.
macOS Homebrew line already installs eigen.

Closes #6903

Generated with the assistance of an AI coding tool.
2026-07-31 12:49:37 +02:00
Petru Conduraru 25713a486a Fix test_rules.py filtering by sys.argv, which empties the corpus under pytest
test_file's parametrize list was filtered with `sys.argv[1] in
os.path.basename(fn)`, reading the raw process argv instead of a
pytest-native option. Under a bare `pytest` invocation sys.argv[1] is
pytest's own first CLI token, never a match, so the 138-fixture EXPRESS
rule corpus in test/fixtures/rules collapses to an empty parametrize and
pytest reports it as a single skipped test rather than an error. Under
CI's actual invocation (pytest -p no:pytest-blender -n $NPROCS test ...)
sys.argv[1] is "-p", which happens to substring-match 47 of the 138
fixtures, so CI has been silently running a coincidental 34% slice of
the corpus with no signal anything was wrong.

Replaced the module-level list comprehension with a pytest_generate_tests
hook plus a --rule CLI option (added via a new test/conftest.py). This
runs the full corpus by default under any pytest invocation, still
allows filtering to one rule for local debugging via --rule, and no
longer collides with pytest's own argv.

Verified all 138 fixtures collect and pass under the fixed harness
(63 fail- fixtures each raise a violation, 75 pass- fixtures raise none).

Generated with the assistance of an AI coding tool.
2026-07-31 10:38:58 +02:00
Petru Conduraru d3b6b82151 ifcmcp: pin mcp below 2.0 to fix broken FastMCP import
mcp 2.0.0 (unpinned in CI and in the ifcmcp[mcp] extra) renamed
mcp.server.fastmcp.FastMCP to mcp.server.mcpserver.MCPServer, which
ifcmcp does not support yet. server.py caught the resulting
ModuleNotFoundError with a bare except Exception and silently
reported it as FastMCP not installed, masking the real breakage
until the ifcmcp test suite failed in CI.

Pinned mcp to >=1.0,<2 in both ci.yml and ifcmcp's pyproject.toml
mcp extra, confirmed the full ifcmcp test suite (70 tests) passes
against mcp 1.29.0, and confirmed the genuinely-not-installed path
still raises the expected ImportError. Also narrowed the except
clause to ImportError only so an unrelated future bug in that
import block surfaces instead of being swallowed as "not installed".

Generated with the assistance of an AI coding tool.
2026-07-31 10:36:39 +02:00