def create_country_geojson(): ''' Creates the countries.geojson file which contains geometries ([Multi]Polygon) for each country in longitude/latitude coordinates. Each country geometry is derived by merging the corresponding cluster geometries from the Shapefile, reprojecting to longitude/latitude, and simplifying the resulting polygons to reduce data volume. ''' # FIXME German clusters can't be merged properly as there are sliver polygons, which means that some inner boundaries remain! # problem description and solution: http://gis.stackexchange.com/a/71729 # tried that in GRASS but got a crash: https://trac.osgeo.org/grass/ticket/3061 inDriver = ogr.GetDriverByName(ESRI_SHP) inDataSource = inDriver.Open(PATH_CLUSTERSHP) inLayer = inDataSource.GetLayer() outGeoJSON = PATH_COUNTRYGEOJSON outDriver = ogr.GetDriverByName(GEOJSON) if os.path.exists(outGeoJSON): outDriver.DeleteDataSource(outGeoJSON) os.makedirs(os.path.dirname(outGeoJSON), exist_ok=True) outDataSource = outDriver.CreateDataSource(outGeoJSON) outLayer = outDataSource.CreateLayer("countries", WGS84, ogr.wkbPolygon, GEOJSON_OPTIONS) outLayer.CreateField(ogr.FieldDefn(GEOJSON_COUNTRY_CODE, ogr.OFTString)) coordTrans = osr.CoordinateTransformation(inLayer.GetSpatialRef(), WGS84) # merge cluster geometries by country for country_code, cluster_codes in get_clusters_by_country().items(): inLayer.ResetReading() country_features = [ feature for feature in inLayer if feature.GetField(SHP_CLUSTER_CODE) in cluster_codes ] country_geoms = [ feature.GetGeometryRef() for feature in country_features ] # Buffer(0) is done to fix invalid geometry (NO_C3 cluster has self-intersecting polygons) # otherwise the Union operation would fail country_geoms = [geom.Buffer(0) for geom in country_geoms] merged_geom = reduce(lambda l, r: l.Union(r), country_geoms) merged_geom.Transform(coordTrans) merged_geom = merged_geom.SimplifyPreserveTopology( POLYGON_SIMPLIFY_TOLERANCE) merged_feature = ogr.Feature(outLayer.GetLayerDefn()) merged_feature.SetGeometry(merged_geom) merged_feature.SetField(GEOJSON_COUNTRY_CODE, country_code) outLayer.CreateFeature(merged_feature) inDataSource.Destroy() outDataSource.Destroy() minify_json(outGeoJSON)
def create_cluster_geojson(): ''' Creates the clusters.geojson file which contains geometries ([Multi]Polygon) for each cluster in longitude/latitude coordinates. Each cluster geometry is derived by reading the geometry from the Shapefile, reprojecting to longitude/latitude, and simplifying the resulting polygons to reduce data volume. Definition of clusters: http://www.e-highway2050.eu/fileadmin/documents/Results/D2_2_European_cluster_model_of_the_Pan-European_transmission_grid_20072015.pdf ''' inDriver = ogr.GetDriverByName(ESRI_SHP) inDataSource = inDriver.Open(PATH_CLUSTERSHP) inLayer = inDataSource.GetLayer() outGeoJSON = PATH_CLUSTERGEOJSON outDriver = ogr.GetDriverByName(GEOJSON) if os.path.exists(outGeoJSON): outDriver.DeleteDataSource(outGeoJSON) os.makedirs(os.path.dirname(outGeoJSON), exist_ok=True) outDataSource = outDriver.CreateDataSource(outGeoJSON) outLayer = outDataSource.CreateLayer("clusters", WGS84, ogr.wkbPolygon, GEOJSON_OPTIONS) outLayer.CreateField(ogr.FieldDefn(GEOJSON_CLUSTER_CODE, ogr.OFTString)) outLayer.CreateField(ogr.FieldDefn(GEOJSON_COUNTRY_CODE, ogr.OFTString)) outLayer.CreateField(ogr.FieldDefn(GEOJSON_COLOR_IDX, ogr.OFTInteger)) coordTrans = osr.CoordinateTransformation(inLayer.GetSpatialRef(), WGS84) clusters = get_clusters() for feature in inLayer: cluster_code = feature.GetField(SHP_CLUSTER_CODE) if cluster_code not in clusters: continue geom = feature.GetGeometryRef() geom.Transform(coordTrans) geom = geom.SimplifyPreserveTopology(POLYGON_SIMPLIFY_TOLERANCE) out_feature = ogr.Feature(outLayer.GetLayerDefn()) out_feature.SetGeometry(geom) out_feature.SetField(GEOJSON_CLUSTER_CODE, cluster_code) out_feature.SetField(GEOJSON_COUNTRY_CODE, clusters[cluster_code]) out_feature.SetField(GEOJSON_COLOR_IDX, feature.GetField(SHP_COLOR_IDX)) outLayer.CreateFeature(out_feature) inDataSource.Destroy() outDataSource.Destroy() minify_json(outGeoJSON)
def create_country_geojson(): ''' Creates the countries.geojson file which contains geometries ([Multi]Polygon) for each country in longitude/latitude coordinates. Each country geometry is derived by merging the corresponding cluster geometries from the Shapefile, reprojecting to longitude/latitude, and simplifying the resulting polygons to reduce data volume. ''' # FIXME German clusters can't be merged properly as there are sliver polygons, which means that some inner boundaries remain! # problem description and solution: http://gis.stackexchange.com/a/71729 # tried that in GRASS but got a crash: https://trac.osgeo.org/grass/ticket/3061 inDriver = ogr.GetDriverByName(ESRI_SHP) inDataSource = inDriver.Open(PATH_CLUSTERSHP) inLayer = inDataSource.GetLayer() outGeoJSON = PATH_COUNTRYGEOJSON outDriver = ogr.GetDriverByName(GEOJSON) if os.path.exists(outGeoJSON): outDriver.DeleteDataSource(outGeoJSON) os.makedirs(os.path.dirname(outGeoJSON), exist_ok=True) outDataSource = outDriver.CreateDataSource(outGeoJSON) outLayer = outDataSource.CreateLayer("countries", WGS84, ogr.wkbPolygon, GEOJSON_OPTIONS) outLayer.CreateField(ogr.FieldDefn(GEOJSON_COUNTRY_CODE, ogr.OFTString)) coordTrans = osr.CoordinateTransformation(inLayer.GetSpatialRef(), WGS84) # merge cluster geometries by country for country_code, cluster_codes in get_clusters_by_country().items(): inLayer.ResetReading() country_features = [feature for feature in inLayer if feature.GetField(SHP_CLUSTER_CODE) in cluster_codes] country_geoms = [feature.GetGeometryRef() for feature in country_features] # Buffer(0) is done to fix invalid geometry (NO_C3 cluster has self-intersecting polygons) # otherwise the Union operation would fail country_geoms = [geom.Buffer(0) for geom in country_geoms] merged_geom = reduce(lambda l, r: l.Union(r), country_geoms) merged_geom.Transform(coordTrans) merged_geom = merged_geom.SimplifyPreserveTopology(POLYGON_SIMPLIFY_TOLERANCE) merged_feature = ogr.Feature(outLayer.GetLayerDefn()) merged_feature.SetGeometry(merged_geom) merged_feature.SetField(GEOJSON_COUNTRY_CODE, country_code) outLayer.CreateFeature(merged_feature) inDataSource.Destroy() outDataSource.Destroy() minify_json(outGeoJSON)