Skip to content

Commit 95b5e54

Browse files
Refactor SOFA components list.
1 parent 001267a commit 95b5e54

File tree

6 files changed

+112
-219
lines changed

6 files changed

+112
-219
lines changed

src/SimRender/sofa/local/factory.py

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
from SimRender.core.local.factory import Factory as _Factory, Objects as _Objects
66
from SimRender.sofa.local.scene_graph import SceneGraph
7-
from SimRender.sofa.local.sofa_objects import SOFA_OBJECTS, Base
7+
from SimRender.sofa.local.sofa_objects import collection, Object
88

99

1010
class Factory(_Factory):
@@ -20,7 +20,7 @@ def __init__(self, root_node: Sofa.Core.Node, sync: bool):
2020
super().__init__(sync=sync)
2121

2222
self.objects = Objects(root_node=root_node, factory=self)
23-
self.callbacks: Dict[int, Base] = {}
23+
self.callbacks: Dict[int, Object] = {}
2424

2525
def update(self) -> None:
2626

@@ -44,6 +44,7 @@ def __init__(self, root_node: Sofa.Core.Node, factory: Factory):
4444

4545
self.__factory = factory
4646
self.__scene_graph = SceneGraph(root_node=root_node)
47+
self.__SOFA_OBJECTS = collection()
4748

4849
def add_sofa_mesh(self,
4950
positions_data: Sofa.Core.Data,
@@ -217,17 +218,17 @@ def add_sofa_object(self, sofa_object: Sofa.Core.Object) -> int:
217218

218219
# Check if the component is implemented
219220
object_class = sofa_object.getClassName()
220-
if object_class in SOFA_OBJECTS:
221+
if object_class in self.__SOFA_OBJECTS:
221222

222-
data_wrapper = SOFA_OBJECTS[object_class](sofa_object=sofa_object)
223+
data_wrapper = self.__SOFA_OBJECTS[object_class](sofa_object=sofa_object)
223224
func = self.__getattribute__(f'add_{data_wrapper.object_type}')
224225
idx = func(**data_wrapper.create())
225226
self.__factory.callbacks[idx] = data_wrapper
226227
return idx
227228

228229
else:
229230
print(f"WARNING: Could not create a 3D object for this component as the class representation is not"
230-
f"implemented. Available components are {SOFA_OBJECTS.keys()}.")
231+
f"implemented. Available components are {self.__SOFA_OBJECTS.keys()}.")
231232

