def cut_dateline(vertices): """Cut a polygon across the dateline, possibly splitting it into multiple polygons. Vertices consist of (longitude, latitude) pairs where longitude is always given in terms of a reference angle (between -pi and pi). This routine is not meant to cover all possible cases; it will only work for convex polygons that extend over less than a hemisphere.""" out_vertices = [] # Ensure that the list of vertices does not contain a repeated endpoint. if (vertices[0, :] == vertices[-1, :]).all(): vertices = vertices[:-1, :] def count_dateline_crossings(phis): n = 0 for i in range(len(phis)): if crosses_dateline(phis[i - 1], phis[i]): n += 1 return n def crosses_dateline(phi0, phi1): """Test if the segment consisting of v0 and v1 croses the meridian.""" phi0, phi1 = sorted((phi0, phi1)) return phi1 - phi0 > np.pi dateline_crossings = count_dateline_crossings(vertices[:, 0]) if dateline_crossings % 2: # Determine index of the (unique) line segment that crosses the dateline. for i in range(len(vertices)): v0 = vertices[i - 1, :] v1 = vertices[i, :] if crosses_dateline(v0[0], v1[0]): delta_lat = abs(reference_angle(v1[0] - v0[0])) lat = (np.pi - abs(v0[0])) / delta_lat * v0[1] + (np.pi - abs(v1[0])) / delta_lat * v1[1] out_vertices += [np.vstack((vertices[:i, :], [ [np.sign(v0[0]) * np.pi, lat], [np.sign(v0[0]) * np.pi, np.sign(lat) * np.pi / 2], [-np.sign(v0[0]) * np.pi, np.sign(lat) * np.pi / 2], [-np.sign(v0[0]) * np.pi, lat], ], vertices[i:, :]))] break elif dateline_crossings: frame_poly = geos.Polygon(np.array([[-np.pi, np.pi/2], [-np.pi, -np.pi/2], [np.pi, -np.pi/2], [np.pi, np.pi/2]])) poly = geos.Polygon(np.vstack((vertices[:, 0] % (2 * np.pi), vertices[:, 1])).T) if poly.intersects(frame_poly): out_vertices += [p.get_coords() for p in poly.intersection(frame_poly)] poly = geos.Polygon(np.vstack((vertices[:, 0] % (-2 * np.pi), vertices[:, 1])).T) if poly.intersects(frame_poly): out_vertices += [p.get_coords() for p in poly.intersection(frame_poly)] else: out_vertices += [vertices] return out_vertices
def cut_prime_meridian(vertices): """Cut a polygon across the prime meridian, possibly splitting it into multiple polygons. Vertices consist of (longitude, latitude) pairs where longitude is always given in terms of a wrapped angle (between 0 and 2*pi). This routine is not meant to cover all possible cases; it will only work for convex polygons that extend over less than a hemisphere.""" out_vertices = [] # Ensure that the list of vertices does not contain a repeated endpoint. if (vertices[0, :] == vertices[-1, :]).all(): vertices = vertices[:-1, :] # Ensure that the longitudes are wrapped from 0 to 2*pi. vertices = np.vstack((wrapped_angle(vertices[:, 0]), vertices[:, 1])).T def count_meridian_crossings(phis): n = 0 for i in range(len(phis)): if crosses_meridian(phis[i - 1], phis[i]): n += 1 return n def crosses_meridian(phi0, phi1): """Test if the segment consisting of v0 and v1 croses the meridian.""" # If the two angles are in [0, 2pi), then the shortest arc connecting # them crosses the meridian if the difference of the angles is greater # than pi. phi0, phi1 = sorted((phi0, phi1)) return phi1 - phi0 > np.pi # Count the number of times that the polygon crosses the meridian. meridian_crossings = count_meridian_crossings(vertices[:, 0]) if meridian_crossings % 2: # If there are an odd number of meridian crossings, then the polygon # encloses the pole. Any meridian-crossing edge has to be extended # into a curve following the nearest polar edge of the map. for i in range(len(vertices)): v0 = vertices[i - 1, :] v1 = vertices[i, :] # Loop through the edges until we find one that crosses the meridian. if crosses_meridian(v0[0], v1[0]): # If this segment crosses the meridian, then fill it to # the edge of the map by inserting new line segments. # Find the latitude at which the meridian crossing occurs by # linear interpolation. delta_lon = abs(reference_angle(v1[0] - v0[0])) lat = abs(reference_angle(v0[0])) / delta_lon * v0[1] + abs( reference_angle(v1[0])) / delta_lon * v1[1] # Find the closer of the left or the right map boundary for # each vertex in the line segment. lon_0 = 0. if v0[0] < np.pi else 2 * np.pi lon_1 = 0. if v1[0] < np.pi else 2 * np.pi # Set the output vertices to the polar cap plus the original # vertices. out_vertices += [ np.vstack((vertices[:i, :], [ [lon_0, lat], [lon_0, np.sign(lat) * np.pi / 2], [lon_1, np.sign(lat) * np.pi / 2], [lon_1, lat], ], vertices[i:, :])) ] # Since the polygon is assumed to be convex, the only possible # odd number of meridian crossings is 1, so we are now done. break elif meridian_crossings: # Since the polygon is assumed to be convex, if there is an even number # of meridian crossings, we know that the polygon does not enclose # either pole. Then we can use ordinary Euclidean polygon intersection # algorithms. # Construct polygon representing map boundaries in longitude and latitude. frame_poly = geos.Polygon( np.array([[0., np.pi / 2], [0., -np.pi / 2], [2 * np.pi, -np.pi / 2], [2 * np.pi, np.pi / 2]])) # Intersect with polygon re-wrapped to lie in [pi, 3*pi). poly = geos.Polygon( np.vstack( (reference_angle(vertices[:, 0]) + 2 * np.pi, vertices[:, 1])).T) if poly.intersects(frame_poly): out_vertices += [ p.get_coords() for p in poly.intersection(frame_poly) ] # Intersect with polygon re-wrapped to lie in [-pi, pi). poly = geos.Polygon( np.vstack((reference_angle(vertices[:, 0]), vertices[:, 1])).T) if poly.intersects(frame_poly): out_vertices += [ p.get_coords() for p in poly.intersection(frame_poly) ] else: # Otherwise, there were zero meridian crossings, so we can use the # original vertices as is. out_vertices += [vertices] # Done! return out_vertices
lon_1 = xlon[row][col+1] lon_2 = xlon[row+1][col+1] lon_3 = xlon[row+1][col] lat_0 = xlat[row][col] lat_1 = xlat[row][col+1] lat_2 = xlat[row+1][col+1] lat_3 = xlat[row+1][col] data = Conc_var[row][col] if data > 0: if row % 10 == 0 and col % 10 == 0: print row,col cell_vertices = np.array([m(lon_0,lat_0),m(lon_1,lat_1),m(lon_2,lat_2),m(lon_3,lat_3)]) cell_poly = _geoslib.Polygon(cell_vertices) #tundra fraction = 0 for info, shape in zip(m.surface_cover_info, m.surface_cover): #print info if info['DN'] == 1 and info['RINGNUM'] == 1: patch = Polygon(np.array(shape), True) poly = _geoslib.Polygon(patch.get_path().vertices) fraction, intersection_poly = INP.calcPolygonOverlapArea(cell_poly, poly,fraction) if fraction >= 1: break land_grid[row][col] = max(0,fraction)