How to find all the intersection points between two contour-set in an efficient way

后端 未结 2 1973

I\'m wondering about the best way to find all the intersection points (to roundoff error) between two sets of contour lines. Which is the best method? Here is the example:

<
2条回答
  •  别那么骄傲
    2021-02-02 04:31

    import collections
    import matplotlib.pyplot as plt
    import numpy as np
    import scipy.spatial as spatial
    import scipy.spatial.distance as dist
    import scipy.cluster.hierarchy as hier
    
    
    def intersection(points1, points2, eps):
        tree = spatial.KDTree(points1)
        distances, indices = tree.query(points2, k=1, distance_upper_bound=eps)
        intersection_points = tree.data[indices[np.isfinite(distances)]]
        return intersection_points
    
    
    def cluster(points, cluster_size):
        dists = dist.pdist(points, metric='sqeuclidean')
        linkage_matrix = hier.linkage(dists, 'average')
        groups = hier.fcluster(linkage_matrix, cluster_size, criterion='distance')
        return np.array([points[cluster].mean(axis=0)
                         for cluster in clusterlists(groups)])
    
    
    def contour_points(contour, steps=1):
        return np.row_stack([path.interpolated(steps).vertices
                             for linecol in contour.collections
                             for path in linecol.get_paths()])
    
    
    def clusterlists(T):
        '''
        http://stackoverflow.com/a/2913071/190597 (denis)
        T = [2, 1, 1, 1, 2, 2, 2, 2, 2, 1]
        Returns [[0, 4, 5, 6, 7, 8], [1, 2, 3, 9]]
        '''
        groups = collections.defaultdict(list)
        for i, elt in enumerate(T):
            groups[elt].append(i)
        return sorted(groups.values(), key=len, reverse=True)
    
    # every intersection point must be within eps of a point on the other
    # contour path
    eps = 1.0
    
    # cluster together intersection points so that the original points in each flat
    # cluster have a cophenetic_distance < cluster_size
    cluster_size = 100
    
    x = np.linspace(-1, 1, 500)
    X, Y = np.meshgrid(x, x)
    Z1 = np.abs(np.sin(2 * X ** 2 + Y))
    Z2 = np.abs(np.cos(2 * Y ** 2 + X ** 2))
    contour1 = plt.contour(Z1, colors='k')
    contour2 = plt.contour(Z2, colors='r')
    
    points1 = contour_points(contour1)
    points2 = contour_points(contour2)
    
    intersection_points = intersection(points1, points2, eps)
    intersection_points = cluster(intersection_points, cluster_size)
    plt.scatter(intersection_points[:, 0], intersection_points[:, 1], s=20)
    plt.show()
    

    yields

    enter image description here

提交回复
热议问题