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)]
Beispiel #3
0
def triangulate (mesh, fid) :
    """Triangulate the given face of a mesh
    
    :Parameters:
     - `mesh` (Mesh)
     - `fid` (did) - id of face to triangulate. Must be of
                     degree 2
    
    :Warning: Modify mesh in place.
    
    :Note: This method does not introduce new points in the
    mesh.
    """
    #store info
    edges = tuple(mesh.borders(fid) )
    if len(edges) == 3 :#face is already a triangle
        return
    
    if len(edges) < 3 :
        raise UserWarning("face is not geometricaly defined")
    
    cells = tuple(mesh.regions(fid) )
    
    #remove face
    mesh.remove_dart(fid)
    
    #walk along edges
    edge_pool = list(edges)
    front_eid = edge_pool.pop()
    ref_pid, front_pid = mesh.borders(front_eid)
    ref_pos = mesh.position(ref_pid)
    
    new_edges = []
    while len(edge_pool) > 2 :#remaining two edges will
                              #naturally form a triangle
        #find next edge
        next_eid, = (eid for eid in edge_pool \
                     if front_pid in mesh.borders(eid) )
        next_pid, = (pid for pid in mesh.borders(next_eid) \
                     if pid != front_pid)
        
        #triangulate, create an edge between ref_pid and
        #next_pid
        new_eid = mesh.add_dart(1)
        mesh.link(new_eid, ref_pid)
        mesh.link(new_eid, next_pid)
        l = norm(mesh.position(next_pid) - ref_pos)
        new_edges.append( (l, new_eid) )
        
        #create new facet
        fid = mesh.add_dart(2)
        for cid in cells :
            mesh.link(cid, fid)
        
        for eid in (front_eid, next_eid, new_eid) :
            mesh.link(fid, eid)
        
        #increment step
        edge_pool.remove(next_eid)
        front_eid = new_eid
        front_pid = next_pid
    
    #create last facet
    fid = mesh.add_dart(2)
    for cid in cells :
        mesh.link(cid, fid)
    
    for eid in edge_pool + [front_eid] :
        mesh.link(fid, eid)
    
    #improve triangulation quality
    new_edges.sort()
    
    for l, eid in new_edges :
        if is_flip_better(mesh, eid) :
            flip_edge(mesh, eid)