def __init__(self, degree=3, topomesh=None, **kwds):
        self._successors = [IdDict(idgenerator = "set") for i in xrange(degree+1)]
        self._predecessors = [IdDict(idgenerator = "set") for i in xrange(degree+1)]

        PropertyTopomesh.__init__(self, degree, topomesh, **kwds)
        if topomesh is not None:
            for d in xrange(degree+1):
                for w in self.wisps(d):
                    self._successors[d][w] = array("L")
                    self._predecessors[d][w] = array("L")
def vertex_topomesh(positions, **kwargs):
    
    positions = array_dict(positions)

    start_time = time()
    print "--> Generating vertex topomesh"

    vertex_topomesh = PropertyTopomesh(3)
    for c in positions.keys():
        vertex_topomesh.add_wisp(0,c)
    vertex_topomesh.update_wisp_property('barycenter',0,positions.values(positions.keys()),keys=positions.keys())    

    end_time = time()
    print "<-- Generating vertex topomesh [",end_time-start_time,"s]"

    return vertex_topomesh
def edge_topomesh(edges, positions, **kwargs):

    positions = array_dict(positions)

    start_time = time()
    print "--> Generating edge topomesh"

    edge_topomesh = PropertyTopomesh(3)
    for c in np.unique(edges):
        edge_topomesh.add_wisp(0,c)
    for e in edges:
        eid = edge_topomesh.add_wisp(1)
        for pid in e:
            edge_topomesh.link(1,eid,pid)
    edge_topomesh.update_wisp_property('barycenter',0,positions.values(np.unique(edges)),keys=np.unique(edges))    

    end_time = time()
    print "<-- Generating edge topomesh [",end_time-start_time,"s]"

    return edge_topomesh
