@@ -80,7 +80,7 @@ def nearest(lon_pt, lat_pt, lon2d, lat2d):
8080 return i , j
8181
8282
83- def uniform_resample (x , y , num_fac = 4 , kind = 'linear' ):
83+ def uniform_resample (x , y , num_fac = 2 , kind = 'linear' ):
8484 '''
8585 Resample contours to have (nearly) equal spacing
8686 '''
@@ -89,6 +89,7 @@ def uniform_resample(x, y, num_fac=4, kind='linear'):
8989 ##x = ndimage.zoom(x.copy(), 2)
9090 ##y = ndimage.zoom(y.copy(), 2)
9191 #plt.plot(x, y, '.-r', lw=2)
92+
9293 # Get distances
9394 d = np .r_ [0 , np .cumsum (haversine_distance_vector (x [:- 1 ],y [:- 1 ], x [1 :],y [1 :]))]
9495 # Get uniform distances
@@ -98,7 +99,15 @@ def uniform_resample(x, y, num_fac=4, kind='linear'):
9899 yfunc = interpolate .interp1d (d , y , kind = kind )
99100 xnew = xfunc (d_uniform )
100101 ynew = yfunc (d_uniform )
101- #plt.plot(xnew, ynew, '.-r', lw=2)
102+
103+ # Akima is slightly slower, but may be more accurate
104+ #xfunc = interpolate.Akima1DInterpolator(d, x)
105+ #yfunc = interpolate.Akima1DInterpolator(d, y)
106+ #xxnew = xfunc(d_uniform)
107+ #yynew = yfunc(d_uniform)
108+
109+ #plt.plot(xnew, ynew, '.-r', lw=1.5)
110+ #plt.plot(xxnew, yynew, '+-b', lw=1.)
102111 #plt.axis('image')
103112 #plt.show()
104113 return xnew , ynew
@@ -107,7 +116,104 @@ def uniform_resample(x, y, num_fac=4, kind='linear'):
107116def strcompare (str1 , str2 ):
108117 return str1 in str2 and str2 in str1
109118
110-
119+
120+
121+
122+
123+
124+
125+ def _find_closest_point_on_leg (p1 , p2 , p0 ):
126+ """find closest point to p0 on line segment connecting p1 and p2"""
127+
128+ # handle degenerate case
129+ if np .all (p2 == p1 ):
130+ d = p0 - p1
131+ d **= 2
132+ return d .sum ()
133+
134+ d21 = p2 - p1
135+ d01 = p0 - p1
136+
137+ # project on to line segment to find closest point
138+ proj = np .dot (d01 , d21 )
139+ proj /= np .dot (d21 , d21 )
140+ if proj < 0 :
141+ proj = 0
142+ elif proj > 1 :
143+ proj = 1
144+ pc = p1 + proj * d21
145+
146+ # find squared distance
147+ d = pc - p0
148+ d **= 2
149+
150+ return d .sum ()#, pc
151+
152+
153+ def _find_closest_point_on_path (lc , point ):
154+ """
155+ lc: coordinates of vertices
156+ point: coordinates of test point
157+ """
158+ # Find index of closest vertex for this segment
159+ ds = np .sum ((lc - point [None , :])** 2 , 1 )
160+ imin = ds .argmin ()
161+
162+ dmin = np .inf
163+ closed = np .alltrue ([lc [0 ,0 ] == lc [- 1 ,0 ], lc [0 ,1 ] == y [- 1 ,1 ]])
164+
165+ # Build list of legs before and after this vertex
166+ legs = []
167+ if imin > 0 or closed :
168+ legs .append (((imin - 1 ) % len (lc ), imin ))
169+ if imin < len (lc ) - 1 or closed :
170+ legs .append ((imin , (imin + 1 ) % len (lc )))
171+
172+ for leg in legs :
173+ #d, xc = _find_closest_point_on_leg(lc[leg[0]], lc[leg[1]], point)
174+ d = _find_closest_point_on_leg (lc [leg [0 ]], lc [leg [1 ]], point )
175+ if d < dmin :
176+ dmin = d
177+
178+ return dmin
179+
180+
181+ def find_nearest_contour (cont_coll , x , y , indices ):
182+ """
183+ Finds contour that is closest to a point.
184+
185+ Returns a tuple containing the contour, segment of minimum point.
186+
187+ Call signature::
188+
189+ conmin, segmin = find_nearest_contour(cont_coll, x, y, indices)
190+ """
191+ dmin = np .inf
192+ conmin = None
193+ segmin = None
194+
195+ point = np .array ([x , y ])
196+
197+ for icon in indices :
198+ con = cont_coll .collections [icon ]
199+ paths = con .get_paths ()
200+
201+ for segNum , linepath in enumerate (paths ):
202+ lc = linepath .vertices
203+ d = _find_closest_point_on_path (lc , point )
204+
205+ if d < dmin :
206+ dmin = d
207+ conmin = icon
208+ segmin = segNum
209+
210+ return conmin , segmin
211+
212+
213+
214+
215+
216+
111217
112218
113219
@@ -1087,7 +1193,7 @@ def _set_global_ellipse(self):
10871193 ew_x = np .hstack ((e_verts [:e_size ,0 ], w_verts [w_size :,0 ]))
10881194 ew_y = np .hstack ((e_verts [:e_size ,1 ], w_verts [w_size :,1 ]))
10891195 self .ellipse_path = path .Path (np .array ([ew_x , ew_y ]).T )
1090- return self .ellipse_path
1196+ return self # .ellipse_path
10911197
10921198 def _set_black_sea_ellipse (self ):
10931199 '''
@@ -1097,13 +1203,14 @@ def _set_black_sea_ellipse(self):
10971203 verts = self .black_sea_ellipse .get_verts ()
10981204 self .ellipse_path = path .Path (np .array ([verts [:,0 ],
10991205 verts [:,1 ]]).T )
1100-
1206+ return self
11011207
11021208 def get_search_ellipse (self , x , y ):
11031209 '''
11041210 '''
11051211 self .x = x
11061212 self .y = y
1213+
11071214 if self .domain in ('Global' , 'ROMS' ):
11081215 self .rw_d [:] = self .rwv .get_rwdistance (x , y , self .days_btwn_recs )
11091216 self .rw_d_mod [:] = 1.75
@@ -1118,8 +1225,10 @@ def get_search_ellipse(self, x, y):
11181225 self .rw_d_mod *= self .rw_d
11191226 self ._set_black_sea_ellipse ()
11201227
1121- else : Exception
1122-
1228+ else :
1229+ Exception
1230+
1231+ return self
11231232
11241233 def view_search_ellipse (self , Eddy ):
11251234 '''
0 commit comments