def singlepart_to_multipart( vector: Union[List[Union[str, ogr.DataSource]], Union[str, ogr.DataSource]], out_path: str = None, overwrite: bool = True, add_index: bool = True, process_layer: int = -1, ) -> Union[List[str], str]: type_check(vector, [list, str, ogr.DataSource], "vector") type_check(out_path, [str], "out_path", allow_none=True) type_check(overwrite, [bool], "overwrite") type_check(add_index, [bool], "add_index") type_check(process_layer, [int], "process_layer") vector_list, path_list = ready_io_vector(vector, out_path, overwrite=overwrite) output = [] for index, in_vector in enumerate(vector_list): output.append( internal_singlepart_to_multipart( in_vector, out_path=path_list[index], overwrite=overwrite, add_index=add_index, process_layer=process_layer, ) ) if isinstance(vector, list): return output[0] return output
def clip_vector( vector: Union[List[Union[str, ogr.DataSource]], Union[str, ogr.DataSource]], clip_geom: Union[str, ogr.DataSource, gdal.Dataset], out_path: str = None, process_layer: int = 0, process_layer_clip: int = 0, to_extent: bool = False, target_projection: Union[str, ogr.DataSource, gdal.Dataset, osr.SpatialReference, int] = None, preserve_fid: bool = True, prefix: str = "", postfix: str = "", add_uuid: bool = False, ) -> Union[List[str], str]: """Clips a vector to a geometry. Returns: A clipped ogr.Datasource or the path to one. """ type_check(vector, [list, str, ogr.DataSource], "vector") type_check(clip_geom, [ogr.DataSource, gdal.Dataset, str, list, tuple], "clip_geom") type_check(out_path, [str], "out_path", allow_none=True) type_check(process_layer, [int], "process_layer") type_check(process_layer_clip, [int], "process_layer_clip") type_check(to_extent, [bool], "to_extent") type_check( target_projection, [str, ogr.DataSource, gdal.Dataset, osr.SpatialReference, int], "target_projection", allow_none=True, ) type_check(preserve_fid, [bool], "preserve_fid") vector_list, path_list = ready_io_vector(vector, out_path, prefix=prefix, postfix=postfix, add_uuid=add_uuid) output: List[str] = [] for index, in_vector in enumerate(vector_list): output.append( internal_clip_vector( in_vector, clip_geom, out_path=path_list[index], process_layer=process_layer, process_layer_clip=process_layer_clip, to_extent=to_extent, target_projection=target_projection, preserve_fid=preserve_fid, )) if isinstance(vector, list): return output return output[0]
def reproject_vector( vector: Union[List[Union[str, ogr.DataSource]], Union[str, ogr.DataSource]], projection: Union[str, int, ogr.DataSource, gdal.Dataset, osr.SpatialReference], out_path: Optional[str] = None, copy_if_same: bool = False, overwrite: bool = True, ) -> Union[List[str], str]: """Reprojects a vector given a target projection. Args: vector (path | vector): The vector to reproject. projection (str | int | vector | raster): The projection is infered from the input. The input can be: WKT proj, EPSG proj, Proj, or read from a vector or raster datasource either from path or in-memory. **kwargs: out_path (path | None): The destination to save to. If None then the output is an in-memory raster. overwite (bool): Is it possible to overwrite the out_path if it exists. Returns: An in-memory vector. If an out_path is given, the output is a string containing the path to the newly created vecotr. """ type_check(vector, [str, ogr.DataSource], "vector") type_check( projection, [str, int, ogr.DataSource, gdal.Dataset, osr.SpatialReference], "projection", ) type_check(out_path, [str], "out_path", allow_none=True) type_check(copy_if_same, [bool], "copy_if_same") type_check(overwrite, [bool], "overwrite") vector_list, path_list = ready_io_vector(vector, out_path, overwrite=overwrite) output = [] for index, in_vector in enumerate(vector_list): output.append( internal_reproject_vector( in_vector, projection, out_path=path_list[index], copy_if_same=copy_if_same, overwrite=overwrite, )) if isinstance(vector, list): return output return output[0]
def intersect_vector( vector: Union[List[Union[str, ogr.DataSource]], str, ogr.DataSource], clip_geom: Union[ List[Union[str, ogr.DataSource, gdal.Dataset]], gdal.Dataset, ogr.DataSource, str, ], out_path: str = None, to_extent: bool = False, process_layer: int = 0, process_layer_clip: int = 0, add_index: bool = True, preserve_fid: bool = True, overwrite: bool = True, ) -> Union[List[str], str]: """Clips a vector to a geometry.""" type_check(vector, [ogr.DataSource, str, list], "vector") type_check(clip_geom, [ogr.DataSource, gdal.Dataset, str, list, tuple], "clip_geom") type_check(out_path, [str], "out_path", allow_none=True) type_check(to_extent, [bool], "to_extent") type_check(process_layer, [int], "process_layer") type_check(process_layer_clip, [int], "process_layer_clip") type_check(add_index, [bool], "add_index") type_check(preserve_fid, [bool], "preserve_fid") type_check(overwrite, [bool], "overwrite") vector_list, path_list = ready_io_vector(vector, out_path, overwrite=overwrite) output = [] for index, in_vector in enumerate(vector_list): output.append( internal_intersect_vector( in_vector, clip_geom, out_path=path_list[index], to_extent=to_extent, process_layer=process_layer, process_layer_clip=process_layer_clip, add_index=add_index, preserve_fid=preserve_fid, overwrite=overwrite, ) ) if isinstance(vector, list): return output return output[0]
def dissolve_vector( vector: Union[List[Union[str, ogr.DataSource]], str, ogr.DataSource], attribute: Optional[str] = None, out_path: str = None, overwrite: bool = True, add_index: bool = True, process_layer: int = -1, ) -> Union[List[str], str]: """Clips a vector to a geometry. Args: vector (list of vectors | path | vector): The vectors(s) to clip. clip_geom (list of geom | path | vector | rasters): The geometry to use for the clipping **kwargs: Returns: A clipped ogr.Datasource or the path to one. """ type_check(vector, [ogr.DataSource, str, list], "vector") type_check(attribute, [str], "attribute", allow_none=True) type_check(out_path, [str], "out_path", allow_none=True) type_check(overwrite, [bool], "overwrite") type_check(add_index, [bool], "add_index") type_check(process_layer, [int], "process_layer") raster_list, path_list = ready_io_vector(vector, out_path) output = [] for index, in_vector in enumerate(raster_list): output.append( internal_dissolve_vector( in_vector, attribute=attribute, out_path=path_list[index], overwrite=overwrite, add_index=add_index, process_layer=process_layer, )) if isinstance(vector, list): return output return output[0]
def internal_singlepart_to_multipart( vector: Union[str, ogr.DataSource], out_path: Optional[str] = None, overwrite: bool = True, add_index: bool = True, process_layer: int = -1, ) -> str: type_check(vector, [str, ogr.DataSource], "vector") type_check(out_path, [str], "out_path", allow_none=True) type_check(overwrite, [bool], "overwrite") type_check(add_index, [bool], "add_index") type_check(process_layer, [int], "process_layer") vector_list, path_list = ready_io_vector(vector, out_path, overwrite=overwrite) ref = open_vector(vector_list[0]) out_name = path_list[0] out_format = path_to_driver_vector(out_name) driver = ogr.GetDriverByName(out_format) overwrite_required(out_name, overwrite) metadata = internal_vector_to_metadata(ref) remove_if_overwrite(out_name, overwrite) destination: ogr.DataSource = driver.CreateDataSource(out_name) for index, layer_meta in enumerate(metadata["layers"]): if process_layer != -1 and index != process_layer: continue name = layer_meta["layer_name"] geom = layer_meta["column_geom"] sql = f"SELECT ST_Collect({geom}) AS geom FROM {name};" result = ref.ExecuteSQL(sql, dialect="SQLITE") destination.CopyLayer(result, name, ["OVERWRITE=YES"]) if add_index: vector_add_index(destination) destination.FlushCache() return out_name
def multipart_to_singlepart( vector: Union[List[Union[str, ogr.DataSource]], Union[str, ogr.DataSource]], out_path: Optional[Union[List[str], str]] = None, copy_attributes: bool = False, overwrite: bool = True, add_index: bool = True, process_layer: int = -1, verbose: int = 1, ) -> Union[List[str], str]: type_check(vector, [ogr.DataSource, str, list], "vector") type_check(out_path, [str], "out_path", allow_none=True) type_check(copy_attributes, [bool], "copy_attributes") type_check(overwrite, [bool], "overwrite") type_check(add_index, [bool], "add_index") type_check(process_layer, [int], "process_layer") type_check(verbose, [int], "verbose") vector_list, path_list = ready_io_vector(vector, out_path, overwrite=overwrite) output = [] for index, in_vector in enumerate(vector_list): output.append( internal_multipart_to_singlepart( in_vector, out_path=path_list[index], copy_attributes=copy_attributes, overwrite=overwrite, add_index=add_index, process_layer=process_layer, verbose=verbose, ) ) if isinstance(vector, list): return output[0] return output
def internal_intersect_vector( vector: Union[str, ogr.DataSource], clip_geom: Union[str, ogr.DataSource, gdal.Dataset], out_path: Optional[str] = None, to_extent: bool = False, process_layer: int = 0, process_layer_clip: int = 0, add_index: bool = True, preserve_fid: bool = True, overwrite: bool = True, return_bool: bool = False, ) -> str: """Clips a vector to a geometry. Returns: A clipped ogr.Datasource or the path to one. """ type_check(vector, [ogr.DataSource, str, list], "vector") type_check(clip_geom, [ogr.DataSource, gdal.Dataset, str, list, tuple], "clip_geom") type_check(out_path, [str], "out_path", allow_none=True) type_check(to_extent, [bool], "to_extent") type_check(process_layer, [int], "process_layer") type_check(process_layer_clip, [int], "process_layer_clip") type_check(add_index, [bool], "add_index") type_check(preserve_fid, [bool], "preserve_fid") type_check(overwrite, [bool], "overwrite") _vector_list, path_list = ready_io_vector(vector, out_path, overwrite=overwrite) out_name = path_list[0] match_projection = internal_reproject_vector(clip_geom, vector) geometry_to_clip = open_vector(match_projection) merged = open_vector(merge_vectors([vector, match_projection])) if add_index: vector_add_index(merged) vector_metadata = internal_vector_to_metadata(vector) vector_layername = vector_metadata["layers"][process_layer]["layer_name"] vector_geom_col = vector_metadata["layers"][process_layer]["column_geom"] clip_geom_metadata = internal_vector_to_metadata(geometry_to_clip) clip_geom_layername = clip_geom_metadata["layers"][process_layer_clip]["layer_name"] clip_geom_col = clip_geom_metadata["layers"][process_layer_clip]["column_geom"] if return_bool: sql = f"SELECT A.* FROM '{vector_layername}' A, '{clip_geom_layername}' B WHERE ST_INTERSECTS(A.{vector_geom_col}, B.{clip_geom_col});" else: sql = f"SELECT A.* FROM '{vector_layername}' A, '{clip_geom_layername}' B WHERE ST_INTERSECTS(A.{vector_geom_col}, B.{clip_geom_col});" result = merged.ExecuteSQL(sql, dialect="SQLITE") if return_bool: if result.GetFeatureCount() == 0: return False else: return True driver = ogr.GetDriverByName(path_to_driver_vector(out_name)) destination: ogr.DataSource = driver.CreateDataSource(out_name) destination.CopyLayer(result, vector_layername, ["OVERWRITE=YES"]) if destination is None: raise Exception("Error while running intersect.") destination.FlushCache() return out_name
def internal_reproject_vector( vector: Union[str, ogr.DataSource], projection: Union[str, int, ogr.DataSource, gdal.Dataset, osr.SpatialReference], out_path: Optional[str] = None, copy_if_same: bool = False, overwrite: bool = True, ) -> str: type_check(vector, [str, ogr.DataSource], "vector") type_check( projection, [str, int, ogr.DataSource, gdal.Dataset, osr.SpatialReference], "projection", ) type_check(out_path, [str], "out_path", allow_none=True) type_check(copy_if_same, [bool], "copy_if_same") type_check(overwrite, [bool], "overwrite") vector_list, path_list = ready_io_vector(vector, out_path, overwrite=overwrite) origin = open_vector(vector_list[0]) metadata = internal_vector_to_metadata(origin) out_name = path_list[0] origin_projection = metadata["projection_osr"] target_projection = parse_projection(projection) if not isinstance(target_projection, osr.SpatialReference): raise Exception("Error ") if origin_projection.IsSame(target_projection): if copy_if_same: if out_path is None: return internal_vector_to_memory(origin) return internal_vector_to_disk(origin, out_name) else: return get_vector_path(vector) # GDAL 3 changes axis order: https://github.com/OSGeo/gdal/issues/1546 if int(osgeo.__version__[0]) >= 3: origin_projection.SetAxisMappingStrategy( osr.OAMS_TRADITIONAL_GIS_ORDER) target_projection.SetAxisMappingStrategy( osr.OAMS_TRADITIONAL_GIS_ORDER) coord_trans = osr.CoordinateTransformation(origin_projection, target_projection) remove_if_overwrite(out_path, overwrite) driver = ogr.GetDriverByName(path_to_driver_vector(out_name)) destination: ogr.DataSource = driver.CreateDataSource(out_name) for layer_idx in range(len(metadata["layers"])): origin_layer = origin.GetLayerByIndex(layer_idx) origin_layer_defn = origin_layer.GetLayerDefn() layer_dict = metadata["layers"][layer_idx] layer_name = layer_dict["layer_name"] layer_geom_type = layer_dict["geom_type_ogr"] destination_layer = destination.CreateLayer(layer_name, target_projection, layer_geom_type) destination_layer_defn = destination_layer.GetLayerDefn() # Copy field definitions origin_layer_defn = origin_layer.GetLayerDefn() for i in range(0, origin_layer_defn.GetFieldCount()): field_defn = origin_layer_defn.GetFieldDefn(i) destination_layer.CreateField(field_defn) # Loop through the input features for _ in range(origin_layer.GetFeatureCount()): feature = origin_layer.GetNextFeature() geom = feature.GetGeometryRef() geom.Transform(coord_trans) new_feature = ogr.Feature(destination_layer_defn) new_feature.SetGeometry(geom) # Copy field values for i in range(0, destination_layer_defn.GetFieldCount()): new_feature.SetField( destination_layer_defn.GetFieldDefn(i).GetNameRef(), feature.GetField(i), ) destination_layer.CreateFeature(new_feature) destination_layer.ResetReading() destination_layer = None destination.FlushCache() return out_name
def internal_dissolve_vector( vector: Union[str, ogr.DataSource], attribute: Optional[str] = None, out_path: str = None, overwrite: bool = True, add_index: bool = True, process_layer: int = -1, ) -> str: """Clips a vector to a geometry.""" type_check(vector, [str, ogr.DataSource], "vector") type_check(attribute, [str], "attribute", allow_none=True) type_check(out_path, [str], "out_path", allow_none=True) type_check(overwrite, [bool], "overwrite") type_check(add_index, [bool], "add_index") type_check(process_layer, [int], "process_layer") vector_list, path_list = ready_io_vector(vector, out_path) out_name = path_list[0] out_format = path_to_driver_vector(out_name) driver = ogr.GetDriverByName(out_format) ref = open_vector(vector_list[0]) metadata = internal_vector_to_metadata(ref) Layer_info = TypedDict( "Layer_info", { "name": str, "geom": str, "fields": List[str] }, ) layers: List[Layer_info] = [] if process_layer == -1: for index in range(len(metadata["layers"])): layers.append({ "name": metadata["layers"][index]["layer_name"], "geom": metadata["layers"][index]["column_geom"], "fields": metadata["layers"][index]["field_names"], }) else: layers.append({ "name": metadata["layers"][process_layer]["layer_name"], "geom": metadata["layers"][process_layer]["column_geom"], "fields": metadata["layers"][process_layer]["field_names"], }) destination: ogr.DataSource = driver.CreateDataSource(out_name) # Check if attribute table is valid for index in range(len(metadata["layers"])): layer = layers[index] if attribute is not None and attribute not in layer["fields"]: layer_fields = layer["fields"] raise ValueError( f"Invalid attribute for layer. Layers has the following fields: {layer_fields}" ) geom_col = layer["geom"] name = layer["name"] sql = None if attribute is None: sql = f"SELECT ST_Union({geom_col}) AS geom FROM {name};" else: sql = f"SELECT {attribute}, ST_Union({geom_col}) AS geom FROM {name} GROUP BY {attribute};" result = ref.ExecuteSQL(sql, dialect="SQLITE") destination.CopyLayer(result, name, ["OVERWRITE=YES"]) if add_index: vector_add_index(destination) destination.FlushCache() return out_name
def internal_multipart_to_singlepart( vector: Union[str, ogr.DataSource], out_path: Optional[str] = None, copy_attributes: bool = False, overwrite: bool = True, add_index: bool = True, process_layer: int = -1, verbose: int = 1, ) -> str: type_check(vector, [str, ogr.DataSource], "vector") type_check(out_path, [str], "out_path", allow_none=True) type_check(overwrite, [bool], "overwrite") type_check(add_index, [bool], "add_index") type_check(process_layer, [int], "process_layer") type_check(verbose, [int], "verbose") vector_list, path_list = ready_io_vector(vector, out_path, overwrite=overwrite) ref = open_vector(vector_list[0]) out_name = path_list[0] driver = ogr.GetDriverByName(path_to_driver_vector(out_name)) metadata = internal_vector_to_metadata(ref) remove_if_overwrite(out_name, overwrite) destination = driver.CreateDataSource(out_name) for index, layer_meta in enumerate(metadata["layers"]): if process_layer != -1 and index != process_layer: continue if verbose == 1: layer_name = layer_meta["layer_name"] print(f"Splitting layer: {layer_name}") target_unknown = False if layer_meta["geom_type_ogr"] == 4: # MultiPoint target_type = 1 # Point elif layer_meta["geom_type_ogr"] == 5: # MultiLineString target_type = 2 # LineString elif layer_meta["geom_type_ogr"] == 6: # MultiPolygon target_type = 3 # Polygon elif layer_meta["geom_type_ogr"] == 1004: # MultiPoint (z) target_type = 1001 # Point (z) elif layer_meta["geom_type_ogr"] == 1005: # MultiLineString (z) target_type = 1002 # LineString (z) elif layer_meta["geom_type_ogr"] == 1006: # MultiPolygon (z) target_type = 1003 # Polygon (z) elif layer_meta["geom_type_ogr"] == 2004: # MultiPoint (m) target_type = 2001 # Point (m) elif layer_meta["geom_type_ogr"] == 2005: # MultiLineString (m) target_type = 2002 # LineString (m) elif layer_meta["geom_type_ogr"] == 2006: # MultiPolygon (m) target_type = 2003 # Polygon (m) elif layer_meta["geom_type_ogr"] == 3004: # MultiPoint (zm) target_type = 3001 # Point (m) elif layer_meta["geom_type_ogr"] == 3005: # MultiLineString (zm) target_type = 3002 # LineString (m) elif layer_meta["geom_type_ogr"] == 3006: # MultiPolygon (zm) target_type = 3003 # Polygon (m) else: target_unknown = True target_type = layer_meta["geom_type_ogr"] destination_layer = destination.CreateLayer( layer_meta["layer_name"], layer_meta["projection_osr"], target_type ) layer_defn = destination_layer.GetLayerDefn() field_count = layer_meta["field_count"] original_target = ref.GetLayerByIndex(index) feature_count = original_target.GetFeatureCount() if copy_attributes: first_feature = original_target.GetNextFeature() original_target.ResetReading() if verbose == 1: print("Creating attribute fields") for field_id in range(field_count): field_defn = first_feature.GetFieldDefnRef(field_id) fname = field_defn.GetName() ftype = field_defn.GetTypeName() fwidth = field_defn.GetWidth() fprecision = field_defn.GetPrecision() if ftype == "String" or ftype == "Date": fielddefn = ogr.FieldDefn(fname, ogr.OFTString) fielddefn.SetWidth(fwidth) elif ftype == "Real": fielddefn = ogr.FieldDefn(fname, ogr.OFTReal) fielddefn.SetWidth(fwidth) fielddefn.SetPrecision(fprecision) else: fielddefn = ogr.FieldDefn(fname, ogr.OFTInteger) destination_layer.CreateField(fielddefn) for _ in range(feature_count): feature = original_target.GetNextFeature() geom = feature.GetGeometryRef() if target_unknown: out_feat = ogr.Feature(layer_defn) out_feat.SetGeometry(geom) if copy_attributes: for field_id in range(field_count): values = feature.GetField(field_id) out_feat.SetField(field_id, values) destination_layer.CreateFeature(out_feat) for geom_part in geom: out_feat = ogr.Feature(layer_defn) out_feat.SetGeometry(geom_part) if copy_attributes: for field_id in range(field_count): values = feature.GetField(field_id) out_feat.SetField(field_id, values) destination_layer.CreateFeature(out_feat) if verbose == 1: progress(_, feature_count - 1, "Splitting.") if add_index: vector_add_index(destination) return out_name