<commit_before>import Sofa

import os.path
import math
import xml.etree.ElementTree as etree 

import Quaternion
import Tools
from Tools import listToStr as concat
import units

def parseIdName(obj,objXml):
    """ set id and name of obj
    """
    obj.id = objXml.attrib["id"]
    obj.name = obj.id
    if not objXml.find("name") is None:
        obj.name = objXml.find("name").text
        
def parseData(xmlData):
    """ return the list of data in xmlData
    """
    if xmlData.attrib["type"]=="float":
        return Tools.strToListFloat(xmlData.text)
    elif xmlData.attrib["type"]=="int":
        return Tools.strToListInt(xmlData.text)
    elif xmlData.attrib["type"]=="string":
        return xmlData.text.split()

class Model:

    class Mesh:

        class Group:
            def __init__(self):
                self.index=list()
                self.data=dict()
        
        def __init__(self, meshXml):
            self.format = meshXml.find("source").attrib["format"]
            self.source = meshXml.find("source").text
        
            self.group=dict()
            self.data=dict()
            for g in meshXml.iter("group"):
                self.group[g.attrib["id"]] = Model.Mesh.Group()
                self.group[g.attrib["id"]].index = Tools.strToListInt(g.find("index").text)
                for d in g.iter("data"):
                    self.group[g.attrib["id"]].data[d.attrib["name"]]=parseData(d)                    
    
    class Rigid:
        def __init__(self, objXml):
            parseIdName(self,objXml)
            self.position=Tools.strToListFloat(objXml.find("position").text)
            self.mesh = None
            self.density=None
            self.mass=None
            if not objXml.find("density") is None:
                self.density=float(objXml.find("density").text)
            if not objXml.find("mass") is None:
                self.mass = float(objXml.find("mass").text)

    class Offset:
        def __init__(self, offsetXml):
            self.name = "offset"
            self.value = Tools.strToListFloat(offsetXml.text)
            self.type = offsetXml.attrib["type"]
            
        def isAbsolute(self):
            return self.type == "absolute"
            
    class Dof:
        def __init__(self, dofXml):
            self.index = Model.dofIndex[dofXml.attrib["index"]]
            self.min = None
            self.max = None
            if "min" in dofXml.attrib:
                self.min = float(dofXml.attrib["min"])
            if "max" in dofXml.attrib:
                self.max = float(dofXml.attrib["max"])
        
    class JointGeneric:
        #def __init__(self, name="Unknown",object1,offset1,object2,offset2):
        def __init__(self, jointXml):
            parseIdName(self,jointXml)
            self.objects = [None,None]
            # offsets
            self.offsets = [None,None]
            objects = jointXml.findall("object")
            for i in range(0,2):
                if not objects[i].find("offset") is None:
                    self.offsets[i] = Model.Offset(objects[i].find("offset"))
                    self.offsets[i].name = "offset_{0}".format(self.name)
                    
            # dofs
            self.dofs = [] 
            for dof in jointXml.iter("dof"):
                self.dofs.append(Model.Dof(dof))
        
    class Deformable:
        
        class Skinning:
            """ Skinning definition, vertices index influenced by rigid with weight
            """
            def __init__(self):
                self.rigid=None
                self.index=list()
                self.weight=list()
        
        def __init__(self,objXml):
            parseIdName(self,objXml)
            self.position = Tools.strToListFloat(objXml.find("position").text)
            self.mesh = None
            self.indices=dict()
            self.weights=dict()
            self.skinnings=list()
    
    dofIndex={"x":0,"y":1,"z":2,"rx":3,"ry":4,"rz":5}
    
    def __init__(self, filename, name=None):
        self.name=os.path.basename(filename)
        self.modelDir = os.path.dirname(filename)
        self.units=dict()
        self.meshes=dict()
        self.rigids=dict()
        #self.rigidsbyType=dict()
        self.genericJoints=dict()
        self.deformables=dict()
        #self.deformablesByType=dict()
        
        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 name is None:
                self.name = modelXml.attrib["name"]

            # 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:
                        print "WARNING: 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:
                        print "WARNING: sml.Model: mesh not found:", mesh.source
                    self.meshes[m.attrib["id"]] = mesh
                    
            # rigids
            for r in modelXml.iter("rigid"):
                if r.attrib["id"] in self.rigids:
                    print "ERROR: sml.Model: rigid defined twice, id:", r.attrib["id"]
                    continue
                rigid=Model.Rigid(r)
                self.parseMesh(rigid, r)
                self.rigids[rigid.id]=rigid
            
            # joints<commit_msg>[SofaPython.sml] take care of model name<commit_after>import Sofa

import os.path
import math
import xml.etree.ElementTree as etree 

