コード例 #1
0
ファイル: pslloader.py プロジェクト: FabienPean/sofa
def load(filename):
        '''Load the scene contained in the file with the provided name.
           The root node is returned
           Currently the supported formats are psl, pslx, pslp.
           '''
        filename = os.path.abspath(filename)
        dirname = os.path.dirname(filename)
        with SetPath(dirname):
            f = open(filename).read()
            ast=[]
            if filename.endswith(".psl"):
                ast = pslparserhjson.parse(f)
            elif filename.endswith(".pslx"):
                ast = pslparserxml.parse(f)
            elif filename.endswith(".pslp"):
                ast = pslparserpickled.parse(f)

            if len(ast) == 0:
                rootNode = Sofa.createNode("root")
                Sofa.msg_error(rootNode, "The file '"+filename+"' does not contains valid PSL content.")
                return rootNode

            directives = preProcess(ast[0][1])

            if not directives["version"] in ["1.0"]:
                rootNode = Sofa.createNode("root")
                Sofa.msg_error(rootNode, "Unsupported PSLVersion"+str(directives["version"]))
                return rootNode

            g=globals()
            g["__file__"]=filename
            ret = pslengine.processTree(ast, directives, g)
            return ret

        return None
コード例 #2
0
ファイル: API.py プロジェクト: FabienPean/sofa
 def addVisual(self, color=[1,1,1,1]):
     if self.dofs is None:
         Sofa.msg_error("Flexible.API.Deformable","addVisual : visual mesh not added because there is no dof, use LoadVisual instead to have a static visual mesh ")
     else:   # create a new deformable
         d = Deformable(self.node,"Visual")
         d.visualFromDeformable(self,color)
         return d
コード例 #3
0
ファイル: pslengine.py プロジェクト: FabienPean/sofa
def processPython(parent, key, token, stack, frame):
        """Process a python fragment of code with context provided by the content of the stack."""
        if not isAStringToken(token, ("s", "m")):
            Sofa.msg_error(parent, "Python expect string only argument instead of '"+str(token)+"'")
            return None

        #if not isAStringToken(token, ("s", "m")):
        #    raise Exception("Only string or multiline string allowed: "+str(token))

        ## retrieve the value as a string.
        stringvalue = token[1]

        p=parent.createObject("Python", name='"'+stringvalue[0:20]+'..."')
        p.addNewData("psl_source","PSL", "This hold a python expression.", "s", str(stringvalue))

        context = flattenStackFrame(stack)
        local = {}
        exec(stringvalue, context, local)

        ## Transfer the local entries to the previously defined context or in the existing variable
        ## somewhere in the stack frame.
        ## This allow import in one line and use the imported in the following ones.
        for k in local:
                lframe = findStackLevelFor(k, stack)
                if lframe != None:
                    lframe[k] = local[k]
                else:
                    stack[-1][k] = local[k]
コード例 #4
0
 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
     )
コード例 #5
0
ファイル: logger.py プロジェクト: 151706061/sofa
def createScene(node):

    # some code before
    a = 0

# w/ emitter
    Sofa.msg_info( "MyPythonEmitter", "my message info  a="+str(a) )
    Sofa.msg_warning( "MyPythonEmitter  a="+str(a), "my message warning" )
    Sofa.msg_error( "MyPythonEmitter", "my message error" )
    Sofa.msg_fatal( "MyPythonEmitter", "my message fatal" )

    # some code in between
    a = 2

# w/o emitter
    Sofa.msg_info( "my message info  a="+str(a) )
    Sofa.msg_warning( "my message warning" )
    Sofa.msg_error( "my message error" )
    Sofa.msg_fatal( "my message fatal" )

    # more complex code was causing trouble, so try it
    model = SofaPython.sml.Model("smlSimple.sml")


    # # invalid calls
    # Sofa.msg_info( 100 )
    # Sofa.msg_info( "emitter", "message", "extra" )


    sys.stdout.flush()
コード例 #6
0
ファイル: pslengine.py プロジェクト: FabienPean/sofa
def processAlias(parent, key, token, stack, frame):
        if not isAStringToken(token, ('p')):
            Sofa.msg_error(parent, pslprefix+" Unable to set an alias because of invalid syntax.")
        global aliases
        value = token[1]
        oldName, newName = value.split(' as ')
        aliases[newName]=oldName
コード例 #7
0
ファイル: API.py プロジェクト: Ngautier/sofa
    def setManually(self, filepath=None, offset=[[0,0,0,0,0,0,1]], voxelSize=0.01, density=1000, generatedDir=None):
        if len(offset) == 0:
            Sofa.msg_error("RigidScale.API","ShearlessAffineBody should have at least 1 ShearLessAffine")
            return
        self.framecom = Frame.Frame()
        self.bodyOffset = Frame.Frame([0,0,0,0,0,0,1])
        path_affine_rigid = '@'+ Tools.node_path_rel(self.affineNode, self.rigidNode)
        path_affine_scale = '@'+ Tools.node_path_rel(self.affineNode, self.scaleNode)
        if len(offset) == 1: self.frame = [Frame.Frame(offset[0])]
        str_position = ""
        for p in offset:
            str_position = str_position + concat(p) + " "

        ### scene creation
        # rigid dof
        self.rigidDofs = self.rigidNode.createObject('MechanicalObject', template='Rigid3'+template_suffix, name='dofs', position=str_position, rest_position=str_position)

        # scale dofs
        self.scaleDofs = self.scaleNode.createObject('MechanicalObject', template='Vec3'+template_suffix, name='dofs', position=concat([1,1,1]*len(offset)))
        positiveNode = self.scaleNode.createChild('positive')
        positiveNode.createObject('MechanicalObject', template='Vec3'+template_suffix, name='positivescaleDOFs')
        positiveNode.createObject('DifferenceFromTargetMapping', template='Vec3'+template_suffix+',Vec3'+template_suffix, applyRestPosition=1, targets=concat(target_scale))
        positiveNode.createObject('UniformCompliance', isCompliance=1, compliance=0)
        positiveNode.createObject('UnilateralConstraint')
        positiveNode.createObject('Stabilization', name='Stabilization')

        # affine dofs
        self.affineDofs = self.affineNode.createObject('MechanicalObject', template='Affine', name='parent', showObject=0)
        self.affineNode.createObject('RigidScaleToAffineMultiMapping', template='Rigid,Vec3,Affine', input1=path_affine_rigid, input2=path_affine_scale, output='@.', autoInit='1', printLog='0')
        if filepath:
            self.image = SofaImage.API.Image(self.affineNode, name="image_" + self.name, imageType="ImageUC")
            self.shapeFunction = Flexible.API.ShapeFunction(self.affineNode)
            if generatedDir is None:
                self.image.addMeshLoader(filepath, value=1, insideValue=1, scale=scale3d)  # TODO support multiple meshes closingValue=1,
                self.image.addMeshToImage(voxelSize)
                self.shapeFunction.addVoronoi(self.image, position='@dofs.rest_position')
                # mass
                self.affineMassNode = self.affineNode.createChild('mass')
                self.affineMassNode.createObject('TransferFunction', name='density', template='ImageUC,ImageD', inputImage='@../image.image', param='0 0 1 '+str(density))
                self.affineMassNode.createObject('MechanicalObject', template='Vec3'+template_suffix)
                self.affineMassNode.createObject('LinearMapping', template='Affine,Vec3'+template_suffix)
                self.affineMassNode.createObject('MassFromDensity',  name='MassFromDensity', template='Affine,ImageD', image='@density.outputImage', transform='@../image.transform', lumping='0')
                self.mass = self.affineNode.createObject('AffineMass', massMatrix='@mass/MassFromDensity.massMatrix')
            else:
                self.image.addContainer(filename=self.node.name + "_rasterization.raw", directory=generatedDir)
                self.shapeFunction.shapeFunction = serialization.importImageShapeFunction(self.affineNode, generatedDir+self.node.name+"_SF_indices.raw", generatedDir+self.node.name+"_SF_weights.raw", 'dofs')
                self.mass = serialization.importAffineMass(self.affineNode, generatedDir+self.node.name+"_affinemass.json")

            # computation of the object mass center
            massInfo = SofaPython.mass.RigidMassInfo()
            massInfo.setFromMesh(filepath, density, [1,1,1])
            # get the object mass center
            self.framecom.rotation = massInfo.inertia_rotation
            self.framecom.translation = massInfo.com
        else:
            print "You need a mesh to create an articulated system"
        self.frame = []
        for o in offset:
            self.frame.append(Frame.Frame(o))
