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