def srs_equal_check(input1, input2, reproject=False): import gdal from geotools.raster import get_srs_ras import ogr if isinstance(input1, (ogr.DataSource, ogr.Layer, ogr.Geometry)): input1_srs = get_srs_vec(input1) elif isinstance(input1, gdal.Dataset): input1_srs = get_srs_ras(input1) if isinstance(input2, (ogr.DataSource, ogr.Layer, ogr.Geometry)): input2_srs = get_srs_vec(input2) elif isinstance(input2, gdal.Dataset): input2_srs = get_srs_ras(input2) return input1_srs.IsSame(input2_srs) is 1
def clip(in_lyr, clip_lyr=None, clip_feat=None, outName=None): import ogr import os if clip_lyr is None and clip_feat is None: print('No clip layer or clip feature defined. Exiting') return out_ds = ogr.GetDriverByName('Memory').CreateDataSource('mem') out_lyr = out_ds.CreateLayer('') clipper = ogr.GetDriverByName('Memory').CreateDataSource('mem') clipper_lyr = clipper.CreateLayer('') defn = clipper_lyr.GetLayerDefn() out_feat = ogr.Feature(defn) if clip_feat is None: clip_feat = clip_lyr.GetNextFeature() clip_geom = clip_feat.geometry().Clone() clip_geom_Wkb = ogr.CreateGeometryFromWkb(clip_geom.ExportToWkb()) out_feat.SetGeometry(clip_geom_Wkb) clipper_lyr.CreateFeature(out_feat) ogr.Layer.Clip(in_lyr, clipper_lyr, out_lyr) if outName is not None: write_vector(out_ds, outName, srs=get_srs_vec(in_lyr)) return out_ds
def write_vector(in_data, out_fp, driver="ESRI Shapefile", srs=None): import ogr out_ds = create_vector(out_fp, driver) if out_ds is None: print("Could not create file. Check if file exists and is in use.") return if srs is not None: if isinstance(srs, int): srs = create_srs(srs) else: srs = get_srs_vec(in_data) # create layer, layer definition if isinstance(in_data, ogr.DataSource): in_lyr = in_data.GetLayer() else: in_lyr = in_data geomType = in_lyr.GetGeomType() # or in_data.GetLayerDefn().GetGeomType() out_lyr = out_ds.CreateLayer('', srs, geomType) # create/copy fiels from input in_feat = in_lyr.GetFeature(0) for i in range(in_feat.GetFieldCount()): out_lyr.CreateField(in_feat.GetFieldDefnRef(i)) defn = out_lyr.GetLayerDefn() for i in range(in_lyr.GetFeatureCount()): in_feat = in_lyr.GetFeature(i) out_feat = ogr.Feature(defn) for i in range(in_feat.GetFieldCount()): value = in_feat.GetField(i) out_feat.SetField(i, value) geometry = in_feat.geometry().Clone() featureWkb = geometry.ExportToWkb() geometry = ogr.CreateGeometryFromWkb(featureWkb) out_feat.SetGeometry(geometry) out_lyr.CreateFeature(out_feat) #experimental change: #for feature in in_lyr: # attribs = feature.items() # out_feat = ogr.Feature(defn) # for i, value in enumerate(attribs.values()): # out_feat.SetField(i, value) # geometry = in_feat.geometry().Clone() # featureWkb = geometry.ExportToWkb() # geometry = ogr.CreateGeometryFromWkb(featureWkb) # out_feat.SetGeometry(geometry) # out_lyr.CreateFeature(out_feat) out_feat = geometry = None # destroy stuff out_ds = out_lyr = out_feat = geometry = None # Save and close
def reproject_point(geom, target_obj): ''' Reproject a point geometry :param geom: ogr.Geometry - geometry to reproject :param target_obj: ogr.DataSource, ogr.Layer, ogr.Feature, ogr.Geometry, gdal.Dataset :return: ogr.Geometry in srs of target_obj ''' import ogr, osr import gdal from geotools.raster import get_srs_ras src_prj = get_srs_vec(geom) if isinstance(target_obj, (ogr.DataSource, ogr.Layer, ogr.Geometry)): target_prj = get_srs_vec(target_obj) elif isinstance(target_obj, gdal.Dataset): target_prj = get_srs_ras(target_obj) coordTrans = osr.CoordinateTransformation(src_prj, target_prj) # transform point geom.Transform(coordTrans) return (geom)
def spatial_filter_by_extent(inputDS, filterDS, datatype=None): ''' Filters an input vector by the extent of a raster or vector file. Automatically detects input type. :param inputPath: Path of the input vector file :param filterDS: Path of the file used as filter :param datatype: :return: ogr.Layer filtered by extent of input dataset ''' import gdal import ogr from geotools.raster import get_corner_coords from geotools.raster import get_srs_ras from geotools.vector import get_srs_vec src_prj = srs_vec(inputDS) # get projection of inputDS if isinstance(filter, gdal.Dataset): filterProj = get_srs_ras(filterDS) rasCoords = get_corner_coords(filterDS, dict=True) UL_x, UL_y, LR_x, LR_y = [ rasCoords[key] for key in ["UL_x", "UL_y", "LR_x", "LR_y"] ] if isinstance(filter, ogr.DataSource): inputLayer = inputDS.GetLayer() filterProj = get_srs_vec(filterDS) UL_x, LR_x, LR_y, UL_y = inputLayer.GetExtent( ) # minX, maxX, minY, maxY if src_prj.IsSame(filterProj) is not 1: print( "Projection of input files does not match. Expect very funky results" ) inputLayer.SetSpatialFilterRect(UL_x, LR_x, LR_y, UL_y) filteredDS = inputDS.GetLayer() return filteredDS
def feature_proximity(src_geom, target_lyr, distance_metric, buff_incr=None): ''' This function takes a geometry and a layer as input and returns the min/max/mean distance between the geometry and the features in the target layer. When using distance_metric min, it is recommended to use the buff_incr variable for layers containing a large amount of geometries. The function will buffer the source geometry incrementally by the distance specified, until a feature is found in the buffer area. This makes sure we don't compute distances for all features in the large dataset. :param source_geom: Geometry :param target_lyr: Layer containing features to check :param buff_incr: Distance in m of the buffer size. With each iteration the buffer size increases by this value. :param distance_metric: float - distance to be returned - min/max/mean :return: float - in units of srs of the target layer ''' import ogr, osr if srs_equal_check(src_geom, target_lyr) is False: src_geom = src_geom.Clone() src_geom.Transform( osr.CoordinateTransformation(get_srs_vec(src_geom), get_srs_vec(target_lyr))) features_found = 0 buff_distance = buff_incr if buff_incr is not None: if distance_metric == 'max': print( 'Using distance_metric=max and buff_incr does not make sense for most applications. Please check ' 'the description of the feature_proximity function.') while features_found < 1: # create buffer around feature and use as Spatial Filter to reduce the distances to calculate geom_filter = src_geom.Buffer(buff_distance) buff_distance += buff_incr target_lyr.SetSpatialFilter(geom_filter) features_found = target_lyr.GetFeatureCount() # only calculate distances if there is features in our buffer distance_list = [] target_feat = target_lyr.GetNextFeature() while target_feat: feature_geom = target_feat.geometry().Clone() distance = src_geom.Distance(feature_geom) if distance != 0.0: distance_list.append(distance) target_feat = target_lyr.GetNextFeature() min_dist = min(distance_list) max_dist = max(distance_list) mean_dist = sum(distance_list) / len(distance_list) target_lyr.SetSpatialFilter(None) target_lyr.ResetReading() if distance_metric == 'min': distance_out = min_dist if distance_metric == 'max': distance_out = max_dist if distance_metric == 'mean': distance_out = mean_dist return distance_out