コード例 #8
0
ファイル: API.py プロジェクト: FabienPean/sofa
 def addMechanicalObject(self, position=None, **kwargs):
     if position is None:
         if not self.mesh is None: # use implicit definition from mesh topology
             self.dof = self.node.createObject("MechanicalObject", template="Vec3", name="dofs", **kwargs)
         else:
             Sofa.msg_error("Flexible.API.FEMDof","addMechanicalObject : no input position")
         return
     self.dof = self.node.createObject("MechanicalObject", template="Vec3", name="dofs", position=position, **kwargs)
コード例 #9
0
ファイル: sml.py プロジェクト: Sreevis/sofa
 def parseImages(self, obj, objXml):
     images=objXml.findall("image")
     for i,m in enumerate(images):
         imageId = m.attrib["id"]
         if imageId in self.images:
             obj.addImage(self.images[imageId])
         else:
             Sofa.msg_error("SofaPython.sml","Model: solid {0} references undefined image {1}".format(obj.name, imageId))
コード例 #10
0
ファイル: sml.py プロジェクト: Sreevis/sofa
 def parseMeshes(self, obj, objXml):
     meshes=objXml.findall("mesh")
     for i,m in enumerate(meshes):
         meshId = m.attrib["id"]
         attr = Model.MeshAttributes(m)
         if meshId in self.meshes:
             obj.addMesh(self.meshes[meshId], attr)
         else:
             Sofa.msg_error("SofaPython.sml","Model: solid {0} references undefined mesh {1}".format(obj.name, meshId))
コード例 #11
0
 def addMeshVisual(self, meshName=None, color=None):
     name = self.meshSeq[0] if meshName is None else meshName
     mesh = self.meshes[name]
     if mesh.mesh is None:
         Sofa.msg_error("Image.API", "addMeshVisual : no mesh for " + meshName)
         return
     mesh.visual = self.node.createObject("VisualModel", name="visual_" + name, src=mesh.mesh.getLinkPath())
     if not color is None:
         mesh.visual.setColor(color[0], color[1], color[2], color[3])
コード例 #12
0
ファイル: API.py プロジェクト: FabienPean/sofa
 def write(self, filenamePrefix=None, directory=""):
     if self.dof is None:
         Sofa.msg_error("Flexible.API.AffineDof","write : no dof")
         return
     filename = self.getFilename(filenamePrefix,directory)
     data = {'template':'Affine', 'rest_position': affineDatatostr(self.dof.rest_position), 'position': affineDatatostr(self.dof.position)}
     with open(filename, 'w') as f:
         json.dump(data, f)
         if printLog:
             Sofa.msg_info("Flexible.API.AffineDof",'Exported Affine Dof to '+filename)
コード例 #13
0
 def addViewer(self):
     if self.image is None:
         Sofa.msg_error("Image.API", "addViewer : no image")
         return
     self.viewer = self.node.createObject(
         "ImageViewer",
         name="viewer",
         template=self.imageType,
         image=self.getImagePath() + ".image",
         transform=self.getImagePath() + ".transform",
     )
コード例 #14
0
 def addMechanicalObject(self, template="Vec3"):
     if self.sampler is None:
         Sofa.msg_error("Image.API", "addMechanicalObject : no sampler")
         return None
     if self.mesh is None:
         self.dofs = self.node.createObject(
             "MechanicalObject", template=template, name="dofs", position="@sampler.position"
         )
     else:
         self.dofs = self.node.createObject("MechanicalObject", template=template, name="dofs")
     return self.dofs
コード例 #15
0
ファイル: pslengine.py プロジェクト: FabienPean/sofa
def processObject(parent, key, kv, stack, frame):
        global sofaComponents
        populateFrame(key, frame, stack)
        frame = {}
        kwargs = {}
        if not isinstance(kv, list):
                kv = [("name" , kv)]

        properties = None
        for k,v in kv:
                if k == "properties":
                    if properties == None:
                        properties = v
                    else:
                        c=parent.createChild("[XX"+key+"XX]")
                        Sofa.msg_error(c, pslprefix+" Unable to create an object '"+key+"' because of duplicated properties keywords.")
                        return None
                elif isAStringToken(v, ('s', 'p')):
                    v = processString(v, stack, frame)
                    kwargs[k] = v
                elif isinstance(v, int):
                    kwargs[k] = v
                elif isinstance(v, float):
                        kwargs[k] = v
                else:
                    c=parent.createChild("[XX"+key+"XX]")
                    Sofa.msg_error(c, pslprefix+" Unable to create an object '"+key+"' because of invalid parameter "+str(k)+"="+str(v))
                    return None

        stack.append(frame)
        frame["self"] = obj = createObject(parent, key, stack, frame, kwargs)

        if properties:
            processProperties(obj, obj.name, properties, stack, frame)

        ### Force all the data field into a non-persistant state.
        for datafield in obj.getListOfDataFields():
            datafield.setPersistant(False)

        for link in obj.getListOfLinks():
            link.setPersistant(False)

        ### Then revert only the ones that have been touched
        for dataname in kwargs:
            try:
                if dataname in datafieldQuirks:
                    continue

                field = getField(obj, dataname)
                if field != None:
                    field.setPersistant(True)

            except Exception,e:
                Sofa.msg_warning(obj, pslprefix+" this does not seems to be a valid field '"+str(dataname)+"'")
コード例 #16
0
ファイル: API.py プロジェクト: FabienPean/sofa
 def addVoronoi(self, image, position='', cells='', nbRef=8):
     """ Add a Voronoi shape function using path to position  and possibly cells
     """
     if position =='':
         Sofa.msg_error("Flexible.API.ShapeFunction","addVoronoi : no position")
         return
     self.prefix = image.prefix # branching or regular image ?
     self.shapeFunction = self.node.createObject(
         "VoronoiShapeFunction", template="ShapeFunction,"+image.template(),
         name="shapeFunction", cell=cells,
         position=position,
         src=image.getImagePath(), method=0, nbRef=nbRef, bias=True)