import Quaternion
import Tools
from Tools import listToStr as concat
import units

def parseIdName(obj,objXml):
    """ set id and name of obj
    """
    obj.id = objXml.attrib["id"]
    obj.name = obj.id
    if not objXml.find("name") is None:
        obj.name = objXml.find("name").text
        
def parseData(xmlData):
    """ return the list of data in xmlData
    """
    if xmlData.attrib["type"]=="float":
        return Tools.strToListFloat(xmlData.text)
    elif xmlData.attrib["type"]=="int":
        return Tools.strToListInt(xmlData.text)
    elif xmlData.attrib["type"]=="string":
        return xmlData.text.split()

class Model:

    class Mesh:

        class Group:
            def __init__(self):
                self.index=list()
                self.data=dict()
        
        def __init__(self, meshXml):
            self.format = meshXml.find("source").attrib["format"]
            self.source = meshXml.find("source").text
        
            self.group=dict()
            self.data=dict()
            for g in meshXml.iter("group"):
                self.group[g.attrib["id"]] = Model.Mesh.Group()
                self.group[g.attrib["id"]].index = Tools.strToListInt(g.find("index").text)
                for d in g.iter("data"):
                    self.group[g.attrib["id"]].data[d.attrib["name"]]=parseData(d)                    
    
    class Rigid:
        def __init__(self, objXml):
            parseIdName(self,objXml)
            self.position=Tools.strToListFloat(objXml.find("position").text)
            self.mesh = None
            self.density=None
            self.mass=None
            if not objXml.find("density") is None:
                self.density=float(objXml.find("density").text)
            if not objXml.find("mass") is None:
                self.mass = float(objXml.find("mass").text)

    class Offset:
        def __init__(self, offsetXml):
            self.name = "offset"
            self.value = Tools.strToListFloat(offsetXml.text)
            self.type = offsetXml.attrib["type"]
            
        def isAbsolute(self):
            return self.type == "absolute"
            
    class Dof:
        def __init__(self, dofXml):
            self.index = Model.dofIndex[dofXml.attrib["index"]]
            self.min = None
            self.max = None
            if "min" in dofXml.attrib:
                self.min = float(dofXml.attrib["min"])
            if "max" in dofXml.attrib:
                self.max = float(dofXml.attrib["max"])
        
    class JointGeneric:
        #def __init__(self, name="Unknown",object1,offset1,object2,offset2):
        def __init__(self, jointXml):
            parseIdName(self,jointXml)
            self.objects = [None,None]
            # offsets
            self.offsets = [None,None]
            objects = jointXml.findall("object")
            for i in range(0,2):
                if not objects[i].find("offset") is None:
                    self.offsets[i] = Model.Offset(objects[i].find("offset"))
                    self.offsets[i].name = "offset_{0}".format(self.name)
                    
            # dofs
            self.dofs = [] 
            for dof in jointXml.iter("dof"):
                self.dofs.append(Model.Dof(dof))
        
    class Deformable:
        
        class Skinning:
            """ Skinning definition, vertices index influenced by rigid with weight
            """
            def __init__(self):
                self.rigid=None
                self.index=list()
                self.weight=list()
        
        def __init__(self,objXml):
            parseIdName(self,objXml)
            self.position = Tools.strToListFloat(objXml.find("position").text)
            self.mesh = None
            self.indices=dict()
            self.weights=dict()
            self.skinnings=list()
    
    dofIndex={"x":0,"y":1,"z":2,"rx":3,"ry":4,"rz":5}
    
    def __init__(self, filename, name=None):
        self.name=name
        self.modelDir = os.path.dirname(filename)
        self.units=dict()
        self.meshes=dict()
        self.rigids=dict()
        #self.rigidsbyType=dict()
        self.genericJoints=dict()
        self.deformables=dict()
        #self.deformablesByType=dict()
        
        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:
                        print "WARNING: 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:
                        print "WARNING: sml.Model: mesh not found:", mesh.source
                    self.meshes[m.attrib["id"]] = mesh
                    
            # rigids
            for r in modelXml.iter("rigid"):
                if r.attrib["id"] in self.rigids:
                    print "ERROR: sml.Model: rigid defined twice, id:", r.attrib["id"]
                    continue
                rigid=Model.Rigid(r)
                self.parseMesh(rigid, r)
                self.rigids[rigid.id]=rigid
            
            # joints
{'fraction_non_alphanumeric': 0.11976355692624004, 'fraction_numerical': 0.0023986978497387134, 'mean_word_length': 1.6139722346618899, 'pattern_counts': {'":': 18, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 18}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6076620', 'n_tokens_mistral': 3423, 'n_tokens_neox': 3333, 'n_words': 663}