class GridGenerator(object): """ This class subdivides the geographical extent of the United States into an equal area grid. Dependencies: /geography_helper.py /equal_area_globe_grid.py /united_states_border.json Usage: Let X be the desired area in square miles of each equal area cell >> GridGenerator(sqrt(X)).run() Output: /beautiful_grid.kml """ def __init__(self, cell_size_miles): # input is desired square of each equal area cell, in miles self._cell_size_miles = cell_size_miles # ecapsulating longitude/latitude boxes for Mainland, Alaska, Hawaii, Puerto Rico self._geo_reference = USABoundsReference().Geographies # we'll store each cell's shape array here self._shape_arrays = [] # a calculator that converts grid (column, row) to (longitude, latitude) and vice versa. # formulas given by the National Snow and Ice Data Center (see EqualAreaGlobeGrid doc-string for more info) self._proj_calc = EqualAreaGlobeGrid(self._cell_size_miles) def run(self): """ Public run method - generates an equal area grid for the United States """ self._load_US_boundary() self._create_equal_area_grid() self._save_to_kml() def _load_US_boundary(self): """ Loads a GeoJSON multipolygon created separately by merging the polygons provided here: https://developers.google.com/kml/documentation/us_states.kml """ geojson_multipolygon_file = open("united_states_border.json", "r") geojson_multipolygon = json.loads(geojson_multipolygon_file.read()) geojson_multipolygon_file.close() # create a shapely multipolygon - this will be used to determine if a generated grid cell lies within the USA self._US_boundary = MultiPolygon(geojson_multipolygon["coordinates"], context_type="geojson") def _create_equal_area_grid(self): """ For each region in the USA, calculate all equal area cells that either intersect, or are contained within that region. Each cell follows the numbering convention: Northwest Corner: (longitude_0, latitude_0) Northeast Corner: (longitude_1, latitude_1) Southeast Corner: (longitude_2, latitude_2) Southwest Corner: (longitude_3, latitude_3) """ # loop over all boxes bounding the separate US geographical regions (Mainland, Alaska, Hawaii, Puerto Rico) for region in self._geo_reference: # start in the northwest corner of the bounding box region_most_west_longitude = self._geo_reference[region]["west"] region_most_north_latitude = self._geo_reference[region]["north"] # get the starting grid column-row coordinate pair self._r_0, self._s_0 = self._proj_calc.get_grid_coordinates( region_most_west_longitude, region_most_north_latitude) start_longitude, start_latitude = self._proj_calc.get_longitude_latitude( self._r_0, self._s_0) # just renaming to keep the crawl semantically consistent latitude_crawl = start_latitude # row index relative to s_0 s = 0 # crawl southward while latitude_crawl > self._geo_reference[region]["south"]: # column index relative to r_0 r = 0 # reset the starting longitude (western-most of the region on the grid) longitude_crawl = start_longitude # crawl eastward while longitude_crawl < self._geo_reference[region]["east"]: # generate a cell, and return the new starting longitude and latitude longitude_crawl, latitude_crawl = self._generate_individual_cell( r, s) r += 1 s += 1 def _generate_individual_cell(self, r, s): # northwest corner longitude_0, latitude_0 = self._proj_calc.get_longitude_latitude( self._r_0 + r, self._s_0 + s) # northeast corner longitude_1, latitude_1 = self._proj_calc.get_longitude_latitude( self._r_0 + r + 1, self._s_0 + s) # southeast corner longitude_2, latitude_2 = self._proj_calc.get_longitude_latitude( self._r_0 + r + 1, self._s_0 + s + 1) # southwest corner longitude_3, latitude_3 = self._proj_calc.get_longitude_latitude( self._r_0 + r, self._s_0 + s + 1) shape_array = [[longitude_0, latitude_0], [longitude_1, latitude_1], [longitude_2, latitude_2], [longitude_3, latitude_3], [longitude_0, latitude_0]] # only add the shape array to the master list if it intersects or is contained within the USA if self._shape_is_in_US(shape_array): self._shape_arrays.append(shape_array) return longitude_3, latitude_0 def _shape_is_in_US(self, shape_array): # create shapely polygon out of the shape array square = Polygon(shape_array) # true if square either intersects the border of _US_boundary, or if it is included within the boundary return self._US_boundary.intersects(square) def _save_to_kml(self): """ Creates a KML file of this grid viewable in Google Maps and Google Earth. See https://developers.google.com/kml/documentation/ """ # call a helper method to convert this array of shape arrays to a KML file kml_text = convert_arrays_of_geocos_to_kml(self._shape_arrays) # save to a file in this directory beautiful_grid_file = open("beautiful_grid.kml", "w") beautiful_grid_file.write(kml_text) beautiful_grid_file.close()
class GridGenerator(object): """ This class subdivides the geographical extent of the United States into an equal area grid. Dependencies: /geography_helper.py /equal_area_globe_grid.py /united_states_border.json Usage: Let X be the desired area in square miles of each equal area cell >> GridGenerator(sqrt(X)).run() Output: /beautiful_grid.kml """ def __init__(self, cell_size_miles): # input is desired square of each equal area cell, in miles self._cell_size_miles = cell_size_miles # ecapsulating longitude/latitude boxes for Mainland, Alaska, Hawaii, Puerto Rico self._geo_reference = USABoundsReference().Geographies # we'll store each cell's shape array here self._shape_arrays = [] # a calculator that converts grid (column, row) to (longitude, latitude) and vice versa. # formulas given by the National Snow and Ice Data Center (see EqualAreaGlobeGrid doc-string for more info) self._proj_calc = EqualAreaGlobeGrid(self._cell_size_miles) def run(self): """ Public run method - generates an equal area grid for the United States """ self._load_US_boundary() self._create_equal_area_grid() self._save_to_kml() def _load_US_boundary(self): """ Loads a GeoJSON multipolygon created separately by merging the polygons provided here: https://developers.google.com/kml/documentation/us_states.kml """ geojson_multipolygon_file = open("united_states_border.json", "r") geojson_multipolygon = json.loads(geojson_multipolygon_file.read()) geojson_multipolygon_file.close() # create a shapely multipolygon - this will be used to determine if a generated grid cell lies within the USA self._US_boundary = MultiPolygon(geojson_multipolygon["coordinates"], context_type = "geojson") def _create_equal_area_grid(self): """ For each region in the USA, calculate all equal area cells that either intersect, or are contained within that region. Each cell follows the numbering convention: Northwest Corner: (longitude_0, latitude_0) Northeast Corner: (longitude_1, latitude_1) Southeast Corner: (longitude_2, latitude_2) Southwest Corner: (longitude_3, latitude_3) """ # loop over all boxes bounding the separate US geographical regions (Mainland, Alaska, Hawaii, Puerto Rico) for region in self._geo_reference: # start in the northwest corner of the bounding box region_most_west_longitude = self._geo_reference[region]["west"] region_most_north_latitude = self._geo_reference[region]["north"] # get the starting grid column-row coordinate pair self._r_0, self._s_0 = self._proj_calc.get_grid_coordinates(region_most_west_longitude, region_most_north_latitude) start_longitude, start_latitude = self._proj_calc.get_longitude_latitude(self._r_0, self._s_0) # just renaming to keep the crawl semantically consistent latitude_crawl = start_latitude # row index relative to s_0 s = 0 # crawl southward while latitude_crawl > self._geo_reference[region]["south"]: # column index relative to r_0 r = 0 # reset the starting longitude (western-most of the region on the grid) longitude_crawl = start_longitude # crawl eastward while longitude_crawl < self._geo_reference[region]["east"]: # generate a cell, and return the new starting longitude and latitude longitude_crawl, latitude_crawl = self._generate_individual_cell(r, s) r += 1 s += 1 def _generate_individual_cell(self, r, s): # northwest corner longitude_0, latitude_0 = self._proj_calc.get_longitude_latitude(self._r_0 + r, self._s_0 + s) # northeast corner longitude_1, latitude_1 = self._proj_calc.get_longitude_latitude(self._r_0 + r + 1, self._s_0 + s) # southeast corner longitude_2, latitude_2 = self._proj_calc.get_longitude_latitude(self._r_0+ r + 1, self._s_0 + s + 1) # southwest corner longitude_3, latitude_3 = self._proj_calc.get_longitude_latitude(self._r_0 + r, self._s_0 + s + 1) shape_array = [ [longitude_0, latitude_0], [longitude_1, latitude_1], [longitude_2, latitude_2], [longitude_3, latitude_3], [longitude_0, latitude_0] ] # only add the shape array to the master list if it intersects or is contained within the USA if self._shape_is_in_US(shape_array): self._shape_arrays.append(shape_array) return longitude_3, latitude_0 def _shape_is_in_US(self, shape_array): # create shapely polygon out of the shape array square = Polygon(shape_array) # true if square either intersects the border of _US_boundary, or if it is included within the boundary return self._US_boundary.intersects(square) def _save_to_kml(self): """ Creates a KML file of this grid viewable in Google Maps and Google Earth. See https://developers.google.com/kml/documentation/ """ # call a helper method to convert this array of shape arrays to a KML file kml_text = convert_arrays_of_geocos_to_kml(self._shape_arrays) # save to a file in this directory beautiful_grid_file = open("beautiful_grid.kml", "w") beautiful_grid_file.write(kml_text) beautiful_grid_file.close()