コード例 #17
0
ファイル: sml.py プロジェクト: Sreevis/sofa
    def parseJointGenerics(self,modelXml):
        for j in modelXml.findall("jointGeneric"):
            if j.attrib["id"] in self.genericJoints:
                Sofa.msg_error("SofaPython.sml","Model: jointGeneric defined twice, id:", j.attrib["id"])
                continue

            joint=Model.JointGeneric(j)
            solids=j.findall("jointSolidRef")
            for i,o in enumerate(solids):
                if o.attrib["id"] in self.solids:
                    joint.solids[i] = self.solids[o.attrib["id"]]
                else:
                    Sofa.msg_error("SofaPython.sml","Model: in joint {0}, unknown solid {1} referenced".format(joint.name, o.attrib["id"]))
            self.genericJoints[joint.id]=joint
コード例 #18
0
ファイル: pslengine.py プロジェクト: FabienPean/sofa
def processImportPY(parent, importname, filename, key, stack, frame):
    Sofa.msg_info(parent, pslprefix+"Importing '"+importname+".py' file format.")
    pythonfile = open(filename).read()

    locals = {}
    frame = flattenStackFrame(stack)
    exec(pythonfile, frame, locals)

    if not "PSLExport" in locals:
            Sofa.msg_error(parent, pslprefix+"The file '"+filename+"' does not seem to contain PSL templates.")
            return

    for name in locals:
            templates[importname+"."+name] = locals[name]
コード例 #19
0
ファイル: pslengine.py プロジェクト: FabienPean/sofa
def processParameter(parent, name, value, stack, frame):
        try:
            if isinstance(value, list):
                    matches = difflib.get_close_matches(name, sofaComponents+templates.keys()+sofaAliases.keys(), n=4)
                    c=parent.createChild("[XX"+name+"XX]")
                    Sofa.msg_error(c, pslprefix+" unknow parameter or component [" + name + "] suggestions -> "+str(matches))
            elif not name in datafieldQuirks:
                    ## Python Hook to build an eval function.
                    value = processString(value, stack, frame)

                    try:
                            field = getField(frame["self"], name)
                            if field != None:
                                field.setValueString(str(value))
                                field.setPersistant(True)
                            else:
                                Sofa.msg_error(parent, pslprefix+" unable to get the field '" +name+"'")

                    except Exception,e:
                            Sofa.msg_error(parent, pslprefix+" exception while parsing field '" +name+"' because "+str(e))

                    if name == "name":
                            frame[value] = frame["self"]
                            #frame["name"] = value

        except Exception, e:
            SofaPython.sendMessageFromException(e)
            Sofa.msg_error(parent, pslprefix+" unable to parse parameter '"+str(name)+ "=" + str(value)+"'")
コード例 #20
0
ファイル: API.py プロジェクト: FabienPean/sofa
 def addExporter(self, filenamePrefix=None, directory=""):
     if self.shapeFunction is None:
         Sofa.msg_error("Flexible.API.ShapeFunction","addExporter : no shapeFunction")
         return
     sfPath = self.shapeFunction.getLinkPath()
     self.node.createObject(
         "ImageExporter", template=self.prefix+"ImageUI", name="exporterIndices",
         image=sfPath+".indices", transform=sfPath+".transform",
         filename=self.getFilenameIndices(filenamePrefix, directory),
         exportAtBegin=True, printLog=printLog)
     self.node.createObject(
         "ImageExporter", template=self.prefix+"ImageR", name="exporterWeights",
         image=sfPath+".weights", transform=sfPath+".transform",
         filename=self.getFilenameWeights(filenamePrefix, directory), exportAtBegin=True, printLog=printLog)
コード例 #21
0
ファイル: pslengine.py プロジェクト: FabienPean/sofa
def createObject(parentNode, name, stack , frame, kv):
        if name in sofaComponents:
                obj = parentNode.createObject(name, **kv)
                for k in kv:
                    if getField(obj, k) == None:
                        Sofa.msg_info(obj, pslprefix+" attribute '"+str(k)+"' is a parsing hook. Let's add Data field to fix it. To remove this warning stop using parsing hook.")
                        d = obj.addNewData(k, "PSL", "", "s", str(kv[k]))
                        obj.findData(k).setPersistant(True)
                return obj

        kv["name"] = name
        failureObject = parentNode.createObject("Undefined", **kv)

        Sofa.msg_error(failureObject, pslprefix+" unable to create the object '"+str(name)+"'")
        return failureObject
コード例 #22
0
 def addClosingVisual(self, meshName=None, color=None):
     name = self.meshSeq[0] if meshName is None else meshName
     mesh = self.meshes[name]
     if mesh.mesh is None:
         Sofa.msg_error("Image.API", "addClosingVisual : no mesh for " + meshName)
         return
     if mesh.mesh.findData("closingPosition") is None:
         Sofa.msg_error("Image.API", "addClosingVisual : mesh is not a closing " + meshName)
         return
     mesh.closingVisual = self.node.createObject(
         "VisualModel",
         name="closingVisual_" + name,
         position=mesh.mesh.getLinkPath() + ".closingPosition",
         triangles=mesh.mesh.getLinkPath() + ".closingTriangles",
     )
     if not color is None:
         mesh.closingVisual.setColor(color[0], color[1], color[2], color[3])
コード例 #23
0
ファイル: pslloader.py プロジェクト: FabienPean/sofa
def loadAst(filename):
    ast=[]
    filename = os.path.abspath(filename)
    dirname = os.path.dirname(filename)
    with SetPath(dirname):
        os.chdir(dirname)
        if not os.path.exists(filename):
            Sofa.msg_error("PSL", "Unable to open file '"+filename+"'")
            return ast

        f = open(filename).read()
        if filename.endswith(".psl"):
            ast = pslparserhjson.parse(f)
        elif filename.endswith(".pslx"):
            ast = pslparserxml.parse(f)
        elif filename.endswith(".pslp"):
            ast = pslparserpickled.parse(f)
    return ast
コード例 #24
0
ファイル: sml.py プロジェクト: Sreevis/sofa
def getValueByTag(valueByTag, tags):
    """ look into the valueByTag dictionary for a tag contained in tags
        \return the corresponding value, or the "default" value if none is found
        \todo print a warning if several matching tags are found in valueByTag
    """
    if "default" in tags:
        Sofa.msg_error("SofaPython.sml.getValueByTag", "default tag has a special meaning, it should not be defined in {0}".format(tags))
    tag = tags & set(valueByTag.keys())
    if len(tag)>1:
        Sofa.msg_warning("SofaPython.sml.getValueByTag", "sevaral tags from {0} are defined in values {1}".format(tags, valueByTag))
    if not len(tag)==0:
        return valueByTag[tag.pop()]
    else:
        if "default" in valueByTag:
            return valueByTag["default"]
        else:
            Sofa.msg_error("SofaPython.sml.getValueByTag", "No default value, and no tag from {0} found in {1}".format(tags, valueByTag))
            return None
