Skip to content

Commit 2d771d6

Browse files
committed
Update relation between frame and transformation
1 parent 333d0a8 commit 2d771d6

File tree

3 files changed

+20
-31
lines changed

3 files changed

+20
-31
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1111

1212
### Changed
1313

14+
* Changed `SceneObject.worldtransformation` to the multiplication of all transformations from the scene object to the root of the scene tree.
15+
* Changed `SceneObject.frame` to read-only result of `Frame.from_transformation(SceneObject.worldtransformation)`, representing the local coordinate system of the scene object in world coordinates.
16+
1417
### Removed
1518

1619

src/compas/scene/sceneobject.py

Lines changed: 11 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from compas.colors import Color
1414
from compas.data import Data
1515
from compas.datastructures import TreeNode
16+
from compas.geometry import Frame
1617
from compas.geometry import Transformation
1718

1819
from .context import clear
@@ -36,10 +37,8 @@ class SceneObject(TreeNode):
3637
The opacity of the object.
3738
show : bool, optional
3839
Flag for showing or hiding the object. Default is ``True``.
39-
frame : :class:`compas.geometry.Frame`, optional
40-
The local frame of the scene object, in relation to its parent frame.
4140
transformation : :class:`compas.geometry.Transformation`, optional
42-
The local transformation of the scene object in relation to its frame.
41+
The local transformation of the scene object in relation to its parent object.
4342
context : str, optional
4443
The context in which the scene object is created.
4544
**kwargs : dict
@@ -56,9 +55,9 @@ class SceneObject(TreeNode):
5655
guids : list[object]
5756
The GUIDs of the items drawn in the visualization context.
5857
frame : :class:`compas.geometry.Frame`
59-
The local frame of the scene object, in relation to its parent frame.
58+
The frame of the local coordinate system of the scene object.
6059
transformation : :class:`compas.geometry.Transformation`
61-
The local transformation of the scene object in relation to its frame.
60+
The local transformation of the scene object in relation to its parent object.
6261
worldtransformation : :class:`compas.geometry.Transformation`
6362
The transformation of the scene object in world coordinates.
6463
color : :class:`compas.colors.Color`
@@ -113,7 +112,6 @@ def __init__(
113112
self._item = item
114113
self._guids = []
115114
self._node = None
116-
self._frame = frame
117115
self._transformation = transformation
118116
self._contrastcolor = None
119117
self.color = color or self.color
@@ -156,12 +154,7 @@ def guids(self):
156154
@property
157155
def frame(self):
158156
# type: () -> compas.geometry.Frame | None
159-
return self._frame
160-
161-
@frame.setter
162-
def frame(self, frame):
163-
# type: (compas.geometry.Frame) -> None
164-
self._frame = frame
157+
return Frame.from_transformation(self.worldtransformation)
165158

166159
@property
167160
def transformation(self):
@@ -176,21 +169,17 @@ def transformation(self, transformation):
176169
@property
177170
def worldtransformation(self):
178171
# type: () -> compas.geometry.Transformation
179-
frame_stack = [self.frame] if self.frame else []
180-
parent = self.parent
172+
transformations = [self.transformation] if self.transformation else []
173+
parent: SceneObject = self.parent
181174
while parent and not parent.is_root:
182-
if parent.frame:
183-
frame_stack.append(parent.frame)
175+
if parent.transformation:
176+
transformations.append(parent.transformation)
184177
parent = parent.parent
185-
matrices = [Transformation.from_frame(f) for f in frame_stack]
186-
if matrices:
187-
worldtransformation = reduce(mul, matrices[::-1])
178+
if transformations:
179+
worldtransformation = reduce(mul, transformations[::-1])
188180
else:
189181
worldtransformation = Transformation()
190182

191-
if self.transformation:
192-
worldtransformation *= self.transformation
193-
194183
return worldtransformation
195184

196185
@property

tests/compas/scene/test_scene.py

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -83,22 +83,19 @@ def test_sceneobject_auto_context_discovery_no_context(mocker):
8383
def test_sceneobject_transform():
8484
scene = Scene()
8585
sceneobj1 = scene.add(Box())
86-
sceneobj1.frame = Frame([1.0, 0.0, 0.0], xaxis=[1.0, 0.0, 0.0], yaxis=[0.0, 1.0, 0.0])
8786
sceneobj1.transformation = Translation.from_vector([10.0, 0.0, 0.0])
88-
assert sceneobj1.worldtransformation == sceneobj1.frame.to_transformation() * sceneobj1.transformation
87+
assert sceneobj1.worldtransformation == Translation.from_vector([10.0, 0.0, 0.0])
88+
assert sceneobj1.frame == Frame([10.0, 0.0, 0.0], [1.0, 0.0, 0.0], [0.0, 1.0, 0.0])
8989

9090
sceneobj2 = scene.add(Box(), parent=sceneobj1)
91-
sceneobj2.frame = Frame([1.0, 1.0, 0.0], xaxis=[1.0, 0.0, 0.0], yaxis=[0.0, 1.0, 0.0])
9291
sceneobj2.transformation = Translation.from_vector([10.0, 10.0, 0.0])
93-
assert sceneobj2.worldtransformation == sceneobj1.frame.to_transformation() * sceneobj2.frame.to_transformation() * sceneobj2.transformation
92+
assert sceneobj2.worldtransformation == sceneobj1.transformation * sceneobj2.transformation
93+
assert sceneobj2.frame == Frame([20.0, 10.0, 0.0], [1.0, 0.0, 0.0], [0.0, 1.0, 0.0])
9494

9595
sceneobj3 = scene.add(Box(), parent=sceneobj2)
96-
sceneobj3.frame = Frame([1.0, 1.0, 1.0], xaxis=[0.0, 1.0, 0.0], yaxis=[1.0, 0.0, 0.0])
9796
sceneobj3.transformation = Translation.from_vector([10.0, 10.0, 10.0])
98-
assert (
99-
sceneobj3.worldtransformation
100-
== sceneobj1.frame.to_transformation() * sceneobj2.frame.to_transformation() * sceneobj3.frame.to_transformation() * sceneobj3.transformation
101-
)
97+
assert sceneobj3.worldtransformation == sceneobj1.transformation * sceneobj2.transformation * sceneobj3.transformation
98+
assert sceneobj3.frame == Frame([30.0, 20.0, 10.0], [1.0, 0.0, 0.0], [0.0, 1.0, 0.0])
10299

103100
def test_scene_clear():
104101
scene = Scene()

0 commit comments

Comments
 (0)