예제 #4
0
def layer_triangle_topomesh_construction(layer_edge_topomesh, positions, omega_criteria = {'distance':1.0,'wall_surface':2.0,'clique':10.0}, **kwargs):

    compute_topomesh_property(layer_edge_topomesh,'length',1)

    edge_weights = np.zeros(layer_edge_topomesh.nb_wisps(1))
    if omega_criteria.has_key('distance'):
        edge_weights += omega_criteria['distance']*np.exp(-np.power(layer_edge_topomesh.wisp_property('length',1).values()/15.0,1))
    
    if omega_criteria.has_key('wall_surface'):
        img_wall_surfaces = kwargs.get('wall_surfaces',None)
        img_volumes = kwargs.get('cell_volumes',dict(zip(positions.keys(),np.ones_like(positions.keys()))))
        assert layer_edge_topomesh.has_wisp_property('wall_surface',1) or img_wall_surfaces is not None
        if not layer_edge_topomesh.has_wisp_property('wall_surface',1):
            layer_edge_vertices = np.sort([list(layer_edge_topomesh.borders(1,e)) for e in layer_edge_topomesh.wisps(1)])
            layer_edge_wall_surface = np.array([img_wall_surfaces[tuple(e)]/np.power(img_volumes.values(e).mean(),2./3.) for e in layer_edge_vertices])
            layer_edge_topomesh.update_wisp_property('wall_surface',1,array_dict(layer_edge_wall_surface,list(layer_edge_topomesh.wisps(1))))
        
        edge_weights += omega_criteria['wall_surface']*layer_edge_topomesh.wisp_property('wall_surface',1).values() 
    
    edge_weights = array_dict(edge_weights,list(layer_edge_topomesh.wisps(1)))
    
    edge_neighbor_vertices = [np.concatenate([list(set(layer_edge_topomesh.region_neighbors(0,c)))+[c] for c in layer_edge_topomesh.borders(1,e)]) for e in layer_edge_topomesh.wisps(1)]
    edge_neighbor_vertices_edges = [np.concatenate([list(layer_edge_topomesh.regions(0,n_v)) for n_v in n_vertices]) for n_vertices in edge_neighbor_vertices]
    edge_triangle_edges = [np.unique(e)[nd.sum(np.ones_like(e),e,index=np.unique(e))>3] for e in edge_neighbor_vertices_edges]
    
    if omega_criteria.has_key('clique'):
        edge_neighbor_weights = array_dict([edge_weights.values(e).min() - omega_criteria['clique']*(len(e)>3) for e in edge_triangle_edges],list(layer_edge_topomesh.wisps(1)))
    else:
        edge_neighbor_weights = array_dict([edge_weights.values(e).min() for e in edge_triangle_edges],list(layer_edge_topomesh.wisps(1)))
    edge_triangle_edges = array_dict(edge_triangle_edges,list(layer_edge_topomesh.wisps(1)))
    
    triangulation_edges = np.array(list(layer_edge_topomesh.wisps(1)))[np.array(map(len,edge_triangle_edges))>=3]
    
    layer_triangulation_topomesh = PropertyTopomesh(3)
    layer_triangulation_topomesh.add_wisp(3,1)
    
    initial_edge = np.array(list(layer_edge_topomesh.wisps(1)))[triangulation_edges][np.argmax(edge_neighbor_weights.values(triangulation_edges))]
    free_edges = [initial_edge]
        
    while len(free_edges) > 0:
        eid_to_add = free_edges.pop(0)
        print "--> Edge",list(layer_edge_topomesh.borders(1,eid_to_add))," : ",edge_neighbor_weights[eid_to_add]
        
        edge_vertex_edges = np.concatenate([list(set(layer_edge_topomesh.regions(0,c)).difference({eid_to_add})) for c in layer_edge_topomesh.borders(1,eid_to_add)])
        edge_vertex_edge_vertices =  np.concatenate([c*np.ones(layer_edge_topomesh.nb_regions(0,c)-1) for c in layer_edge_topomesh.borders(1,eid_to_add)])
        edge_vertex_edge_neighbor_vertices = np.array([list(set(layer_edge_topomesh.borders(1,e)).difference({v}))[0] for e,v in zip(edge_vertex_edges,edge_vertex_edge_vertices)])
    
        candidate_triangle_vertices = np.unique(edge_vertex_edge_neighbor_vertices)[nd.sum(np.ones_like(edge_vertex_edge_neighbor_vertices),edge_vertex_edge_neighbor_vertices,index=np.unique(edge_vertex_edge_neighbor_vertices))==2]
        candidate_triangle_edges = np.array([np.concatenate([[eid_to_add],edge_vertex_edges[edge_vertex_edge_neighbor_vertices==c]]) for c in candidate_triangle_vertices])
        
        if len(candidate_triangle_edges)>0:
            candidate_triangle_free_edges = np.array([np.sum([e in free_edges for e in triangle_edges]) for triangle_edges in candidate_triangle_edges])
            candidate_triangle_edge_weights = edge_weights.values(candidate_triangle_edges[:,1:]).min(axis=1)
            
            if (candidate_triangle_free_edges ==candidate_triangle_free_edges.max()).sum() == 1:
                sorted_candidate_triangle_edges = candidate_triangle_edges[np.argsort(-candidate_triangle_free_edges)]
            else:
                sorted_candidate_triangle_edges = candidate_triangle_edges[np.argsort(-candidate_triangle_edge_weights)]
            
            for triangle_edges in sorted_candidate_triangle_edges:
                if np.all(np.array([0 if not layer_triangulation_topomesh.has_wisp(1,e) else layer_triangulation_topomesh.nb_regions(1,e) for e in triangle_edges])<2):
                    triangle_vertices = np.unique([list(layer_edge_topomesh.borders(1,e)) for e in triangle_edges])
                    if layer_triangulation_topomesh.nb_wisps(2)!=1 or vq(np.sort([triangle_vertices]),np.sort([list(layer_triangulation_topomesh.borders(2,t,2)) for t in layer_triangulation_topomesh.wisps(2)]))[1][0]>0:
                        fid = layer_triangulation_topomesh.add_wisp(2)
                        layer_triangulation_topomesh.link(3,1,fid)
                        print "  --> Triangle",fid,triangle_vertices," : ",edge_weights.values(triangle_edges[1:]).min()
                        for c in triangle_vertices:
                            if not layer_triangulation_topomesh.has_wisp(0,c):
                                layer_triangulation_topomesh.add_wisp(0,c)
                        for e in triangle_edges:
                            if not layer_triangulation_topomesh.has_wisp(1,e):
                                layer_triangulation_topomesh.add_wisp(1,e)
                                for c in layer_edge_topomesh.borders(1,e):
                                    layer_triangulation_topomesh.link(1,e,c)
                            layer_triangulation_topomesh.link(2,fid,e)
                        
                            if layer_triangulation_topomesh.nb_regions(1,e)<2:
                                if not e in free_edges:
                                    free_edges.append(e)
                                edge_future_triangle_edges = list(set(edge_triangle_edges[e]).difference(set(layer_triangulation_topomesh.wisps(1)).difference(set(free_edges))))
                                
                                if omega_criteria.has_key('clique'):
                                    edge_neighbor_weights[e] = np.min(edge_weights.values(edge_future_triangle_edges)) - omega_criteria['clique']*(len(edge_future_triangle_edges)>3)
                                else:
                                    edge_neighbor_weights[e] = np.min(edge_weights.values(edge_future_triangle_edges))
            
            print free_edges
            if len(free_edges)>0:
                free_edges = list(np.array(free_edges)[np.argsort(-edge_neighbor_weights.values(free_edges))])                    
        layer_triangulation_topomesh.update_wisp_property('barycenter',0,array_dict(positions.values(list(layer_triangulation_topomesh.wisps(0))),list(layer_triangulation_topomesh.wisps(0))))
    return layer_triangulation_topomesh