コード例 #25
0
ファイル: __init__.py プロジェクト: david-cazier/sofa
def sofaExceptHandler(type, value, tb):
    global oldexcepthook
    """This exception handler, convert python exceptions & traceback into more classical sofa error messages of the form:
       Message Description
       Python Stack (most recent are at the end)
          File file1.py line 4  ...
          File file1.py line 10 ...
          File file1.py line 40 ...
          File file1.py line 23 ...
            faulty line
    """
    h = type.__name__

    if str(value) != '':
        h += ': ' + str(value)
    
    s = ''.join(traceback.format_tb(tb))
    
    Sofa.msg_error(h + '\n' + s, "line", 7)
コード例 #26
0
ファイル: pslengine.py プロジェクト: FabienPean/sofa
def processRootNode(kv, stack, frame):
        global templates, aliases
        stack.append(frame)
        populateFrame("", frame, stack)

        if isinstance(kv, list):
                for key,value in kv:
                        if isinstance(key, unicode):
                                key = str(key)

                        if key == "Node":
                                n = processNode(None, key, value, stack, {})
                                return n
                        else:
                                Sofa.msg_error(tself, pslprefix+"Unable to find a root Node in this file")
                                return None

        Sofa.msg_error(tself, pslprefix+"Unable to find a root Node in this file")
        return None
コード例 #27
0
ファイル: MeshLoader.py プロジェクト: FabienPean/sofa
def loadOBJ(filename):
    ## quickly written .obj import
    # Sofa.msg_info("PythonMeshLoader","loadOBJ: "+filename)

    m = Mesh()

    if not os.path.exists(filename):
        Sofa.msg_error("PythonMeshLoader","loadOBJ: inexistent file "+filename)
        return Mesh()

    for line in open(filename, "r"):
        vals = line.split()
        if len(vals)==0: # empty line
            continue
        if vals[0] == "v":
            v = map(float, vals[1:4])
            m.vertices.append(v)
        elif vals[0] == "vn":
            n = map(float, vals[1:4])
            m.normals.append(n)
        elif vals[0] == "vt":
            t = map(float, vals[1:3])
            m.uv.append(t)
        elif vals[0] == "f" or vals[0] == "l":
            faceV = []
            faceUV = []
            faceN = []
            for f in vals[1:]:
                w = f.split("/")
                
                faceV.append(int(w[0])-1)

                if len(w) > 1 and w[1]:
                    faceUV.append(int(w[1])-1)
                if len(w) > 2 and w[2]:
                    faceN.append(int(w[2])-1)
                    
            m.faceVertices.append(faceV)
            m.faceUv.append(faceUV)
            m.faceNormals.append(faceN)

    return m
コード例 #28
0
ファイル: API.py プロジェクト: FabienPean/sofa
def insertLinearMapping(node, dofRigidNode=None, dofAffineNode=None, cell='', assemble=True, geometricStiffness=2, isMechanical=True):
    """ insert the correct Linear(Multi)Mapping
    hopefully the template is deduced automatically by the component
    TODO: better names for input dofRigidNode and dofAffineNode, they can be any kind of nodes
    """
    if dofRigidNode is None and dofAffineNode is None:
        Sofa.msg_error("Flexible.API","insertLinearMapping : no dof given")
    else:
        if dofRigidNode is None:
            return node.createObject(
                "LinearMapping", cell=cell, shapeFunction = 'shapeFunction',
                input="@"+dofAffineNode.getPathName(), output="@.", assemble=assemble, geometricStiffness=geometricStiffness, mapForces=isMechanical, mapConstraints=isMechanical, mapMasses=isMechanical)
        elif dofAffineNode is None:
            return node.createObject(
                "LinearMapping", cell=cell, shapeFunction = 'shapeFunction',
                input="@"+dofRigidNode.getPathName(), output="@.", assemble=assemble, geometricStiffness=geometricStiffness, mapForces=isMechanical, mapConstraints=isMechanical, mapMasses=isMechanical)
        else:
            return node.createObject(
                "LinearMultiMapping", cell=cell, shapeFunction = 'shapeFunction',
                input1="@"+dofRigidNode.getPathName(), input2="@"+dofAffineNode.getPathName(), output="@.", assemble=assemble, geometricStiffness=geometricStiffness, mapForces=isMechanical, mapConstraints=isMechanical, mapMasses=isMechanical)
コード例 #29
0
ファイル: pslengine.py プロジェクト: FabienPean/sofa
def processImport(parent, key, kv, stack, frame):
        """ This function "import" the file provided as parameter """

        ## Check that the kv value is in fact a string or an unicode
        if not isAStringToken(kv):
                Sofa.msg_error(parent, pslprefix+" to much parameter given in procesImport " + str(type(kv)))
                return

        importname=processString(kv, stack, frame)
        if isinstance(importname, unicode):
            importname=str(importname)

        ## If it is we get complete the filename and try to open it.
        filename = getFileToImportFromPartialName(parent, importname)
        if filename == None or not os.path.exists(filename):
                dircontent = os.listdir(os.getcwd())
                matches = difflib.get_close_matches(filename, dircontent, n=4)
                Sofa.msg_error(parent, pslprefix+" the file '" + filename + "' does not exists. Do you mean: "+str(matches))
                return

        if filename.endswith(".psl"):
            return processImportPSL(parent, importname, filename, key, stack, frame)
        elif filename.endswith(".pslx"):
            return processImportPSLX(parent, importname, filename, key, stack, frame)
        elif filename.endswith(".py"):
            return processImportPY(parent, importname, filename, key, stack, frame)

        Sofa.msg_error(parent, pslprefix+"invalid file format to import "+ os.getcwd() + "/"+filename+ " supproted format are [psl, pslx, py]")
コード例 #30
0
ファイル: API.py プロジェクト: FabienPean/sofa
 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="@.")
