def __init__(self, degree=3, topomesh=None, **kwds): """todo""" self._wisp_properties = [{} for d in xrange(degree+1)] self._interface_properties = [{} for d in xrange(degree+1)] self._topomesh_properties= {} self._interface = [None] + [IdDict(idgenerator="set") for i in xrange(degree)] Topomesh.__init__(self, degree, **kwds) if topomesh is not None: self.extend(topomesh)
def __init__(self, degree=3, topomesh=None, **kwds): """todo""" self._wisp_properties = [{} for d in xrange(degree+1)] self._interface_properties = [{} for d in xrange(degree+1)] self._topomesh_properties= {} self._interface = [None] + [IdDict(idgenerator="set") for i in xrange(degree)] Topomesh.__init__(self, degree, **kwds) if topomesh is not None: from copy import deepcopy self._borders = deepcopy(topomesh._borders) self._regions = deepcopy(topomesh._regions)
def __init__(self, degree=3, topomesh=None, **kwds): """todo""" self._wisp_properties = [{} for d in xrange(degree + 1)] self._interface_properties = [{} for d in xrange(degree + 1)] self._topomesh_properties = {} self._interface = [None] + [IdDict(idgenerator="set") for i in xrange(degree)] Topomesh.__init__(self, degree, **kwds) if topomesh is not None: from copy import deepcopy self._borders = deepcopy(topomesh._borders) self._regions = deepcopy(topomesh._regions)
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
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
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 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
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)]