예제 #5
0
def layered_tetrahedra_topomesh_construction(layer_triangle_topomesh, positions, cell_layer, omega_criteria = {'distance':1.0,'wall_surface':2.0,'clique':10.0}, **kwargs):
    compute_topomesh_property(layer_triangle_topomesh,'length',1)
    compute_topomesh_property(layer_triangle_topomesh,'borders',2)
    compute_topomesh_property(layer_triangle_topomesh,'perimeter',2)
    
    if omega_criteria.has_key('wall_surface'):
        img_wall_surfaces = kwargs.get('wall_surfaces',None)
        img_volumes = kwargs.get('cell_volumes',dict(zip(positions.keys(),np.ones_like(positions.keys()))))
        assert layer_triangle_topomesh.has_wisp_property('wall_surface',1) or img_wall_surfaces is not None
        if not layer_triangle_topomesh.has_wisp_property('wall_surface',1):
            L1_L2_triangle_edge_vertices = np.array([np.sort([list(layer_triangle_topomesh.borders(1,e)) for e in layer_triangle_topomesh.borders(2,t)]) for t in layer_triangle_topomesh.wisps(2)])
            L1_L2_triangle_edge_wall_surface = np.array([[-1. if tuple(e) not in img_wall_surfaces.keys() else img_wall_surfaces[tuple(e)]/np.power(img_volumes.values(e).mean(),2./3.) for e in t] for t in L1_L2_triangle_edge_vertices])
            layer_triangle_topomesh.update_wisp_property('wall_surface',2,array_dict(L1_L2_triangle_edge_wall_surface.min(axis=1),list(layer_triangle_topomesh.wisps(2))))
            layer_triangle_topomesh = layer_triangle_topomesh

    triangle_weights = np.zeros(layer_triangle_topomesh.nb_wisps(2))
    if omega_criteria.has_key('distance'):
        triangle_weights += omega_criteria['distance']*np.exp(-np.power(layer_triangle_topomesh.wisp_property('length',1).values(layer_triangle_topomesh.wisp_property('borders',2).values()).max(axis=1)/15.0,1))
    if omega_criteria.has_key('wall_surface'):
        triangle_weights += omega_criteria['wall_surface']*layer_triangle_topomesh.wisp_property('wall_surface',2).values() 
    triangle_weights = array_dict(triangle_weights,list(layer_triangle_topomesh.wisps(2)))
        
    triangle_neighbor_edges = [np.concatenate([list(set(layer_triangle_topomesh.region_neighbors(1,e)))+[e] for e in layer_triangle_topomesh.borders(2,t)]) for t in layer_triangle_topomesh.wisps(2)]
    triangle_neighbor_edge_triangles = [np.concatenate([list(layer_triangle_topomesh.regions(1,n_e)) for n_e in n_edges]) for n_edges in triangle_neighbor_edges]
    triangle_tetrahedra_triangles = [np.unique(t)[nd.sum(np.ones_like(t),t,index=np.unique(t))>5] for t in triangle_neighbor_edge_triangles]

    if omega_criteria.has_key('clique'):
        triangle_neighbor_weights = array_dict([triangle_weights.values(t).min() - omega_criteria['clique']*(len(t)-4) for t in triangle_tetrahedra_triangles],list(layer_triangle_topomesh.wisps(2)))
    else:
        triangle_neighbor_weights = array_dict([triangle_weights.values(t).min() for t in triangle_tetrahedra_triangles],list(layer_triangle_topomesh.wisps(2)))
    triangle_tetrahedra_triangles = array_dict(triangle_tetrahedra_triangles,list(layer_triangle_topomesh.wisps(2)))

    tetrahedrization_triangles = np.array(list(layer_triangle_topomesh.wisps(2)))[np.array(map(len,triangle_tetrahedra_triangles))>=4]
        
    constructed_triangulation_topomesh = PropertyTopomesh(3)
    initial_triangle = np.array(list(layer_triangle_topomesh.wisps(2)))[tetrahedrization_triangles][np.argmax(triangle_neighbor_weights.values(tetrahedrization_triangles))]
    free_triangles = [initial_triangle]

    while len(free_triangles) > 0:
        fid_to_add = free_triangles.pop(0)
        print "--> Triangle",list(layer_triangle_topomesh.borders(2,fid_to_add))," : ",triangle_neighbor_weights[fid_to_add]
        
        triangle_vertex_edges = np.concatenate([list(set(layer_triangle_topomesh.regions(0,c)).difference(set(layer_triangle_topomesh.borders(2,fid_to_add)))) for c in layer_triangle_topomesh.borders(2,fid_to_add,2)])
        triangle_vertex_edge_vertices = np.concatenate([c*np.ones(layer_triangle_topomesh.nb_regions(0,c)-2) for c in layer_triangle_topomesh.borders(2,fid_to_add,2)])
        triangle_vertex_edge_neighbor_vertices = np.array([list(set(layer_triangle_topomesh.borders(1,e)).difference({v}))[0] for e,v in zip(triangle_vertex_edges,triangle_vertex_edge_vertices)])

        candidate_tetra_vertices = np.unique(triangle_vertex_edge_neighbor_vertices)[nd.sum(np.ones_like(triangle_vertex_edge_neighbor_vertices),triangle_vertex_edge_neighbor_vertices,index=np.unique(triangle_vertex_edge_neighbor_vertices))==3]
        candidate_tetra_edges = np.array([triangle_vertex_edges[triangle_vertex_edge_neighbor_vertices==c] for c in candidate_tetra_vertices])
        
        candidate_tetra_edge_triangles = [np.concatenate([list(set(layer_triangle_topomesh.regions(1,e)).difference({fid_to_add})) for e in candidate_edges]) for candidate_edges in candidate_tetra_edges]
        candidate_tetra_triangles = np.array([np.concatenate([[fid_to_add],np.unique(t)[nd.sum(np.ones_like(t),t,index=np.unique(t))==2]]) for t in candidate_tetra_edge_triangles])
        
        if len(candidate_tetra_triangles)>0:
            candidate_tetra_free_triangles = np.array([np.sum([t in free_triangles for t in tetra_triangles]) for tetra_triangles in candidate_tetra_triangles])
            candidate_tetra_triangle_weights = triangle_weights.values(candidate_tetra_triangles[:,1:]).min(axis=1)
            
            if (candidate_tetra_free_triangles == candidate_tetra_free_triangles.max()).sum() == 1:
                sorted_candidate_tetra_triangles = candidate_tetra_triangles[np.argsort(-candidate_tetra_free_triangles)]
            else:
                sorted_candidate_tetra_triangles = candidate_tetra_triangles[np.argsort(-candidate_tetra_triangle_weights)]
            
            for tetra_triangles in sorted_candidate_tetra_triangles:
                if np.all(np.array([0 if not constructed_triangulation_topomesh.has_wisp(2,t) else constructed_triangulation_topomesh.nb_regions(2,t) for t in tetra_triangles])<2):
                    tetra_vertices = np.unique([list(layer_triangle_topomesh.borders(2,t,2)) for t in tetra_triangles])
                    tetra_edges = np.unique([list(layer_triangle_topomesh.borders(2,t)) for t in tetra_triangles])
                    if constructed_triangulation_topomesh.nb_wisps(3)!=1 or vq(np.sort([tetra_vertices]),np.sort([list(constructed_triangulation_topomesh.borders(3,t,3)) for t in constructed_triangulation_topomesh.wisps(3)]))[1][0]>0:
                        if len(np.unique(cell_layer.values(tetra_vertices)))==2:
                            #tetra_triangle_tetras = np.unique([list(constructed_triangulation_topomesh.regions(2,t)) for t in tetra_triangles if constructed_triangulation_topomesh.has_wisp(2,t)])
                            tetra_triangle_tetras = np.array(list(constructed_triangulation_topomesh.wisps(3)))
                            if len(tetra_triangle_tetras)>0:
                                tetra_triangle_tetra_edges = np.unique([list(constructed_triangulation_topomesh.borders(3,t,2)) for t in tetra_triangle_tetras])
                                tetra_triangle_points = positions.values(np.array([list(layer_triangle_topomesh.borders(2,t,2)) for t in tetra_triangles]))
                                tetra_triangle_tetra_edge_points = positions.values(np.array([list(layer_triangle_topomesh.borders(1,e)) for e in tetra_triangle_tetra_edges]))
                                tetra_triangle_intersection = np.ravel([intersecting_triangle(edge_points,tetra_triangle_points) for edge_points in tetra_triangle_tetra_edge_points])
                            
                                tetra_triangle_edges = np.unique([list(layer_triangle_topomesh.borders(2,t)) for t in tetra_triangles])
                                tetra_triangle_tetra_triangles = np.unique([list(constructed_triangulation_topomesh.borders(3,t)) for t in tetra_triangle_tetras])
                                tetra_triangle_edge_points = positions.values(np.array([list(layer_triangle_topomesh.borders(1,e)) for e in tetra_triangle_edges]))
                                tetra_triangle_tetra_triangle_points = positions.values(np.array([list(layer_triangle_topomesh.borders(2,t,2)) for t in tetra_triangle_tetra_triangles]))
                                tetra_edge_intersection = np.ravel([intersecting_triangle(edge_points,tetra_triangle_tetra_triangle_points) for edge_points in tetra_triangle_edge_points])
                                tetra_triangle_intersection = np.concatenate([tetra_triangle_intersection,tetra_edge_intersection])
                            else:
                                tetra_triangle_intersection = [False]
                            if not np.any(tetra_triangle_intersection):
                                tid = constructed_triangulation_topomesh.add_wisp(3)
                                print "  --> Tetrahedron",tid,tetra_vertices," : ", triangle_weights.values(tetra_triangles[1:]).min()
                                for c in tetra_vertices:
                                    if not constructed_triangulation_topomesh.has_wisp(0,c):
                                        constructed_triangulation_topomesh.add_wisp(0,c)
                                for e in tetra_edges:
                                    if not constructed_triangulation_topomesh.has_wisp(1,e):
                                        constructed_triangulation_topomesh.add_wisp(1,e)
                                        for c in layer_triangle_topomesh.borders(1,e):
                                            constructed_triangulation_topomesh.link(1,e,c)
                                for t in tetra_triangles:
                                    if not constructed_triangulation_topomesh.has_wisp(2,t):
                                        constructed_triangulation_topomesh.add_wisp(2,t)
                                        for e in layer_triangle_topomesh.borders(2,t):
                                            constructed_triangulation_topomesh.link(2,t,e)
                                    constructed_triangulation_topomesh.link(3,tid,t)
                                    
                                    if constructed_triangulation_topomesh.nb_regions(2,t)<2 and len(np.unique(cell_layer.values(list(constructed_triangulation_topomesh.borders(2,t,2)))))==2:
                                        if not t in free_triangles:
                                            free_triangles.append(t)
                                        
                                        triangle_future_tetra_triangles = list(set(triangle_tetrahedra_triangles[t]).difference(set(constructed_triangulation_topomesh.wisps(2)).difference(set(free_triangles))))
                                        
                                        if omega_criteria.has_key('clique'):
                                            triangle_neighbor_weights[t] = np.min(triangle_weights.values(triangle_future_tetra_triangles)) - omega_criteria['clique']*(len(triangle_future_tetra_triangles)-4)
                                        else:
                                            triangle_neighbor_weights[t] = np.min(triangle_weights.values(triangle_future_tetra_triangles))
        
        # print free_triangles
        if len(free_triangles)>0:
            free_triangles = list(np.array(free_triangles)[np.argsort(-triangle_neighbor_weights.values(free_triangles))])
        constructed_triangulation_topomesh.update_wisp_property('barycenter',0,array_dict(positions.values(list(constructed_triangulation_topomesh.wisps(0))),list(constructed_triangulation_topomesh.wisps(0))))

    return constructed_triangulation_topomesh
