Fix drawing camera being rebuilt on every create_drawing

BIMCameraProperties.update_representation caches a JSON "block representation" of
the camera and compares it as a string to decide whether the camera's IFC
representation needs refreshing. round() preserves the sign of zero and json.dumps
writes it out as "-0.0", so a matrix differing from the cached one only in a zero's
sign serialises differently forever: the strings never match even though the values
compare equal.

Reflected plan views hit this reliably, because Drawing.get_camera_shape_matrix
negates mat[1][1] for REFLECTED_PLAN_VIEW, and create_camera seeds the cache from
that matrix while CreateDrawing compares against camera.matrix_world.

The consequences were larger than a redundant IFC write. Every create_drawing ran
bim.update_representation, which reimports the drawing and builds a brand new Camera
datablock, resetting every PropertyGroup on it. Most visibly
BIMCameraProperties.active_drawing_style_index fell back to its default of 0, so the
drawing silently rendered with whichever style happens to be first in the list
instead of the activated one -- an RCP set to "Blender Default" (DEFAULT) rendered
as "Technical" (VIEWPORT) on every run, no matter how many times the style was
reactivated.

Normalising -0.0 to 0.0 lets the cache converge. On an affected drawing this drops
"Initialize drawing generation process" from ~0.34s to ~0.012s, since the camera is
no longer reimported every time.

Generated with the assistance of an AI coding tool.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Ryan Schultz
2026-08-16 21:00:58 -05:00
parent 1af5cc9bbe
commit 57c4dde34d
+7 -1
View File
@@ -671,7 +671,13 @@ class BIMCameraProperties(PropertyGroup):
# Rounding is necessary to avoid float garbage differences
# forcing unnecessary representation update.
def round_(f: float) -> float:
return round(f, 6)
# "+ 0.0" normalises -0.0 to 0.0. round() keeps the sign of zero and
# json.dumps writes it out as "-0.0", so without this a matrix differing
# only in a zero's sign serialises to a different string forever: the
# cached blob never matches and the camera datablock is rebuilt on every
# create_drawing (resetting every PropertyGroup on it). Reflected plan
# views hit this because get_camera_shape_matrix negates mat[1][1].
return round(f, 6) + 0.0
representation = json.dumps(
{