Commit Graph

33 Commits

Author SHA1 Message Date
Dion Moult 19a1d88970 Fix all ty diagnostics on ifcviewer-wgpu (ci-lint ty-ios + ty-bonsai)
This branch carried v0.8.0's strict `[tool.ty.rules] all = "error"` config but
not the source fixes that were made upstream to satisfy it, so both ci-lint ty
gates were failing: `poe ty-ios` reported 256 diagnostics and `poe ty-bonsai`
258. Both are now clean.

Most fixes are ported from v0.8.0 and follow two idioms: initialise a name
before a conditional that may not bind it (plus an `assert` where the invariant
is real but not provable), and close an exhaustive `if`/`elif` chain with
`else: assert False, <discriminant>`.

The branch's own newer accessors are preserved throughout - `.file`,
`.declaration`, `file.types()`, `get_max_id()` are kept rather than reverted to
`wrapped_data.*`, and non-ty upstream changes (notably the in-progress geometry
cache removal) are deliberately not pulled in.

Notable fixes that are not straight ports:

* ifcopenshell_wrapper.pyi: `entity_instance.file` was declared as
  `def file(self) -> file`, where the property name shadows the `class file`
  below it, so the annotation resolved to `Unknown`. Every `element.file` in
  the codebase was therefore unchecked. Qualifying it to `ifcopenshell.file`
  restores `.schema` to its Literal union and surfaces no new diagnostics.

* model/wall.py: a duplicated merge fragment in the void-straddle path ran an
  always-true `if void_straddles:` that read `new_opening` from the mutually
  exclusive branch (stale value, or NameError on the first iteration), followed
  by an unreachable duplicate `elif`. Removing it makes the file match v0.8.0.

* light/operator.py: upstream's own fix unpacks three targets from two values
  and raises ValueError unconditionally; corrected to `None, None, None`.

* assign_system.py, validate.py, geom/main.py: walrus-in-genexp is valid at
  runtime (PEP 572 binds in the containing scope) but ty does not model it;
  rewritten as explicit loops, matching upstream.