def save_property_topomesh(topomesh, path, cells_to_save=None, properties_to_save=dict([(0,['barycenter']),(1,[]),(2,[]),(3,[])]),**kwargs):
    if cells_to_save is None:
        cells_to_save = np.array(list(topomesh.wisps(3)))
    triangles_to_save = np.array(np.unique(np.concatenate([np.array(list(topomesh.borders(3,c))) for c in cells_to_save])),int)
    edges_to_save = np.array(np.unique(np.concatenate([np.array(list(topomesh.borders(2,t))) for t in triangles_to_save])),int)
    vertices_to_save = np.array(np.unique(np.concatenate([np.array(list(topomesh.borders(1,e))) for e in edges_to_save])),int)

    original_pids = kwargs.get('original_pids',False)
    original_eids = kwargs.get('original_eids',False)
    original_fids = kwargs.get('original_fids',False)
    original_cids = kwargs.get('original_cids',True)

    sub_topomesh = PropertyTopomesh(3)

    vertices_to_pids = {}
    for v in vertices_to_save:
        if original_pids:
            pid = sub_topomesh.add_wisp(0,v)
        else:
            pid = sub_topomesh.add_wisp(0)
        vertices_to_pids[v] = pid

    edges_to_eids = {}
    for e in edges_to_save:
        if original_eids:
            eid = sub_topomesh.add_wisp(1,e)
        else:
            eid = sub_topomesh.add_wisp(1)
        edges_to_eids[e] = eid
        for v in topomesh.borders(1,e):
            sub_topomesh.link(1,eid,vertices_to_pids[v])

    triangles_to_fids = {}
    for t in triangles_to_save:
        if original_fids:
            fid = sub_topomesh.add_wisp(2,t)
        else:
            fid = sub_topomesh.add_wisp(2)
        triangles_to_fids[t] = fid
        for e in topomesh.borders(2,t):
            sub_topomesh.link(2,fid,edges_to_eids[e])

    cells_to_cids = {}
    for c in cells_to_save:
        if original_cids:
            cid = sub_topomesh.add_wisp(3,c)
        else:
            cid = sub_topomesh.add_wisp(3,c)
        cells_to_cids[c] = cid
        for t in topomesh.borders(3,c):
            sub_topomesh.link(3,cid,triangles_to_fids[t])

    wisps_to_save = {}
    wisps_to_save[0] = vertices_to_save
    wisps_to_save[1] = edges_to_save
    wisps_to_save[2] = triangles_to_save
    wisps_to_save[3] = cells_to_save

    wisps_to_wids = {}
    wisps_to_wids[0] = vertices_to_pids 
    wisps_to_wids[1] = edges_to_eids 
    wisps_to_wids[2] = triangles_to_fids 
    wisps_to_wids[3] = cells_to_cids 

    if not 0 in properties_to_save.keys():
        properties_to_save[0] = []
    if not 'barycenter' in properties_to_save[0]:
        properties_to_save[0].append('barycenter')

    for degree in properties_to_save.keys():
        for property_name in properties_to_save[degree]:
            print "Property ",property_name,'(',degree,')'
            if topomesh.has_wisp_property(property_name,degree=degree,is_computed=True):
                wids_to_save = array_dict(wisps_to_wids[degree]).values(wisps_to_save[degree])
                sub_topomesh.update_wisp_property(property_name,degree,array_dict(topomesh.wisp_property(property_name,degree).values(wisps_to_save[degree]),wids_to_save))

    pickle.dump(sub_topomesh,open(path,"wb"))
                for f in element_properties['volume'][c]['face_index']:
                    face_cells[triangle_matching[f]] = face_cells[triangle_matching[f]].union({cell_matching[c]})
        else:
            for f in xrange(len(unique_triangles)):
                face_cells[triangle_matching[f]] = {0}
    else:
        cell_matching[0] = 0
        for f in xrange(len(unique_triangles)):
            face_cells[triangle_matching[f]] = {0}
    element_matching['volume'] = cell_matching
    if verbose: print len(cell_matching)," Cells"
    if timecheck: print 'cell unicity test:',time()-check_time 


    if timecheck: check_time =time()
    topomesh = PropertyTopomesh(3)

    for pid in xrange(len(unique_points)):
        topomesh.add_wisp(0,pid)
    
    for fid in xrange(len(unique_triangles)):
        topomesh.add_wisp(2,fid)
        for cid in face_cells[fid]:           
            if not topomesh.has_wisp(3, cid):
                topomesh.add_wisp(3,cid)
            topomesh.link(3,cid,fid)

    for eid,e in enumerate(unique_edges):
        topomesh.add_wisp(1,eid)
        for pid in e:
            topomesh.link(1,eid,pid)
