Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1import numpy as np 

2from scipy._lib.decorator import decorator as _decorator 

3 

4__all__ = ['delaunay_plot_2d', 'convex_hull_plot_2d', 'voronoi_plot_2d'] 

5 

6 

7@_decorator 

8def _held_figure(func, obj, ax=None, **kw): 

9 import matplotlib.pyplot as plt # type: ignore[import] 

10 

11 if ax is None: 

12 fig = plt.figure() 

13 ax = fig.gca() 

14 return func(obj, ax=ax, **kw) 

15 

16 # As of matplotlib 2.0, the "hold" mechanism is deprecated. 

17 # When matplotlib 1.x is no longer supported, this check can be removed. 

18 was_held = getattr(ax, 'ishold', lambda: True)() 

19 if was_held: 

20 return func(obj, ax=ax, **kw) 

21 try: 

22 ax.hold(True) 

23 return func(obj, ax=ax, **kw) 

24 finally: 

25 ax.hold(was_held) 

26 

27 

28def _adjust_bounds(ax, points): 

29 margin = 0.1 * points.ptp(axis=0) 

30 xy_min = points.min(axis=0) - margin 

31 xy_max = points.max(axis=0) + margin 

32 ax.set_xlim(xy_min[0], xy_max[0]) 

33 ax.set_ylim(xy_min[1], xy_max[1]) 

34 

35 

36@_held_figure 

37def delaunay_plot_2d(tri, ax=None): 

38 """ 

39 Plot the given Delaunay triangulation in 2-D 

40 

41 Parameters 

42 ---------- 

43 tri : scipy.spatial.Delaunay instance 

44 Triangulation to plot 

45 ax : matplotlib.axes.Axes instance, optional 

46 Axes to plot on 

47 

48 Returns 

49 ------- 

50 fig : matplotlib.figure.Figure instance 

51 Figure for the plot 

52 

53 See Also 

54 -------- 

55 Delaunay 

56 matplotlib.pyplot.triplot 

57 

58 Notes 

59 ----- 

60 Requires Matplotlib. 

61 

62 Examples 

63 -------- 

64 

65 >>> import matplotlib.pyplot as plt 

66 >>> from scipy.spatial import Delaunay, delaunay_plot_2d 

67 

68 The Delaunay triangulation of a set of random points: 

69 

70 >>> points = np.random.rand(30, 2) 

71 >>> tri = Delaunay(points) 

72 

73 Plot it: 

74 

75 >>> _ = delaunay_plot_2d(tri) 

76 >>> plt.show() 

77 

78 """ 

79 if tri.points.shape[1] != 2: 

80 raise ValueError("Delaunay triangulation is not 2-D") 

81 

82 x, y = tri.points.T 

83 ax.plot(x, y, 'o') 

84 ax.triplot(x, y, tri.simplices.copy()) 

85 

86 _adjust_bounds(ax, tri.points) 

87 

88 return ax.figure 

89 

90 

91@_held_figure 

92def convex_hull_plot_2d(hull, ax=None): 

93 """ 

94 Plot the given convex hull diagram in 2-D 

95 

96 Parameters 

97 ---------- 

98 hull : scipy.spatial.ConvexHull instance 

99 Convex hull to plot 

100 ax : matplotlib.axes.Axes instance, optional 

101 Axes to plot on 

102 

103 Returns 

104 ------- 

105 fig : matplotlib.figure.Figure instance 

106 Figure for the plot 

107 

108 See Also 

109 -------- 

110 ConvexHull 

111 

112 Notes 

113 ----- 

114 Requires Matplotlib. 

115 

116 

117 Examples 

118 -------- 

119 

120 >>> import matplotlib.pyplot as plt 

121 >>> from scipy.spatial import ConvexHull, convex_hull_plot_2d 

122 

123 The convex hull of a random set of points: 

124 

125 >>> points = np.random.rand(30, 2) 

126 >>> hull = ConvexHull(points) 

127 

128 Plot it: 

129 

130 >>> _ = convex_hull_plot_2d(hull) 

131 >>> plt.show() 

132 

133 """ 

134 from matplotlib.collections import LineCollection # type: ignore[import] 

135 

136 if hull.points.shape[1] != 2: 

137 raise ValueError("Convex hull is not 2-D") 

138 

139 ax.plot(hull.points[:,0], hull.points[:,1], 'o') 

140 line_segments = [hull.points[simplex] for simplex in hull.simplices] 

