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)]
Exemple #2
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
Exemple #3
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