def implicit_surface_topomesh(density_field,size,resolution,iso=0.5,center=True):
    import numpy as np
    from scipy.cluster.vq                       import kmeans, vq
    from openalea.container import array_dict, PropertyTopomesh

    surface_points, surface_triangles = vtk_marching_cubes(density_field,iso)

    surface_points = (np.array(surface_points))*(size*resolution/np.array(density_field.shape)) 
    if center:
        surface_points -= np.array(density_field.shape)*resolution/2.

    # points_ids = np.arange(len(surface_points))
    # points_to_delete = []
    # for p,point in enumerate(surface_points):
    #     matching_points = np.sort(np.where(vq(surface_points,np.array([point]))[1] == 0)[0])
    #     if len(matching_points) > 1:
    #         points_to_fuse = matching_points[1:]
    #         for m_p in points_to_fuse:
    #             surface_triangles[np.where(surface_triangles==m_p)] = matching_points[0]
    #             points_to_delete.append(m_p)

    # points_to_delete = np.unique(points_to_delete)
    # print len(points_to_delete),"points deleted"
    # surface_points = np.delete(surface_points,points_to_delete,0)
    # points_ids = np.delete(points_ids,points_to_delete,0)
    # surface_triangles = array_dict(np.arange(len(surface_points)),points_ids).values(surface_triangles)

    # for p,point in enumerate(surface_points):
    #     matching_points = np.where(vq(surface_points,np.array([point]))[1] == 0)[0]
    #     if len(matching_points) > 1:
    #         print p,point
    #         raw_input()

    # triangles_to_delete = []
    # for t,triangle in enumerate(surface_triangles):
    #     if len(np.unique(triangle)) < 3:
    #         triangles_to_delete.append(t)
    #     # elif triangle.max() >= len(surface_points):
    #     #     triangles_to_delete.append(t)
    # surface_triangles = np.delete(surface_triangles,triangles_to_delete,0)

    surface_topomesh = PropertyTopomesh(3)

    for p in surface_points:
        pid = surface_topomesh.add_wisp(0)

    triangle_edge_list  = np.array([[1, 2],[0, 2],[0, 1]])
    surface_edges = np.sort(np.concatenate(surface_triangles[:,triangle_edge_list]))
    _,unique_edges = np.unique(np.ascontiguousarray(surface_edges).view(np.dtype((np.void,surface_edges.dtype.itemsize * surface_edges.shape[1]))),return_index=True)
    surface_edges = surface_edges[unique_edges]

    for e in surface_edges:
        eid = surface_topomesh.add_wisp(1)
        for pid in e:
            surface_topomesh.link(1,eid,pid)

    surface_triangle_edges = np.sort(np.concatenate(surface_triangles[:,triangle_edge_list]))
    surface_triangle_edge_matching = vq(surface_triangle_edges,surface_edges)[0].reshape(surface_triangles.shape[0],3)

    for t in surface_triangles:
        fid = surface_topomesh.add_wisp(2)
        for eid in surface_triangle_edge_matching[fid]:
            surface_topomesh.link(2,fid,eid)

    cid = surface_topomesh.add_wisp(3)
    for fid in surface_topomesh.wisps(2):
        surface_topomesh.link(3,cid,fid)

    surface_topomesh.update_wisp_property('barycenter',0,array_dict(surface_points),keys=list(surface_topomesh.wisps(0)))

    return surface_topomesh
