def create_edge_indices(positions): n = len(positions) nodes = np.arange(n) simplices = Delaunay(positions).simplices simplices.sort() edges = set() for s in simplices: edges |= set(itertools.combinations(s, 2)) edges = np.array(list(edges)) return edges
def medialaxis(boundary): # Function: medialaxis(boundary) # Description: given sorted boundary points, outputs a matrix medial data: medial points, radii and triangles # Input: bounday - a vector of sorted complex valued boundary points. # Output: medialdata[m r triin] - m is the collection of points on the medial axis, r is the associated radii, and triin is the delaunay triangulation of the boundary corresponding to triangles entirely inside the boundary. if np.dot(np.squeeze(boundary.real - np.roll(boundary.real, -1)), np.squeeze(boundary.imag + np.roll(boundary.imag, -1))) > 0: boundary = np.flipud(boundary) coordinates = [] for i in boundary: coordinates.append([int(i.real), int(i.imag)]) points = np.array(coordinates) tri = Delaunay(points) # ''' plt.triplot(points[:, 0], points[:, 1], tri.simplices) # plt.plot(points.real, points.imag, 'o') # plt.show() # ''' tri = np.array(tri.simplices) tri.sort(axis=1) u = boundary[tri[:, 0]] v = boundary[tri[:, 1]] w = boundary[tri[:, 2]] dot = (u - w) * np.conj(v - w) m = (u + v + 1j * (u - v) * dot.real / dot.imag) / 2 r = abs(u - m) inside = dot.imag > 0 triin = tri[inside, :] m = m[inside] r = r[inside] plt.plot(m.real, m.imag, 'o') plt.show() result = [] result.append(m) result.append(r) result.append(triin) return result
def adjacency(positions, em_indices, edges=None, direction_weight=False, em_weight=100.0, dbscan_weight=0.02, dbscan_eps=10): n = len(positions) nodes = np.arange(n) simplices = Delaunay(positions).simplices simplices.sort() edges = set() for s in simplices: edges |= set(itertools.combinations(s, 2)) edges = np.array(list(edges)) # print('# of edges', len(edges)) # edges = np.vstack(np.triu_indices(n, k=1)).T dists = dist_metric(positions[edges[:, 0]], positions[edges[:, 1]]) weights = dists # print('distance weights', weights) if direction_weight: directions = direction_metric(edges, positions, dists) weights = directions * dists # print('directions', directions) # create adjacency matrix where weights are nonzero # on_edges = np.where(weights != 0) # edges = edges[on_edges] # print('Fraction of edges turned on:', len(edges)/len(weights)) # weights = weights[on_edges] # this is only upper triangular A_upper_half = coo_matrix((weights, (edges[:, 0], edges[:, 1])), shape=(n, n), dtype=weights.dtype).tocsc() A_lower_half = coo_matrix((weights, (edges[:, 1], edges[:, 0])), shape=(n, n), dtype=weights.dtype).tocsc() A = A_upper_half + A_lower_half # add DBSCAN bias # closely attach EM primaries to their DBSCAN cluster, repulse different EM primary clusters clusters = DBSCAN(eps=dbscan_eps, min_samples=2).fit(positions).labels_ primary_clusters = clusters[em_indices] dbscan_indices = [] dbscan_weights = [] for i in range(np.amax(clusters)): same_cluster = np.zeros(n) dbscan_filter = np.where(clusters == i)[0] if i in primary_clusters: # sparsely repulse all other primary clusters for j in primary_clusters: if j != i: db_filter = np.where(clusters == j)[0] sparse_indices = cartesian_product(db_filter, dbscan_filter) # print('sparse_indices', len(sparse_indices)) dbscan_indices.extend(sparse_indices) dbscan_weights.extend( len(sparse_indices) * [-1 * em_weight]) indices = list(itertools.combinations(dbscan_filter, 2)) dbscan_indices.extend(indices) dbscan_weights.extend(len(indices) * [dbscan_weight]) dbscan_indices = np.array(dbscan_indices) dbscan_weights = np.array(dbscan_weights) if len(dbscan_weights) > 0: A += coo_matrix( (dbscan_weights, (dbscan_indices[:, 0], dbscan_indices[:, 1])), shape=(n, n), dtype=weights.dtype).tocsc() A += coo_matrix( (dbscan_weights, (dbscan_indices[:, 1], dbscan_indices[:, 0])), shape=(n, n), dtype=weights.dtype).tocsc() # print('DBSCAN processed') # indices = np.array(list(itertools.combinations(em_indices, 2))) # if len(indices) > 0: # D_vec = np.array(A.sum(axis=1)).flatten() # em_repulsion = -10.0 * np.ones(len(indices)) # A += coo_matrix((em_repulsion, (indices[:, 0], indices[:, 1])), shape=(n, n), dtype=weights.dtype).tocsc() # A += coo_matrix((em_repulsion, (indices[:, 1], indices[:, 0])), shape=(n, n), dtype=weights.dtype).tocsc() D_vec = np.abs(np.array(A.sum(axis=1)).flatten()) D_norm_vec = 1 / np.sqrt(D_vec) D = diags(D_vec) D_norm = diags(D_norm_vec) A_norm = D_norm * A * D_norm # print('A normalized') return A_norm