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 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 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
Exemplo n.º 4
0
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
    return cmesh
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
Exemplo n.º 6
0
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
    return True
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
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