def transformToData(scale, offset, timeOffset=0, timeScale=1, isPerspective=0): """ Returns a transform, formatted to sofa data given voxelsize, rigid position (offset), time and camera parameters """ return concat(offset[:3]) + ' ' + concat( quat.to_euler(offset[3:]) * 180. / math.pi) + ' ' + concat( scale) + ' ' + str(timeOffset) + ' ' + str(timeScale) + ' ' + str( int(isPerspective))
def addGaussPointSampler(self, shapeFunction, nbPoints, **kwargs): shapeFunctionPath = shapeFunction.shapeFunction.getLinkPath() samplerArgs = dict() samplerArgs.update(kwargs) if not self.labelImage is None: samplerArgs["mask"] = self.labelImage.getImagePath() + ".image" samplerArgs["maskLabels"] = concat(self.labels) self.sampler = self.node.createObject( "ImageGaussPointSampler", template=shapeFunction.prefix + "ImageR," + (self.labelImage.template() if not self.labelImage is None else "ImageUC"), name="sampler", evaluateShapeFunction=False, indices=shapeFunctionPath + ".indices", weights=shapeFunctionPath + ".weights", transform=shapeFunctionPath + ".transform", method="2", order=self.type[2:], targetNumber=nbPoints, **samplerArgs) if shapeFunction.prefix == "Branching": celloffsets = self.node.createObject( "BranchingCellOffsetsFromPositions", template=shapeFunction.prefix + "ImageUC", name="cell", position=self.sampler.getLinkPath() + ".position", src=self.labelImage.getImagePath(), labels=concat(self.labels)) self.cell = celloffsets.getLinkPath() + ".cell"
def subsetFromDeformable(self, deformable, indices): if not deformable.topology is None: topo = deformable.topology.getLinkPath() self.meshLoader = self.node.createObject( "MeshSubsetEngine", template="Vec3", name='MeshSubsetEngine', inputPosition=topo + '.position', inputTriangles=topo + '.triangles', inputQuads=topo + '.quads', indices=concat(indices)) self.topology = self.node.createObject("MeshTopology", name="topology", src="@" + self.meshLoader.name) if not deformable.dofs is None: deformable.node.addChild(self.node) self.dofs = self.node.createObject("MechanicalObject", template="Vec3", name="dofs") self.mapping = self.node.createObject( "SubsetMapping", name='mapping', indices=concat(indices), input='@' + deformable.node.getPathName(), output="@.")
def addModel(node,resolution,tr,useQuads=False, smooth=False,drawPlain=False): # node.createObject("MeshObjLoader", name="loader", filename="mesh/sphere_"+resolution+".obj", triangulate="1", scale="1 1 1") # node.createObject("Mesh", src="@loader", name="mesh") # node.createObject("SurfacePressureForceField", pressure="1E2", volumeConservationMode='1', drawForceScale="0.00001") if useQuads: node.createObject("GridMeshCreator", name="loader" ,filename="nofile", resolution=concat(resolution), trianglePattern="0", translation="0 0 "+str(tr), rotation="0 0 0", scale3d="0.2 1 0" ) node.createObject("QuadSetTopologyContainer", name="mesh", src="@loader" ) else: node.createObject("GridMeshCreator", name="loader", filename="nofile", resolution=concat(resolution), trianglePattern="1", translation="0 0 "+str(tr), rotation="0 0 0", scale3d="0.2 1 0" ) node.createObject("MeshTopology", name="mesh", src="@loader" ) node.createObject("MechanicalObject", src="@loader" ) node.createObject("BarycentricShapeFunction" ) node.createObject("UniformMass", totalMass="1000") g = 0.0 node.createObject("BoxROI", name="box1", box=concat([g-0.005,-0.005,-0.005+tr,1.005-g,0.005 ,0.005+tr]) ) node.createObject("FixedConstraint", indices="@[-1].indices" ) node.createObject("BoxROI", name="box2", box=concat([g-0.005,0.995,-0.005+tr,1.005-g,1.005 ,0.005+tr]) ) # node.createObject("FixedConstraint", indices="@[-1].indices" ) node.createObject("ConstantForceField", template="Vec3d", points="@[-1].indices", totalForce="-3 -3 0") node.createObject("PartialFixedConstraint", fixedDirections="0 0 1", fixAll=True ) Fnode = node.createChild("F") GPsampler = Fnode.createObject("TopologyGaussPointSampler", name="sampler", inPosition="@../loader.position", method="0", order="2" if useQuads else "1", orientation="0 0 25", useLocalOrientation="0") Fnode.createObject("MechanicalObject", template="F321" ) Fnode.createObject("LinearMapping", template="Vec3d,F321", showDeformationGradientScale="0.0", showDeformationGradientStyle="1") Enode = Fnode.createChild("E") Enode.createObject("MechanicalObject", template="E321", name="E") Enode.createObject("GreenStrainMapping", template="F321,E321" ) # Enode.createObject("CorotationalStrainMapping", template="F321,E321", method="polar", geometricStiffness=True) if smooth: Esnode = Enode.createChild("Es") # Esnode.createObject("HatShapeFunction", nbRef="4", param="0.5", position=GPsampler.getLinkPath()+".position" ) Esnode.createObject("ShepardShapeFunction", nbRef="4", position=GPsampler.getLinkPath()+".position" ) Esnode.createObject("GridMeshCreator", name="sampler" ,filename="nofile", resolution=concat([2*r for r in resolution]), trianglePattern="0", translation="0 0 "+str(tr), rotation="0 0 0", scale3d="0.2 1 0" ) Esnode.createObject("GaussPointSmoother", name="GP", position="@sampler.position", showSamplesScale=0, inputVolume=GPsampler.getLinkPath()+".volume", inputTransforms=GPsampler.getLinkPath()+".transforms" ) Esnode.createObject("MechanicalObject", template="E321", name="E" ) Esnode.createObject("LinearStrainMapping", template="E321,E321", indices="@GP.indices", weights="@GP.weights") Esnode.createObject("HookeForceField", template="E321", name="ff", youngModulus="3000.0", poissonRatio="0.4", viscosity="0" ) else: # Enode.createObject("HookeOrthotropicForceField", template="E321", youngModulusX="200", youngModulusY="20", poissonRatioXY="0.4", shearModulusXY="3.6", viscosity="0") Enode.createObject("HookeForceField", template="E321", name="ff", youngModulus="3000.0", poissonRatio="0.4", viscosity="0" ) vnode = node.createChild("Visual") if drawPlain: vnode.createObject("VisualModel", color="0.8 0.8 1 1") else: vnode.createObject("VisualModel", color="0.8 0.8 1 1",edges="@../mesh.edges",position="@../mesh.position") vnode.createObject("IdentityMapping" )
def __addMesh(self, mesh, closingValue=None, roiIndices=list(), roiValue=list(), name=None): """ some code factorization between addMeshLoader and addExternMesh """ args = dict() if not closingValue is None: # close mesh if closingValue is defined meshPath = mesh.mesh.getLinkPath() mesh.mesh = self.node.createObject( "MeshClosingEngine", name="closer_" + name, inputPosition=meshPath + ".position", inputTriangles=meshPath + ".triangles", ) mesh.roiValue = [closingValue] mesh.roiIndices = mesh.mesh.getLinkPath() + ".indices" elif len(roiIndices) != 0 and len(roiValue) != 0: mesh.roiValue = roiValue args = dict() for i, roi in enumerate(roiIndices): args["indices" + str(i + 1)] = concat(roi) mesh.mergeROIs = self.node.createObject( "MergeROIs", name="mergeROIs_" + name, nbROIs=len(roiIndices), **args ) mesh.roiIndices = mesh.mergeROIs.getLinkPath() + ".roiIndices" # use mergeROIs to potentially combine other rois (from meshclosing, boxRois, etc.) # but here, roiIndices reformating to "[i,j,..] [k,l,..]" would work.. self.meshes[name] = mesh self.meshSeq.append(name)
def addMeshToImage(self, voxelSize): args = dict() i = 1 for name in self.meshSeq: mesh = self.meshes[name] if mesh.mesh is None: Sofa.msg_error("Image.API", "addMeshToImage : no mesh for " + name) return meshPath = mesh.mesh.getLinkPath() args["position" + str(i)] = meshPath + ".position" args["triangles" + str(i)] = meshPath + ".triangles" args["value" + str(i)] = mesh.value if mesh.insideValue is None: args["fillInside" + str(i)] = False else: args["insideValue" + str(i)] = mesh.insideValue if not mesh.roiIndices is None and len(mesh.roiValue) != 0: args["roiIndices" + str(i)] = mesh.roiIndices args["roiValue" + str(i)] = concat(mesh.roiValue) i += 1 self.image = self.node.createObject( "MeshToImageEngine", template=self.template(), name="image", voxelSize=voxelSize, padSize=1, subdiv=8, rotateImage=False, nbMeshes=len(self.meshes), **args )
def read(self, filenamePrefix=None, directory="", **kwargs): filename = self.getFilename(filenamePrefix, directory) data = dict() with open(filename, 'r') as f: data.update(json.load(f)) self.type = data['type'] self.sampler = self.node.createObject( 'GaussPointContainer', name='GPContainer', volumeDim=data['volumeDim'], inputVolume=data['inputVolume'], position=data['position'], **kwargs) if not self.labelImage is None and not self.labels is None: if self.labelImage.prefix == "Branching": celloffsets = self.node.createObject( "BranchingCellOffsetsFromPositions", template=self.labelImage.template(), name="cell", position=self.sampler.getLinkPath() + ".position", src=self.labelImage.getImagePath(), labels=concat(self.labels)) self.cell = celloffsets.getLinkPath() + ".cell" if printLog: Sofa.msg_info("Flexible.API.Behavior", 'Imported Gauss Points from ' + filename)
def loadMesh(self, meshPath, offset=[0, 0, 0, 0, 0, 0, 1], scale=[1, 1, 1], triangulate=False): r = Quaternion.to_euler(offset[3:]) * 180.0 / math.pi self.meshLoader = SofaPython.Tools.meshLoader(self.node, meshPath, translation=concat( offset[:3]), rotation=concat(r), scale3d=concat(scale), triangulate=triangulate) self.topology = self.node.createObject("MeshTopology", name="topology", src="@" + self.meshLoader.name)
def addMapping(self, dofRigidNode=None, dofAffineNode=None, labelImage=None, labels=None, useGlobalIndices=False, useIndexLabelPairs=False, assemble=True, isMechanical=True): cell = '' if not labelImage is None and not labels is None: # use labels to select specific voxels in branching image if labelImage.prefix == 'Branching': position = "@" + self.topology.name + ".position" if not self.topology is None else "@" + self.visual.name + ".position" offsets = self.node.createObject( "BranchingCellOffsetsFromPositions", template=labelImage.template(), name="cell", position=position, image=labelImage.getImagePath() + ".image", transform=labelImage.getImagePath() + ".transform", labels=concat(labels), useGlobalIndices=useGlobalIndices, useIndexLabelPairs=useIndexLabelPairs) cell = offsets.getLinkPath() + ".cell" self.mapping = insertLinearMapping(self.node, dofRigidNode, dofAffineNode, cell, assemble, isMechanical=isMechanical)
def addBeam(node,resolution,tr,smooth=False,drawPlain=False): node.createObject("RegularGrid", name="mesh", n=concat(resolution), min=concat([-0.2+tr,-0.2,-1]), max=concat([0.2+tr,0.2,1])) node.createObject("MechanicalObject", template="Vec3", name="dofs" ) node.createObject("BoxROI", template="Vec3d", position="@mesh.position", box=concat([-1+tr,-1,-1.1,1+tr,1,-0.99]) ) node.createObject("FixedConstraint", indices="@[-1].indices" ) node.createObject("BoxROI", template="Vec3d", position="@mesh.position", box=concat([-1+tr,-1,0.99,1+tr,1,1.1]), drawBoxes="1" ) node.createObject("ConstantForceField", template="Vec3d", points="@[-1].indices", totalForce="0 -3 0") # node.createObject("ConstantForceField", template="Vec3d", points="@[-1].indices", totalForce="0 -6 0") # node.createObject("ConstantForceField", template="Vec3d", points="@[-1].indices", totalForce="0 0 100") node.createObject("UniformMass", totalMass="10" ) # node.createObject("HexahedronFEMForceField", youngModulus="1000.0" ,poissonRatio="0", method="polar", updateStiffnessMatrix="false" ) node.createObject("BarycentricShapeFunction", nbRef="8" ) Fnode = node.createChild("F") GPsampler = Fnode.createObject("TopologyGaussPointSampler", name="sampler", inPosition="@../mesh.position", showSamplesScale="0", method="0", order="2" ) Fnode.createObject("MechanicalObject", template="F331", name="F" ) mapping = Fnode.createObject("LinearMapping", name="FMapping", template="Vec3d,F331" ) Enode = Fnode.createChild("E") Enode.createObject("MechanicalObject", template="E331", name="E" ) # Enode.createObject("CorotationalStrainMapping", template="F331,E331", method="svd", geometricStiffness=True) Enode.createObject("GreenStrainMapping", template="F331,E331", geometricStiffness=True) if smooth: Esnode = Enode.createChild("Es") # Esnode.createObject("HatShapeFunction", nbRef="8", param="0.5", position=GPsampler.getLinkPath()+".position" ) Esnode.createObject("ShepardShapeFunction", nbRef="8", position=GPsampler.getLinkPath()+".position" ) Esnode.createObject("RegularGrid", name="sampler", n=concat([2*r for r in resolution]), min=concat([-0.2+tr,-0.2,-1]), max=concat([0.2+tr,0.2,1])) Esnode.createObject("GaussPointSmoother", name="GP", position="@sampler.position", inputVolume=GPsampler.getLinkPath()+".volume", inputTransforms=GPsampler.getLinkPath()+".transforms" ) Esnode.createObject("MechanicalObject", template="E331", name="E" ) Esnode.createObject("LinearStrainMapping", template="E331,E331", indices="@GP.indices", weights="@GP.weights") Esnode.createObject("HookeForceField", template="E331", name="ff", youngModulus="3000.0", poissonRatio="0.3", viscosity="0" ) else: Enode.createObject("HookeForceField", template="E331", name="ff", youngModulus="3000.0", poissonRatio="0.3", viscosity="0" ) vnode = node.createChild("Visual") if drawPlain: vnode.createObject("VisualModel", color="0.8 0.8 1 1") else: vnode.createObject("VisualModel", color="0.8 0.8 1 1",edges="@../mesh.edges",position="@../mesh.position") vnode.createObject("IdentityMapping" )
def addVisualCylinder(self, radius=0.01, color=[1, 1, 1, 1]): if not self.dofs is None: d = Deformable(self.node, "Visual") d.visual = d.node.createObject("OglCylinderModel", name="model", radius=radius, color=concat(color)) return d
def createSceneAndController(rootNode): rootNode.createObject('RequiredPlugin', pluginName="Flexible") rootNode.createObject('RequiredPlugin', pluginName="Compliant") rootNode.createObject('RequiredPlugin', pluginName="ContactMapping") rootNode.createObject('BackgroundSetting', color='1 1 1') rootNode.createObject('VisualStyle', displayFlags='showBehavior') rootNode.dt = 0.01 rootNode.gravity = [0, -10, 0] rootNode.createObject('CompliantImplicitSolver', name="odesolver") # rootNode.createObject('SequentialSolver', name="numsolver", iterations =10, precision=1e-14) rootNode.createObject('LDLTSolver', name="numsolver") # rootNode.createObject('MinresSolver', name="numsolver", iterations =10, precision=1e-14) # rootNode.createObject('EulerImplicitSolver') # rootNode.createObject('CGSolver', tolerance="1.0e-9" ,threshold="1.0e-9" ) pos = [[0, 0, 0], [0, 1, 0], [0.1, 1, 0], [0.1, 0.5, 0], [0.2, 0.5, 0], [0.2, 1, 0], [0.3, 1, 0], [0.3, 0, 0]] edges = [[i, i + 1] for i in xrange(len(pos) - 1)] rootNode.createObject('Mesh', name="mesh", position=lconcat(pos), lines=lconcat(edges)) rootNode.createObject('MechanicalObject', template="Vec3d", name="DOFs", src="@mesh") rootNode.createObject('UniformMass', name="mass", totalMass="2") rootNode.createObject('FixedConstraint', name="FixedConstraint", indices=concat([1, 2, 3, 4, 5, 6])) # rootNode.createObject('UniformVelocityDampingForceField',dampingCoefficient="0.1") rootNode.createObject('RestShapeSpringsForceField', points="0 7", stiffness="10") Lnode = rootNode.createChild("L") Lnode.createObject('MechanicalObject', template="Vec1") Lnode.createObject('LengthMapping', template="Vec3,Vec1", edges="@../mesh.lines", offset="-3.3", geometricStiffness=1) Lnode.createObject('UniformCompliance', compliance=1E-2, rayleighStiffness=1, isCompliance='0') Vnode = rootNode.createChild("visual") Vnode.createObject('VisualModel', edges="@../mesh.lines") Vnode.createObject('IdentityMapping')
def addSkinning(self, armatureNode, indices, weights, assemble=True, isMechanical=True): """ Add skinning (linear) mapping based on the armature (Rigid3) in armatureNode using """ self.mapping = self.node.createObject("LinearMapping", template="Rigid3,Vec3", name="mapping", input="@" + armatureNode.getPathName(), indices=concat(indices), weights=concat(weights), assemble=assemble, mapForces=isMechanical, mapConstraints=isMechanical, mapMasses=isMechanical)
def loadVisual(self, meshPath, offset=[0, 0, 0, 0, 0, 0, 1], scale=[1, 1, 1], color=[1, 1, 1, 1], **kwargs): r = Quaternion.to_euler(offset[3:]) * 180.0 / math.pi self.visual = self.node.createObject("VisualModel", name="model", filename=meshPath, translation=concat(offset[:3]), rotation=concat(r), scale3d=concat(scale), color=concat(color), putOnlyTexCoords=True, computeTangents=True, **kwargs) # self.visual = self.node.createObject("VisualModel", name="model", filename=meshPath, translation=concat(offset[:3]) , rotation=concat(r), scale3d=concat(scale), color=concat(color), **kwargs) self.visual.setColor( color[0], color[1], color[2], color[3] ) # the previous assignement fails when reloading a scene.. self.normals = self.visual
def addMeshLoader( self, meshFile, value, insideValue=None, closingValue=None, roiIndices=list(), roiValue=list(), name=None, offset=[0, 0, 0, 0, 0, 0, 1], scale=[1, 1, 1], ): mesh = Image.Mesh(value, insideValue) _name = name if not name is None else os.path.splitext(os.path.basename(meshFile))[0] mesh.mesh = SofaPython.Tools.meshLoader( self.node, meshFile, name="meshLoader_" + _name, triangulate=True, translation=concat(offset[:3]), rotation=concat(Quaternion.to_euler(offset[3:]) * 180.0 / math.pi), scale3d=concat(scale), ) self.__addMesh(mesh, closingValue, roiIndices, roiValue, _name)
def addGaussPointSampler(self, shapeFunction, nbPoints, **kwargs): shapeFunctionPath = shapeFunction.shapeFunction.getLinkPath() samplerArgs = dict() samplerArgs.update(kwargs) if not self.labelImage is None: samplerArgs["mask"]=self.labelImage.getImagePath()+".image" samplerArgs["maskLabels"]=concat(self.labels) self.sampler = self.node.createObject( "ImageGaussPointSampler", template=shapeFunction.prefix+"ImageR,"+(self.labelImage.template() if not self.labelImage is None else "ImageUC"), name="sampler", indices=shapeFunctionPath+".indices", weights=shapeFunctionPath+".weights", transform=shapeFunctionPath+".transform", method="2", order=self.type[2:], targetNumber=nbPoints, **samplerArgs) if shapeFunction.prefix == "Branching": celloffsets = self.node.createObject("BranchingCellOffsetsFromPositions", template=shapeFunction.prefix+"ImageUC", name="cell", position =self.sampler.getLinkPath()+".position", src=self.labelImage.getImagePath(), labels=concat(self.labels)) self.cell = celloffsets.getLinkPath()+".cell"
def visualFromDeformable(self, deformable, color=[1, 1, 1, 1]): deformable.node.addChild(self.node) self.visual = self.node.createObject( "VisualModel", name="model", filename="@" + deformable.meshLoader.getPathName() + ".filename", color=concat(color)) self.visual.setColor( color[0], color[1], color[2], color[3] ) # the previous assignement fails when reloading a scene.. self.mapping = self.node.createObject("IdentityMapping", name="mapping", input='@' + deformable.node.getPathName(), output="@.", mapForces=False, mapConstraints=False, mapMasses=False) self.normals = self.visual
def addMeshToImage(self, voxelSize): args=dict() i=1 for name in self.meshSeq: mesh = self.meshes[name] if mesh.mesh is None: Sofa.msg_error('Image.API',"addMeshToImage : no mesh for "+ name) return meshPath = mesh.mesh.getLinkPath() args["position"+str(i)]=meshPath+".position" args["triangles"+str(i)]=meshPath+".triangles" args["value"+str(i)]=mesh.value if mesh.insideValue is None: args["fillInside"+str(i)]=False else: args["insideValue"+str(i)]=mesh.insideValue if not mesh.roiIndices is None and len(mesh.roiValue)!=0 : args["roiIndices"+str(i)]=mesh.roiIndices args["roiValue"+str(i)]=concat(mesh.roiValue) i+=1 self.image = self.node.createObject('MeshToImageEngine', template=self.template(), name="image", voxelSize=voxelSize, padSize=1, subdiv=8, rotateImage=False, nbMeshes=len(self.meshes), **args)
def __addMesh(self, mesh, closingValue=None, roiIndices=list(), roiValue=list(), name=None): """ some code factorization between addMeshLoader and addExternMesh """ args=dict() if not closingValue is None : # close mesh if closingValue is defined meshPath = mesh.mesh.getLinkPath() mesh.mesh = self.node.createObject("MeshClosingEngine", name="closer_"+name, inputPosition=meshPath+".position", inputTriangles=meshPath+".triangles") mesh.roiValue=[closingValue] mesh.roiIndices=mesh.mesh.getLinkPath()+".indices" elif len(roiIndices)!=0 and len(roiValue)!=0 : mesh.roiValue=roiValue args=dict() for i,roi in enumerate(roiIndices): args["indices"+str(i+1)]=concat(roi) mesh.mergeROIs = self.node.createObject('MergeROIs', name="mergeROIs_"+name, nbROIs=len(roiIndices), **args) mesh.roiIndices=mesh.mergeROIs.getLinkPath()+".roiIndices" # use mergeROIs to potentially combine other rois (from meshclosing, boxRois, etc.) # but here, roiIndices reformating to "[i,j,..] [k,l,..]" would work.. self.meshes[name] = mesh self.meshSeq.append(name)
def loadMesh(self, meshPath, offset = [0,0,0,0,0,0,1], scale=[1,1,1], triangulate=False): r = Quaternion.to_euler(offset[3:]) * 180.0 / math.pi self.meshLoader = SofaPython.Tools.meshLoader(self.node, meshPath, translation=concat(offset[:3]) , rotation=concat(r), scale3d=concat(scale), triangulate=triangulate) self.topology = self.node.createObject("MeshTopology", name="topology", src="@"+self.meshLoader.name )
def read(self, filenamePrefix=None, directory="", **kwargs): filename = self.getFilename(filenamePrefix,directory) data = dict() with open(filename,'r') as f: data.update(json.load(f)) self.type = data['type'] self.sampler = self.node.createObject('GaussPointContainer',name='GPContainer', volumeDim=data['volumeDim'], inputVolume=data['inputVolume'], position=data['position'], **kwargs) if not self.labelImage is None and not self.labels is None: if self.labelImage.prefix == "Branching": celloffsets = self.node.createObject("BranchingCellOffsetsFromPositions", template=self.labelImage.template(), name="cell", position =self.sampler.getLinkPath()+".position", src=self.labelImage.getImagePath(), labels=concat(self.labels)) self.cell = celloffsets.getLinkPath()+".cell" if printLog: Sofa.msg_info("Flexible.API.Behavior",'Imported Gauss Points from '+filename)
def addSkinning(self, armatureNode, indices, weights, assemble=True, isMechanical=True): """ Add skinning (linear) mapping based on the armature (Rigid3) in armatureNode using """ self.mapping = self.node.createObject("LinearMapping", template="Rigid3,Vec3", name="mapping", input="@"+armatureNode.getPathName(), indices=concat(indices), weights=concat(weights), assemble=assemble, mapForces=isMechanical, mapConstraints=isMechanical, mapMasses=isMechanical)
def addMapping(self, dofRigidNode=None, dofAffineNode=None, labelImage=None, labels=None, useGlobalIndices=False, useIndexLabelPairs=False, assemble=True, isMechanical=True): cell = '' if not labelImage is None and not labels is None : # use labels to select specific voxels in branching image if labelImage.prefix=='Branching': position="@"+self.topology.name+".position" if not self.topology is None else "@"+self.visual.name+".position" offsets = self.node.createObject("BranchingCellOffsetsFromPositions", template=labelImage.template(), name="cell", position =position, image=labelImage.getImagePath()+".image", transform=labelImage.getImagePath()+".transform", labels=concat(labels), useGlobalIndices=useGlobalIndices, useIndexLabelPairs=useIndexLabelPairs) cell = offsets.getLinkPath()+".cell" self.mapping = insertLinearMapping(self.node, dofRigidNode, dofAffineNode, cell, assemble, isMechanical=isMechanical)
def subsetFromDeformables(self, deformableIndicesList = list() ): args=dict() inputs=[] indexPairs=[] i=1 mapTopo = True mapDofs = True for s,ind in deformableIndicesList: s.node.addChild(self.node) if s.dofs is None: mapDofs = False else: if not ind is None: for p in ind: indexPairs+=[i-1,p] else: # no roi -> take all points. Warning: does not work if parent dofs are not initialized size = len(s.dofs.position) if size==0: Sofa.msg_error("Flexible.API.Deformable","subsetFromDeformables: no dof from "+ s.name) for p in xrange(size): indexPairs+=[i-1,p] if s.topology is None: mapTopo = False else: if not ind is None: subset = self.node.createObject("MeshSubsetEngine", template = "Vec3", name='MeshSubsetEngine_'+s.name, inputPosition=s.topology.getLinkPath()+'.position', inputTriangles=s.topology.getLinkPath()+'.triangles', inputQuads=s.topology.getLinkPath()+'.quads', indices=concat(ind)) path = '@'+subset.name else: # map all path = s.topology.getLinkPath() args["position"+str(i)]=path+".position" args["triangles"+str(i)]=path+".triangles" args["quads"+str(i)]=path+".quads" inputs.append('@'+s.node.getPathName()) i+=1 if mapTopo: self.meshLoader = self.node.createObject('MergeMeshes', name='MergeMeshes', nbMeshes=len(inputs), **args ) self.topology = self.node.createObject("MeshTopology", name="topology", src="@"+self.meshLoader.name ) if mapDofs: self.dofs = self.node.createObject("MechanicalObject", template = "Vec3", name="dofs") self.mapping = self.node.createObject("SubsetMultiMapping", name='mapping', indexPairs=concat(indexPairs), input=concat(inputs),output="@.")
def subsetFromDeformable(self, deformable, indices ): if not deformable.topology is None: topo = deformable.topology.getLinkPath() self.meshLoader = self.node.createObject("MeshSubsetEngine", template = "Vec3", name='MeshSubsetEngine', inputPosition=topo+'.position', inputTriangles=topo+'.triangles', inputQuads=topo+'.quads', indices=concat(indices)) self.topology = self.node.createObject("MeshTopology", name="topology", src="@"+self.meshLoader.name) if not deformable.dofs is None: deformable.node.addChild(self.node) self.dofs = self.node.createObject("MechanicalObject", template = "Vec3", name="dofs") self.mapping = self.node.createObject("SubsetMapping", name='mapping', indices=concat(indices), input='@'+deformable.node.getPathName(),output="@.")
def visualFromDeformable(self, deformable, color=[1,1,1,1]): deformable.node.addChild(self.node) self.visual = self.node.createObject("VisualModel", name="model", filename="@"+deformable.meshLoader.getPathName()+".filename", color=concat(color)) self.visual.setColor(color[0],color[1],color[2],color[3]) # the previous assignement fails when reloading a scene.. self.mapping = self.node.createObject("IdentityMapping", name="mapping", input='@'+deformable.node.getPathName(),output="@.", mapForces=False, mapConstraints=False, mapMasses=False ) self.normals = self.visual
def addModel(node, resolution, tr, useQuads=False, smooth=False, drawPlain=False): # node.createObject("MeshObjLoader", name="loader", filename="mesh/sphere_"+resolution+".obj", triangulate="1", scale="1 1 1") # node.createObject("Mesh", src="@loader", name="mesh") # node.createObject("SurfacePressureForceField", pressure="1E2", volumeConservationMode='1', drawForceScale="0.00001") if useQuads: node.createObject("GridMeshCreator", name="loader", filename="nofile", resolution=concat(resolution), trianglePattern="0", translation="0 0 " + str(tr), rotation="0 0 0", scale3d="0.2 1 0") node.createObject("QuadSetTopologyContainer", name="mesh", src="@loader") else: node.createObject("GridMeshCreator", name="loader", filename="nofile", resolution=concat(resolution), trianglePattern="1", translation="0 0 " + str(tr), rotation="0 0 0", scale3d="0.2 1 0") node.createObject("MeshTopology", name="mesh", src="@loader") node.createObject("MechanicalObject", src="@loader") node.createObject("BarycentricShapeFunction") node.createObject("UniformMass", totalMass="1000") g = 0.0 node.createObject("BoxROI", name="box1", box=concat([ g - 0.005, -0.005, -0.005 + tr, 1.005 - g, 0.005, 0.005 + tr ])) node.createObject("FixedConstraint", indices="@[-1].indices") node.createObject("BoxROI", name="box2", box=concat([ g - 0.005, 0.995, -0.005 + tr, 1.005 - g, 1.005, 0.005 + tr ])) # node.createObject("FixedConstraint", indices="@[-1].indices" ) node.createObject("ConstantForceField", template="Vec3d", points="@[-1].indices", totalForce="-3 -3 0") node.createObject("PartialFixedConstraint", fixedDirections="0 0 1", fixAll=True) Fnode = node.createChild("F") GPsampler = Fnode.createObject("TopologyGaussPointSampler", name="sampler", inPosition="@../loader.position", method="0", order="2" if useQuads else "1", orientation="0 0 25", useLocalOrientation="0") Fnode.createObject("MechanicalObject", template="F321") Fnode.createObject("LinearMapping", template="Vec3d,F321", showDeformationGradientScale="0.0", showDeformationGradientStyle="1") Enode = Fnode.createChild("E") Enode.createObject("MechanicalObject", template="E321", name="E") Enode.createObject("GreenStrainMapping", template="F321,E321") # Enode.createObject("CorotationalStrainMapping", template="F321,E321", method="polar", geometricStiffness=True) if smooth: Esnode = Enode.createChild("Es") # Esnode.createObject("HatShapeFunction", nbRef="4", param="0.5", position=GPsampler.getLinkPath()+".position" ) Esnode.createObject("ShepardShapeFunction", nbRef="4", position=GPsampler.getLinkPath() + ".position") Esnode.createObject("GridMeshCreator", name="sampler", filename="nofile", resolution=concat([2 * r for r in resolution]), trianglePattern="0", translation="0 0 " + str(tr), rotation="0 0 0", scale3d="0.2 1 0") Esnode.createObject("GaussPointSmoother", name="GP", position="@sampler.position", showSamplesScale=0, inputVolume=GPsampler.getLinkPath() + ".volume", inputTransforms=GPsampler.getLinkPath() + ".transforms") Esnode.createObject("MechanicalObject", template="E321", name="E") Esnode.createObject("LinearStrainMapping", template="E321,E321", indices="@GP.indices", weights="@GP.weights") Esnode.createObject("HookeForceField", template="E321", name="ff", youngModulus="3000.0", poissonRatio="0.4", viscosity="0") else: # Enode.createObject("HookeOrthotropicForceField", template="E321", youngModulusX="200", youngModulusY="20", poissonRatioXY="0.4", shearModulusXY="3.6", viscosity="0") Enode.createObject("HookeForceField", template="E321", name="ff", youngModulus="3000.0", poissonRatio="0.4", viscosity="0") vnode = node.createChild("Visual") if drawPlain: vnode.createObject("VisualModel", color="0.8 0.8 1 1") else: vnode.createObject("VisualModel", color="0.8 0.8 1 1", edges="@../mesh.edges", position="@../mesh.position") vnode.createObject("IdentityMapping")
def addMeshLoader(self, meshFile, value, insideValue=None, closingValue=None, roiIndices=list(), roiValue=list(), name=None, offset = [0,0,0,0,0,0,1], scale=[1,1,1]): mesh = Image.Mesh(value, insideValue) _name = name if not name is None else os.path.splitext(os.path.basename(meshFile))[0] mesh.mesh = SofaPython.Tools.meshLoader(self.node, meshFile, name="meshLoader_"+_name, triangulate=True, translation=concat(offset[:3]) , rotation=concat(Quaternion.to_euler(offset[3:]) * 180.0 / math.pi), scale3d=concat(scale)) self.__addMesh(mesh,closingValue,roiIndices,roiValue,_name)
def transformToData(scale,offset,timeOffset=0,timeScale=1,isPerspective=0): """ Returns a transform, formatted to sofa data given voxelsize, rigid position (offset), time and camera parameters """ return concat(offset[:3])+' '+concat(quat.to_euler(offset[3:])*180./math.pi)+' '+concat(scale)+' '+str(timeOffset)+' '+str(timeScale)+' '+str(int(isPerspective))
def loadVisual(self, meshPath, offset = [0,0,0,0,0,0,1], scale=[1,1,1], color=[1,1,1,1],**kwargs): r = Quaternion.to_euler(offset[3:]) * 180.0 / math.pi self.visual = self.node.createObject("VisualModel", name="model", filename=meshPath, translation=concat(offset[:3]) , rotation=concat(r), scale3d=concat(scale), color=concat(color), putOnlyTexCoords=True,computeTangents=True,**kwargs) # self.visual = self.node.createObject("VisualModel", name="model", filename=meshPath, translation=concat(offset[:3]) , rotation=concat(r), scale3d=concat(scale), color=concat(color), **kwargs) self.visual.setColor(color[0],color[1],color[2],color[3]) # the previous assignement fails when reloading a scene.. self.normals = self.visual
def addVisualCylinder(self,radius=0.01, color=[1,1,1,1]): if not self.dofs is None: d = Deformable(self.node,"Visual") d.visual = d.node.createObject("OglCylinderModel", name="model",radius=radius, color=concat(color)) return d
def createScene(root): # root node setup root.createObject('RequiredPlugin', pluginName='Flexible') root.createObject('RequiredPlugin', pluginName='Compliant') root.createObject('VisualStyle', displayFlags="showBehavior") root.createObject('CompliantAttachButtonSetting') root.createObject('BackgroundSetting', color='1 1 1') # simuation parameters root.dt = 1e-1 root.gravity = [0, 0, 0] # ode solver ode = root.createObject( 'CompliantImplicitSolver', neglecting_compliance_forces_in_geometric_stiffness=False, stabilization="pre-stabilization") # numerical solver # root.createObject('LDLTSolver', name="numsolver") root.createObject('SequentialSolver', name='numsolver', iterations=250, precision=1e-14, iterateOnBilaterals=True) # root.createObject('LDLTResponse', name='response') # root.createObject('LUResponse', name='response') # scene node scene = root.createChild('scene') # script variables nbLink = 7 linkSize = 2 # links creation links = [] # rigid bodies for i in xrange(nbLink): body = StructuralAPI.RigidBody(root, "link-{0}".format(i)) body.setManually(offset=[0, -1. * linkSize * i, 0, 0, 0, 0, 1], inertia_forces=False) body.dofs.showObject = True body.dofs.showObjectScale = 0.25 * linkSize body.addVisualModel("mesh/cylinder.obj", scale3d=[.3, .1 * linkSize, .3], offset=[0, -0.5 * linkSize, 0, 0, 0, 0, 1]) links.append(body) # attach first link links[0].setFixed() # joints creation points = [] for i in xrange(nbLink - 1): off1 = links[i].addOffset("offset-{0}-{1}".format(i, i + 1), [0, -0.5 * linkSize, 0, 0, 0, 0, 1]) off2 = links[i + 1].addOffset("offset-{0}-{1}".format(i + 1, i), [0, 0.5 * linkSize, 0, 0, 0, 0, 1]) j = StructuralAPI.HingeRigidJoint(2, "joint-{0}-{1}".format(i, i + 1), off1.node, off2.node, isCompliance=False, compliance=1E-5) #StructuralAPI.BallAndSocketRigidJoint("joint-{0}-{1}".format(i, i+1), off1.node, off2.node, isCompliance=True, compliance=0) j.addLimits(0, .8, compliance=1E-15) points.append(links[i].addAbsoluteMappedPoint( "point-{0}-{1}".format(i, i + 1), [0.5, -1. * linkSize * i - 0.25 * linkSize, 0])) points.append(links[i + 1].addAbsoluteMappedPoint( "point-{0}-{1}".format(i + 1, i), [0.5, -1. * linkSize * (i + 1) + 0.25 * linkSize, 0])) points.append(links[nbLink - 1].addAbsoluteMappedPoint( "point-{0}".format(nbLink), [0.5, -1. * linkSize * (nbLink - 1) - 0.5 * linkSize, 0])) # rod rodNode = scene.createChild('rod') rodNode.createObject('MechanicalObject', name='dofs', template="Vec3", position=concat([0.5, 0.5 * linkSize, 0])) rodNode.createObject('UniformMass', name="mass", totalMass="1") rodNode.createObject('RestShapeSpringsForceField', points="0", stiffness="1E3") fullrodNode = rodNode.createChild('fullrod') input = '@' + rodNode.getPathName() + ' ' indexPairs = '0 0 ' edges = '' for i, p in enumerate(points): input += '@' + p.node.getPathName() + ' ' indexPairs += str(i + 1) + ' 0 ' edges += str(i) + ' ' + str(i + 1) + ' ' p.node.addChild(fullrodNode) fullrodNode.createObject('MechanicalObject', template="Vec3", showObject=True, showObjectScale=0.1, showColor="0 1 0 1", drawMode=1) fullrodNode.createObject('SubsetMultiMapping', template="Vec3,Vec3", name="mapping", input=input, output='@./', indexPairs=indexPairs) Lnode = fullrodNode.createChild("L") Lnode.createObject('MechanicalObject', template="Vec1") Lnode.createObject('LengthMapping', template="Vec3,Vec1", edges=edges, offset=str(-nbLink * linkSize), geometricStiffness=1) Lnode.createObject('UniformCompliance', compliance=1E-10, rayleighStiffness=0, isCompliance='1') Vnode = fullrodNode.createChild("visual") Vnode.createObject('VisualModel', edges=edges) Vnode.createObject('IdentityMapping')