def triangle_topomesh(triangles, positions, **kwargs):

    triangles = np.array(triangles)
    positions = array_dict(positions)

    edges = array_unique(np.sort(np.concatenate(triangles[:,triangle_edge_list],axis=0)))

    triangle_edges = np.sort(np.concatenate(triangles[:,triangle_edge_list]))

    start_time = time()
    print "--> Generating triangle topomesh"

    triangle_edge_matching = vq(triangle_edges,edges)[0]

    triangle_topomesh = PropertyTopomesh(3)
    for c in np.unique(triangles):
        triangle_topomesh.add_wisp(0,c)
    for e in edges:
        eid = triangle_topomesh.add_wisp(1)
        for pid in e:
            triangle_topomesh.link(1,eid,pid)
    for t in triangles:
        fid = triangle_topomesh.add_wisp(2)
        for eid in triangle_edge_matching[3*fid:3*fid+3]:
            triangle_topomesh.link(2,fid,eid)
    triangle_topomesh.add_wisp(3,0)
    for fid in triangle_topomesh.wisps(2):
        triangle_topomesh.link(3,0,fid)
    triangle_topomesh.update_wisp_property('barycenter',0,positions.values(np.unique(triangles)),keys=np.unique(triangles))    

    end_time = time()
    print "<-- Generating triangle topomesh [",end_time-start_time,"s]"

    return triangle_topomesh
