Search code examples
pythonnumpymatplotlibshapelydescartes

How to display Polygon List into one Graph with For Loops


so I'm working on a Line of Sight script where the Polygons act as buildings and return a boolean value based on whether a line intersects with a Polygon.

The logic behind it works, but when I try to integrate more Polygons from a list called polycoords and use a For Loop so it can instantiate it on the Graph, it comes out as two separate graphs rather than a single one.

import numpy as np
import matplotlib.pyplot as plt
import shapely.geometry
from shapely.geometry import LineString
from shapely.geometry import Point, Polygon
import descartes

origin = [-1.0, 0.0] # Set a point to view from
quality = 7 # Number of grid points squared
polycoords = [[[-1, 1], [-1, 0.5], [0, 0.5], [0, 1]],[[1, -1], [1, -0.5], [0, -0.5], [-0, -1]]] # Coordinates of the Polygon
fullresults = []
newbool = []

def los (origin, quality, polycoords):
    
    for buildingpoints in range(len(polycoords)):
        x = np.linspace(-1,1,quality)
        y = np.linspace(-1,1,quality)
        X,Y = np.meshgrid(x,y)
        clip_poly = shapely.geometry.Polygon(polycoords[buildingpoints]) 
        fig = plt.figure()
        ax = fig.add_subplot(111)
        polygonbuilding = ax.add_patch(descartes.PolygonPatch(clip_poly, fc='pink', alpha=0.3))
        positions = np.vstack([Y.ravel(), X.ravel()])

        for i in range(len(positions)):
            for j in range(len(positions[i])):
                plt.scatter(*positions[::-1])
                x1 = positions[0][j]
                y1 = positions[1][j]
                line = LineString([origin, (x1, y1)])

                if line.intersects(clip_poly) == True:
                    ax.plot(*np.array(line).T, color='red', linewidth=1, solid_capstyle='round')
                else:
                    ax.plot(*np.array(line).T, color='green', linewidth=1, solid_capstyle='round')

                boolintersect = line.intersects(clip_poly)
                listresults = origin, [x1,y1],boolintersect
                fullresults.append(listresults)
                boollist = [x[2] for x in fullresults]
                newbool.append(sum(boollist))
                
    return(fullresults, newbool)

def analysis (losresults):
        percenteq = round((100-(newbool[-1]/len(fullresults))*100))
        print (percenteq,'% of the space is PUBLICALLY visible from point', fullresults[0][0])
        print (100-percenteq,'% of the space is PRIVATE/ISNT visible from point', fullresults[0][0])
        
los(origin, quality, polycoords)
analysis (los)
plt.show()

The results show two separate graphs when I need just one with both polygons present. I believe it's something to do with the structure of my code regarding the For loops, but I'm still pretty new and not too sure how to solve this.

enter image description here


Solution

  • Resolved meshgrid creation in the loop has been moved out and done once as given below:

    import numpy as np
    import matplotlib.pyplot as plt
    import shapely.geometry
    from shapely.geometry import LineString
    from shapely.geometry import Point, Polygon
    import descartes
    
    origin = [-1.0, 0.0] # Set a point to view from
    quality = 7 # Number of grid points squared
    polycoords = [[[-1, 1], [-1, 0.5], [0, 0.5], [0, 1]],[[1, -1], [1, -0.5], [0, -0.5], [-0, -1]]] # Coordinates of the Polygon
    fullresults = []
    newbool = []
    
    def init (origin, quality):
        global ax, positions
        x = np.linspace(-1,1,quality)
        y = np.linspace(-1,1,quality)
        X,Y = np.meshgrid(x,y)
        fig = plt.figure()
        ax = fig.add_subplot(111)
        positions = np.vstack([Y.ravel(), X.ravel()])
            
    def los (origin, quality, polycoords):
        global ax, positions
        for buildingpoints in range(len(polycoords)):
            clip_poly = shapely.geometry.Polygon(polycoords[buildingpoints]) 
            polygonbuilding = ax.add_patch(descartes.PolygonPatch(clip_poly, fc='pink', alpha=0.3))
    
            for i in range(len(positions)):
                for j in range(len(positions[i])):
                    plt.scatter(*positions[::-1])
                    x1 = positions[0][j]
                    y1 = positions[1][j]
                    line = LineString([origin, (x1, y1)])
    
                    if line.intersects(clip_poly) == True:
                        ax.plot(*np.array(line).T, color='red', linewidth=1, solid_capstyle='round')
                    else:
                        ax.plot(*np.array(line).T, color='green', linewidth=1, solid_capstyle='round')
    
                    boolintersect = line.intersects(clip_poly)
                    listresults = origin, [x1,y1],boolintersect
                    fullresults.append(listresults)
                    boollist = [x[2] for x in fullresults]
                    newbool.append(sum(boollist))
                    
        return(fullresults, newbool)
    
    def analysis (losresults):
            percenteq = round((100-(newbool[-1]/len(fullresults))*100))
            print (percenteq,'% of the space is PUBLICALLY visible from point', fullresults[0][0])
            print (100-percenteq,'% of the space is PRIVATE/ISNT visible from point', fullresults[0][0])
            
    init (origin, quality)
    los(origin, quality, polycoords)
    analysis (los)
    plt.show()