コード例 #31
0
def VolumeEffector(surfaceMeshFileName=None,
                   attachedAsAChildOf=None,
                   attachedTo=None,
                   name="VolumeEffector",
                   rotation=[0.0, 0.0, 0.0],
                   translation=[0.0, 0.0, 0.0],
                   uniformScale=1,
                   initialValue=0,
                   valueType="volumeGrowth"):
    """Creates and adds a volume effector constraint.

    This creates all the components necessary in Sofa to include a cavity model whose volume should be determined by optimizing an external force.

    The constraint apply to a parent mesh.

    Args:
        cavityMeshFile (string): path to the cavity mesh (the mesh should be a surfacic mesh, ie only triangles or quads).

        name (string): name of the created node.

        initialValue (real): value to apply, default is 0.

        valueType (string): type of the parameter value (volumeGrowth or pressure), default is volumeGrowth.

    Structure:
    .. sourcecode:: qml
        Node : {
                name : "VolumeEffector"
                MeshTopology,
                MechanicalObject,
                SurfacePressureConstraint,
                BarycentricMapping
        }

    """
    if attachedAsAChildOf == None and attachedTo == None:
        Sofa.msg_error(
            "Your VolumeEffector isn't link/child of any node, please set the argument attachedTo or attachedAsAChildOf"
        )
        return None

    if surfaceMeshFileName == None:
        Sofa.msg_error("No surfaceMeshFileName specified, please specify one")
        return None

    veffector = getOrCreateTheTemplateNode(
        attachedAsAChildOf=attachedAsAChildOf,
        attachedTo=attachedTo,
        name=name)

    # This create a MeshSTLLoader, a componant loading the topology of the cavity.
    if surfaceMeshFileName.endswith(".stl"):
        veffector.createObject('MeshSTLLoader',
                               name='MeshLoader',
                               filename=surfaceMeshFileName,
                               rotation=rotation,
                               translation=translation,
                               scale=uniformScale)
    elif surfaceMeshFileName.endswith(".obj"):
        veffector.createObject('MeshObjLoader',
                               name='MeshLoader',
                               filename=surfaceMeshFileName,
                               rotation=rotation,
                               translation=translation,
                               scale=uniformScale)
    else:
        Sofa.msg_error(
            "Your surfaceMeshFileName extension is not the right one, you have to give a surfacic mesh with .stl or .obj extension"
        )
        return None

    # This create a MeshTopology, a componant holding the topology of the cavity.
    # veffector.createObject('MeshTopology', name="topology", filename=surfaceMeshFileName)
    veffector.createObject('MeshTopology', name='topology', src='@MeshLoader')

    # This create a MechanicalObject, a componant holding the degree of freedom of our
    # mechanical modelling. In the case of a cavity actuated with veffector, it is a set of positions specifying
    # the points where the pressure is applied.
    veffector.createObject('MechanicalObject', src="@topology")
    veffector.createObject('VolumeEffector',
                           template='Vec3',
                           triangles='@topology.triangles')
    #veffector.createObject('SurfacePressureConstraint',
    #                      value=initialValue,
    #                      valueType=valueType)

    # This create a BarycentricMapping. A BarycentricMapping is a key element as it will create a bi-directional link
    # between the cavity's DoFs and the parents's ones so that the pressure applied on the cavity wall will be mapped
    # to the volume structure and vice-versa;
    veffector.createObject('BarycentricMapping',
                           name="Mapping",
                           mapForces=False,
                           mapMasses=False)
    return veffector
コード例 #32
0
ファイル: API.py プロジェクト: RemiPires/sofa
    def setManually(self,
                    filepath=None,
                    offset=[[0, 0, 0, 0, 0, 0, 1]],
                    voxelSize=0.01,
                    density=1000,
                    mass=1,
                    inertia=[1, 1, 1],
                    inertia_forces=0,
                    generatedDir=None,
                    uniformScale=False):

        if len(offset) == 0:
            Sofa.msg_error(
                "RigidScale.API",
                "ShearlessAffineBody should have at least 1 ShearLessAffine")
            return

        self.framecom = Frame.Frame()
        self.bodyOffset = Frame.Frame([0, 0, 0, 0, 0, 0, 1])
        path_affine_rigid = '@' + Tools.node_path_rel(self.affineNode,
                                                      self.rigidNode)
        path_affine_scale = '@' + Tools.node_path_rel(self.affineNode,
                                                      self.scaleNode)
        if len(offset) == 1:
            self.frame = [Frame.Frame(offset[0])]
        str_position = ""
        for p in offset:
            str_position = str_position + concat(p) + " "
        if uniformScale:
            scaleTemplate = "Vec1"
        else:
            scaleTemplate = "Vec3"

        ### scene creation
        # rigid dof
        self.rigidDofs = self.rigidNode.createObject(
            'MechanicalObject',
            template='Rigid3' + template_suffix,
            name='dofs',
            position=str_position,
            rest_position=str_position)

        # scale dofs
        self.scaleDofs = self.scaleNode.createObject(
            'MechanicalObject',
            template=scaleTemplate + template_suffix,
            name='dofs',
            position=concat([1, 1, 1] * len(offset)))
        # The positiveNode is now commented for the moment since it seems not working
        """positiveNode = self.scaleNode.createChild('positive')
        positiveNode.createObject('MechanicalObject', template='Vec3'+template_suffix, name='positivescaleDOFs')
        positiveNode.createObject('DifferenceFromTargetMapping', template='Vec3'+template_suffix+',Vec3'+template_suffix, applyRestPosition=1, targets=concat(target_scale))
        positiveNode.createObject('UniformCompliance', isCompliance=1, compliance=0)
        positiveNode.createObject('UnilateralConstraint')
        positiveNode.createObject('Stabilization', name='Stabilization')"""

        # affine dofs
        self.affineDofs = self.affineNode.createObject('MechanicalObject',
                                                       template='Affine',
                                                       name='parent',
                                                       showObject=0)
        self.affineNode.createObject('RigidScaleToAffineMultiMapping',
                                     template='Rigid,' + scaleTemplate +
                                     ',Affine',
                                     input1=path_affine_rigid,
                                     input2=path_affine_scale,
                                     output='@.',
                                     autoInit='1',
                                     printLog='0')
        if filepath:
            self.image = SofaImage.API.Image(self.rigidNode,
                                             name="image_" + self.name,
                                             imageType="ImageUC")
            self.shapeFunction = Flexible.API.ShapeFunction(self.affineNode)
            if generatedDir is None:
                self.image.addMeshLoader(
                    filepath, value=1, insideValue=1
                )  # TODO support multiple meshes closingValue=1,
                self.image.addMeshToImage(voxelSize)
                self.shapeFunction.addVoronoi(self.image,
                                              position='@dofs.rest_position')
                # mass
                self.affineMassNode = self.affineNode.createChild('mass')
                self.affineMassNode.createObject(
                    'TransferFunction',
                    name='density',
                    template='ImageUC,ImageD',
                    inputImage='@' +
                    Tools.node_path_rel(self.affineMassNode, self.image.node) +
                    '/image.image',
                    param='0 0 1 ' + str(density))
                self.affineMassNode.createObject('MechanicalObject',
                                                 template='Vec3' +
                                                 template_suffix)
                self.affineMassNode.createObject('LinearMapping',
                                                 template='Affine,Vec3' +
                                                 template_suffix)
                self.affineMassNode.createObject(
                    'MassFromDensity',
                    name='MassFromDensity',
                    template='Affine,ImageD',
                    image='@density.outputImage',
                    transform='@' +
                    Tools.node_path_rel(self.affineMassNode, self.image.node) +
                    '/image.transform',
                    lumping='0')
                self.mass = self.affineNode.createObject(
                    'AffineMass',
                    massMatrix='@mass/MassFromDensity.massMatrix')
            else:
                self.image.addContainer(filename=self.node.name +
                                        "_rasterization.raw",
                                        directory=generatedDir)
                self.shapeFunction.shapeFunction = serialization.importImageShapeFunction(
                    self.affineNode,
                    generatedDir + self.node.name + "_SF_indices.raw",
                    generatedDir + self.node.name + "_SF_weights.raw", 'dofs')
                self.mass = serialization.importAffineMass(
                    self.affineNode,
                    generatedDir + self.node.name + "_affinemass.json")

            # computation of the object mass center
            massInfo = SofaPython.mass.RigidMassInfo()
            massInfo.setFromMesh(filepath, density, [1, 1, 1])
            # get the object mass center
            self.framecom.rotation = massInfo.inertia_rotation
            self.framecom.translation = massInfo.com
        else:
            if (mass and inertia) and inertia != [0, 0, 0]:
                Sofa.msg_info(
                    "RigidScale",
                    "A RigidMass and a UniformMass are created for respectively the rigid and the scale since there is no mesh which can be used to compute the model mass."
                )
                self.mass = self.rigidNode.createObject(
                    'RigidMass',
                    name='mass',
                    mass=mass,
                    inertia=concat(inertia[:3]),
                    inertia_forces=inertia_forces)
                self.scaleNode.createObject('UniformMass',
                                            name='mass',
                                            mass=mass)

        self.frame = []
        for o in offset:
            self.frame.append(Frame.Frame(o))