def tetrahedra_topomesh(tetrahedra, positions, **kwargs):

    tetrahedra = np.array(tetrahedra)
    positions = array_dict(positions)

    tetrahedra_triangles = array_unique(np.concatenate(np.sort(tetrahedra[:,tetra_triangle_list])))

    tetrahedra_triangle_edges = tetrahedra_triangles[:,triangle_edge_list]
    tetrahedra_triangle_vectors = positions.values(tetrahedra_triangle_edges[...,1]) - positions.values(tetrahedra_triangle_edges[...,0])
    tetrahedra_triangle_lengths = np.linalg.norm(tetrahedra_triangle_vectors,axis=2)
    tetrahedra_triangle_perimeters = tetrahedra_triangle_lengths.sum(axis=1)

    tetrahedra_edges = array_unique(np.concatenate(tetrahedra_triangles[:,triangle_edge_list],axis=0))

    start_time = time()
    print "--> Generating tetrahedra topomesh"
    triangle_edges = np.concatenate(tetrahedra_triangles[:,triangle_edge_list],axis=0)
    triangle_edge_matching = vq(triangle_edges,tetrahedra_edges)[0]

    tetrahedra_faces = np.concatenate(np.sort(tetrahedra[:,tetra_triangle_list]))
    tetrahedra_triangle_matching = vq(tetrahedra_faces,tetrahedra_triangles)[0]

    tetrahedra_topomesh = PropertyTopomesh(3)
    for c in np.unique(tetrahedra_triangles):
        tetrahedra_topomesh.add_wisp(0,c)
    for e in tetrahedra_edges:
        eid = tetrahedra_topomesh.add_wisp(1)
        for pid in e:
            tetrahedra_topomesh.link(1,eid,pid)
    for t in tetrahedra_triangles:
        fid = tetrahedra_topomesh.add_wisp(2)
        for eid in triangle_edge_matching[3*fid:3*fid+3]:
            tetrahedra_topomesh.link(2,fid,eid)
    for t in tetrahedra:
        cid = tetrahedra_topomesh.add_wisp(3)
        for fid in tetrahedra_triangle_matching[4*cid:4*cid+4]:
            tetrahedra_topomesh.link(3,cid,fid)
    tetrahedra_topomesh.update_wisp_property('barycenter',0,positions.values(np.unique(tetrahedra_triangles)),keys=np.unique(tetrahedra_triangles))        

    end_time = time()
    print "<-- Generating tetrahedra topomesh [",end_time-start_time,"s]"

    return tetrahedra_topomesh
