Skip to content

Commit 0b655a2

Browse files
authored
propagate element geometry (#1570)
1 parent c73a31b commit 0b655a2

3 files changed

Lines changed: 54 additions & 0 deletions

File tree

src/OMSimulatorPython/capi.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,19 @@ class ssd_connector_geometry_t(ctypes.Structure):
2525
("x", ctypes.c_double),
2626
("y", ctypes.c_double)
2727
]
28+
## C structure for element geometry to properly pass the data from Python to C API
29+
class ssd_element_geometry_t(ctypes.Structure):
30+
_fields_ = [
31+
("x1", ctypes.c_double),
32+
("y1", ctypes.c_double),
33+
("x2", ctypes.c_double),
34+
("y2", ctypes.c_double),
35+
("rotation", ctypes.c_double),
36+
("iconSource", ctypes.c_char_p),
37+
("iconRotation", ctypes.c_double),
38+
("iconFlip", ctypes.c_bool),
39+
("iconFixedAspectRatio", ctypes.c_bool),
40+
]
2841
class capi:
2942
def __init__(self):
3043
dirname = os.path.dirname(__file__)
@@ -92,6 +105,8 @@ def __init__(self):
92105
self.obj.oms_setConnectionGeometry.restype = ctypes.c_int
93106
self.obj.oms_setConnectorGeometry.argtypes = [ctypes.c_char_p, ctypes.POINTER(ssd_connector_geometry_t)]
94107
self.obj.oms_setConnectorGeometry.restype = ctypes.c_int
108+
self.obj.oms_setElementGeometry.argtypes = [ctypes.c_char_p, ctypes.POINTER(ssd_element_geometry_t)]
109+
self.obj.oms_setElementGeometry.restype = ctypes.c_int
95110
self.obj.oms_setTempDirectory.argtypes = [ctypes.c_char_p]
96111
self.obj.oms_setTempDirectory.restype = ctypes.c_int
97112
self.obj.oms_setExportName.argtypes = [ctypes.c_char_p, ctypes.c_char_p]
@@ -244,6 +259,13 @@ def setConnectorGeometry(self, cref, x, y):
244259
status = self.obj.oms_setConnectorGeometry(cref.encode(), ctypes.byref(geometry))
245260
return Status(status)
246261

262+
def setElementGeometry(self, cref, x1, y1, x2, y2, rotation=0.0, iconSource=b"", iconRotation=0.0, iconFlip=False, iconFixedAspectRatio=False):
263+
'''Set the element geometry for a model or system.
264+
The element geometry is defined by a bounding box (x1, y1, x2, y2) that defines the position and size of the element in the diagram, as well as optional rotation and icon information.'''
265+
geometry = ssd_element_geometry_t(x1, y1, x2, y2, rotation, iconSource, iconRotation, iconFlip, iconFixedAspectRatio)
266+
status = self.obj.oms_setElementGeometry(cref.encode(), ctypes.byref(geometry))
267+
return Status(status)
268+
247269
def setTempDirectory(self, newTempDir):
248270
status = self.obj.oms_setTempDirectory(newTempDir.encode())
249271
return Status(status)

src/OMSimulatorPython/instantiated_model.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,23 @@ def __init__(self, json_description, system: System, resources: dict):
134134
raise RuntimeError(f"Failed to set connector geometry for {connector_path}: {status}")
135135
self.apiCall.append(f'oms_setConnectorGeometry("{connector_path}", {x}, {y})')
136136

137+
## parse element geometry for the component if exist and set it to capi after adding the component, this is needed for proper mapping of element geometry
138+
if "element geometry" in comp:
139+
geometry = comp["element geometry"]
140+
x1 = geometry.get("x1", 0.0)
141+
y1 = geometry.get("y1", 0.0)
142+
x2 = geometry.get("x2", 0.0)
143+
y2 = geometry.get("y2", 0.0)
144+
rotation = geometry.get("rotation")
145+
iconSource = geometry.get("iconSource", b"")
146+
iconRotation = geometry.get("iconRotation", 0.0)
147+
iconFlip = geometry.get("iconFlip", False)
148+
iconFixedAspectRatio = geometry.get("iconFixedAspectRatio", False)
149+
status = Capi.setElementGeometry(comp_path, x1, y1, x2, y2, rotation, iconSource, iconRotation, iconFlip, iconFixedAspectRatio)
150+
if status != Status.ok:
151+
raise RuntimeError(f"Failed to set element geometry for {comp_path}: {status}")
152+
self.apiCall.append(f'oms_setElementGeometry("{comp_path}", {x1}, {y1}, {x2}, {y2}, {rotation}, "{iconSource}", {iconRotation}, {iconFlip}, {iconFixedAspectRatio})')
153+
137154
if not export_name in self.mappedCrefs:
138155
self.mappedCrefs[export_name] = comp_path
139156
self.mappedCrefs[".".join(comp["name"][:-1])] = solver_path # map parent system too for connector lookup

src/OMSimulatorPython/system.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -664,6 +664,21 @@ def processElements(self, elements_dict: dict, connections: list, data: dict, so
664664
"path": str(Path(tempdir, str(element.fmuPath))) if tempdir is not None else str(element.fmuPath),
665665
"connectors": connector_info
666666
})
667+
## add element geometry if available, this is needed for propagating element geometry to capi
668+
if element.elementgeometry:
669+
element_geometry = {
670+
"x1": element.elementgeometry.x1,
671+
"y1": element.elementgeometry.y1,
672+
"x2": element.elementgeometry.x2,
673+
"y2": element.elementgeometry.y2,
674+
"rotation": element.elementgeometry.rotation,
675+
"iconSource": element.elementgeometry.icon_source,
676+
"iconRotation": element.elementgeometry.icon_rotation,
677+
"iconFlip": element.elementgeometry.icon_flip,
678+
"iconFixedAspectRatio": element.elementgeometry.icon_fixed_aspect_ratio
679+
}
680+
solver_groups[element.solver][-1]["element geometry"] = element_geometry
681+
667682
componentSolver[str(element.name)] = element.solver
668683
elif isinstance(element, ComponentTable):
669684
solver_groups[element.solver].append({

0 commit comments

Comments
 (0)