Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
3ae4099
add folder for STLIB
bakpaul Apr 14, 2025
4754eb9
Add reusable methods
bakpaul Apr 14, 2025
9461530
Add working files
bakpaul Apr 14, 2025
c5cb491
Created example scenes
bakpaul Apr 14, 2025
8c32a2e
Fix example
bakpaul Apr 14, 2025
e70b49c
orga folders
hugtalbot Apr 14, 2025
1afa8ed
Fix package
bakpaul Apr 14, 2025
44ce518
bootstrap examples
bakpaul Apr 14, 2025
abec07b
start beginner scene
hugtalbot Apr 14, 2025
4c3890f
Move around files
bakpaul Apr 14, 2025
8b2333d
Move examples into SofaPython3 main example folder
bakpaul Apr 14, 2025
b0711e3
Add unsaved modifications
bakpaul Apr 14, 2025
1b1622e
reoganisation after discussion
EulalieCoevoet Apr 14, 2025
b5efd73
Add gemetries
bakpaul Apr 14, 2025
97eda89
WIP FileParameters
bakpaul Apr 14, 2025
a5cba09
Add beginner example
bakpaul Apr 14, 2025
d1cad66
Add unsaved changes
bakpaul Apr 14, 2025
6db1a4a
Start work on visual and collision
bakpaul Apr 14, 2025
d0c514b
work on Tuesday : visual, geometry
hugtalbot Apr 15, 2025
266e54b
add basePrefabParameters.py
hugtalbot Apr 15, 2025
33fbc73
Add extracted geometry
bakpaul Apr 15, 2025
f6f5946
Fix visual example
bakpaul Apr 15, 2025
9b7afa7
Finished collisions
bakpaul Apr 15, 2025
a903e01
Add addObject as reusable method and use it in Collision to enable kw…
bakpaul Apr 15, 2025
b69dabe
Add addObject as reusable method and use it in Collision to enable kw…
bakpaul Apr 15, 2025
b74ebb7
[stlib-splib] work on prefabs: cleaning (#501)
EulalieCoevoet Jun 2, 2025
6ba87ce
[stlib] adds README
EulalieCoevoet Jun 2, 2025
a44134a
[stlib] minor changes from discussion
EulalieCoevoet Jun 2, 2025
f2e1ed9
[splib] updates entity
EulalieCoevoet Jun 3, 2025
f34b1f5
update README
hugtalbot Jun 3, 2025
29fc2bf
add init in prefab
hugtalbot Jun 3, 2025
d78ec40
Add first implem of entity
bakpaul Jun 3, 2025
b590d85
Merge branch '25_04_work_on_new_prefabs' into 25_04_use_reusable_meth…
bakpaul Jun 3, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
[stlib-splib] work on prefabs: cleaning (#501)
* [stlib-splib] cleaning

* revert collisionModel
  • Loading branch information
EulalieCoevoet authored Jun 2, 2025
commit b74ebb72070b35e4589f4ffecfac6a85b45002c5
41 changes: 20 additions & 21 deletions splib/core/enum_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,34 +5,33 @@ class ConstitutiveLaw(Enum):
HYPERELASTIC = 2

class ODEType(Enum):
EXPLICIT = 1
IMPLICIT = 2
EXPLICIT = 1
IMPLICIT = 2

class SolverType(Enum):
DIRECT = 1
ITERATIVE = 2
DIRECT = 1
ITERATIVE = 2

class MappingType(Enum):
BARYCENTRIC = 1
IDENTITY = 2
RIGID = 3

BARYCENTRIC = 1
IDENTITY = 2
RIGID = 3

class ConstraintType(Enum):
PROJECTIVE = 1
WEAK = 2
LAGRANGIAN = 3
PROJECTIVE = 1
WEAK = 2
LAGRANGIAN = 3

class CollisionPrimitive(Enum):
POINTS = 1
LINES = 2
TRIANGLES = 3
SPHERES = 4
POINTS = 1
LINES = 2
TRIANGLES = 3
SPHERES = 4

class ElementType(Enum):
POINTS = 1
EDGES = 2
TRIANGLES = 3
QUAD = 4
TETRA = 5
HEXA = 6
POINTS = 1
EDGES = 2
TRIANGLES = 3
QUADS = 4
TETRAHEDRONS = 5
HEXAHEDRONS = 6
21 changes: 14 additions & 7 deletions splib/mechanics/collision_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,28 @@
from splib.core.enum_types import CollisionPrimitive



@ReusableMethod
def addCollisionModels(node, primitive : CollisionPrimitive, topology=DEFAULT_VALUE, selfCollision=DEFAULT_VALUE, proximity=DEFAULT_VALUE, group=DEFAULT_VALUE, contactStiffness=DEFAULT_VALUE, contactFriction=DEFAULT_VALUE,spheresRadius=DEFAULT_VALUE,**kwargs):
def addCollisionModels(node, primitive : CollisionPrimitive,
topology=DEFAULT_VALUE,
selfCollision=DEFAULT_VALUE,
proximity=DEFAULT_VALUE,
group=DEFAULT_VALUE,
contactStiffness=DEFAULT_VALUE,
contactFriction=DEFAULT_VALUE,
spheresRadius=DEFAULT_VALUE,
**kwargs):
match primitive:
case CollisionPrimitive.POINTS:
node.addObject("PointCollisionModel",name="PointCollision", topology=topology, selfCollision=selfCollision, proximity=proximity, contactStiffness=contactStiffness, contactFriction=contactFriction, group=group, **kwargs)
node.addObject("PointCollisionModel", name="PointCollision", topology=topology, selfCollision=selfCollision, proximity=proximity, contactStiffness=contactStiffness, contactFriction=contactFriction, group=group, **kwargs)
return
case CollisionPrimitive.LINES:
node.addObject("LineCollisionModel",name="EdgeCollision", topology=topology, selfCollision=selfCollision, proximity=proximity, contactStiffness=contactStiffness, contactFriction=contactFriction, group=group,**kwargs)
case CollisionPrimitive.LINES:
node.addObject("LineCollisionModel", name="EdgeCollision", topology=topology, selfCollision=selfCollision, proximity=proximity, contactStiffness=contactStiffness, contactFriction=contactFriction, group=group, **kwargs)
return
case CollisionPrimitive.TRIANGLES:
node.addObject("TriangleCollisionModel",name="TriangleCollision", topology=topology, selfCollision=selfCollision, proximity=proximity, contactStiffness=contactStiffness, contactFriction=contactFriction, group=group,**kwargs)
node.addObject("TriangleCollisionModel", name="TriangleCollision", topology=topology, selfCollision=selfCollision, proximity=proximity, contactStiffness=contactStiffness, contactFriction=contactFriction, group=group,**kwargs)
return
case CollisionPrimitive.SPHERES:
node.addObject("SphereCollisionModel",name="SphereCollision", topology=topology, selfCollision=selfCollision, proximity=proximity, contactStiffness=contactStiffness, contactFriction=contactFriction, group=group, radius=spheresRadius, **kwargs)
node.addObject("SphereCollisionModel", name="SphereCollision", topology=topology, selfCollision=selfCollision, proximity=proximity, contactStiffness=contactStiffness, contactFriction=contactFriction, group=group, radius=spheresRadius, **kwargs)
return
case _:
return
Expand Down
2 changes: 1 addition & 1 deletion splib/mechanics/hyperelasticity.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
@ReusableMethod
def addHyperelasticity(node,elem:ElementType,materialName=DEFAULT_VALUE, parameterSet=DEFAULT_VALUE, matrixRegularization=DEFAULT_VALUE,**kwargs):
match elem:
case ElementType.TETRA:
case ElementType.TETRAHEDRONS:
node.addObject("TetrahedronHyperelasticityFEMForceField",name="constitutiveLaw", materialName=materialName, parameterSet=parameterSet, matrixRegularization=matrixRegularization, **kwargs)
return
case _:
Expand Down
6 changes: 3 additions & 3 deletions splib/mechanics/linear_elasticity.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ def addLinearElasticity(node,elem:ElementType,youngModulus=DEFAULT_VALUE, poisso
case ElementType.TRIANGLES:
node.addObject("TriangleFEMForceField",name="constitutiveLaw", youngModulus=youngModulus, poissonRatio=poissonRatio, method=method,**kwargs)
return
case ElementType.QUAD:
case ElementType.QUADS:
node.addObject("QuadBendingFEMForceField",name="constitutiveLaw", youngModulus=youngModulus, poissonRatio=poissonRatio, method=method,**kwargs)
return
case ElementType.TETRA:
case ElementType.TETRAHEDRONS:
node.addObject("TetrahedronFEMForceField",name="constitutiveLaw", youngModulus=youngModulus, poissonRatio=poissonRatio, method=method,**kwargs)
return
case ElementType.HEXA:
case ElementType.HEXAHEDRONS:
node.addObject("HexahedronFEMForceField",name="constitutiveLaw", youngModulus=youngModulus, poissonRatio=poissonRatio, method=method,**kwargs)
return
case _:
Expand Down
8 changes: 4 additions & 4 deletions splib/topology/dynamic.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,15 @@ def addDynamicTopology(node,type:ElementType,**kwargs):
case ElementType.TRIANGLES:
addTriangleTopology(node,**kwargs)
return
case ElementType.QUAD:
case ElementType.QUADS:
addQuadTopology(node,**kwargs)
return
case ElementType.TETRA:
case ElementType.TETRAHEDRONS:
addTetrahedronTopology(node,**kwargs)
return
case ElementType.HEXA:
case ElementType.HEXAHEDRONS:
addHexahedronTopology(node,**kwargs)
return
case _:
print('Topology type should be one of the following : "ElementType.POINTS, ElementType.EDGES, ElementType.TRIANGLES, ElementType.QUAD, ElementType.TETRA, ElementType.HEXA" ')
print('Topology type should be one of the following : "ElementType.POINTS, ElementType.EDGES, ElementType.TRIANGLES, ElementType.QUADS, ElementType.TETRAHEDRONS, ElementType.HEXAHEDRONS" ')
return
5 changes: 1 addition & 4 deletions stlib/geometry/__geometry__.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,8 @@ class GeometryParameters(BaseParameters):
dynamicTopology : bool = False





class Geometry(BasePrefab):
container : Object # This should be more specialized into the right SOFA type
container : Object # This should be more specialized into the right SOFA type
modifier : Optional[Object]

params : GeometryParameters
Expand Down
35 changes: 24 additions & 11 deletions stlib/geometry/extract.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,32 @@


class ExtractInternalDataProvider(InternalDataProvider):
destElemType : ElementType
fromElemType : ElementType
destElementType : ElementType
fromElemenType : ElementType
fromNodeName : str

def __init__(self, destElementType : ElementType, fromElementType : ElementType, fromNodeName : str):
self.destElementType = destElementType,
self.fromElementType = fromElementType,
self.fromNodeName = fromNodeName

def __post_init__(self):
if(not (self.fromElemType == ElementType.TETRA and self.destElemType == ElementType.TRIANGLES)
and not (self.fromElemType == ElementType.HEXA and self.destElemType == ElementType.QUAD) ):
raise ValueError("Only configuration possible are 'Tetra to Triangle' and 'Hexa to quad'")
if(not (self.fromElementType == ElementType.TETRAHEDRONS and self.destElementType == ElementType.TRIANGLES)
and not (self.fromElementType == ElementType.HEXAHEDRONS and self.destElementType == ElementType.QUADS) ):
raise ValueError("Only configuration possible are 'Tetrahedrons to Triangles' and 'Hexahedrons to Quads'")

InternalDataProvider.__init__(self)


def generateAttribute(self, parent : Geometry):
tmn = parent.addChild("topologicalMappingNode")
tmn = parent.addChild("TopologicalMappingNode")

#TODO: Specify somewhere in the doc that this should only be used for mapped topologies that extract parent topology surface
fromLink = parent.parents[0].parents[0].getChild(self.fromNodeName).container.linkpath
addDynamicTopology(tmn, type=self.destElemType)
if self.fromElemType == ElementType.TETRA:
addDynamicTopology(tmn, type=self.destElementType)
if self.fromElementType == ElementType.TETRAHEDRONS:
tmn.addObject("Tetra2TriangleTopologicalMapping", input=fromLink, output=tmn.container.linkpath)
elif self.fromElemType == ElementType.HEXA:
elif self.fromElementType == ElementType.HEXAHEDRONS:
tmn.addObject("Hexa2QuadTopologicalMapping", input=fromLink, output=tmn.container.linkpath)

self.position = tmn.container.position.linkpath
Expand All @@ -41,6 +46,14 @@ def generateAttribute(self, parent : Geometry):


class ExtractParameters(GeometryParameters):
def __init__(self, fromGeometry : GeometryParameters, destElementType : ElementType, dynamicTopology = False, ):
GeometryParameters.__init__(data = ExtractInternalDataProvider(destElemType = destElementType, fromElemType = fromGeometry.elementType,fromNodeName = fromGeometry.name), dynamicTopology = dynamicTopology, elementType = destElementType)
def __init__(self,
fromGeometry : GeometryParameters,
destElementType : ElementType,
dynamicTopology = False, ):
GeometryParameters.__init__(self,
data = ExtractInternalDataProvider(destElementType = destElementType,
fromElementType = fromGeometry.elementType,
fromNodeName = fromGeometry.name),
dynamicTopology = dynamicTopology,
elementType = destElementType)

12 changes: 7 additions & 5 deletions stlib/geometry/file.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,8 @@ class FileInternalDataProvider(InternalDataProvider):
def __post_init__(self, **kwargs):
InternalDataProvider.__init__(self,**kwargs)

def generateAttribute(self, parent : Geometry):

loadMesh(parent, self.filename)
def generateAttribute(self, parent : Geometry):
loadMesh(parent, self.filename)

self.position = str(parent.loader.position.linkpath)
self.edges = str(parent.loader.edges.linkpath)
Expand All @@ -26,6 +25,9 @@ def generateAttribute(self, parent : Geometry):


class FileParameters(GeometryParameters):
def __init__(self, filename, dynamicTopology = False, elementType : ElementType = None ):
GeometryParameters.__init__(self,data = FileInternalDataProvider(filename), dynamicTopology = dynamicTopology, elementType = elementType)
def __init__(self, filename, dynamicTopology = False, elementType : ElementType = None ):
GeometryParameters.__init__(self,
data = FileInternalDataProvider(filename),
dynamicTopology = dynamicTopology,
elementType = elementType)

21 changes: 10 additions & 11 deletions stlib/prefabs/collision.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,10 @@

@dataclasses.dataclass
class CollisionParameters(BaseParameters):
primitives : list[CollisionPrimitive] = dataclasses.field(default_factory = lambda :[CollisionPrimitive.POINTS])
primitives : list[CollisionPrimitive] = dataclasses.field(default_factory = lambda :[CollisionPrimitive.TRIANGLES])

selfCollision : Optional[bool] = DEFAULT_VALUE
proximity : Optional[float] = DEFAULT_VALUE
group : Optional[int] = DEFAULT_VALUE
contactStiffness : Optional[float] = DEFAULT_VALUE
contactFriction : Optional[float] = DEFAULT_VALUE
spheresRadius : Optional[float] = DEFAULT_VALUE

geometry : GeometryParameters = dataclasses.field(default_factory = lambda : GeometryParameters())
addMapping : Optional[Callable] = None
Expand All @@ -28,16 +24,12 @@ def __init__(self, params: CollisionParameters):

geom = self.add(Geometry, params.geometry)

self.addObject("MechanicalObject",template="Vec3", position=f"@{params.geometry.name}/container.position")
self.addObject("MechanicalObject", template="Vec3", position=f"@{params.geometry.name}/container.position")
for primitive in params.primitives:
addCollisionModels(self,primitive,
addCollisionModels(self, primitive,
topology=f"@{params.geometry.name}/container",
selfCollision=params.selfCollision,
proximity=params.proximity,
group=params.group,
contactStiffness=params.contactStiffness,
contactFriction=params.contactFriction,
spheresRadius=params.spheresRadius,
**params.kwargs)

if params.addMapping is not None:
Expand All @@ -50,7 +42,14 @@ def getParameters(**kwargs) -> CollisionParameters:

def createScene(root):

root.addObject("VisualStyle", displayFlags="showCollisionModels")

# Create a visual from a mesh file
params = Collision.getParameters()
params.geometry = FileParameters(filename="mesh/cube.obj")
# Expert parameters
params.kwargs = {
"contactStiffness": 100.0,
"contactFriction": 0.5
}
root.add(Collision, params)
13 changes: 12 additions & 1 deletion stlib/prefabs/visual.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from stlib.core.basePrefab import BasePrefab
from stlib.core.baseParameters import BaseParameters, Callable, Optional, dataclasses, Any
from stlib.geometry import Geometry, GeometryParameters
from stlib.geometry.extract import ExtractParameters
from stlib.geometry.file import FileParameters
from splib.core.enum_types import ElementType
from Sofa.Core import Object

@dataclasses.dataclass
Expand Down Expand Up @@ -32,6 +34,15 @@ def getParameters(**kwargs) -> VisualParameters:
def createScene(root):

# Create a visual from a mesh file
params = Visual.getParameters()
params = Visual.getParameters()
params.name = "VisualFromFile"
params.geometry = FileParameters(filename="mesh/cube.obj")
root.add(Visual, params)


# Create a visual from a mesh file
# params = Visual.getParameters()
# params.name = "ExtractedVisual"
# params.geometry = ExtractParameters(fromGeometry=FileParameters(filename="mesh/cube.vtk"),
# destElementType=ElementType.TRIANGLES)
# root.add(Visual, params)