Пример #1
0
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)
Пример #2
0
    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
Пример #3
0
    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
Пример #4
0
    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
Пример #5
0
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