Skip to content

srs

Functions:

  • centeredLAEA

    Load a Lambert-Azimuthal-Equal_Area spatial reference system (SRS) centered

  • loadSRS

    Load a spatial reference system (SRS) from various sources.

  • tileIndexAt

    Get the "slippery tile" index at the given zoom, around the

  • xyTransform

    Transform xy points between coordinate systems.

centeredLAEA

centeredLAEA(
    lon=None, lat=None, name="unnamed_m", geom=None
)

Load a Lambert-Azimuthal-Equal_Area spatial reference system (SRS) centered on a given set of latitude and longitude coordinates. Alternatively, a geom can be passed to center the LAEA on.

Parameters:

  • lon

    (float, default: None ) –

    The longitude of the projection's center. Required if no geom is given.

  • lat

    (float, default: None ) –

    The latitude of the projection's center. Required if no geom is given.

  • geom

    The region shape to center the LAEA in. If given, lat and lon must not be given, instead they will be defined automatically as the coordinates of the region centroid.

Returns:

  • SpatialReference
Source code in geokit/core/srs.py
def centeredLAEA(lon=None, lat=None, name="unnamed_m", geom=None):
    """
    Load a Lambert-Azimuthal-Equal_Area spatial reference system (SRS) centered
    on a given set of latitude and longitude coordinates. Alternatively, a geom
    can be passed to center the LAEA on.

    Parameters
    ----------
    lon : float
        The longitude of the projection's center. Required if no geom is given.

    lat : float
        The latitude of the projection's center. Required if no geom is given.

    geom: osgeo.ogr.Geometry
        The region shape to center the LAEA in. If given, lat and lon must not
        be given, instead they will be defined automatically as the coordinates
        of the region centroid.

    Returns
    -------
    osr.SpatialReference
    """
    if geom is None:
        assert isinstance(lat, numbers.Number) and isinstance(lon, numbers.Number), (
            "If geom is not passed, lat and lon must be given as float values."
        )
    else:
        assert isinstance(geom, ogr.Geometry), "geom must be given as osgeo.ogr.Geometry class object if not None."
        assert lat is None and lon is None, "If geom is given, lat and lon must not be given."

    # check if lat/lon can be used or if it must be extracted from geom first
    if not geom is None:
        # transform to EPSG:4326 in case it not already is lat/lon projection
        geom = GEOM.transform(geom, toSRS=4326)
        # extract lat/lon centroid coordinates to center LAEA upon
        lon = geom.Centroid().GetX()
        lat = geom.Centroid().GetY()

    srs = osr.SpatialReference()
    srs.ImportFromWkt(
        'PROJCS["{}",GEOGCS["GRS 1980(IUGG, 1980)",DATUM["unknown",SPHEROID["GRS80",6378137,298.257222101],TOWGS84[0,0,0,0,0,0,0]],PRIMEM["Greenwich",0],UNIT["degree",0.0174532925199433]],PROJECTION["Lambert_Azimuthal_Equal_Area"],PARAMETER["latitude_of_center",{}],PARAMETER["longitude_of_center",{}],PARAMETER["false_easting",0],PARAMETER["false_northing",0],UNIT["Meter",1]]'.format(
            name, float(lat), float(lon)
        )
    )

    if gdal.__version__ >= "3.0.0":
        srs.SetAxisMappingStrategy(osr.OAMS_TRADITIONAL_GIS_ORDER)

    # assert that the srs is valid (may be invalid if e.g. wrong integer codes were passed)
    assert srs.Validate() == 0, f"Created srs is invalid."

    return srs

loadSRS

loadSRS(
    source: srs_input,
    geom: Geometry | None = None,
    **kwargs,
) -> SpatialReference

Load a spatial reference system (SRS) from various sources.

Parameters:

  • source

    (str | int | SpatialReference | None) –

    The SRS to load. Can be: * osr.SpatialReference object * EPSG integer ID * Standardized SRS string like 'EPSG:4326' * Common SRS name in SRSCOMMON (e.g. 'europe_laea') * WKT string * 'laea' — creates a Lambert Azimuthal Equal Area projection (optionally centered on a geometry)

  • geom

    (Geometry, default: None ) –

    Geometry to center the projection on if 'laea' is used.

  • **kwargs

    Passed directly to SRSCOMMON.laea(**kwargs), allowing customization such as lon, lat, or name.

Returns:

  • SpatialReference