コード例 #33
0
def SubTopology(attachedTo=None,
                containerLink=None,
                boxRoiLink=None,
                linkType='tetrahedron',
                name="modelSubTopo",
                poissonRatio=0.3,
                youngModulus=18000):
    """
    Args:

        attachedTo (Sofa.Node): Where the node is created.

        containerLink (str): path to container with the dataField to link, ie: '@../container.position'

        boxRoiLink (str): path to boxRoi with the dataField to link,

        linkType (str):	indicate of which type is the subTopo,
                        ei: 'triangle' -> TriangleSetTopologyContainer & TriangleFEMForceField

        name (str):	name of the child node

        youngModulus (float):  The young modulus.

        poissonRatio (float):  The poisson parameter.

    Structure:
        .. sourcecode:: qml

            Node : {
                name : "modelSubTopo",
                TetrahedronSetTopologyContainer,
                TetrahedronFEMForceField
            }
    """
    if attachedTo is None:
        Sofa.msg_error(
            "Your SubTopology isn't child of any node, please set the argument attachedTo"
        )
        return None

    if containerLink is None or boxRoiLink is None:
        Sofa.msg_error(
            "You have to specify at least a container & boxROI link ")
        return None

    linkTypeUp = linkType[0].upper() + linkType[1:]

    # From the linkType which type of topology & forcefield to create :
    # ex : tetrahedra -> create  TetrahedraSetTopologyContainer & TetrahedraFEMForceField
    # From the containerLink we have the position of our TetrahedraSetTopologyContainer
    # From the boxRoiLink we have the elements we want from our boxROI

    # here we extract from the boxRoiLink the name of the data field to link it to
    strTmp = boxRoiLink[::-1]
    start = strTmp.find('nI') + 2
    end = strTmp.find('.')
    strTmp = strTmp[start:end]
    argument = strTmp[::-1]

    modelSubTopo = attachedTo.createChild(name)
    modelSubTopo.createObject(linkTypeUp + 'SetTopologyContainer',
                              name='container',
                              position=containerLink)

    modelSubTopo.getObject('container').findData(argument).value = boxRoiLink

    modelSubTopo.createObject(linkTypeUp + 'FEMForceField',
                              name='FEM',
                              method='large',
                              poissonRatio=poissonRatio,
                              youngModulus=youngModulus)

    return modelSubTopo
コード例 #34
0
def PneumaticCavity(surfaceMeshFileName=None,
                    attachedTo=None,
                    name="PneumaticCavity",
                    minPressure=None,
                    maxPressure=None,
                    minVolumeGrowth=None,
                    maxVolumeGrowth=None,
                    maxVolumeGrowthVariation=None,
                    rotation=[0.0, 0.0, 0.0],
                    translation=[0.0, 0.0, 0.0],
                    uniformScale=1):

    """Creates and adds a pneumatic actuation. Should be used in the context of the resolution of an inverse problem: find the actuation that leads to a desired deformation.
    See documentation at: https://project.inria.fr/softrobot/documentation/constraint/surface-pressure-actuator/

    The constraint is applied to a parent mesh.

    Args:
        cavityMeshFile (string): path to the cavity mesh (the mesh should be a surfacic mesh, ie only triangles or quads).

        name (string): name of the created node.

        minPressure:

        maxPressure:

        minVolumeGrowth:

        maxVolumeGrowth:

        maxVolumeGrowthVariation:

    Structure:
    .. sourcecode:: qml
        Node : {
                name : "PneumaticCavity"
                MeshTopology,
                MechanicalObject,
                SurfacePressureConstraint,
                BarycentricMapping
        }

    """
    if attachedTo == None:
        Sofa.msg_error("Your PneumaticCavity isn't child of any node, please set the argument attachedTo")
        return None

    if surfaceMeshFileName == None:
        Sofa.msg_error("No surfaceMeshFileName specified, please specify one")
        return None

    # This create a componant loading the topology of the cavity.
    if surfaceMeshFileName.endswith(".stl"):
        pneumatic.createObject('MeshSTLLoader', name='MeshLoader', filename=surfaceMeshFileName, rotation=rotation, translation=translation, scale=uniformScale)
    elif surfaceMeshFileName.endswith(".obj"):
        pneumatic.createObject('MeshObjLoader', name='MeshLoader', filename=surfaceMeshFileName, rotation=rotation, translation=translation, scale=uniformScale)
    else :
        Sofa.msg_error("Your surfaceMeshFileName extension is not the right one, you have to give a surfacic mesh with .stl or .obj extension")
        return None

    # This create a MeshTopology, a componant holding the topology of the cavity.
    # pneumatic.createObject('MeshTopology', name="topology", filename=surfaceMeshFileName)
    pneumatic.createObject('MeshTopology', name='topology', src='@MeshLoader')

    # This create a MechanicalObject, a componant holding the degree of freedom of our
    # mechanical modelling. In the case of a cavity actuated with pneumatic, it is a set of positions specifying
    # the points where the pressure is applied.
    pneumatic.createObject('MechanicalObject', src="@topology")

    # Create a SurfacePressureConstraint object with a name.
    # the indices are referring to the MechanicalObject's positions.
    pneumatic.createObject('SurfacePressureActuator')

    if minPressure != None : pneumatic.minPressure = minPressure
    if maxPressure != None : pneumatic.maxPressure = maxPressure
    if minVolumeGrowth != None : pneumatic.minVolumeGrowth = minVolumeGrowth
    if maxVolumeGrowth != None : pneumatic.maxVolumeGrowth = maxVolumeGrowth
    if maxVolumeGrowthVariation != None : pneumatic.maxVolumeGrowthVariation = maxVolumeGrowthVariation

    # This create a BarycentricMapping. A BarycentricMapping is a key element as it will create a bi-directional link
    # between the cavity's DoFs and the parents's ones so that the pressure applied on the cavity wall will be mapped
    # to the volume structure and vice-versa;
    pneumatic.createObject('BarycentricMapping', name="Mapping", mapForces=False, mapMasses=False)
    return pneumatic
