def __init__(self, degree=3, topomesh=None, **kwds):
        """todo"""
        self._wisp_properties = [{} for d in xrange(degree+1)]
        self._interface_properties = [{} for d in xrange(degree+1)]
        self._topomesh_properties= {}

        self._interface = [None] + [IdDict(idgenerator="set") for i in xrange(degree)]

        Topomesh.__init__(self, degree, **kwds)
        if topomesh is not None:
            self.extend(topomesh)
    def __init__(self, degree=3, topomesh=None, **kwds):
        """todo"""
        self._wisp_properties = [{} for d in xrange(degree+1)]
        self._interface_properties = [{} for d in xrange(degree+1)]
        self._topomesh_properties= {}

        self._interface = [None] + [IdDict(idgenerator="set") for i in xrange(degree)]

        Topomesh.__init__(self, degree, **kwds)
        if topomesh is not None:
            from copy import deepcopy
            self._borders = deepcopy(topomesh._borders)
            self._regions = deepcopy(topomesh._regions)
def clone_mesh (mesh, wids) :
	"""Clone a mesh around a set of elements
	
	Create a new mesh with the same ids
	than the old one where all wisps not
	connected to the given one are ommited.
	
	:Parameters:
	 - `mesh` (:class:`Topomesh`) - the master
	            mesh to clone
	 - `wids` (list of wid) - a list of top
	    wisps id that will remain in the clone
	
	:Returns Type: :class:`Topomesh`
	"""
	deg_max = mesh.degree()
	
	cmesh = Topomesh(deg_max,"max")
	
	#find local wisps
	loc_wisps = []
	for deg in xrange(deg_max) :
		wisps = set()
		for wid in wids :
			wisps.update(mesh.borders(deg_max,wid,deg_max - deg) )
		loc_wisps.append( (deg,wisps) )
	
	loc_wisps.append( (deg_max,wids) )
	
	#copy wisps
	for deg,wids in loc_wisps :
		for wid in wids :
			cmesh.add_wisp(deg,wid)
	
	#copy links between wisps
	for deg,wids in loc_wisps[-1:0:-1] :
		for wid in wids :
			for bid in mesh.borders(deg,wid) :
				cmesh.link(deg,wid,bid)
	
	#return
def is_collapse_topo_allowed (mesh, eid, protected_edges) :
    """Test wether collapse of the edge is safe.

    mesh: a topomesh object
    eid: id of the edge to flip
    """
    #collapse enabled only if faces are triangle or square
    for fid in mesh.regions(1,eid) :
        if mesh.nb_borders(2,fid) not in (3,4) :
            return False
    #construct a local copy of the mesh
    #including all the faces that touch one
    #of the extremity of the edge
    #find relevant elements
    fids = set()
    for pid in mesh.borders(1,eid) :
        for bid in mesh.regions(0,pid) :
            fids.update(mesh.regions(1,bid))

    eids = set()
    pids = set()
    for fid in fids :
        eids.update(mesh.borders(2,fid))
        pids.update(mesh.borders(2,fid,2))
    elms = (pids,eids,fids)
    if mesh.degree() == 3 :
        cids = set()
        for fid in fids :
            cids.update(mesh.regions(2,fid))
        elms = elms + (cids,)
    
    #construct local mesh
    lmesh = Topomesh(mesh.degree(),"max")
    for deg,wids in enumerate(elms) :
        for wid in wids :
            lmesh.add_wisp(deg,wid)
    for deg,wids in enumerate(elms[:-1]) :
        for wid in wids :
            for rid in set(mesh.regions(deg,wid)) & elms[deg + 1] :
                lmesh.link(deg + 1,rid,wid)
    #collapse edge on this local copy
    try :
    	pid1,pid2 = collapse_edge(lmesh,eid,protected_edges)
    except UserWarning :
    	return False
    #test the result
    #edges without any face
    for wid in lmesh.wisps(1) :
        if lmesh.nb_regions(1,wid) == 0 :
            return False
    #surperposed faces
    #TODO optimization
    for ref_fid in lmesh.wisps(2) :
        ref_pids = set(lmesh.borders(2,ref_fid,2) )
        for fid in [wid for wid in lmesh.wisps(2) if wid != ref_fid] :
            pids = set(lmesh.borders(2,fid,2) )
            if len(pids) == len(ref_pids) :
                if pids == ref_pids :
                    return False
            elif len(pids) > len(ref_pids) :
                if len(pids - ref_pids) == 1 :
                    return False
            else :
                if len(ref_pids - pids) == 1 :
                    return False
    #return