232233
def add_scene_graph(self,
233234
visual_models: bool = True,
@@ -243,8 +244,8 @@ def add_scene_graph(self,
243244
:param collision_models: If True, display each detected collision model in the scene graph.
244245
"""
245246

246-
display_models = {'visual': visual_models, 'behavior': behavior_models,
247-
'force': force_fields, 'collision': collision_models}
247+
display_models = {'visual_model': visual_models, 'behavior_model': behavior_models,
248+
'force_field': force_fields, 'collision_model': collision_models}
248249

249250
# Process each sofa object in the scene graph
250251
for key, sofa_object in self.__scene_graph.graph.items():
@@ -258,8 +259,8 @@ def add_scene_graph(self,
258259
# TODO: apply the display flags
259260

260261
# Check if a configuration exists for the object
261-
elif object_class in SOFA_OBJECTS:
262-
data_wrapper = SOFA_OBJECTS[object_class](sofa_object=sofa_object)
262+
elif object_class in self.__SOFA_OBJECTS:
263+
data_wrapper = self.__SOFA_OBJECTS[object_class](sofa_object=sofa_object)
263264
if display_models[data_wrapper.display_model]:
264265
func = self.__getattribute__(f'add_{data_wrapper.object_type}')
265266
idx = func(**data_wrapper.create())
Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
from typing import Dict, Type
22
from inspect import getmembers, isclass
33

4-
from SimRender.sofa.local.sofa_objects.base import Base
4+
from SimRender.sofa.local.sofa_objects.base import Object
55
from SimRender.sofa.local.sofa_objects import meshes, points, arrows
66

77

8-
SOFA_OBJECTS: Dict[str, Type[Base]] = {}
9-
for (name, cls) in getmembers(meshes, isclass) + getmembers(points, isclass) + getmembers(arrows, isclass):
10-
if name not in ['Mesh', 'Points', 'Arrows']:
11-
SOFA_OBJECTS[name] = cls
8+
def collection() -> Dict[str, Type[Object]]:
9+
10+
objects = {}
11+
for (name, cls) in getmembers(meshes, isclass) + getmembers(points, isclass) + getmembers(arrows, isclass):
12+
if name not in ['Mesh', 'Points', 'Arrows', 'Object', 'Any']:
13+
objects[name] = cls
14+
return objects

src/SimRender/sofa/local/sofa_objects/arrows.py

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,34 +2,27 @@
22
import numpy as np
33
import Sofa
44

5-
from SimRender.sofa.local.sofa_objects.base import Arrows
5+
from SimRender.sofa.local.sofa_objects.base import Object
66

77

8-
class ConstantForceField(Arrows):
8+
class ConstantForceField(Object):
99

1010
def __init__(self, sofa_object: Sofa.Core.Object):
1111

1212
super().__init__(sofa_object=sofa_object)
13-
self.display_model = 'force'
13+
self.object_type = 'arrows'
14+
self.display_model = 'force_field'
1415

1516
def create(self) -> Dict[str, Any]:
1617

17-
# Position
18-
self.positions = self.sofa_node.getMechanicalState().getData('position').value
19-
self.positions = self.positions[self.sofa_object.getData('indices').value]
20-
# Vectors
21-
self.vectors = self.sofa_object.getData('forces').value * self.sofa_object.getData('showArrowSize').value
22-
self.vectors = np.tile(self.vectors, self.positions.shape[0]).reshape(-1, 3)
23-
# Color & alpha
24-
self.color = 'green5'
25-
self.alpha = 1.
26-
return super().create()
18+
pos = self.sofa_node.getMechanicalState().getData('position').value[self.sofa_object.getData('indices').value]
19+
vec = self.sofa_object.getData('forces').value * self.sofa_object.getData('showArrowSize').value
20+
return {'positions': pos,
21+
'vectors': np.tile(vec, pos.shape[0]).reshape(-1, 3),
22+
'color': 'green5',
23+
'alpha': 1.}
2724

2825
def update(self) -> Dict[str, Any]:
2926

30-
# Position
31-
self.positions = self.sofa_node.getMechanicalState().getData('position').value
32-
self.positions = self.positions[self.sofa_object.getData('indices').value]
33-
# Vectors
34-
self.vectors = self.sofa_object.getData('forces').value * self.sofa_object.getData('showArrowSize').value
35-
return super().update()
27+
return {'positions': self.sofa_node.getMechanicalState().getData('position').value[self.sofa_object.getData('indices').value],
28+
'vectors': self.sofa_object.getData('forces').value * self.sofa_object.getData('showArrowSize').value}
Lines changed: 6 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -1,111 +1,18 @@
1-
from typing import Dict, Optional, Any
1+
from typing import Dict, Any
22
import Sofa
33

44

5-
class Base:
5+
class Object:
66

77
def __init__(self, sofa_object: Sofa.Core.Object):
88

9-
self.sofa_object = sofa_object
10-
self.sofa_node: Sofa.Core.Node = sofa_object.getLinks()[0].getLinkedBase()
9+
self.sofa_object: Sofa.Core.Object = sofa_object
10+
self.sofa_node: Sofa.Core.Node = sofa_object.getContext()
1111
self.object_type = ''
1212
self.display_model = ''
1313

1414
def create(self) -> Dict[str, Any]:
15-
raise NotImplementedError
15+
return {}
1616

1717
def update(self) -> Dict[str, Any]:
18-
raise NotImplementedError
19-
20-
21-
class Mesh(Base):
22-
23-
def __init__(self, sofa_object: Sofa.Core.Object):
24-
25-
super().__init__(sofa_object=sofa_object)
26-
27-
self.object_type = 'mesh'
28-
self.positions: Optional[Any] = None
29-
self.cells: Optional[Any] = None
30-
self.color: Optional[Any] = None
31-
self.alpha: Optional[Any] = None
32-
self.wireframe: Optional[Any] = None
33-
self.line_width: Optional[Any] = None
34-
self.texture_name: Optional[Any] = None
35-
self.texture_coords: Optional[Any] = None
36-
37-
def create(self) -> Dict[str, Any]:
38-
39-
res = {'positions': self.positions,
40-
'cells': self.cells,
41-
'color': self.color,
42-
'alpha': self.alpha,
43-
'wireframe': self.wireframe,
44-
'line_width': self.line_width,
45-
'texture_name': self.texture_name,
46-
'texture_coords': self.texture_coords}
47-
return {key: value for key, value in res.items() if value is not None}
48-
49-
def update(self) -> Dict[str, Any]:
50-
51-
res = {'positions': self.positions,
52-
'color': self.color,
53-
'alpha': self.alpha}
54-
return {key: value for key, value in res.items() if value is not None}
55-
56-
57-
class Points(Base):
58-
59-
def __init__(self, sofa_object: Sofa.Core.Object):
60-
61-
super().__init__(sofa_object=sofa_object)
62-
63-
self.object_type = 'points'
64-
self.positions: Optional[Any] = None
65-
self.color: Optional[Any] = None
66-
self.alpha: Optional[Any] = None
67-
self.point_size: Optional[Any] = None
68-
69-
def create(self) -> Dict[str, Any]:
70-
71-
res = {'positions': self.positions,
72-
'color': self.color,
73-
'alpha': self.alpha,
74-
'point_size': self.point_size}
75-
return {key: value for key, value in res.items() if value is not None}
76-
77-
def update(self) -> Dict[str, Any]:
78-
79-
res = {'positions': self.positions,
80-
'color': self.color,
81-
'alpha': self.alpha}
82-
return {key: value for key, value in res.items() if value is not None}
83-
84-
85-
class Arrows(Base):
86-
87-
def __init__(self, sofa_object: Sofa.Core.Object):
88-
89-
super().__init__(sofa_object=sofa_object)
90-
91-
self.object_type = 'arrows'
92-
self.positions: Optional[Any] = None
93-
self.vectors: Optional[Any] = None
94-
self.color: Optional[Any] = None
95-
self.alpha: Optional[Any] = None
96-
97-
def create(self) -> Dict[str, Any]:
98-
99-
res = {'positions': self.positions,
100-
'vectors': self.vectors,
101-
'color': self.color,
102-
'alpha': self.alpha}
103-
return {key: value for key, value in res.items() if value is not None}
104-
105-
def update(self) -> Dict[str, Any]:
106-
107-
res = {'positions': self.positions,
108-
'vectors': self.vectors,
109-
'color': self.color,
110-
'alpha': self.alpha}
111-
return {key: value for key, value in res.items() if value is not None}
18+
return {}
Lines changed: 39 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,102 +1,79 @@
11
from typing import Dict, Any
22
import Sofa
33

4-
from SimRender.sofa.local.sofa_objects.base import Mesh
4+
from SimRender.sofa.local.sofa_objects.base import Object
55

66

7-
class OglModel(Mesh):
7+
class OglModel(Object):
88

99
def __init__(self, sofa_object: Sofa.Core.Object):
1010

1111
super().__init__(sofa_object=sofa_object)
12-
self.display_model = 'visual'
12+
self.object_type = 'mesh'
13+
self.display_model = 'visual_model'
1314

1415
def create(self) -> Dict[str, Any]:
1516

16-
# Position
17-
self.positions = self.sofa_object.getData('position').value
18-
# Cells
19-
self.cells = []
17+
cells = []
2018
for topology in ['triangles', 'quads']:
21-
cells = self.sofa_object.getData(topology).value
22-
if len(cells) > 0:
23-
self.cells += cells.tolist()
24-
# Color & alpha
25-
material = self.sofa_object.getData('material').value
26-
color = material.split('Diffuse')[1].split('Ambient')[0].split(' ')[2:-1]
27-
self.alpha = max(0.1, float(color[-1]))
28-
self.color = [float(c) for c in color[:-1]]
29-
# Wireframe & line width
30-
self.wireframe = False
31-
self.line_width = 0
32-
# Texture
33-
self.texture_name = self.sofa_object.getData('texturename').value
34-
self.texture_coords = self.sofa_object.getData('texcoords').value
35-
return super().create()
19+
cells += self.sofa_object.getData(topology).value.tolist()
20+
color = self.sofa_object.getData('material').value.split('Diffuse')[1].split('Ambient')[0].split(' ')[2: -1]
21+
return {'positions': self.sofa_object.getData('position').value,
22+
'cells': cells,
23+
'color': [float(c) for c in color[:-1]],
24+
'alpha': max(0.1, float(color[-1])),
25+
'wireframe': False,
26+
'line_width': 0.,
27+
'texture_name': self.sofa_object.getData('texturename').value,
28+
'texture_coords': self.sofa_object.getData('texcoords').value}
3629

3730
def update(self) -> Dict[str, Any]:
3831

39-
# Position
40-
self.positions = self.sofa_object.getData('position').value
41-
# Color & alpha
42-
material = self.sofa_object.getData('material').value
43-
color = material.split('Diffuse')[1].split('Ambient')[0].split(' ')[2:-1]
44-
self.alpha = max(0.1, float(color[-1]))
45-
self.color = [float(c) for c in color[:-1]]
46-
return super().update()
32+
color = self.sofa_object.getData('material').value.split('Diffuse')[1].split('Ambient')[0].split(' ')[2: -1]
33+
return {'positions': self.sofa_object.getData('position').value,
34+
'color': [float(c) for c in color[:-1]],
35+
'alpha': max(0.1, float(color[-1]))}
4736

4837

49-
class TriangleCollisionModel(Mesh):
38+
class TriangleCollisionModel(Object):
5039

5140
def __init__(self, sofa_object: Sofa.Core.Object):
5241

5342
super().__init__(sofa_object=sofa_object)
54-
self.display_model = 'collision'
43+
self.object_type = 'mesh'
44+
self.display_model = 'collision_model'
5545

5646
def create(self) -> Dict[str, Any]:
5747

58-
# Position
59-
self.positions = self.sofa_node.getMechanicalState().getData('position').value
60-
# Cells
61-
self.cells = self.sofa_object.findLink('topology').getLinkedBase().getData('triangles').value
62-
# Color & alpha
63-
self.alpha = 1.
64-
self.color = 'orange5'
65-
# Wireframe & line width
66-
self.wireframe = True
67-
self.line_width = 2
68-
return super().create()
48+
return {'positions': self.sofa_node.getMechanicalState().getData('position').value,
49+
'cells': self.sofa_object.findLink('topology').getLinkedBase().getData('triangles').value,
50+
'color': 'orange5',
51+
'alpha': 1.,
52+
'wireframe': True,
53+
'line_width': 2.}
6954

7055
def update(self) -> Dict[str, Any]:
7156

72-
# Position
73-
self.positions = self.sofa_node.getMechanicalState().getData('position').value
74-
return super().update()
57+
return {'positions': self.sofa_node.getMechanicalState().getData('position').value}
7558

7659

77-
class LineCollisionModel(Mesh):
60+
class LineCollisionModel(Object):
7861

7962
def __init__(self, sofa_object: Sofa.Core.Object):
8063

8164
super().__init__(sofa_object=sofa_object)
82-
self.display_model = 'collision'
65+
self.object_type = 'mesh'
66+
self.display_model = 'collision_model'
8367

8468
def create(self) -> Dict[str, Any]:
8569

86-
# Position
87-
self.positions = self.sofa_node.getMechanicalState().getData('position').value
88-
# Cells
89-
self.cells = self.sofa_object.findLink('topology').getLinkedBase().getData('edges').value
90-
# Color & alpha
91-
self.alpha = 1.
92-
self.color = 'orange5'
93-
# Wireframe & line width
94-
self.wireframe = True
95-
self.line_width = 2
96-
return super().create()
70+
return {'positions': self.sofa_node.getMechanicalState().getData('position').value,
71+
'cells': self.sofa_object.findLink('topology').getLinkedBase().getData('edges').value,
72+
'color': 'orange5',
73+
'alpha': 1.,
74+
'wireframe': True,
75+
'line_width': 2.}
9776

9877
def update(self) -> Dict[str, Any]:
9978

100-
# Position
101-
self.positions = self.sofa_node.getMechanicalState().getData('position').value
102-
return super().update()
79+
return {'positions': self.sofa_node.getMechanicalState().getData('position').value}

0 commit comments

Comments
 (0)