def dual_topomesh(topomesh,degree=2,vertex_positions='barycenter'):

    dual_topomesh = PropertyTopomesh(topomesh.degree())
    
    if degree == 2:
        for d in xrange(3):
            if d<2:
                dual_topomesh._regions[d] = deepcopy(topomesh._borders[2-d])
            if d>0:
                dual_topomesh._borders[d] = deepcopy(topomesh._regions[2-d])
        
        dual_topomesh._borders[3] = dict(zip(dual_topomesh._borders[2].keys(),[[w] for w in dual_topomesh._borders[2].keys()]))
        dual_topomesh._regions[2] = dict(zip(dual_topomesh._borders[2].keys(),[[w] for w in dual_topomesh._borders[2].keys()]))
    
        edges_to_remove = [e for e in dual_topomesh.wisps(1) if len(list(dual_topomesh.borders(1,e)))<2]
        faces_to_remove = [f for f in dual_topomesh.wisps(2) if np.any([e in edges_to_remove for e in dual_topomesh.borders(2,f)])]
        cells_to_remove = faces_to_remove
    
    for e in edges_to_remove:
        dual_topomesh.remove_wisp(1,e)
    for f in faces_to_remove:
        dual_topomesh.remove_wisp(2,f)
    for c in cells_to_remove:
        dual_topomesh.remove_wisp(3,c)
    
    if 'voronoi' in vertex_positions:
        assert is_triangular(topomesh)
        if degree==2:
            from openalea.cellcomplex.property_topomesh.utils.geometry_tools import triangle_geometric_features
            compute_topomesh_property(topomesh,'vertices',2)
            triangles = topomesh.wisp_property('vertices',2).values(list(dual_topomesh.wisps(0)))
            positions = topomesh.wisp_property('barycenter',0)
            if vertex_positions == 'projected_voronoi':
                centers = triangle_geometric_features(triangles,positions,features=['projected_circumscribed_circle_center'])[:,0]
            else:
                centers = triangle_geometric_features(triangles,positions,features=['circumscribed_circle_center'])[:,0]
            dual_positions = array_dict(centers,list(dual_topomesh.wisps(0)))
    else:
        compute_topomesh_property(topomesh,'barycenter',degree)
        dual_positions = array_dict(topomesh.wisp_property('barycenter',degree).values(list(dual_topomesh.wisps(0))),list(dual_topomesh.wisps(0)))
    
   
    dual_topomesh.update_wisp_property('barycenter',0,dual_positions)
    
    return dual_topomesh
def poly_topomesh(polys, positions, faces_as_cells=False, **kwargs):
    polys = np.array(polys)
    positions = array_dict(positions)

    poly_lengths = np.array(map(len,polys))
    poly_edge_list = [np.transpose([np.arange(l),(np.arange(l)+1)%l]) for l in poly_lengths]

    edges = array_unique(np.sort(np.concatenate([np.array(p)[l] for p,l in zip(polys,poly_edge_list)],axis=0)))

    poly_edges = np.sort(np.concatenate([np.array(p)[l] for p,l in zip(polys,poly_edge_list)],axis=0))

    start_time = time()
    print "--> Generating poly topomesh"

    poly_edge_matching = vq(poly_edges,edges)[0]

    poly_topomesh = PropertyTopomesh(3)
    for c in np.unique(polys):
        poly_topomesh.add_wisp(0,c)
    for e in edges:
        eid = poly_topomesh.add_wisp(1)
        for pid in e:
            poly_topomesh.link(1,eid,pid)
    total_poly_length = 0
    for q,l in zip(polys,poly_lengths):
        fid = poly_topomesh.add_wisp(2)
        for eid in poly_edge_matching[total_poly_length:total_poly_length+l]:
            poly_topomesh.link(2,fid,eid)
        total_poly_length += l
    if not faces_as_cells:
        poly_topomesh.add_wisp(3,0)
        for fid in poly_topomesh.wisps(2):
            poly_topomesh.link(3,0,fid)
    else:
        for fid in poly_topomesh.wisps(2):
            poly_topomesh.add_wisp(3,fid)
            poly_topomesh.link(3,fid,fid)
    poly_topomesh.update_wisp_property('barycenter',0,positions.values(np.unique(polys)),keys=np.unique(polys))    

    end_time = time()
    print "<-- Generating poly topomesh [",end_time-start_time,"s]"

    return poly_topomesh
def quad_topomesh(quads, positions, faces_as_cells=False, **kwargs):
    quads = np.array(quads)
    positions = array_dict(positions)

    edges = array_unique(np.sort(np.concatenate(quads[:,quad_edge_list],axis=0)))

    quad_edges = np.sort(np.concatenate(quads[:,quad_edge_list]))

    start_time = time()
    print "--> Generating quad topomesh"

    quad_edge_matching = vq(quad_edges,edges)[0]

    quad_topomesh = PropertyTopomesh(3)
    for c in np.unique(quads):
        quad_topomesh.add_wisp(0,c)
    for e in edges:
        eid = quad_topomesh.add_wisp(1)
        for pid in e:
            quad_topomesh.link(1,eid,pid)
    for q in quads:
        fid = quad_topomesh.add_wisp(2)
        for eid in quad_edge_matching[4*fid:4*fid+4]:
            quad_topomesh.link(2,fid,eid)
    if not faces_as_cells:
        quad_topomesh.add_wisp(3,0)
        for fid in quad_topomesh.wisps(2):
            quad_topomesh.link(3,0,fid)
    else:
        for fid in quad_topomesh.wisps(2):
            quad_topomesh.add_wisp(3,fid)
            quad_topomesh.link(3,fid,fid)

    quad_topomesh.update_wisp_property('barycenter',0,positions.values(np.unique(quads)),keys=np.unique(quads))    

    end_time = time()
    print "<-- Generating quad topomesh [",end_time-start_time,"s]"

    return quad_topomesh