Search code examples
pythonalgorithmmatplotlibmathgeometry

How to check if given points form a continuous figure? (Python)


I need to implement a function that takes coordinates of any number of points (in 3D space) and return True if points form a continuous figure. There are three figures below (in 2D space for simplicity). For the first two situations, True must be returned. The last one should return False.

enter image description here

enter image description here

enter image description here

It is assumed that all points in the array are located at the nodes of a square grid, the step of which is taken by the function as the second argument.

The function should look like this:

def is_continuous(points, step): # points is a list of tuples with coordinates
    # if points form a continuous figure:
        return True
    # else:
        return False

Solution

  • IIUC and if you're tempted to use , you can try :

    def as_grid(points):
        import matplotlib.pyplot as plt
        plt.grid(linewidth=4, color="black", zorder=1)
        plt.scatter(*points, color="red", zorder=2, s=300)
        plt.xticks(range(-1, 8)); plt.yticks(range(-1, 8))
        plt.show()
        
    def is_conn(points):
        import networkx as nx
        from libpysal import weights
        ws = weights.KNN.from_array(list(zip(*points)), k=3)
        G = ws.to_networkx().to_undirected()
        return "Connected" if nx.is_connected(G) else "Not connected"
    #https://networkx.org/documentation/stable/auto_examples/geospatial/plot_points
    

    Note : The edges will vary based on the k nearest neighbors. For e.g, the 3rd dataset :

    enter image description here

    If you instead want to consider an x-y step, maybe you can use a DistandBrand :

    def is_conn(points, stepx, stepy):
        import networkx as nx
        from libpysal import weights
        mdis = ((stepx)**2 + (stepy)**2)**0.5
        ws = weights.DistanceBand.from_array(list(zip(*points)), threshold=mdis)
        G = ws.to_networkx().to_undirected()
        return "Connected" if nx.is_connected(G) else "Not connected"
    
    is_conn([x3, y3], 1, 1) #'Not connected'
    is_conn([x3, y3], 2, 2) #'Connected'
    

    enter image description here

    Output :

    for p in [(x1, y1), (x2, y2), (x3, y3)]:
        print(is_conn(p))
        as_grid(p)
    

    enter image description here

    enter image description here

    enter image description here

    Used config :

    x1 = [1, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5]
    y1 = [4, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3]
    
    x2 = [1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5]
    y2 = [2, 3, 4, 5, 6, 2, 3, 5, 6, 2, 6, 2, 3, 4, 5, 6, 2, 3, 4, 5]
    
    x3 = [1, 1, 2, 2, 3, 4, 4, 5, 5, 6]
    y3 = [5, 6, 5, 6, 6, 2, 3, 2, 3, 2]