-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpolplot.py
More file actions
121 lines (105 loc) · 5.61 KB
/
polplot.py
File metadata and controls
121 lines (105 loc) · 5.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import matplotlib.pyplot as plt
import numpy as np
from shapely.geometry import Point, LineString, MultiLineString, Polygon, \
MultiPolygon
from matplotlib.collections import PatchCollection
from matplotlib.patches import Polygon as PolygonPatch
def polPlot(XY, XY_inner = None, plot_title = None, show_vertices = False,
show_vertices_labels = False, show_vertices_labels_interval = 1, plot_on_axis = False,
empty = False, set_limits = 'True',
vertices_color = 'darkgray', fill_color = 'silver', edge_color = 'turquoise'):
"""
Function to plot polygon
Args:
XY: (Required) Shapely (Multi)Polygon, list of coordinate pairs or Numpy Array with dimension n x 2 representing the polygon to plot
XY_inner: (Optional, defaults no None) If XY is a list or Numpy Array, indicate the inner rings by a list of Numpy n x 2 arrays or a list of coordinate pair lists
plot_title: (Optional, defaults to None) String describing the title for the plot
show_vertices: (Optional, defaults to False) True/False boolean to indicate whether the polygon vertices should be shown
show_verticeslabels: (Optional, defaults to False) True/False boolean to indicate whether the labels of the vertices should be shown
show_verticeslabels_interval: (Optional, defaults to 1) Interval of which vertices labels should be shown
plot_on_axis: (Optional, defaults to False) False/plt-axis indicating to plot on an existing axis
empty: (Optional, defaults to False) True/False boolean indicating whether to fill the polygon or keep it transparent
set_limits: (Optional, defaults to True) True/False boolean to adapt the limits of the axes.
vertices_color: (Optional, defaults to 'darkgray') Color string or code to indicate the color of the vertices.
fill_color: (Optional, defaults to 'silver') Color string or code to indicate the color of the polygon body.
edge_color: (Optional, defaults to 'turquoise') Color string or code to indicate the color of the polygon edges.
"""
# make sure the function can handle a shapely Polygon, MultiPolygon, Numpy array or list of coordinate pairs
if type(XY) == Polygon:
XY_np = np.rot90(XY.exterior.xy)
XY_inner = [i.xy for i in XY.interiors]
pols = [[XY_np, XY_inner]]
elif type(XY) == MultiPolygon:
pols = []
for xy in XY:
XY_np =np.rot90(xy.exterior.xy)
XY_inner = [i.xy for i in xy.interiors]
pols.append([XY_np, XY_inner])
else:
pols = [[np.asarray(XY), XY_inner]]
# plot on existing axis if indicated
if not plot_on_axis: f, a = plt.subplots()
else: a = plot_on_axis
# set plot title if indicated
if plot_title: a.set_title(plottitle, fontweight = 'bold')
# initialize graph limits
xmin = float('inf'); ymin = float('inf')
xmax = float('-inf'); ymax = float('-inf')
# search min and max coordinates along polygons to determine graph limits
for pol in pols:
XY_np = pol[0]
XY = list(XY_np)
XY_inner = pol[1]
if np.min(XY_np[:, 0]) < xmin: xmin = np.min(XY_np[:, 0])
if np.max(XY_np[:, 0]) > xmax: xmax = np.max(XY_np[:, 0])
if np.min(XY_np[:, 1]) < ymin: ymin = np.min(XY_np[:, 1])
if np.max(XY_np[:, 1]) > ymax: ymax = np.max(XY_np[:, 1])
# determine fill colors
if empty:
col = 'none'
colin = 'none'
else:
col = fill_color
colin = 'white'
# create a matplotlib patch representing the polygon
if XY_np.shape[0] <= 2: XY_np = np.rot90(XY_np)
pol = PolygonPatch(XY_np, facecolor = col, edgecolor = edge_color ) # matplotlib.patches.Polygon
# if there are inner rings, plot them
if XY_inner is not None:
pols_inner = []
for i in XY_inner:
i = np.asarray(i)
if i.shape[0] <= 2: i = np.rot90(i)
pol_inner = PolygonPatch(i, facecolor=colin, edgecolor = edge_color) # matplotlib.patches.Polygon
pols_inner.append(pol_inner)
# add the patches to the plot
a.add_patch(pol)
if XY_inner is not None:
for pol_inner in pols_inner:
a.add_patch(pol_inner)
# if indicated plot the vertices
if show_vertices:
a.scatter(XY_np[:,0], XY_np[:,1], s = 4, edgecolor = vertices_color, facecolor = vertices_color, zorder = 10)
if XY_inner:
for i in XY_inner:
a.scatter(np.asarray(i)[:, 0], np.asarray(i)[:, 1], s=4, edgecolor= vertices_color, facecolor = vertices_color, zorder = 10)
# if indicated, show the vertices labels
if show_vertices_labels:
# counter
t = 1
for x,y in XY:
# only plot the vertices labels on a given interval
if t%show_vertices_labels_interval == 0: a.annotate(str(t),(x,y))
t += 1
if XY_inner:
for i in XY_inner:
for j in range(len(i)):
x,y = i[j][0],i[j][1]
# only plot the vertices labels on a given interval
if t%show_vertices_labels_interval == 0: a.annotate(str(t), (x, y))
t += 1
# set the axes limits, if indicated
if set_limits:
a.set_xlim(xmin - 0.1*(xmax-xmin), xmax + 0.1*(xmax-xmin))
a.set_ylim(ymin - 0.1*(ymax-ymin), ymax + 0.1*(ymax-ymin))
a.set_aspect('equal')