Source code in geokit/core/srs.py
def loadSRS(source: srs_input, geom: ogr.Geometry | None = None, **kwargs) -> osr.SpatialReference:
    """
    Load a spatial reference system (SRS) from various sources.

    Parameters
    ----------
    source : str | int | osr.SpatialReference | None
        The SRS to load. Can be:
          * osr.SpatialReference object
          * EPSG integer ID
          * Standardized SRS string like 'EPSG:4326'
          * Common SRS name in SRSCOMMON (e.g. 'europe_laea')
          * WKT string
          * 'laea' — creates a Lambert Azimuthal Equal Area projection
            (optionally centered on a geometry)

    geom : osgeo.ogr.Geometry, optional
        Geometry to center the projection on if 'laea' is used.

    **kwargs :
        Passed directly to `SRSCOMMON.laea(**kwargs)`, allowing
        customization such as `lon`, `lat`, or `name`.

    Returns
    -------
    osr.SpatialReference
    """
    # Do initial check of source
    if isinstance(source, osr.SpatialReference):
        return source
    elif source is None:
        return None

    # Create an empty SRS
    srs = osr.SpatialReference()

    # Check if source is a string
    if isinstance(source, str):
        src_upper = source.strip().upper()

        # Handle special LAEA case
        if src_upper == "LAEA":
            # merge geom into kwargs if provided
            if geom is not None and "geom" not in kwargs:
                kwargs["geom"] = geom
            return SRSCOMMON.laea(**kwargs)

        elif hasattr(SRSCOMMON, source):
            # assume a name for one of the common SRS's was given
            srs = SRSCOMMON[source]
        else:
            try:
                # try handling as a standardized epsg or esri etc. code
                srs = osr.SpatialReference()
                _val = srs.SetFromUserInput(source)
                assert _val == 0
            except:
                srs.ImportFromWkt(source)  # assume a Wkt string was input
    elif isinstance(source, int):
        srs.ImportFromEPSG(source)
    else:
        raise GeoKitSRSError("Unknown srs source type: ", type(source))

    if gdal.__version__ >= "3.0.0":
        srs.SetAxisMappingStrategy(osr.OAMS_TRADITIONAL_GIS_ORDER)

    # assert that the srs is valid (may be invalid if e.g. wrong integer codes were passed)
    if srs.Validate() != 0:
        raise RuntimeError(f"Created srs is invalid.")

    return srs

tileIndexAt

tileIndexAt(x, y, zoom, srs)

Get the "slippery tile" index at the given zoom, around the coordinates ('x', 'y') within the specified 'srs'.

Source code in geokit/core/srs.py
def tileIndexAt(x, y, zoom, srs):
    """Get the "slippery tile" index at the given zoom, around the
    coordinates ('x', 'y') within the specified 'srs'.
    """
    srs = loadSRS(srs)

    iterable_input = isinstance(x, Iterable) or isinstance(y, Iterable)

    if not srs.IsSame(EPSG4326):
        pt = xyTransform(x, y, fromSRS=srs, toSRS=EPSG4326, outputFormat="xy")

        if iterable_input:
            x, y = pt.x, pt.y
        else:
            x, y = pt.x[0], pt.y[0]

    if iterable_input:
        x = np.array(x)
        y = np.array(y)

    xi, yi = smopy.deg2num(y, x, zoom)

    return Tile(xi, yi, zoom)

xyTransform

xyTransform(
    *args,
    toSRS: srs_input,
    fromSRS: srs_input,
    outputFormat: Literal["raw", "xy", "xyz"] = "raw",
) -> (
    list[tuple] | TransformedPointsXY | TransformedPointsXYZ
)

Transform xy points between coordinate systems.

Returns:

  • list of tuples, or namedtuple
    • See the point for the 'outputFormat' argument
Source code in geokit/core/srs.py
def xyTransform(
    *args, toSRS: srs_input, fromSRS: srs_input, outputFormat: Literal["raw", "xy", "xyz"] = "raw"
) -> list[tuple] | TransformedPointsXY | TransformedPointsXYZ:
    """Transform xy points between coordinate systems.

    Parameters
    ----------
        xy : A single, or an iterable of (x,y) tuples
            The coordinates to transform

        toSRS : Anything acceptable by geokit.srs.loadSRS
            The srs of the output points

        fromSRS : Anything acceptable by geokit.srs.loadSRS
            The srs of the input points

        outputFormat : str
            Determine return value format
            * if 'raw', the raw output from osr.TransformPoints is given
            * if 'xy', or 'xyz' the points are given as named tuples

    Returns
    -------
    list of tuples, or namedtuple
      * See the point for the 'outputFormat' argument
    """
    # load srs's
    fromSRS = loadSRS(fromSRS)
    toSRS = loadSRS(toSRS)

    # make a transformer
    trx = osr.CoordinateTransformation(fromSRS, toSRS)

    # Do transformation
    if len(args) == 0:
        raise GeoKitSRSError("no positional inputs given")
    elif len(args) == 1:
        xy = args[0]
        if isinstance(xy, tuple):
            x, y = xy
            out = [
                trx.TransformPoint(x, y),
            ]
        else:
            out = trx.TransformPoints(xy)
    elif len(args) == 2:
        x = np.array(args[0])
        y = np.array(args[1])
        xy = np.column_stack([x, y])

        out = trx.TransformPoints(xy)

    else:
        raise GeoKitSRSError("Too many positional inputs")
    # Done!
    if outputFormat == "raw":
        return out
    elif outputFormat == "xy":
        x = np.array([o[0] for o in out])
        y = np.array([o[1] for o in out])

        return TransformedPointsXY(x, y)

    elif outputFormat == "xyz":
        x = out[:, 0]
        y = out[:, 1]
        z = out[:, 2]

        return TransformedPointsXYZ(x, y, z)