Verified: poe ty-ios, poe ty-bonsai, ruff check src/ nix/, black --check .,
and compileall -W error at py3.10 (ifcopenshell-python) and py3.11 (bonsai).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-27 19:14:39 +10:00
Andrej730 619848823c Sort out imports 2026-03-06 19:07:32 +05:00
falken10vdl b246998f68 Linked IFC projects enhancement (multiple links to same project file) (#7607)
* Linked IFC projects enhancement (multiple links to same project file)

- Implement link management system using UUIDs as identifiers to support multiple links to the same IFC file
- Add georeferencing compatibility detection and UI display (NONE, NOT_COMPATIBLE, PARTIAL_COMPATIBLE, FULL_COMPATIBLE)
- Support for duplicate link creation with Shift+D shortcut and automatic position offset
- Add false origin and project north calculation from 3D cursor for MANUAL mode
- Only store one cache per file, regardless of the amount of links
- Prevent duplicate links based on filepath and position comparison
- Improve error handling for missing files and loading failures
- Update tests

* Remove duplicate georef UI

I try to avoid duplicate UI (especially for one that can be as
sophisticated as georef - e.g. missing is WCS) as it means double the
code, double the tests, potential user confusion. BTW the note about
vertical datum isn't quite accurate as it may be included in the CRS
definition so vertical datum is optional.

* Remove depsgraph_update_post handler for update_link_ui_on_transform as per core developer feedback

* Move get_projected_crs to geolocation module

* Refactor get_projected_crs to simplify as per core developer feedback

* Remove unused import of bonsai.tool from project module

* Use IfcDocumentInformation per linked file and IfcDocumentReference for locaiton information

* Refactor SaveBlendMetadataFile operator to remove  try-except blocks and remove linked projects collections since they are recreated by bonsai

* Cleanup removing empty collection instances for linked models in metadata.blend file and call determine_georeferencing_compatibility on link reload

* Add locking mechanism for linked models and update UI to reflect lock status

* Update logic that track IFC to execute_ifc_duplicate_operator instead of having it in execute() which does not track IFC undo/redo

* Refactor link handling to use get_link_empty_handle and set_link_empty_handle methods which in turn use the standard blender-ifc integrations patters (tool.Ifc.get_object(doc_reference) and tool.Ifc.link(doc_reference, empty_handle)

* remove operator.DuplicateLink and move it to tool.Project.duplicate_link()

* Refactor link handling to use sequential identifiers (no need for STEP ID DocRef)

* Refactor IFC linking logic to handle cases without a parent IFC file loaded. Firts link flase origin becomes parent origin

* Lock should not affect selection.

This makes it consistent with grid / spatial lock, and also toggle
selectability is already implemented.

* Remove unnecessary check for loaded library as Blender seems to do this internally already

* Rename util to get_crs because in IFC4X3 you can also have geographic CRS not just projected

* Remove unnecessary call to determine_georeferencing_compatibility

This function is already always called prior to calculate_link_position
so shouldn't be called here. It's also a very expensive function: as it
currently stands, just to link a single IFC, ifcopenshell.open() is
called 3 times. This reduces it to 2.

* Store CRS as metadata for linked models, and compare metadata when indicating georeferencing compatibility

Previously, to check georeferencing compatibility, ifcopenshell.open()
was used. When linking large models, this adds considerable time and
memory usage. This instead captures the georef as standard metadata in
our .cache.json. This now reduces the ifcopenshell.open() calls back
down to only 1 as necessary (see previous commit).

* Use link index instead of link name to fetch link collection item

Link name runs into issues with name uniqueness. This is why you created
a function for "get next link ID". After this refactoring, we can no
longer worry about uniqueness and that function may be removed.

* Simplify reloadlink into just unload and reload (with cache disabled)

This function should not be responsible for editing any data.

* Remove unnecessary get_next_link_id as names no longer need uniqueness

This now frees up the name variable to track a more meaningful, human
name like IfcDocumentInformation's Name attribute.

* Rewrite get / set link_empty_handle to just use the link directly

This prevents needless logic to fetch the link and also removes issues
related to duplicate names.

* Temporarily remove logic in prop callback

Right now, pretty much all the logic is done in a prop callback. In
general logic in prop callbacks should be minimised, since it's hard to
test and easily triggered as a domino effect of another change, and may
also impact undo/redo.

* Remove code that unnecessarily removes cache

This code removes cache, which means any project unlinking an IFC auto
clears the cache for any other project which doesn't make sense, and
also breaks the ability to readd it quickly.

* Rewrite link, unlink, load, and unload IFC

There were a few issues tackled here:

 - Operators that change any IFC data must use tool.Ifc.Operator and
_execute, otherwise undo/redo will break. That's one of the risks of
using prop callbacks, as it is not explicit when an IFC edit happens.
 - The usage of IfcDocumentReference was not correct. The Location
should store the URL, _not_ the position. The position should be in the
Identification attribute.
 - The URL was stored in IfcDocumentInformation location, which does not
work in IFC2X3. There are a few changes here to make it IFC2X3
compatible.
 - Generally move logic in operators, not prop callback.

* Remove restriction around manual mode.

Users should be able to use manual mode if they want.

* Restore AUTOMATIC mode to identical behaviour to file open

This is the first step to reusing cache files agnostic of the host.

* Revert tests for a fresh start for updating tests

* Revert "test_feature - clean up .ifc.cache. files after test was executed"

This reverts commit 99ae768ddf.

* Update tests and reimplement calculations for matrix of empty handle

Previously, the empty would always be placed at the origin, unless a
"position" offset was present. This is a problem, because the "position"
is simply a local offset relative to the Blender cache! If the cache was
regenerated, the offsets would be outdated. Also, the cache appeared in
different locations depending on the false origin mode, so the offset
would mean different things to different people.

Instead, a more robust method is:

 1. When you link a file, a Blender cache is generated. The Blender
origin of this cache is arbitrary! It depends on the user's false origin
mode and is purely a Blender session specific thing.
 2. When you load a link, a link is _always_ loaded into the correct
location with regards to IFC global coordinates. All math is done from
the perspective of IFC.
 3. If you choose to transform (move / rotate / scale!?) this link from
its correct location, that gets recorded as a 4x4 transformation matrix.
Note: I haven't implemented this properly yet.

Tests all pass, with a minor modification to the new behaviour that
false origin mode now won't affect the location it ends up in, only the
generation of the cache.

* Remove arbitrary convention around display name

Not needed anymore now that A/M/D is a detail and not significant on
actual coordinates, and also that the UUID is no longer needed.

* Simplify implementation of loading linked models when opening an IFC

* Move link matrix calculation from operator to tool for reuse

* Implement editing link location and calculation of transformation matrix

I changed my mind on the is_locked thing, since it isn't clear to the
user that locking need to be done to save changes.

* Remove old is_locked, prop update callback no longer needed (dedicated operator instead), remove old calculation code

* Simplify code related to placed_as_per_georef

* For now, simple skip for duplicate / delete

IMO duplicate / delete / move a link are very rare and explicit
operations.

* Update tests

* Remove host_model coordinate data as cache is no longer host model dependent

* Move icons outside list because there are too many

* Minor tweaks

---------

Co-authored-by: Dion Moult <dionmoult@gmail.com>
Co-authored-by: Dion Moult <dion@thinkmoult.com>
2026-02-15 19:28:43 +11:00
Andrej730 13be6ccd45 Sort imports 2025-12-19 18:53:14 +05:00
Andrea Ghensi 1b5b9fdcf6 fix: use numpy 2d indexing, avoid np.matrix
fixes #7141
2025-09-29 23:29:08 +10:00
falken10vdl 5304072892 dms2dd and dd2dms - fix doc-strings, refactor, add tests (#6763) 2025-09-04 11:55:13 +00:00
Andrej730 eca1d47d06 typing 2024-08-08 18:12:45 +05:00
Dion Moult 95f71a2e2f You can now specify custom project norths when loading in models in absolute terms 2024-07-06 15:43:16 +10:00
Dion Moult 7a36c05c30 Implement WCS consideration in XYZ <-> ENH conversions. 2024-06-24 18:21:06 +10:00
Dion Moult 03ee826e67 Add tests for xaxis and yaxis angle conversions
This tricked me today, the "XAxis" and "YAxis" vectors are from different perspectives (yikes!). XAxis is from the perspective of grid north, and YAxis is from the perspective of project north. I'm following this convention because that's what buildingSMART docs do but just FYI they serve two different purposes!
2024-06-23 22:23:48 +10:00
Dion Moult fd8cb7e8ed Implement Blender UI for handling new coordinate operations in IFC4X3 2024-06-22 23:32:25 +10:00
Dion Moult a6c3ae8446 Typing and update geolocation conversion utils to follow IFC4X3 rules about unit scaling 2024-06-22 15:52:00 +10:00
Dion Moult d0373da0ad Update XYZ <-> ENH geolocation conversion after the clarifications made on how to handle scale in IFC4X3 2024-06-22 14:47:42 +10:00
Dion Moult 93639e9e50 Even more cleaning of documentation references 2024-05-07 19:08:13 +10:00
Dion Moult 6660bf7618 Document geolocation util and add support for ePSet IFC2X3 fallbacks. 2023-10-05 16:15:28 +11:00
Dion Moult 9a34b94568 Fix #3682. You can now tag setout points with dynamic xyz / enh values. 2023-09-07 13:47:54 +10:00
Dion Moult 945836f578 Initial implementation of scale dependent map conversion for IFC4X3 2023-08-04 14:42:43 +10:00
Sigma Dimensions 9c4fa666c9 Georeferencing utility to convert an angle in degrees to X Axis Abscissa and Ordinate 2023-07-06 16:02:03 +01:00
Dion Moult 30d6289942 New utility to quickly get the grid north or true north angles. 2023-03-06 17:47:22 +11:00
Dion Moult 7c275a99a2 New utility functions for automatic local to global elevation conversions and easier unit conversions 2023-02-02 23:01:12 +11:00
Dion Moult 95881c6258 Fix embarrassing geolocation bug for showing / setting grid north 2022-06-09 10:22:02 +10:00
Dion Moult 810c71dfa2 IfcOpenShell-python licensing and black. See #1082. 2022-01-19 12:18:33 +11:00
Dion Moult 6e6cbcef6f Test edit object placement. See #1711 2021-10-04 13:14:47 +11:00
Dion Moult 09be170820 Geolocation utilities now support converting either X axis or Y axis to an angle 2021-04-03 21:58:35 +11:00
Dion Moult 1142c5285c Geolocation util can now apply georeferencing to matrices 2021-01-20 10:07:48 +11:00
Dion Moult 6ecf7a80f5 You can now convert from global to local coordinates 2020-11-05 18:17:45 +11:00
htlcnn 286c77e3b0 black ifcopenshell-python 2020-11-02 08:28:02 +11:00
Dion Moult c6a5bdf4eb Fix bugs in geocoding and geolocation MicroMVDs. 2020-09-10 17:43:30 +10:00
Dion Moult 7f95759df0 Implement model federation MicroMVD for BIMTester 2020-09-09 16:44:36 +10:00
Dion Moult 9359c388d1 Add true north conversion function to IfcOpenShell geolocation util lib 2020-07-27 18:38:34 +10:00
carlopav 35ea0b1b8b further fix to geolocation.py 2020-05-17 15:26:54 +02:00
carlopav 8fe4eb1dba util/geolocation.py fix imports and dms2dd 2020-05-17 12:32:52 +02:00
Dion Moult c7e3dba8c4 Add util module to IfcOpenShell, including element, geolocation, unit, and selector. See #829. 2020-05-17 18:32:56 +10:00