141 ax.add_collection(LineCollection(line_segments, 

142 colors='k', 

143 linestyle='solid')) 

144 _adjust_bounds(ax, hull.points) 

145 

146 return ax.figure 

147 

148 

149@_held_figure 

150def voronoi_plot_2d(vor, ax=None, **kw): 

151 """ 

152 Plot the given Voronoi diagram in 2-D 

153 

154 Parameters 

155 ---------- 

156 vor : scipy.spatial.Voronoi instance 

157 Diagram to plot 

158 ax : matplotlib.axes.Axes instance, optional 

159 Axes to plot on 

160 show_points: bool, optional 

161 Add the Voronoi points to the plot. 

162 show_vertices : bool, optional 

163 Add the Voronoi vertices to the plot. 

164 line_colors : string, optional 

165 Specifies the line color for polygon boundaries 

166 line_width : float, optional 

167 Specifies the line width for polygon boundaries 

168 line_alpha: float, optional 

169 Specifies the line alpha for polygon boundaries 

170 point_size: float, optional 

171 Specifies the size of points 

172 

173 

174 Returns 

175 ------- 

176 fig : matplotlib.figure.Figure instance 

177 Figure for the plot 

178 

179 See Also 

180 -------- 

181 Voronoi 

182 

183 Notes 

184 ----- 

185 Requires Matplotlib. 

186 

187 Examples 

188 -------- 

189 Set of point: 

190 

191 >>> import matplotlib.pyplot as plt 

192 >>> points = np.random.rand(10,2) #random 

193 

194 Voronoi diagram of the points: 

195 

196 >>> from scipy.spatial import Voronoi, voronoi_plot_2d 

197 >>> vor = Voronoi(points) 

198 

199 using `voronoi_plot_2d` for visualisation: 

200 

201 >>> fig = voronoi_plot_2d(vor) 

202 

203 using `voronoi_plot_2d` for visualisation with enhancements: 

204 

205 >>> fig = voronoi_plot_2d(vor, show_vertices=False, line_colors='orange', 

206 ... line_width=2, line_alpha=0.6, point_size=2) 

207 >>> plt.show() 

208 

209 """ 

210 from matplotlib.collections import LineCollection 

211 

212 if vor.points.shape[1] != 2: 

213 raise ValueError("Voronoi diagram is not 2-D") 

214 

215 if kw.get('show_points', True): 

216 point_size = kw.get('point_size', None) 

217 ax.plot(vor.points[:,0], vor.points[:,1], '.', markersize=point_size) 

218 if kw.get('show_vertices', True): 

219 ax.plot(vor.vertices[:,0], vor.vertices[:,1], 'o') 

220 

221 line_colors = kw.get('line_colors', 'k') 

222 line_width = kw.get('line_width', 1.0) 

223 line_alpha = kw.get('line_alpha', 1.0) 

224 

225 center = vor.points.mean(axis=0) 

226 ptp_bound = vor.points.ptp(axis=0) 

227 

228 finite_segments = [] 

229 infinite_segments = [] 

230 for pointidx, simplex in zip(vor.ridge_points, vor.ridge_vertices): 

231 simplex = np.asarray(simplex) 

232 if np.all(simplex >= 0): 

233 finite_segments.append(vor.vertices[simplex]) 

234 else: 

235 i = simplex[simplex >= 0][0] # finite end Voronoi vertex 

236 

237 t = vor.points[pointidx[1]] - vor.points[pointidx[0]] # tangent 

238 t /= np.linalg.norm(t) 

239 n = np.array([-t[1], t[0]]) # normal 

240 

241 midpoint = vor.points[pointidx].mean(axis=0) 

242 direction = np.sign(np.dot(midpoint - center, n)) * n 

243 if (vor.furthest_site): 

244 direction = -direction 

245 far_point = vor.vertices[i] + direction * ptp_bound.max() 

246 

247 infinite_segments.append([vor.vertices[i], far_point]) 

248 

249 ax.add_collection(LineCollection(finite_segments, 

250 colors=line_colors, 

251 lw=line_width, 

252 alpha=line_alpha, 

253 linestyle='solid')) 

254 ax.add_collection(LineCollection(infinite_segments, 

255 colors=line_colors, 

256 lw=line_width, 

257 alpha=line_alpha, 

258 linestyle='dashed')) 

259 

260 _adjust_bounds(ax, vor.points) 

261 

262 return ax.figure