From ebdade2f44682a4a0a6aa2f01e1a6ee46964764b Mon Sep 17 00:00:00 2001 From: EulalieCoevoet Date: Tue, 28 Oct 2025 14:27:58 +0100 Subject: [PATCH 1/3] cleaning to fix deformable example --- splib/mechanics/mass.py | 16 ++++++------ stlib/__init__.py | 48 +++++++++++++++++------------------ stlib/core/basePrefab.py | 6 ++--- stlib/entities/__entity__.py | 8 +++--- stlib/materials/deformable.py | 4 ++- stlib/visual.py | 2 +- 6 files changed, 42 insertions(+), 42 deletions(-) diff --git a/splib/mechanics/mass.py b/splib/mechanics/mass.py index cb3478564..a3ee1fe28 100644 --- a/splib/mechanics/mass.py +++ b/splib/mechanics/mass.py @@ -11,13 +11,13 @@ def addMass(node, elem:ElementType, totalMass=DEFAULT_VALUE, massDensity=DEFAULT print("[warning] You defined the totalMass and the massDensity in the same time, only taking massDensity into account") del kwargs["massDensity"] - if(elem !=ElementType.POINTS and elem !=ElementType.EDGES): - node.addObject("MeshMatrixMass",name="mass", totalMass=totalMass, massDensity=massDensity, lumping=lumping, **kwargs) - else: - if (not isDefault(massDensity)) : - print("[warning] mass density can only be used on a surface or volumetric topology. Please use totalMass instead") - if (not isDefault(lumping)) : - print("[warning] lumping can only be set for surface or volumetric topology") + # if(elem !=ElementType.POINTS and elem !=ElementType.EDGES): + # node.addObject("MeshMatrixMass",name="mass", totalMass=totalMass, massDensity=massDensity, lumping=lumping, **kwargs) + # else: + # if (not isDefault(massDensity)) : + # print("[warning] mass density can only be used on a surface or volumetric topology. Please use totalMass instead") + # if (not isDefault(lumping)) : + # print("[warning] lumping can only be set for surface or volumetric topology") - node.addObject("UniformMass",name="mass", totalMass=totalMass, **kwargs) + node.addObject("UniformMass",name="mass", totalMass=totalMass, **kwargs) diff --git a/stlib/__init__.py b/stlib/__init__.py index 94db0b9c1..8c44861da 100644 --- a/stlib/__init__.py +++ b/stlib/__init__.py @@ -1,6 +1,7 @@ __all__ = ["core","entities","geometries","materials","collision","visual"] import Sofa.Core + def __genericAdd(self : Sofa.Core.Node, typeName, **kwargs): def findName(cname, names): """Compute a working unique name in the node""" @@ -13,35 +14,32 @@ def findName(cname, names): # Check if a name is provided, if not, use the one of the class params = kwargs.copy() - isNode = False - if "name" not in params: - if isinstance(typeName, str): - params["name"] = typeName - isNode=True - elif isinstance(typeName, type) and issubclass(typeName, Sofa.Core.Node): - params["name"] = "Node" - isNode=True - elif isinstance(typeName, Sofa.Core.Node): - params["name"] = "Node" - isNode=True - elif isinstance(typeName, type) and issubclass(typeName, Sofa.Core.Object): - params["name"] = typeName.name.value - elif isinstance(typeName, type) and issubclass(typeName, Sofa.Core.ObjectDeclaration): - params["name"] = typeName.__name__ - else: - raise RuntimeError("Invalid argument ", typeName) + # if "name" not in params: + # if isinstance(typeName, str): + # params["name"] = typeName + # elif isinstance(typeName, type) and issubclass(typeName, Sofa.Core.Node): + # params["name"] = typeName.__name__ + # elif isinstance(typeName, Sofa.Core.Node): + # params["name"] = "Node" + # elif isinstance(typeName, type) and issubclass(typeName, Sofa.Core.Object): + # params["name"] = typeName.name.value + # elif isinstance(typeName, type) and issubclass(typeName, Sofa.Core.ObjectDeclaration): + # params["name"] = typeName.__name__ + # else: + # raise RuntimeError("Invalid argument ", typeName) - # Check if the name already exists, if this happens, create a new one. - if params["name"] in self.children or params["name"] in self.objects: - names = {node.name.value for node in self.children} - names = names.union({object.name.value for object in self.objects}) - params["name"] = findName(params["name"], names) + # # Check if the name already exists, if this happens, create a new one. + # if params["name"] in self.children or params["name"] in self.objects: + # names = {node.name.value for node in self.children} + # names = names.union({object.name.value for object in self.objects}) + # params["name"] = findName(params["name"], names) # Dispatch the creation to either addObject or addChild - if isinstance(typeName, type) and issubclass(typeName, Sofa.Core.Node): - pref = self.addChild(typeName(params["name"])) + if isinstance(typeName, type) and issubclass(typeName, core.basePrefab.BasePrefab): + pref = self.addChild(typeName(**params)) + pref.init() elif isinstance(typeName, Sofa.Core.Node): - pref = self.addChild(typeName) + pref = self.addChild(typeName(**params)) elif isinstance(typeName, type) and issubclass(typeName, Sofa.Core.Object): pref = self.addObject(typeName(**params)) elif isinstance(typeName, type) and issubclass(typeName, Sofa.Core.ObjectDeclaration): diff --git a/stlib/core/basePrefab.py b/stlib/core/basePrefab.py index 1dd5665a3..83d29f55d 100644 --- a/stlib/core/basePrefab.py +++ b/stlib/core/basePrefab.py @@ -8,9 +8,9 @@ class BasePrefab(Sofa.Core.Node): A Prefab is a Sofa.Node that assembles a set of components and nodes """ - def __init__(self, params: BasePrefabParameters): - Sofa.Core.Node.__init__(self, name=params.name) - self.parameters = params + def __init__(self, parameters: BasePrefabParameters): + Sofa.Core.Node.__init__(self, name=parameters.name) + self.parameters = parameters def init(self): raise NotImplemented("To be overridden by child class") diff --git a/stlib/entities/__entity__.py b/stlib/entities/__entity__.py index a60aa5a41..9a332dca2 100644 --- a/stlib/entities/__entity__.py +++ b/stlib/entities/__entity__.py @@ -43,22 +43,22 @@ def __init__(self, parameters=EntityParameters(), **kwargs): def init(self): - self.geometry = self.add(Geometry, self.parameters.geometry) + self.geometry = self.add(Geometry, parameters=self.parameters.geometry) ### Check compatilibility of Material if self.parameters.material.stateType != self.parameters.stateType: print("WARNING: imcompatibility between templates of both the entity and the material") self.parameters.material.stateType = self.parameters.stateType - self.material = self.add(Material, self.parameters.material) + self.material = self.add(Material, parameters=self.parameters.material) self.material.States.position.parent = self.geometry.container.position.linkpath if self.parameters.collision is not None: - self.collision = self.add(Collision, self.parameters.collision) + self.collision = self.add(Collision, parameters=self.parameters.collision) self.addMapping(self.collision) if self.parameters.visual is not None: - self.visual = self.add(Visual, self.parameters.visual) + self.visual = self.add(Visual, parameters=self.parameters.visual) self.addMapping(self.visual) diff --git a/stlib/materials/deformable.py b/stlib/materials/deformable.py index cb424ed43..69a9558bb 100644 --- a/stlib/materials/deformable.py +++ b/stlib/materials/deformable.py @@ -29,6 +29,7 @@ def createScene(root) : from stlib.visual import VisualParameters from stlib.geometries.file import FileParameters + root.addObject('RequiredPlugin', name='Sofa.Component.Visual') # Needed to use components [VisualStyle] root.addObject("VisualStyle", displayFlags=["showBehavior"]) bunnyParameters = EntityParameters() @@ -42,4 +43,5 @@ def createScene(root) : # destinationType=ElementType.TRIANGLES) bunnyParameters.visual.geometry = FileParameters(filename="mesh/Bunny.stl") bunnyParameters.visual.color = [1, 1, 1, 0.5] - bunny = root.add(Entity, bunnyParameters) \ No newline at end of file + bunny = root.add(Entity, parameters=bunnyParameters) + # bunny.init() \ No newline at end of file diff --git a/stlib/visual.py b/stlib/visual.py index 271aad3c7..a0f377f7d 100644 --- a/stlib/visual.py +++ b/stlib/visual.py @@ -21,7 +21,7 @@ def __init__(self, parameters: VisualParameters): BasePrefab.__init__(self, parameters) def init(self): - self.geometry = self.add(Geometry, self.parameters.geometry) + self.geometry = self.add(Geometry, parameters=self.parameters.geometry) self.addObject("OglModel", color=self.parameters.color, src=self.geometry.container.linkpath) From 270d86700510672547a729b1fd7b1d505704fd2f Mon Sep 17 00:00:00 2001 From: Paul Baksic Date: Tue, 28 Oct 2025 16:09:50 +0100 Subject: [PATCH 2/3] Restore checks on name and add check on the presence of parameters --- stlib/__init__.py | 53 +++++++++++++++++++++++++++++------------------ 1 file changed, 33 insertions(+), 20 deletions(-) diff --git a/stlib/__init__.py b/stlib/__init__.py index 8c44861da..45a24b017 100644 --- a/stlib/__init__.py +++ b/stlib/__init__.py @@ -1,6 +1,7 @@ __all__ = ["core","entities","geometries","materials","collision","visual"] import Sofa.Core +from stlib.core.basePrefab import BasePrefab def __genericAdd(self : Sofa.Core.Node, typeName, **kwargs): def findName(cname, names): @@ -12,30 +13,42 @@ def findName(cname, names): rname = cname + str(i+1) return rname + + def checkName(context : Sofa.Core.Node, name): + # Check if the name already exists, if this happens, create a new one. + if name in context.children or name in context.objects: + names = {node.name.value for node in context.children} + names = names.union({object.name.value for object in context.objects}) + name = findName(name, names) + return name + + # Check if a name is provided, if not, use the one of the class params = kwargs.copy() - # if "name" not in params: - # if isinstance(typeName, str): - # params["name"] = typeName - # elif isinstance(typeName, type) and issubclass(typeName, Sofa.Core.Node): - # params["name"] = typeName.__name__ - # elif isinstance(typeName, Sofa.Core.Node): - # params["name"] = "Node" - # elif isinstance(typeName, type) and issubclass(typeName, Sofa.Core.Object): - # params["name"] = typeName.name.value - # elif isinstance(typeName, type) and issubclass(typeName, Sofa.Core.ObjectDeclaration): - # params["name"] = typeName.__name__ - # else: - # raise RuntimeError("Invalid argument ", typeName) - - # # Check if the name already exists, if this happens, create a new one. - # if params["name"] in self.children or params["name"] in self.objects: - # names = {node.name.value for node in self.children} - # names = names.union({object.name.value for object in self.objects}) - # params["name"] = findName(params["name"], names) + if isinstance(typeName, type) and issubclass(typeName, BasePrefab): #Only for prefabs + if "parameters" not in params or len(params.keys()) > 1: + raise RuntimeError("Invalid argument, a prefab takes only the \"parameters\" kwargs as input") + elif "name" not in params : #This doesn't apply to prefab + if isinstance(typeName, str): + params["name"] = typeName + elif isinstance(typeName, type) and issubclass(typeName, Sofa.Core.Node): + params["name"] = typeName.__name__ + elif isinstance(typeName, Sofa.Core.Node): + params["name"] = "Node" + elif isinstance(typeName, type) and issubclass(typeName, Sofa.Core.Object): + params["name"] = typeName.name.value + elif isinstance(typeName, type) and issubclass(typeName, Sofa.Core.ObjectDeclaration): + params["name"] = typeName.__name__ + else: + raise RuntimeError("Invalid argument ", typeName) + + if isinstance(typeName, type) and issubclass(typeName, BasePrefab): + params["parameters"].name = checkName(self, params["parameters"].name) + else: + params["name"] = checkName(self, params["name"]) # Dispatch the creation to either addObject or addChild - if isinstance(typeName, type) and issubclass(typeName, core.basePrefab.BasePrefab): + if isinstance(typeName, type) and issubclass(typeName, BasePrefab): pref = self.addChild(typeName(**params)) pref.init() elif isinstance(typeName, Sofa.Core.Node): From 05aafc1c3e3146c491f810029d27ddd1d342c9ac Mon Sep 17 00:00:00 2001 From: Paul Baksic Date: Tue, 28 Oct 2025 16:14:27 +0100 Subject: [PATCH 3/3] Allow to use default parameters (passing nothing to the add method except the class name --- stlib/__init__.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/stlib/__init__.py b/stlib/__init__.py index 45a24b017..0ad659858 100644 --- a/stlib/__init__.py +++ b/stlib/__init__.py @@ -26,8 +26,9 @@ def checkName(context : Sofa.Core.Node, name): # Check if a name is provided, if not, use the one of the class params = kwargs.copy() if isinstance(typeName, type) and issubclass(typeName, BasePrefab): #Only for prefabs - if "parameters" not in params or len(params.keys()) > 1: + if len(params.keys()) > 1 or (len(params.keys()) == 1 and "parameters" not in params): raise RuntimeError("Invalid argument, a prefab takes only the \"parameters\" kwargs as input") + elif "name" not in params : #This doesn't apply to prefab if isinstance(typeName, str): params["name"] = typeName @@ -42,7 +43,7 @@ def checkName(context : Sofa.Core.Node, name): else: raise RuntimeError("Invalid argument ", typeName) - if isinstance(typeName, type) and issubclass(typeName, BasePrefab): + if isinstance(typeName, type) and issubclass(typeName, BasePrefab) and len(params.keys()) == 1: params["parameters"].name = checkName(self, params["parameters"].name) else: params["name"] = checkName(self, params["name"])