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 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 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