コード例 #35
0
def Rigidify(targetObject,
             sourceObject,
             groupIndices,
             frames=None,
             name=None,
             frameOrientation=None):
    """ Transform a deformable object into a mixed one containing both rigid and deformable parts.

            :param targetObject: parent node where to attach the final object.
            :param sourceObject: node containing the deformable object. The object should be following
                                 the ElasticMaterialObject template.
            :param list groupIndices: array of array indices to rigidify. The length of the array should be equal to the number
                                      of rigid component.
            :param list frames: array of frames. The length of the array should be equal to the number
                                of rigid component. The orientation are given in eulerAngles (in degree) by passing
                                three values or using a quaternion by passing four values.
                                [[rx,ry,rz], [qx,qy,qz,w]]
                                User can also specify the position of the frame by passing six values (position and orientation in degree)
                                or seven values (position and quaternion).
                                [[x,y,z,rx,ry,rz], [x,y,z,qx,qy,qz,w]]
                                If the position is not specified, the position of the rigids will be the barycenter of the region to rigidify.
            :param str name: specify the name of the Rigidified object, is none provided use the name of the SOurceObject.
        """
    # Deprecation Warning
    if frameOrientation is not None:
        Sofa.msg_warning(
            "The parameter frameOrientations of the function Rigidify is now deprecated. Please use frames instead."
        )
        frames = frameOrientation

    if frames is None:
        frames = [[0., 0., 0.]] * len(groupIndices)

    assert len(groupIndices) == len(frames), "size mismatch."

    if name is None:
        name = sourceObject.name

    sourceObject.init()
    ero = targetObject.createChild(name)

    allPositions = sourceObject.container.position
    allIndices = map(lambda x: x[0], sourceObject.container.points)

    rigids = []
    indicesMap = []

    def mfilter(si, ai, pts):
        tmp = []
        for i in ai:
            if i in si:
                tmp.append(pts[i])
        return tmp

    # get all the points from the source.
    sourcePoints = map(Vec3, sourceObject.dofs.position)
    selectedIndices = []
    for i in range(len(groupIndices)):
        selectedPoints = mfilter(groupIndices[i], allIndices, sourcePoints)

        if len(frames[i]) == 3:
            orientation = Quat.createFromEuler(frames[i], inDegree=True)
            poscenter = getBarycenter(selectedPoints)
        elif len(frames[i]) == 4:
            orientation = frames[i]
            poscenter = getBarycenter(selectedPoints)
        elif len(frames[i]) == 6:
            orientation = Quat.createFromEuler(
                [frames[i][3], frames[i][4], frames[i][5]], inDegree=True)
            poscenter = [frames[i][0], frames[i][1], frames[i][2]]
        elif len(frames[i]) == 7:
            orientation = [
                frames[i][3], frames[i][4], frames[i][5], frames[i][6]
            ]
            poscenter = [frames[i][0], frames[i][1], frames[i][2]]
        else:
            Sofa.msg_error("Do not understand the size of a frame.")

        rigids.append(poscenter + list(orientation))

        selectedIndices += map(lambda x: x, groupIndices[i])
        indicesMap += [i] * len(groupIndices[i])

    otherIndices = filter(lambda x: x not in selectedIndices, allIndices)
    Kd = {v: None for k, v in enumerate(allIndices)}
    Kd.update({v: [0, k] for k, v in enumerate(otherIndices)})
    Kd.update({v: [1, k] for k, v in enumerate(selectedIndices)})
    indexPairs = [v for kv in Kd.values() for v in kv]

    freeParticules = ero.createChild("DeformableParts")
    freeParticules.createObject(
        "MechanicalObject",
        template="Vec3",
        name="dofs",
        position=[allPositions[i] for i in otherIndices])

    rigidParts = ero.createChild("RigidParts")
    rigidParts.createObject("MechanicalObject",
                            template="Rigid3",
                            name="dofs",
                            reserve=len(rigids),
                            position=rigids)

    rigidifiedParticules = rigidParts.createChild("RigidifiedParticules")
    rigidifiedParticules.createObject(
        "MechanicalObject",
        template="Vec3",
        name="dofs",
        position=[allPositions[i] for i in selectedIndices])
    rigidifiedParticules.createObject("RigidMapping",
                                      name="mapping",
                                      globalToLocalCoords='true',
                                      rigidIndexPerPoint=indicesMap)

    sourceObject.removeObject(sourceObject.solver)
    sourceObject.removeObject(sourceObject.integration)
    sourceObject.removeObject(sourceObject.LinearSolverConstraintCorrection)

    # The coupling is made with the sourceObject. If the source object is from an ElasticMaterialObject
    # We need to get the owning node form the current python object (this is a hack because of the not yet
    # Finalized design of stlib.
    coupling = sourceObject
    if hasattr(sourceObject, "node"):
        coupling = sourceObject.node

    coupling.createObject("SubsetMultiMapping",
                          name="mapping",
                          template="Vec3,Vec3",
                          input=freeParticules.dofs.getLinkPath() + " " +
                          rigidifiedParticules.dofs.getLinkPath(),
                          output=sourceObject.dofs.getLinkPath(),
                          indexPairs=indexPairs)

    rigidifiedParticules.addChild(coupling)
    freeParticules.addChild(coupling)
    return ero
コード例 #36
0
 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="@.")
コード例 #37
0
 def addMass(self, totalMass):
     if self.dofs is None:
         Sofa.msg_error("Flexible.API.Deformable",
                        "addMass : no dofs for " + self.name)
         return
     self.mass = self.node.createObject('UniformMass', totalMass=totalMass)
