Traccia lo shapefile con matplotlib


13

Sto cercando di leggere un file di forma e di tracciarlo usando matplotlib. Ecco il codice:

import matplotlib.pyplot as plt
import shapefile   

shpFilePath = "D:\test.shp"  
listx=[]
listy=[]
test = shapefile.Reader(shpFilePath)
for sr in test.shapeRecords():
    for xNew,yNew in sr.shape.points:
        listx.append(xNew)
        listy.append(yNew)
plt.plot(listx,listy)
plt.show()

Tuttavia, ottengo linee che collegano i miei poligoni. Come posso disegnare i poligoni in modo che siano il modo nel file di forma. Ecco alcuni screenshot della trama e dello shapefile quando viene aperto con ArcGIS.Generato dal codice File reale


Non ho familiarità con il lettore shapefile, tuttavia posso dire che stai semplicemente aggiungendo tutti i punti nel file a un grande elenco senza separare ogni forma nelle sue parti componenti. È necessario un grande elenco di forme a cui si aggiungono i punti di ciascuna forma

Giusto. Devono trovare un modo per separare le forme. Ma è quello che non riesco a fare al momento.
statBeginner

@DanPatterson Puoi specificare come tracciare più forme nella stessa figura dopo che sono riuscito a separare le forme? Se uso plt.plot (listx, listy) per ogni forma, continua a generare una nuova figura ogni volta, invece di usare la stessa figura.
statBeginner,

Risposte:


10

Lascerò a te come raccogliere le forme ma questo è il principio

import numpy as np
from matplotlib import pyplot as p  #contains both numpy and pyplot
x1 = [-1,-1,10,10,-1]; y1 = [-1,10,10,-1,-1]
x2 = [21,21,29,29,21]; y2 = [21,29,29,21,21]
shapes = [[x1,y1],[x2,y2]]
for shape in shapes:
  x,y = shape
  p.plot(x,y)
p.show()

oh .. mi chiedo come mi sia perso. faccio comunque stampare le forme in diversi colori. Dovrà risolvere il problema :)
statBeginner,

come ottenere o isolare le diverse forme?
FaCoffee

15

Per riferimenti futuri, ecco la soluzione a cui sono arrivato dopo aver seguito i consigli sopra.

import shapefile as shp  # Requires the pyshp package
import matplotlib.pyplot as plt

sf = shp.Reader("test.shp")

plt.figure()
for shape in sf.shapeRecords():
    x = [i[0] for i in shape.shape.points[:]]
    y = [i[1] for i in shape.shape.points[:]]
    plt.plot(x,y)
plt.show()

La figura risultante sarà molto colorata, ma dovrai solo modificare le parole chiave della trama.


6
So che questa potrebbe essere un'informazione ridondante, ma per coloro che non hanno ancora familiarità con l'argomento sarebbe stato utile dire che si import shapefileriferisce al pyshppacchetto: pypi.python.org/pypi/pyshp
FaCoffee

Questo non va bene quando hai un gruppo di isole, poiché questi punti saranno collegati da linee a punti sulla terraferma, creando qualcosa di simile a ciò che l'OP ha pubblicato.
FaCoffee,

1
@FaCoffee, hai ragione. La mia risposta gis.stackexchange.com/a/309780/126618 dovrebbe rispondere a questo.
Gus

7

Devi usare percorsi e patch matplotlib e c'è un modulo Python dedicato a tracciare poligoni da file di forma usando queste funzioni Descartes .

Poiché Pyshp (shapefile) ha la convenzione geo_interface ( New geo_interface for PyShp ), puoi usarla.

polys  = shapefile.Reader("polygon")
# first polygon
poly = polys.iterShapes().next().__geo_interface__
print poly
{'type': 'Polygon', 'coordinates': (((151116.87238259654, 135890.8706318218), (153492.19971554304, 134793.3055883224), (153934.50204650551, 133892.31935858406), (152623.97662143156, 131811.86024627919), (150903.91200102202, 130894.49244872745), (149347.66305874675, 132991.33312884573), (149151.08424498566, 134383.76639298678), (151116.87238259654, 135890.8706318218)),)}

Il risultato è la rappresentazione GeoJSON della geometria e puoi usare la soluzione di come tracciare i dati geografici usando matplotlib / python

import matplotlib.pyplot as plt 
from descartes import PolygonPatch
BLUE = '#6699cc'
fig = plt.figure() 
ax = fig.gca() 
ax.add_patch(PolygonPatch(poly, fc=BLUE, ec=BLUE, alpha=0.5, zorder=2 ))
ax.axis('scaled')
plt.show()

inserisci qui la descrizione dell'immagine


È davvero utile, ma puoi farlo in un ciclo for se hai più poligoni da tracciare?
FaCoffee

Sì senza problemi
gene

Ho notato che la descartessoluzione non funziona se si tenta di tracciare due diversi shapefile su due sottotrame adiacenti utilizzando fig, ax = plt.subplots(1,2,figsize=(15, 8))e quindi ax[0].add_patch(PolygonPatch(poly_geo, fc='#d3d3d3', ec='#000000', alpha=0, zorder=5))e ax[1].add_patch(PolygonPatch(poly_geo, fc='#d3d3d3', ec='#000000', alpha=0, zorder=5)). Il risultato è un'immagine vuota. Qualche idea?
FaCoffee


2

Oltre alla risposta ldocao e alla risposta alla domanda FaCoffee. Quando hai isole isolate e fanno parte della stessa funzione, puoi provare dopo:

import shapefile as shp
import matplotlib.pyplot as plt

sf = shp.Reader("test.shp")

plt.figure()
for shape in sf.shapeRecords():
    for i in range(len(shape.shape.parts)):
        i_start = shape.shape.parts[i]
        if i==len(shape.shape.parts)-1:
            i_end = len(shape.shape.points)
        else:
            i_end = shape.shape.parts[i+1]
        x = [i[0] for i in shape.shape.points[i_start:i_end]]
        y = [i[1] for i in shape.shape.points[i_start:i_end]]
        plt.plot(x,y)
plt.show()

Questo lo fa funzionare per me. Le "parti" corrette di una forma restituiscono gli indici iniziali di diverse geometrie all'interno di una feature.


0

Tuttavia, in una forma di file di forma, possono esserci più parti. In questo modo ogni parte verrà tracciata in una forma, separatamente.

import matplotlib.pyplot as plt
import shapefile
import numpy as np

this_shapefile = shapefile.Reader(map_file_base) # whichever file
shape = this_shapefile.shape(i) # whichever shape
points = np.array(shape.points)

intervals = list(shape.parts) + [len(shape.points)]

ax = plt.gca()
ax.set_aspect(1)

for (i, j) in zip(intervals[:-1], intervals[1:]):
    ax.plot(*zip(*points[i:j]))
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.