Source code for cellcomplex.property_topomesh.composition

import numpy as np

from cellcomplex.property_topomesh import PropertyTopomesh
from cellcomplex.property_topomesh.creation import triangle_topomesh, poly_topomesh
# from cellcomplex.property_topomesh.extraction import clean_topomesh_properties
from cellcomplex.property_topomesh.analysis import compute_topomesh_property

# from cellcomplex.property_topomesh.utils.matching_tools import kd_tree_match as match
# from cellcomplex.property_topomesh.utils.matching_tools import vector_quantization_match as match

from cellcomplex.utils import array_dict

from copy import deepcopy
from time import time as current_time

[docs]def match(obs, codebook): from scipy.cluster.vq import vq return vq(obs,codebook)[0]
[docs]def clean_topomesh_properties(topomesh): for degree in range(topomesh.degree()+1): for property_name in topomesh.wisp_property_names(degree): if np.all([w in topomesh.wisp_property(property_name,degree).keys() for w in topomesh.wisps(degree)]): topomesh.update_wisp_property(property_name,degree,dict(list(zip(list(topomesh.wisps(degree)),topomesh.wisp_property(property_name,degree).values(list(topomesh.wisps(degree)))))))
[docs]def concatenate_topomesh(topomesh_list): if len(topomesh_list)>0: topomesh = deepcopy(topomesh_list[0]) for topomesh_to_append in topomesh_list[1:]: append_topomesh(topomesh,topomesh_to_append) else: topomesh = PropertyTopomesh(3) return topomesh
[docs]def append_topomesh(input_topomesh, topomesh_to_append, copy=False, properties_to_append=None): if copy: start_time = current_time() topomesh = deepcopy(input_topomesh) print(" --> Copying input mesh [",current_time()-start_time,"s]") else: topomesh = input_topomesh if properties_to_append is None: properties_to_append = dict([(degree,list(topomesh.wisp_property_names(degree))) for degree in range(4)]) if not 'barycenter' in properties_to_append[0]: properties_to_append[0] += ['barycenter'] start_time = current_time() wisp_dict = {} for degree in range(4): wisp_dict[degree] = {} for w in topomesh_to_append.wisps(degree): new_w = topomesh.add_wisp(degree) wisp_dict[degree][w] = new_w if degree>0: for b in topomesh_to_append.borders(degree,w): topomesh.link(degree,wisp_dict[degree][w],wisp_dict[degree-1][b]) print(" --> Appending mesh elements [",current_time()-start_time,"s]") start_time = current_time() for degree in range(4): for p in properties_to_append[degree]: property_dict = topomesh.wisp_property(p,degree) if topomesh.has_wisp_property(p,degree) and topomesh_to_append.has_wisp_property(p,degree,is_computed=True): property_to_append = topomesh_to_append.wisp_property(p,degree) # new_property_to_append = dict(zip([wisp_dict[degree][w] for w in topomesh_to_append.wisps(degree)],[property_to_append[w] for w in topomesh_to_append.wisps(degree)])) # new_property = property_dict.to_dict() # new_property.update(new_property_to_append) new_property = dict(list(zip(list(property_dict.keys())+[wisp_dict[degree][w] for w in topomesh_to_append.wisps(degree)],list(property_dict.values())+[property_to_append[w] for w in topomesh_to_append.wisps(degree)]))) topomesh.update_wisp_property(p,degree,new_property) # for w in topomesh_to_append.wisps(degree): # print w," (",wisp_dict[degree][w]," ) :",property_to_append[w] # property_dict[wisp_dict[degree][w]] = property_to_append[w] else: raise KeyError("Property"+p+" not computed on elements of degree "+str(degree)+"!") print(" --> Appending mesh properties [",current_time()-start_time,"s]") return topomesh, wisp_dict
[docs]def merge_topomesh_vertices(topomesh, vertex_to_keep, vertex_to_merge, verbose=False): if verbose: print("--> Merging vertex ",vertex_to_merge," ->",vertex_to_keep) for e in topomesh.regions(0,vertex_to_merge): if not vertex_to_keep in topomesh.borders(1,e): topomesh.unlink(1,e,vertex_to_merge) topomesh.link(1,e,vertex_to_keep) else: topomesh.remove_wisp(1,e) topomesh.wisp_property('barycenter',0)[vertex_to_keep] = topomesh.wisp_property('barycenter',0).values([vertex_to_keep, vertex_to_merge]).mean(axis=0) topomesh.remove_wisp(0,vertex_to_merge)
[docs]def merge_topomesh_edges(topomesh, edge_to_keep, edge_to_merge, verbose=False): if verbose: print("--> Merging edge ",edge_to_merge," ->",edge_to_keep) vertices_to_keep = list(topomesh.borders(1,edge_to_keep)) vertices_to_merge = list(topomesh.borders(1,edge_to_merge)) if topomesh.has_wisp_property('barycenter',0): # TODO # Reorder edge vertices to match vertex positions if np.any(topomesh.wisp_property('barycenter',0)[vertices_to_keep[0]] != topomesh.wisp_property('barycenter',0)[vertices_to_merge[0]]): vertices_to_merge = vertices_to_merge[::-1] for vertex_to_keep, vertex_to_merge in zip(vertices_to_keep,vertices_to_merge): if vertex_to_keep != vertex_to_merge: merge_topomesh_vertices(topomesh,vertex_to_keep,vertex_to_merge) for f in topomesh.regions(1,edge_to_merge): topomesh.unlink(2,f,edge_to_merge) topomesh.link(2,f,edge_to_keep) topomesh.remove_wisp(1,edge_to_merge)
[docs]def merge_topomesh_faces(topomesh, face_to_keep, face_to_merge, verbose=False): if verbose: print("--> Merging face ",face_to_merge," ->",face_to_keep) edges_to_keep = list(topomesh.borders(2,face_to_keep)) vertices_to_keep = np.unique(list(topomesh.borders(2,face_to_keep,2))) edges_to_merge = list(topomesh.borders(2,face_to_merge)) vertices_to_merge = np.unique(list(topomesh.borders(2,face_to_merge,2))) oriented_edges_to_keep = [edges_to_keep[0]] remaining_edges_to_keep = set(edges_to_keep).difference(set(oriented_edges_to_keep)) oriented_vertices_to_keep = [list(topomesh.borders(1,edges_to_keep[0]))[0]] remaining_vertices_to_keep = set(vertices_to_keep) while len(remaining_edges_to_keep)>0: current_edge = oriented_edges_to_keep[-1] previous_vertex, current_vertex = topomesh.borders(1,current_edge) if current_vertex in oriented_vertices_to_keep: current_vertex, previous_vertex = topomesh.borders(1,current_edge) next_vertex = list(set(topomesh.region_neighbors(0,current_vertex)).difference(set([previous_vertex])).intersection(remaining_vertices_to_keep))[0] next_edge = list(set(remaining_edges_to_keep).intersection(set(topomesh.regions(0,next_vertex))).intersection(set(topomesh.regions(0,current_vertex))))[0] oriented_edges_to_keep += [next_edge] remaining_edges_to_keep -= set([next_edge]) oriented_vertices_to_keep += [current_vertex] remaining_vertices_to_keep -= set([current_vertex]) oriented_edges_to_merge = [edges_to_merge[0]] remaining_edges_to_merge = set(edges_to_merge).difference(set(oriented_edges_to_merge)) oriented_vertices_to_merge = [list(topomesh.borders(1,edges_to_merge[0]))[0]] remaining_vertices_to_merge = set(vertices_to_merge) while len(remaining_edges_to_merge)>0: current_edge = oriented_edges_to_merge[-1] previous_vertex, current_vertex = topomesh.borders(1,current_edge) if current_vertex in oriented_vertices_to_merge: current_vertex, previous_vertex = topomesh.borders(1,current_edge) next_vertex = list(set(topomesh.region_neighbors(0,current_vertex)).difference(set([previous_vertex])).intersection(remaining_vertices_to_merge))[0] next_edge = list(set(remaining_edges_to_merge).intersection(set(topomesh.regions(0,next_vertex))).intersection(set(topomesh.regions(0,current_vertex))))[0] oriented_edges_to_merge += [next_edge] remaining_edges_to_merge -= set([next_edge]) oriented_vertices_to_merge += [current_vertex] remaining_vertices_to_merge -= set([current_vertex]) # print oriented_vertices_to_merge," -> ",oriented_vertices_to_keep # print oriented_edges_to_merge," -> ",oriented_edges_to_keep if topomesh.has_wisp_property('barycenter',0): # TODO # Reorder face edges to match vertex positions (need reordering edges first?) oriented_vertex_matching = match(topomesh.wisp_property('barycenter',0).values(oriented_vertices_to_keep),topomesh.wisp_property('barycenter',0).values(oriented_vertices_to_merge)) # print oriented_vertex_matching oriented_edge_vertices_to_keep = np.sort([list(topomesh.borders(1,e)) for e in oriented_edges_to_keep]) oriented_edge_vertices_to_merge = np.sort(np.transpose([oriented_vertices_to_merge,list(oriented_vertices_to_merge[1:])+[oriented_vertices_to_merge[0]]])) # print oriented_edge_vertices_to_merge," -> ",oriented_edge_vertices_to_keep oriented_edge_matching = match(oriented_edge_vertices_to_keep,oriented_edge_vertices_to_merge) # print oriented_edge_matching oriented_vertices_to_merge = np.array(oriented_vertices_to_merge)[oriented_vertex_matching] oriented_edges_to_merge = np.array(oriented_edges_to_merge)[oriented_edge_matching] # print oriented_vertices_to_merge," -> ",oriented_vertices_to_keep # print oriented_edges_to_merge," -> ",oriented_edges_to_keep for edge_to_keep, edge_to_merge in zip(oriented_edges_to_keep,oriented_edges_to_merge): # for edge_to_keep, edge_to_merge in zip(edges_to_keep,edges_to_merge): if edge_to_keep != edge_to_merge: merge_topomesh_edges(topomesh,edge_to_keep,edge_to_merge) for c in topomesh.regions(2,face_to_merge): topomesh.unlink(3,c,face_to_merge) topomesh.link(3,c,face_to_keep) topomesh.remove_wisp(2,face_to_merge)
[docs]def fuse_vertices(topomesh, vertex_to_fuse): for vertex_to_keep, vertices_to_fuse in vertex_to_fuse.items(): for vertex_to_merge in [v for v in vertices_to_fuse if v != vertex_to_keep]: merge_topomesh_vertices(topomesh,vertex_to_keep,vertex_to_merge) edge_vertices = np.sort([list(topomesh.borders(1,e)) for e in topomesh.wisps(1)]) edge_matching = np.array(list(topomesh.wisps(1)))[match(edge_vertices,edge_vertices)] edge_to_fuse = {} for e in np.unique(edge_matching): edge_to_fuse[e] = np.array(list(topomesh.wisps(1)))[edge_matching==e] for edge_to_keep, edges_to_fuse in edge_to_fuse.items(): for edge_to_merge in [e for e in edges_to_fuse if e != edge_to_keep]: merge_topomesh_edges(topomesh,edge_to_keep,edge_to_merge) face_vertices = np.array([np.sort(list(topomesh.borders(2,f,2))) for f in topomesh.wisps(2)]) if face_vertices.ndim == 2: face_matching = np.array(list(topomesh.wisps(2)))[match(face_vertices,face_vertices)] face_to_fuse = {} for f in np.unique(face_matching): face_to_fuse[f] = np.array(list(topomesh.wisps(2)))[face_matching==f] for face_to_keep, faces_to_fuse in face_to_fuse.items(): for face_to_merge in [f for f in faces_to_fuse if f != face_to_keep]: merge_topomesh_faces(topomesh,face_to_keep,face_to_merge) else: face_lengths = np.unique(list(map(len,face_vertices))) for l in face_lengths: length_face_vertices = np.array([f_v for f_v in face_vertices if len(f_v) == l]) length_faces = np.array([f for (f,f_v) in zip(topomesh.wisps(2),face_vertices) if len(f_v) == l]) # print length_face_vertices.shape, len(length_faces) face_matching = length_faces[match(length_face_vertices,length_face_vertices)] face_to_fuse = {} for f in np.unique(face_matching): face_to_fuse[f] = length_faces[face_matching==f] for face_to_keep, faces_to_fuse in face_to_fuse.items(): for face_to_merge in [f for f in faces_to_fuse if f != face_to_keep]: merge_topomesh_faces(topomesh,face_to_keep,face_to_merge) face_vertices = np.array([np.sort(list(topomesh.borders(2,f,2))) for f in topomesh.wisps(2)]) clean_topomesh_properties(topomesh)
[docs]def fuse_close_vertices(topomesh, tolerance=1e-5): vertices = np.sort(list(topomesh.wisps(0))) points = topomesh.wisp_property('barycenter', 0).values(vertices) vertex_distances = np.linalg.norm(points[:, np.newaxis] - points[np.newaxis], axis=2) vertex_to_fuse = {} for v, dist in zip(vertices, vertex_distances): vertex_to_fuse[v] = np.array(list(topomesh.wisps(0)))[dist < tolerance] vertex_to_fuse[v] = vertex_to_fuse[v][vertex_to_fuse[v] != v] for v in vertices: for v_f in vertex_to_fuse[v]: vertex_to_fuse[v] = np.array(list(set(list(vertex_to_fuse[v]) + list(vertex_to_fuse[v_f])).difference({v}))) for v in vertices: if v in vertex_to_fuse.keys(): if len(vertex_to_fuse[v]) == 0: del vertex_to_fuse[v] else: for v_f in vertex_to_fuse[v]: if v_f in vertex_to_fuse.keys(): del vertex_to_fuse[v_f] if len(vertex_to_fuse) > 0: print(vertex_to_fuse) return fuse_vertices(topomesh, vertex_to_fuse)
[docs]def fuse_topomesh_identical_vertices(topomesh): positions = topomesh.wisp_property('barycenter',0) points = np.round(positions.values(list(topomesh.wisps(0))).astype(np.float),5) vertex_matching = np.array(list(topomesh.wisps(0)))[match(points,points)] vertex_to_fuse = {} for v in np.unique(vertex_matching): vertex_to_fuse[v] = np.array(list(topomesh.wisps(0)))[vertex_matching==v] # print v," -> ",vertex_to_fuse[v]," (",positions.values(vertex_to_fuse[v]),")" return fuse_vertices(topomesh,vertex_to_fuse)
[docs]def fuse_topomesh_cells(topomesh, cell_to_keep, cell_to_merge): faces_to_keep = list(topomesh.borders(3,cell_to_keep)) faces_to_merge = list(topomesh.borders(3,cell_to_merge)) for face_to_keep, face_to_merge in zip(faces_to_keep, faces_to_merge): topomesh.unlink(3,cell_to_merge,face_to_merge) topomesh.link(3,cell_to_keep,face_to_merge) topomesh.remove_wisp(3,cell_to_merge)