def triangulate_polygon (pids, pos) :
    """Sort pids in tuples of 3 points
    
    .. seealso:: Compared to `topo_triangulate_polygon`, this function will use
                 geometrical informations to produce nice triangles
    :Parameters:
     - `pids` (list of pid) - ordered list of points that form a closed polygon
     - `pos` (dict of (pid|Vector) ) - position of points in the mesh.
    
    :Returns Type: list of (pid,pid,pid)
    """
    triangles = topo_triangulate_polygon(pids)
    if len(triangles) == 1 :
        return triangles
    
    #change triangles to tends towards equilateral one
    #local triangulated mesh
    mesh = Topomesh(2)
    for pid in pids :
        mesh.add_wisp(0,pid)
    edge = {}
    for pid1,pid2,pid3 in triangles :
        tid = mesh.add_wisp(2)
        for pida,pidb in [(pid1,pid2),(pid2,pid3),(pid3,pid1)] :
            key = (min(pida,pidb),max(pida,pidb) )
            try :
                eid = edge[key]
            except KeyError :
                eid = mesh.add_wisp(1)
                mesh.link(1,eid,pida)
                mesh.link(1,eid,pidb)
                edge[key] = eid
            mesh.link(2,tid,eid)
    
    #flip edges
    test = True
    while test :
        test = False
        for eid in tuple(mesh.wisps(1) ) :
            if flip_necessary(mesh,eid,pos) :
                flip_edge(mesh,eid)
                test = True
    
    return [tuple(mesh.borders(2,fid,2) ) for fid in mesh.wisps(2)]
def txt_to_topomesh (f, method = "set") :
    """
    retrieve the topomesh structure from txt stream
    returns topomesh,description
    """
    #create topomesh
    line = ""
    while "BEGIN topomesh" not in line :
        line = f.readline()
    deg = int(line.split(" ")[3])
    mesh = Topomesh(deg,method)
    #read description
    descr = read_description(f)
    
    #read properties
    props = [[] for i in xrange(mesh.degree() + 1)]
    line = ""
    while "BEGIN properties description" not in line :
        line = f.readline()
    line = f.readline()
    while "END properties description" not in line :
        gr = line[:-1].split("\t")
        prop_deg = int(gr[0][3:])
        for prop_descr in gr[1:] :
            name,prop = prop_descr.split("(")
            typ,unit = prop[:-1].split(",")
            props[prop_deg].append( (name,DataProp(type = typ,unit = unit) ) )
        
        line = f.readline()

    #wisps
    for i in xrange(mesh.degree() + 1) :
        line = ""
        while "BEGIN wisp" not in line :
            line = f.readline()
        deg = int(line.split(" ")[3])
        line = f.readline().rstrip()
        while "END wisp" not in line :
            gr = line.split()
            wid = int(gr[1])
            mesh.add_wisp(deg,wid)
            #props
            for ind,val in enumerate(gr[2:]) :
                if props[deg][ind][1].type() == 'str' :
                    props[deg][ind][1][wid] = val
                else :
                    props[deg][ind][1][wid] = eval("%s(%s)" % (props[deg][ind][1].type(),val) )
            line = f.readline().rstrip()

    #links
    line = ""
    while "BEGIN decomposition" not in line :
        line = f.readline()
    line = f.readline()
    while "END decomposition" not in line :
        gr = line.split(" ")
        mesh.link(int(gr[2]),int(gr[4]),int(gr[6]))
        line = f.readline()

    #return
    return mesh,descr,props