Bonsai: set unit scale when a project is loaded from a .blend (#9490) - #9491
Open
theoryshaw wants to merge 1 commit into
Open
theoryshaw wants to merge 1 commit into
theoryshaw wants to merge 1 commit into
Conversation
Loader.unit_scale is a class attribute that defaults to 1 and is only populated by set_unit_scale(), which is called when an IFC is imported (IfcImporter.calculate_unit_scale), when a project is created (CreateProject) and when a large project is opened. Reopening a saved .blend does none of those, so the whole session runs with unit_scale 1. For a project measured in metres that default is accidentally correct, which is why this has gone unnoticed. For any other project every consumer of Loader.unit_scale is then wrong by the unit scale factor. The most visible victim is Loader.slice_layerset_mesh(), which places its bisect planes at layer.LayerThickness * unit_scale: in a project measured in feet the planes land 1/0.3048 times too far out, so bmesh.ops.bisect_plane() never cuts and the first layer's band test claims every face. The element then renders as a single layer, and because has_layer_styles is still set to True the material creator early-returns and never repairs it. This is the same root cause as IfcOpenShell#7169, which was fixed for the new-project path only. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #9490
Problem
Loader.unit_scaleis a class attribute defaulting to1, andLoader.set_unit_scale()is only called when a project is imported, created, or opened through the large-project path. Reopening a saved.blenddoes none of those, so the session keeps the default.For a project measured in metres that default is accidentally correct. For any other project every consumer of
Loader.unit_scaleis then wrong by the unit scale factor.The most visible victim is
Loader.slice_layerset_mesh(), which places its bisect planes atlayer.LayerThickness * cls.unit_scale. In a project measured in feet the planes land 1/0.3048 ≈ 3.28× too far out, sobmesh.ops.bisect_plane()never cuts and the first layer's band test claims every face — the element renders as a single layer. Becausehas_layer_stylesis still set toTrue,material_creator.create()early-returns and never repairs it.Fix
Set the unit scale in
handler.loadIfcStore, theload_posthandler that restores a project when a.blendis opened.Verification
With a 3-layer wall in a project measured in feet, replaying the real bmesh algorithm on the wall's actual geometry:
In a live session,
tool.Loader.unit_scalereads1after opening a.blendand0.3048with this change. A wall that was correct on disk and broke on regeneration now re-slices correctly.Note for reviewers
This is the same root cause as #7169, which was fixed for the
CreateProjectpath only in 0bb21fe. That makes this the second timeunit_scalehas been patched per entry point.A more durable alternative would be to have
Loader.unit_scalederive itself fromtool.Ifc.get()on access, so a missed entry path cannot reintroduce this. I kept this PR narrow for reviewability — happy to switch to that approach if preferred.🤖 Generated with Claude Code