def corners(self): """Returns the corners of the current area. """ from pyresample.spherical_geometry import Coordinate return [Coordinate(*self.get_lonlat(0, 0)), Coordinate(*self.get_lonlat(0, -1)), Coordinate(*self.get_lonlat(-1, -1)), Coordinate(*self.get_lonlat(-1, 0))]
def outer_boundary_corners(self): """Returns the lon,lat of the outer edges of the corner points """ from pyresample.spherical_geometry import Coordinate proj = _spatial_mp.Proj(**self.proj_dict) corner_lons, corner_lats = proj((self.area_extent[0], self.area_extent[2], self.area_extent[2], self.area_extent[0]), (self.area_extent[3], self.area_extent[3], self.area_extent[1], self.area_extent[1]), inverse=True) return [Coordinate(corner_lons[0], corner_lats[0]), Coordinate(corner_lons[1], corner_lats[1]), Coordinate(corner_lons[2], corner_lats[2]), Coordinate(corner_lons[3], corner_lats[3])]
def __contains__(self, point): """Is a point inside the 4 corners of the current area? This uses great circle arcs as area boundaries. """ from pyresample.spherical_geometry import point_inside, Coordinate corners = self.corners if isinstance(point, tuple): return point_inside(Coordinate(*point), corners) else: return point_inside(point, corners)
def __contains__(self, point): """Is a point inside the 4 corners of the current area? This DOES NOT use spherical geometry / great circle arcs. """ corners = self.corners if isinstance(point, tuple): from pyresample.spherical_geometry import Coordinate retval = planar_point_inside(Coordinate(*point), corners) else: retval = planar_point_inside(point, corners) #print ' retval from FALSE CORNERS contains '+str(retval) return retval
def granule_inside_area(start_time, end_time, platform_name, area_def): """Check if the IASI granule is over area interest, using the times from the filename """ metop = orbital.Orbital(PLATFORMS.get(platform_name, platform_name)) corners = area_def.corners is_inside = False for dtobj in [start_time, end_time]: lon, lat, dummy = metop.get_lonlatalt(dtobj) point = Coordinate(lon, lat) if point_inside(point, corners): is_inside = True break return is_inside
def test_inside(self): """Testing if a point is inside an area. """ lons = np.array([[-11, 11], [-11, 11]]) lats = np.array([[11, 11], [-11, -11]]) area = geometry.SwathDefinition(lons, lats) point = Coordinate(0, 0) self.assertTrue(point in area) point = Coordinate(0, 12) self.assertFalse(point in area) lons = np.array([[-179, 179], [-179, 179]]) lats = np.array([[1, 1], [-1, -1]]) area = geometry.SwathDefinition(lons, lats) point = Coordinate(180, 0) self.assertTrue(point in area) point = Coordinate(180, 12) self.assertFalse(point in area) point = Coordinate(-180, 12) self.assertFalse(point in area) self.assert_raises(ValueError, Coordinate, 0, 192) self.assert_raises(ValueError, Coordinate, 15, -91) # case of the north pole lons = np.array([[0, 90], [-90, 180]]) lats = np.array([[89, 89], [89, 89]]) area = geometry.SwathDefinition(lons, lats) point = Coordinate(90, 90) self.assertTrue(point in area)
def test_intersects(self): """Test if two arcs intersect.""" p0_ = Coordinate(0, 0) p1_ = Coordinate(0, 1) p2_ = Coordinate(1, 0) p3_ = Coordinate(0, -1) p4_ = Coordinate(-1, 0) p5_ = Coordinate(1, 1) p6_ = Coordinate(1, -1) arc13 = Arc(p1_, p3_) arc24 = Arc(p2_, p4_) arc32 = Arc(p3_, p2_) arc41 = Arc(p4_, p1_) arc40 = Arc(p4_, p0_) arc56 = Arc(p5_, p6_) arc45 = Arc(p4_, p5_) arc02 = Arc(p0_, p2_) arc35 = Arc(p3_, p5_) self.assertTrue(arc13.intersects(arc24)) self.assertFalse(arc32.intersects(arc41)) self.assertFalse(arc56.intersects(arc40)) self.assertFalse(arc56.intersects(arc40)) self.assertFalse(arc45.intersects(arc02)) self.assertTrue(arc35.intersects(arc24)) p0_ = Coordinate(180, 0) p1_ = Coordinate(180, 1) p2_ = Coordinate(-179, 0) p3_ = Coordinate(-180, -1) p4_ = Coordinate(179, 0) p5_ = Coordinate(-179, 1) p6_ = Coordinate(-179, -1) arc13 = Arc(p1_, p3_) arc24 = Arc(p2_, p4_) arc32 = Arc(p3_, p2_) arc41 = Arc(p4_, p1_) arc40 = Arc(p4_, p0_) arc56 = Arc(p5_, p6_) arc45 = Arc(p4_, p5_) arc02 = Arc(p0_, p2_) arc35 = Arc(p3_, p5_) self.assertTrue(arc13.intersects(arc24)) self.assertFalse(arc32.intersects(arc41)) self.assertFalse(arc56.intersects(arc40)) self.assertFalse(arc56.intersects(arc40)) self.assertFalse(arc45.intersects(arc02)) self.assertTrue(arc35.intersects(arc24)) # case of the north pole p0_ = Coordinate(0, 90) p1_ = Coordinate(0, 89) p2_ = Coordinate(90, 89) p3_ = Coordinate(180, 89) p4_ = Coordinate(-90, 89) p5_ = Coordinate(45, 89) p6_ = Coordinate(135, 89) arc13 = Arc(p1_, p3_) arc24 = Arc(p2_, p4_) arc32 = Arc(p3_, p2_) arc41 = Arc(p4_, p1_) arc40 = Arc(p4_, p0_) arc56 = Arc(p5_, p6_) arc45 = Arc(p4_, p5_) arc02 = Arc(p0_, p2_) arc35 = Arc(p3_, p5_) self.assertTrue(arc13.intersects(arc24)) self.assertFalse(arc32.intersects(arc41)) self.assertFalse(arc56.intersects(arc40)) self.assertFalse(arc56.intersects(arc40)) self.assertFalse(arc45.intersects(arc02)) self.assertTrue(arc35.intersects(arc24))
def test_angle(self): """Testing the angle value between two arcs.""" base = 0 p0_ = Coordinate(base, base) p1_ = Coordinate(base, base + 1) p2_ = Coordinate(base + 1, base) p3_ = Coordinate(base, base - 1) p4_ = Coordinate(base - 1, base) arc1 = Arc(p0_, p1_) arc2 = Arc(p0_, p2_) arc3 = Arc(p0_, p3_) arc4 = Arc(p0_, p4_) self.assertAlmostEqual(arc1.angle(arc2), math.pi / 2, msg="this should be pi/2") self.assertAlmostEqual(arc2.angle(arc3), math.pi / 2, msg="this should be pi/2") self.assertAlmostEqual(arc3.angle(arc4), math.pi / 2, msg="this should be pi/2") self.assertAlmostEqual(arc4.angle(arc1), math.pi / 2, msg="this should be pi/2") self.assertAlmostEqual(arc1.angle(arc4), -math.pi / 2, msg="this should be -pi/2") self.assertAlmostEqual(arc4.angle(arc3), -math.pi / 2, msg="this should be -pi/2") self.assertAlmostEqual(arc3.angle(arc2), -math.pi / 2, msg="this should be -pi/2") self.assertAlmostEqual(arc2.angle(arc1), -math.pi / 2, msg="this should be -pi/2") self.assertAlmostEqual(arc1.angle(arc3), math.pi, msg="this should be pi") self.assertAlmostEqual(arc3.angle(arc1), math.pi, msg="this should be pi") self.assertAlmostEqual(arc2.angle(arc4), math.pi, msg="this should be pi") self.assertAlmostEqual(arc4.angle(arc2), math.pi, msg="this should be pi") p5_ = Coordinate(base + 1, base + 1) p6_ = Coordinate(base + 1, base - 1) p7_ = Coordinate(base - 1, base - 1) p8_ = Coordinate(base - 1, base + 1) arc5 = Arc(p0_, p5_) arc6 = Arc(p0_, p6_) arc7 = Arc(p0_, p7_) arc8 = Arc(p0_, p8_) self.assertAlmostEqual(arc1.angle(arc5), math.pi / 4, 3, msg="this should be pi/4") self.assertAlmostEqual(arc5.angle(arc2), math.pi / 4, 3, msg="this should be pi/4") self.assertAlmostEqual(arc2.angle(arc6), math.pi / 4, 3, msg="this should be pi/4") self.assertAlmostEqual(arc6.angle(arc3), math.pi / 4, 3, msg="this should be pi/4") self.assertAlmostEqual(arc3.angle(arc7), math.pi / 4, 3, msg="this should be pi/4") self.assertAlmostEqual(arc7.angle(arc4), math.pi / 4, 3, msg="this should be pi/4") self.assertAlmostEqual(arc4.angle(arc8), math.pi / 4, 3, msg="this should be pi/4") self.assertAlmostEqual(arc8.angle(arc1), math.pi / 4, 3, msg="this should be pi/4") self.assertAlmostEqual(arc1.angle(arc6), 3 * math.pi / 4, 3, msg="this should be 3pi/4") c0_ = Coordinate(180, 0) c1_ = Coordinate(180, 1) c2_ = Coordinate(-179, 0) c3_ = Coordinate(-180, -1) c4_ = Coordinate(179, 0) arc1 = Arc(c0_, c1_) arc2 = Arc(c0_, c2_) arc3 = Arc(c0_, c3_) arc4 = Arc(c0_, c4_) self.assertAlmostEqual(arc1.angle(arc2), math.pi / 2, msg="this should be pi/2") self.assertAlmostEqual(arc2.angle(arc3), math.pi / 2, msg="this should be pi/2") self.assertAlmostEqual(arc3.angle(arc4), math.pi / 2, msg="this should be pi/2") self.assertAlmostEqual(arc4.angle(arc1), math.pi / 2, msg="this should be pi/2") self.assertAlmostEqual(arc1.angle(arc4), -math.pi / 2, msg="this should be -pi/2") self.assertAlmostEqual(arc4.angle(arc3), -math.pi / 2, msg="this should be -pi/2") self.assertAlmostEqual(arc3.angle(arc2), -math.pi / 2, msg="this should be -pi/2") self.assertAlmostEqual(arc2.angle(arc1), -math.pi / 2, msg="this should be -pi/2") # case of the north pole c0_ = Coordinate(0, 90) c1_ = Coordinate(0, 89) c2_ = Coordinate(-90, 89) c3_ = Coordinate(180, 89) c4_ = Coordinate(90, 89) arc1 = Arc(c0_, c1_) arc2 = Arc(c0_, c2_) arc3 = Arc(c0_, c3_) arc4 = Arc(c0_, c4_) self.assertAlmostEqual(arc1.angle(arc2), math.pi / 2, msg="this should be pi/2") self.assertAlmostEqual(arc2.angle(arc3), math.pi / 2, msg="this should be pi/2") self.assertAlmostEqual(arc3.angle(arc4), math.pi / 2, msg="this should be pi/2") self.assertAlmostEqual(arc4.angle(arc1), math.pi / 2, msg="this should be pi/2") self.assertAlmostEqual(arc1.angle(arc4), -math.pi / 2, msg="this should be -pi/2") self.assertAlmostEqual(arc4.angle(arc3), -math.pi / 2, msg="this should be -pi/2") self.assertAlmostEqual(arc3.angle(arc2), -math.pi / 2, msg="this should be -pi/2") self.assertAlmostEqual(arc2.angle(arc1), -math.pi / 2, msg="this should be -pi/2") self.assertAlmostEqual(Arc(c1_, c2_).angle(arc1), math.pi / 4, 3, msg="this should be pi/4") self.assertAlmostEqual(Arc(c4_, c3_).angle(arc4), -math.pi / 4, 3, msg="this should be -pi/4") self.assertAlmostEqual(Arc(c1_, c4_).angle(arc1), -math.pi / 4, 3, msg="this should be -pi/4")
def planar_intersection_polygon(area_corners, segment_corners): """Get the intersection polygon between two areas. """ # First test each lons = np.array([]) lats = np.array([]) for segment_corner in segment_corners: if planar_point_inside(segment_corner, area_corners): currlon = segment_corner.lon # MLS use wrap_longitudes? if currlon < 0: currlon += 2 * math.pi lons = np.concatenate((lons, [currlon])) lats = np.concatenate((lats, [segment_corner.lat])) log.info('Adding intersection from segment ' + str(segment_corner)) for area_corner in area_corners: if planar_point_inside(area_corner, segment_corners): currlon = area_corner.lon # MLS use wrap_longitudes? if currlon < 0: currlon += 2 * math.pi lons = np.concatenate((lons, [currlon])) lats = np.concatenate((lats, [area_corner.lat])) log.info('Adding intersection from area ' + str(area_corner)) area_line1 = Line(area_corners[0], area_corners[1]) area_line2 = Line(area_corners[1], area_corners[2]) area_line3 = Line(area_corners[2], area_corners[3]) area_line4 = Line(area_corners[3], area_corners[0]) segment_line1 = Line(segment_corners[0], segment_corners[1]) segment_line2 = Line(segment_corners[1], segment_corners[2]) segment_line3 = Line(segment_corners[2], segment_corners[3]) segment_line4 = Line(segment_corners[3], segment_corners[0]) for i in (area_line1, area_line2, area_line3, area_line4): for j in (segment_line1, segment_line2, segment_line3, segment_line4): intersect = i.intersection(j) if intersect: log.info('Adding actual intersection ' + str(intersect)) currlon = intersect.lon # MLS use wrap_longitudes? if intersect.lon < 0: currlon += 2 * math.pi lons = np.concatenate((lons, [currlon])) lats = np.concatenate((lats, [intersect.lat])) minlon = math.degrees(lons.min()) maxlon = math.degrees(lons.max()) minlat = math.degrees(lats.min()) maxlat = math.degrees(lats.max()) # Coordinate MUST be between -180 and 180 # MLS use wrap_longitudes? if minlon > 180: minlon -= 180 if maxlon > 180: maxlon -= 180 from pyresample.spherical_geometry import Coordinate return [ Coordinate(minlon, maxlat), Coordinate(maxlon, maxlat), Coordinate(maxlon, minlat), Coordinate(minlon, minlat) ]
def get_2d_false_corners(box_def): #print ' In 2D false corners for: '+str(box_def.name) min_row = 0 max_row = -1 min_col = 0 max_col = -1 side1 = box_def.get_lonlats(data_slice=(min_row, slice(None))) side2 = box_def.get_lonlats(data_slice=(slice(None), max_col)) side3 = box_def.get_lonlats(data_slice=(max_row, slice(None))) side4 = box_def.get_lonlats(data_slice=(slice(None), min_col)) tries = 0 while (tries < 500 and np.ma.count( box_def.get_lonlats(data_slice=(min_row, slice(None)))[1]) < 10): min_row += 1 tries += 1 if tries: side1 = box_def.get_lonlats(data_slice=(min_row + 1, slice(None))) log.info('Needed some data in side 1, incremented slice number ' + str(tries) + ' times. Now have ' + str(np.ma.count(side1[1])) + ' valid of ' + str(np.ma.count(side1[1].mask))) tries = 0 while (tries < 500 and np.ma.count( box_def.get_lonlats(data_slice=(slice(None), max_col))[0]) < 10): max_col -= 1 tries += 1 if tries: side2 = box_def.get_lonlats(data_slice=(slice(None), max_col - 1)) log.info('Needed some data in side 2, decremented slice number ' + str(tries) + ' times. Now have ' + str(np.ma.count(side2[0])) + ' valid of ' + str(np.ma.count(side2[0].mask))) tries = 0 while (tries < 500 and np.ma.count( box_def.get_lonlats(data_slice=(max_row, slice(None)))[0]) < 10): max_row -= 1 tries += 1 if tries: side3 = box_def.get_lonlats(data_slice=(max_row - 1, slice(None))) log.info('Needed some data in side 3, decremented slice number ' + str(tries) + ' times. Now have ' + str(np.ma.count(side3[0])) + ' valid of ' + str(np.ma.count(side3[0].mask))) tries = 0 while (tries < 500 and np.ma.count( box_def.get_lonlats(data_slice=(slice(None), min_col))[1]) < 10): min_col += 1 tries += 1 if tries: side4 = box_def.get_lonlats(data_slice=(slice(None), min_col + 1)) log.info('Needed some data in side 4, incremented slice number ' + str(tries) + ' times. Now have ' + str(np.ma.count(side4[1])) + ' valid of ' + str(np.ma.count(side4[1].mask))) #shell() # These all need to maintain mask. selflons = np.ma.concatenate((side1[0], side2[0], side3[0], side4[0])) selflons = np.ma.where(selflons < 0, selflons + 360, selflons) # MLS use wrap_longitudes? Figure out prime meridian vs dateline... #if side4[0].min() > side2[0].max(): # selflons = np.ma.where(selflons<0,selflons+360,selflons) selflats = np.ma.concatenate((side1[1], side2[1], side3[1], side4[1])) #self_corners = self.corners #other_corners = other.corners minlon = selflons.min() maxlon = selflons.max() # MLS use wrap_longitudes? if minlon > 180: minlon -= 360 if maxlon > 180: maxlon -= 360 minlat = selflats.min() maxlat = selflats.max() #print 'IN PlanarPolygonDefinition CORNERS for '+box_def.name+\ # ' min/max lat min/max lon:'+\ # str(minlat)+' '+str(maxlat)+' '+str(minlon)+' '+str(maxlon) from pyresample.spherical_geometry import Coordinate return [ Coordinate(minlon, maxlat), Coordinate(maxlon, maxlat), Coordinate(maxlon, minlat), Coordinate(minlon, minlat) ]
def intersection(self, other): """Says where, if two lines defined by the current line and the *other_line* intersect. """ log.info('self: ' + str(self) + ' other: ' + str(other)) if self == other: # Used to be return True, that is definitely not right (expects Coordinate) # Do we want start or end ? Does it matter? Lines are the same, everything is # an intersection. return self.start # If any of the start/end points match, return that point. if self.end == other.start or self.end == other.end: return self.end if self.start == other.start or self.start == other.end: return self.start # Line equation: y = mx + b # m = (y2-y1)/(x2-x1) # B_self = y - M_self*x # Pick any x/y on the line - try end point # B_self = self.end.lat - M_self*self.end.lon # B_other = other.end.lat - M_self*self.end.lon from pyresample.spherical_geometry import Coordinate selfendlon = self.end.lon selfstartlon = self.start.lon otherendlon = other.end.lon otherstartlon = other.start.lon # Not sure if this is necessary, or good... # if self.end.lon < 0: # selfendlon = self.end.lon + 2*math.pi # if self.start.lon < 0: # selfstartlon = self.start.lon + 2*math.pi # if other.end.lon < 0: # otherendlon = other.end.lon + 2*math.pi # if other.start.lon < 0: # otherstartlon = other.start.lon + 2*math.pi log.info(' self lons: ' + str(math.degrees(selfstartlon)) + ' ' + str(math.degrees(selfendlon)) + ' other lons: ' + str(math.degrees(otherstartlon)) + ' ' + str(math.degrees(otherendlon))) # If both vertical, will be no intersection if abs(selfendlon - selfstartlon) < EPSILON and abs( otherendlon - otherstartlon) < EPSILON: log.info(' Both vertical, no intersection') return None # If self is vertical, but not parallel, intersection will be selfstartlon and lat = Mother*lon+B_other if abs(selfendlon - selfstartlon) < EPSILON: lon = selfstartlon M_other = (other.end.lat - other.start.lat) / (otherendlon - otherstartlon) B_other = other.end.lat - M_other * otherendlon lat = M_other * lon + B_other log.info(' self is vertical') #Make sure it falls within the segment and not outside. # Previously was only checking lat, need to # also check lon or opposite side of world would match if (lat > min([self.end.lat, self.start.lat]) and lat < max([self.end.lat, self.start.lat]) and lon > min([otherendlon, otherstartlon]) and lon < max([otherendlon, otherstartlon])): log.info(' and intersects') # Apparently Coordinate takes degrees ??? And must be -180 to 180 ?! # MLS use wrap_longitudes? if lon > math.pi: lon -= 2 * math.pi return Coordinate(math.degrees(lon), math.degrees(lat)) else: return None # same for other if abs(otherendlon - otherstartlon) < EPSILON: lon = otherstartlon M_self = (self.end.lat - self.start.lat) / (selfendlon - selfstartlon) B_self = self.end.lat - M_self * selfendlon lat = M_self * lon + B_self log.info(' other is vertical') #Make sure it falls within the segment and not outside. # Previously was only checking lat, need to # also check lon or opposite side of world would match if (lat > min([other.end.lat, other.start.lat]) and lat < max([other.end.lat, other.start.lat]) and lon > min([selfendlon, selfstartlon]) and lon < max([selfendlon, selfstartlon])): log.info(' and intersects') # Apparently Coordinate takes degrees ??? And must be -180 to 180 ?! # MLS Use wrap_longitudes? if lon > math.pi: lon -= 2 * math.pi return Coordinate(math.degrees(lon), math.degrees(lat)) else: return None # Get slopes of the lines M_self = (self.end.lat - self.start.lat) / (selfendlon - selfstartlon) M_other = (other.end.lat - other.start.lat) / (otherendlon - otherstartlon) # If they are parallel, no intersection if (M_self - M_other) < EPSILON: log.info(' self and other are parallel, no intersection') return None # Get the y-intercepts of the lines B_self = self.end.lat - M_self * selfendlon B_other = other.end.lat - M_other * otherendlon # Solve the equation # y=m1x+b1 and y=m2x+b2, equate y's so m1x+b1=m2x+b2, x = (b1-b2)/(m2-m1) # equate x's so x=(y-b1)/m1=(y-b2)/m2, y = (b1m2-b2m1)/(m2-m1) lon = (B_self - B_other) / (M_other - M_self) lat = (B_self * M_other - B_other * M_self) / (M_other - M_self) # Make sure lat/lon intersects within the line segment, and not outside. if (lat > min([other.end.lat, other.start.lat]) and lat < max([other.end.lat, other.start.lat]) and lon > min([otherendlon, otherstartlon]) and lon < max([otherendlon, otherstartlon]) and lat > min([self.end.lat, self.start.lat]) and lat < max([self.end.lat, self.start.lat]) and lon > min([selfendlon, selfstartlon]) and lon < max([selfendlon, selfstartlon])): log.info(' self and other intersect within segment') # Apparently Coordinate takes degrees ??? And must be -180 to 180 ?! # MLS use wrap longitudes? if lon > math.pi: lon -= 2 * math.pi return Coordinate(math.degrees(lon), math.degrees(lat)) else: log.info(' self and other intersect, but not within segment') return None
def corners(self): """Returns the corners of the current area. """ try: # Try to just set normal CoordinateDefinition corners # (Which doesn't work with bad vals in corners) return super(CoordinateDefinition, self).corners except ValueError: #print ' Corners failed on CoordinateDefinition, try falsecorners' pass lons, lats = self.get_lonlats() #Determine which rows and columns contain good data rows = lons.any(axis=1) cols = lons.any(axis=0) #Get the minimum and maximum row and column that contain good data good_row_inds = np.where(~rows.mask)[0] min_row = good_row_inds.min() max_row = good_row_inds.max() good_col_inds = np.where(~cols.mask)[0] min_col = good_col_inds.min() max_col = good_col_inds.max() log.info(' USING FALSE CORNERS!! setting corners. min row/col: '+\ str(min_row)+' '+str(min_col)+' '+\ 'max row/col: '+str(max_row)+' '+str(max_col)+' '+\ 'shape: '+str(lons.shape)) #from .spherical import SCoordinate as Coordinate #from .spherical import Arc from pyresample.spherical_geometry import Coordinate, Arc #Calculate the eight possible corners and produce arcs for each pair #Corners for top side # Right side was failing with Divide by Zero error for NCC data because there was # a single good point in the max_col. Keep incrementing or decrementing until good.min # doesn't equal good.max good = np.where(~lons[min_row, :].mask)[0] tries = 0 while (tries < 20 and good.min() == good.max()): #print 'good.min() can\'t equal good.max() for top side, incrementing min_row! Would have failed with ZeroDivisionError before!' min_row += 1 tries += 1 good = np.where(~lons[min_row, :].mask)[0] top_corners = [ Coordinate(*self.get_lonlat(min_row, good.min())), Coordinate(*self.get_lonlat(min_row, good.max())) ] top_arc = Arc(top_corners[0], top_corners[1]) #Corners for bottom side good = np.where(~lons[max_row, :].mask)[0] tries = 0 while (tries < 20 and good.min() == good.max()): #print 'good.min() can\'t equal good.max() for bottom side, decrementing max_row! Would have failed with ZeroDivisionError before!' max_row -= 1 tries += 1 good = np.where(~lons[max_row, :].mask)[0] bot_corners = [ Coordinate(*self.get_lonlat(max_row, good.min())), Coordinate(*self.get_lonlat(max_row, good.max())) ] bot_arc = Arc(bot_corners[0], bot_corners[1]) #Corners for left side good = np.where(~lons[:, min_col].mask)[0] tries = 0 while (tries < 20 and good.min() == good.max()): #print 'good.min() can\'t equal good.max() for left side, incrementing min_col! Would have failed with ZeroDivisionError before!' min_col += 1 tries += 1 good = np.where(~lons[:, min_col].mask)[0] left_corners = [ Coordinate(*self.get_lonlat(good.min(), min_col)), Coordinate(*self.get_lonlat(good.max(), min_col)) ] left_arc = Arc(left_corners[0], left_corners[1]) #Corners for right side good = np.where(~lons[:, max_col].mask)[0] tries = 0 while (tries < 20 and good.min() == good.max()): #print 'good.min() can\'t equal good.max() for right side, decrementing max_col! Would have failed with ZeroDivisionError before!' max_col -= 1 tries += 1 good = np.where(~lons[:, max_col].mask)[0] right_corners = [ Coordinate(*self.get_lonlat(good.min(), max_col)), Coordinate(*self.get_lonlat(good.max(), max_col)) ] right_arc = Arc(right_corners[0], right_corners[1]) #Calculate the four false corners _corners = [] #Top left false corner top_intersections = top_arc.intersections(left_arc) dists = [inter.distance(top_corners[0]) for inter in top_intersections] if dists[0] < dists[1]: _corners.append(top_intersections[0]) else: _corners.append(top_intersections[1]) #Top right false corner top_intersections = top_arc.intersections(right_arc) dists = [inter.distance(top_corners[1]) for inter in top_intersections] if dists[0] < dists[1]: _corners.append(top_intersections[0]) else: _corners.append(top_intersections[1]) #Bottom right false corner bot_intersections = bot_arc.intersections(right_arc) dists = [inter.distance(bot_corners[1]) for inter in bot_intersections] if dists[0] < dists[1]: _corners.append(bot_intersections[0]) else: _corners.append(bot_intersections[1]) #Bottom left false corner bot_intersections = bot_arc.intersections(left_arc) dists = [inter.distance(bot_corners[0]) for inter in bot_intersections] if dists[0] < dists[1]: _corners.append(bot_intersections[0]) else: _corners.append(bot_intersections[1]) return _corners