def geometry_to_geojson(geom: ogr.Geometry, alt_coord_type: str = None, alt_coord_code: str = None) -> str: """Converts a geometry to geojson. Args: geom: The geometry to convert to JSON alt_coord_type: the alternate geographic coordinate system type if geometry doesn't have one defined alt_coord_code: the alternate geographic coordinate system associated with the type Returns: The geojson string for the geometry Note: If the geometry doesn't have a spatial reference associated with it, both the default coordinate system type and code must be specified for a coordinate system to be assigned to the returning JSON. The original geometry is left unaltered. """ ref_sys = geom.GetSpatialReference() geom_json = json.loads(geom.ExportToJson()) if not ref_sys: if alt_coord_type and alt_coord_code: # No coordinate system, use what was passed in geom_json['crs'] = { 'type': str(alt_coord_type), 'properties': { 'code': str(alt_coord_code) } } else: # Use the existing coordinate system to inform the GeoJSON geom_json['crs'] = { 'type': ref_sys.GetAttrValue("AUTHORITY", 0), 'properties': { 'code': ref_sys.GetAttrValue("AUTHORITY", 1) } } return json.dumps(geom_json)
def find_plots_intersect_boundingbox(bounding_box: ogr.Geometry, all_plots: dict) -> dict: """Take a list of plots and return only those overlapping bounding box. Arguments: bounding_box: the geometry of the bounding box all_plots: the dictionary of all available plots Return: A dictionary of all intersecting plots """ bb_sr = bounding_box.GetSpatialReference() intersecting_plots = {} logging.debug("[find_plots_intersect_boundingbox] Bounding box %s %s", str(bb_sr), str(bounding_box)) for plot_name in all_plots: current_poly = all_plots[plot_name] # Check for a need to convert coordinate systems check_poly = current_poly if bb_sr: poly_sr = current_poly.GetSpatialReference() if poly_sr and not bb_sr.IsSame(poly_sr): # We need to convert to the same coordinate system before an intersection check_poly = geometries.convert_geometry(current_poly, bb_sr) logging.debug("[find_plots_intersect_boundingbox] Intersection with %s", str(check_poly)) intersection_with_bounding_box = bounding_box.Intersection(check_poly) if intersection_with_bounding_box is not None: intersection = json.loads(intersection_with_bounding_box.ExportToJson()) if 'coordinates' in intersection and len(intersection['coordinates']) > 0: intersecting_plots[str(plot_name)] = current_poly return intersecting_plots
def get_parallel_offset(self, linestring: ogr.Geometry, side: Sides, distance: Distance) -> ogr.Geometry: """ Get a linestring geometry that is parallel to a given linestring. :param linestring: the linestring for which you want a parallel linestring :type linestring: :py:class:`ogr.Geometry` :param side: Which side of the line should the parallel line fall on? :type side: :py:class:`Sides` :param distance: How far should the parallel linestring be from the original linestring? :type distance: :py:class:`Distance` :return: the parallel linestring :rtype: :py:class:`ogr.Geometry` """ # TODO: This method is a target for performance improvements. Right now we are switching back and forth between OGR and Shapely geometries a couple of times. # Make not of the geometry argument's SRID. (We'll need it a few times below.) _original_srid = self.get_srid(geometry=linestring) # If the incoming geometry is in a projected coordinate system that uses meters, we can use it directly. # Otherwise, we need to make a copy and transform the copy. _linestring = (linestring if _original_srid == self._projected_srid else self.project(geometry=linestring, srs=self._projected_srs, copy=True)) # Now we need to convert the distance to the units of the projected coordinate system. # (See http://python-measurement.readthedocs.io/en/latest/topics/measures.html#distance) offset_distance_in_meters = distance.m # For our next trick, we'll need a Shapely geometry. shapely_linestring: LineString = self.ogr_to_shapely(_linestring) # The shapely call takes string values for the 'side' parameter. Let's figure out what we're going to use. side_arg = 'left' if side == Sides.LEFT else 'right' # Now we have enough information to use the Shapely parallel_offset() function. # (http://toblerity.org/shapely/shapely.geometry.html) shapely_linestring_offset = shapely_linestring.parallel_offset( distance=offset_distance_in_meters, side=side_arg, resolution=16, join_style=1, mitre_limit=1.0) # Now we convert back to an OGR geometry. ogr_linestring_offset = self.shapely_to_ogr( shapely_geometry=shapely_linestring_offset, srs=self._projected_srs) # If we projected the original geometry, we need to project it back to the original coordinate system. if _original_srid != self._projected_srid: ogr_linestring_offset = self.project( geometry=ogr_linestring_offset, srs=linestring.GetSpatialReference(), copy=False) # OK. That's that. return ogr_linestring_offset
def get_srid(self, geometry: ogr.Geometry) -> int or None: """ Get the SRID of an OGR geometry's spatial reference :param geometry: the geometry :type geometry: :py:class:`ogr.Geometry` :return: the SRID (or ``None`` if the geometry has no spatial reference) :rtype: ``int`` or ``None`` """ # Get the spatial reference. srs: ogr.osr.SpatialReference = geometry.GetSpatialReference() # If the geometry has no spatial reference, return None to the caller. if srs is None: return None else: # Dig out the SRID. # https://gis.stackexchange.com/questions/20298/is-it-possible-to-get-the-epsg-value-from-an-osr-spatialreference-class-using-th srid = int(srs.GetAttrValue('AUTHORITY', 1)) return srid
def convert_geometry( geometry: ogr.Geometry, new_spatialreference: osr.SpatialReference) -> ogr.Geometry: """Converts the geometry to the new spatial reference if possible Arguments: geometry - The geometry to transform new_spatialreference - The spatial reference to change to Returns: The transformed geometry or the original geometry. If either the new Spatial Reference parameter is None, or the geometry doesn't have a spatial reference, then the original geometry is returned. """ if not new_spatialreference or not geometry: return geometry return_geometry = geometry try: geom_sr = geometry.GetSpatialReference() if int(osgeo.__version__[0]) >= 3: # GDAL 3 changes axis order: https://github.com/OSGeo/gdal/issues/1546 # pylint: disable=no-member geom_sr.SetAxisMappingStrategy( osgeo.osr.OAMS_TRADITIONAL_GIS_ORDER) if geom_sr and not new_spatialreference.IsSame(geom_sr): transform = osr.CreateCoordinateTransformation( geom_sr, new_spatialreference) new_geom = geometry.Clone() if new_geom: new_geom.Transform(transform) return_geometry = new_geom except Exception as ex: logging.warning("Exception caught while transforming geometries: %s", str(ex)) logging.warning(" Returning original geometry") return return_geometry