Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
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)
Loading