コード例 #38
0
    def open(self, filename):
        self.modelDir = os.path.dirname(filename)
        with open(filename,'r') as f:
            # TODO automatic DTD validation could go here, not available in python builtin ElementTree module
            modelXml = etree.parse(f).getroot()
            if self.name is None and "name" in modelXml.attrib:
                self.name = modelXml.attrib["name"]
            else:
                self.name = os.path.basename(filename)

            # units
            self.parseUnits(modelXml)
            
            # meshes
            for m in modelXml.iter("mesh"):
                if not m.find("source") is None:
                    if m.attrib["id"] in self.meshes:
                        Sofa.msg_warning("SofaPython.sml","Model: mesh id {0} already defined".format(m.attrib["id"]) )
                    mesh = Model.Mesh(m)
                    sourceFullPath = os.path.join(self.modelDir,mesh.source)
                    if os.path.exists(sourceFullPath):
                        mesh.source=sourceFullPath
                    else:
                        Sofa.msg_warning("SofaPython.sml","Model: mesh not found: "+mesh.source )
                    self.meshes[m.attrib["id"]] = mesh

            # images
            for m in modelXml.iter("image"):
                if not m.find("source") is None:
                    if m.attrib["id"] in self.images:
                        Sofa.msg_warning("SofaPython.sml","Model: image id {0} already defined".format(m.attrib["id"]) )
                    image = Model.Image(m)
                    sourceFullPath = os.path.join(self.modelDir,image.source)
                    if os.path.exists(sourceFullPath):
                        image.source=sourceFullPath
                    else:
                        Sofa.msg_warning("SofaPython.sml","Model: image not found: "+image.source )
                    self.images[m.attrib["id"]] = image


            # solids
            for objXml in modelXml.findall("solid"):
                if objXml.attrib["id"] in self.solids:
                    Sofa.msg_error("SofaPython.sml","Model: solid defined twice, id:" + objXml.attrib["id"])
                    continue
                solid=Model.Solid(objXml)
                self.parseMeshes(solid, objXml)
                self.parseImages(solid, objXml)
                self.solids[solid.id]=solid

            # skinning
            for objXml in modelXml.findall("solid"):
                solid=self.solids[objXml.attrib["id"]]
                # TODO: support multiple meshes for skinning (currently only the first mesh is skinned)
                for s in objXml.findall("skinning"):
                    if not s.attrib["solid"] in self.solids:
                        Sofa.msg_error("SofaPython.sml","Model: skinning for solid {0}: solid {1} is not defined".format(solid.name, s.attrib["solid"]) )
                        continue
                    skinning = Model.Skinning()
                    if not s.attrib["solid"] in self.solids :
                        Sofa.msg_error("SofaPython.sml","Model: skinning for solid {0}: bone (solid) {1} not defined".format(solid.name, s.attrib["solid"]) )
                        continue
                    skinning.solid = self.solids[s.attrib["solid"]]
                    if not s.attrib["mesh"] in self.meshes :
                        Sofa.msg_error("SofaPython.sml","Model: skinning for solid {0}: mesh {1} not defined".format(solid.name, s.attrib["mesh"]) )
                        continue
                    skinning.mesh = self.meshes[s.attrib["mesh"]]
                    #TODO: check that this mesh is also part of the solid
                    if not (s.attrib["group"] in skinning.mesh.group and s.attrib["weight"] in skinning.mesh.group[s.attrib["group"]].data):
                        Sofa.msg_error("SofaPython.sml","Model: skinning for solid {0}: mesh {1} - group {2} - weight {3} is not defined".format(solid.name, s.attrib["mesh"], s.attrib["group"], s.attrib["weight"]))
                        continue
                    skinning.index = skinning.mesh.group[s.attrib["group"]].index
                    skinning.weight = skinning.mesh.group[s.attrib["group"]].data[s.attrib["weight"]]
                    solid.skinnings.append(skinning)



            # joints
            self.parseJointGenerics(modelXml)
                
            # contacts
            for c in modelXml.findall("surfaceLink"):
                if c.attrib["id"] in self.surfaceLinks:
                    Sofa.msg_error("SofaPython.sml","Model: surfaceLink defined twice, id:", c.attrib["id"])
                    continue
                surfaceLink = Model.SurfaceLink(c)
                surfaces=c.findall("surface")
                for i,s in enumerate(surfaces):
                    surfaceLink.surfaces[i] = Model.Surface()
                    if s.attrib["solid"] in self.solids:
                        surfaceLink.surfaces[i].solid = self.solids[s.attrib["solid"]]
                    else:
                        Sofa.msg_error("SofaPython.sml","Model: in contact {0}, unknown solid {1} referenced".format(surfaceLink.name, s.attrib["solid"]))
                    if s.attrib["mesh"] in self.meshes:
                        surfaceLink.surfaces[i].mesh = self.meshes[s.attrib["mesh"]]
                    else:
                        Sofa.msg_error("SofaPython.sml","Model: in contact {0}, unknown mesh {1} referenced".format(surfaceLink.name, s.attrib["mesh"]))
                    if "group" in s.attrib: # optional
                        if len(s.attrib["group"]): # discard empty string
                            surfaceLink.surfaces[i].group = s.attrib["group"]
#                    if "image" in s.attrib: # optional
#                        if len(s.attrib["image"]): # discard empty string
#                            if s.attrib["image"] in self.images:
#                               reg.surfaces[i].image = self.images[s.attrib["image"]]
                self.surfaceLinks[surfaceLink.id]=surfaceLink
コード例 #39
0
def PneumaticSensor(surfaceMeshFileName=None,
                    attachedAsAChildOf=None,
                    attachedTo=None,
                    name="PneumaticSensor",
                    rotation=[0.0, 0.0, 0.0],
                    translation=[0.0, 0.0, 0.0],
                    uniformScale=1,
                    initialValue=0,
                    valueType="volumeGrowth"):

    """Creates and adds a pneumatic sensor constraint.

    This initializes all the components necessary to implement a virtual volume sensor. For a given geometry this will initialize a cavity that will deform as the mesh deforms. The component calculates the volume, but doesn't apply any constraint, i.e. there is no
    forces coming from a change in pressure for instance. This is the case when in real life air flow sensors are being used.

    The constraint apply to a parent mesh.

    Args:
        cavityMeshFile (string): path to the cavity mesh (the mesh should be a surfacic mesh, ie only triangles or quads).

        name (string): name of the created node.

        initialValue (real): value to apply, default is 0.

        valueType (string): type of the parameter value (volumeGrowth or pressure), default is volumeGrowth.

    Structure:
    .. sourcecode:: qml
        Node : {
                name : "PneumaticSensor"
                MeshTopology,
                MechanicalObject,
                SurfacePressureConstraint,
                BarycentricMapping
        }

    """
    if attachedAsAChildOf == None and attachedTo == None:
        Sofa.msg_error("Your PneumaticSensor isn't link/child of any node, please set the argument attachedTo or attachedAsAChildOf")
        return None

    if surfaceMeshFileName == None:
        Sofa.msg_error("No surfaceMeshFileName specified, please specify one")
        return None

    PneumaticSensor = getOrCreateTheTemplateNode(attachedAsAChildOf=attachedAsAChildOf,
                                           attachedTo=attachedTo,
                                           name=name)

    # This create a MeshSTLLoader, a componant loading the topology of the cavity.
    if surfaceMeshFileName.endswith(".stl"):
        PneumaticSensor.createObject('MeshSTLLoader', name='MeshLoader', filename=surfaceMeshFileName, rotation=rotation, translation=translation, scale=uniformScale)
    elif surfaceMeshFileName.endswith(".obj"):
        PneumaticSensor.createObject('MeshObjLoader', name='MeshLoader', filename=surfaceMeshFileName, rotation=rotation, translation=translation, scale=uniformScale)
    else :
        Sofa.msg_error("Your surfaceMeshFileName extension is not the right one, you have to give a surfacic mesh with .stl or .obj extension")
        return None

    # This create a MeshTopology, a componant holding the topology of the cavity.
    # PneumaticSensor.createObject('MeshTopology', name="topology", filename=surfaceMeshFileName)
    PneumaticSensor.createObject('MeshTopology', name='topology', src='@MeshLoader')

    # This create a MechanicalObject, a componant holding the degree of freedom of our
    # mechanical modelling. In the case of a cavity actuated with PneumaticSensor, it is a set of positions specifying
    # the points where the pressure is applied.
    PneumaticSensor.createObject('MechanicalObject', src="@topology")

    # Create a SurfacePressureConstraint object with a name.
    # the indices are referring to the MechanicalObject's positions.
    #PneumaticSensor.createObject('SurfacePressureConstraint',
    #                      value=initialValue,
    #                      valueType=valueType)

    # This create a BarycentricMapping. A BarycentricMapping is a key element as it will create a bi-directional link
    # between the cavity's DoFs and the parents's ones so that the pressure applied on the cavity wall will be mapped
    # to the volume structure and vice-versa;
    PneumaticSensor.createObject('BarycentricMapping', name="Mapping", mapForces=False, mapMasses=False)
    PneumaticSensor.createObject('SurfacePressureSensor',  triangles='@topology.triangles')
    return PneumaticSensor