Exemplo n.º 1
0
def transform(src_crs, dst_crs, xs, ys, zs=None):
    """Transform vectors from source to target coordinate reference system.

    Transform vectors of x, y and optionally z from source
    coordinate reference system into target.

    Parameters
    ------------
    src_crs: CRS or dict
        Source coordinate reference system, as a rasterio CRS object.
        Example: CRS({'init': 'EPSG:4326'})
    dst_crs: CRS or dict
        Target coordinate reference system.
    xs: array_like
        Contains x values.  Will be cast to double floating point values.
    ys:  array_like
        Contains y values.
    zs: array_like, optional
        Contains z values.  Assumed to be all 0 if absent.

    Returns
    ---------
    out: tuple of array_like, (xs, ys, [zs])
        Tuple of x, y, and optionally z vectors, transformed into the target
        coordinate reference system.

    """
    if len(xs) != len(ys):
        raise TransformError("xs and ys arrays must be the same length")
    elif zs is not None and len(xs) != len(zs):
        raise TransformError("zs, xs, and ys arrays must be the same length")
    if len(xs) == 0:
        return ([], [], []) if zs is not None else ([], [])
    else:
        return _transform(src_crs, dst_crs, xs, ys, zs)
Exemplo n.º 2
0
    def rowcol(self, xs, ys, zs=None, op=math.floor, precision=None):
        """
        Returns rows and cols coordinates given geographic coordinates

        Parameters
        ----------
        xs, ys : float or list of float
            Geographic coordinates
        zs : float or list of float, optional
            Height associated with coordinates. Primarily used for RPC based 
            coordinate transformations. Ignored for affine based 
            transformations. Default: 0.
        op : function, optional (default: math.floor)
            Function to convert fractional pixels to whole numbers (floor,
            ceiling, round)
        precision : int, optional (default: None)
            Decimal places of precision in indexing, as in `round()`.
        

        Raises
        ------
        ValueError
            If input coordinates are not all equal length

        Returns
        -------
            tuple of float or list of float
        """
        AS_ARR = True if hasattr(xs, "__iter__") else False
        xs, ys, zs = self._ensure_arr_input(xs, ys, zs=zs)

        if precision is None:
            eps = sys.float_info.epsilon
        elif isinstance(precision, int):
            eps = 10.0**-precision
        else:
            eps = precision

        # If op rounds up, switch the sign of eps.
        if op(0.1) >= 1:
            eps = -eps
        f = lambda val: val + eps

        try:
            xs = list(map(f, xs))
            ys = list(map(f, ys))
            new_cols, new_rows = self._transform(
                xs, ys, zs, transform_direction=TransformDirection.reverse)

            if len(new_rows) == 1 and not AS_ARR:
                return (op(new_rows[0]), op(new_cols[0]))
            else:
                return ([op(r) for r in new_rows], [op(c) for c in new_cols])
        except TypeError:
            raise TransformError("Invalid inputs")
Exemplo n.º 3
0
 def _ensure_arr_input(self, xs, ys, zs=None):
     """Ensure all input coordinates are mapped to array-like objects
     
     Raises
     ------
     TransformError
         If input coordinates are not all of the same length
     """
     if (isinstance(xs, Iterable) and not isinstance(ys, Iterable)) or (
             isinstance(ys, Iterable) and not isinstance(xs, Iterable)):
         raise TransformError("Invalid inputs")
     if not isinstance(xs, Iterable) and not isinstance(ys, Iterable):
         xs = [xs]
         ys = [ys]
     if zs is None:
         zs = [0] * len(xs)
     elif not isinstance(zs, Iterable):
         zs = [zs]
     if len(set((len(xs), len(ys), len(zs)))) > 1:
         raise TransformError("Input coordinates must be of equal length")
     return xs, ys, zs
Exemplo n.º 4
0
    def rowcol(self, xs, ys, zs=None, op=math.floor, precision=None):
        """Get rows and cols coordinates given geographic coordinates.

        Parameters
        ----------
        xs, ys : float or list of float
            Geographic coordinates
        zs : float or list of float, optional
            Height associated with coordinates. Primarily used for RPC based 
            coordinate transformations. Ignored for affine based 
            transformations. Default: 0.
        op : function, optional (default: math.floor)
            Function to convert fractional pixels to whole numbers (floor,
            ceiling, round)
        precision : int, optional (default: None)
            This parameter is unused, deprecated in rasterio 1.3.0, and
            will be removed in version 2.0.0.

        Raises
        ------
        ValueError
            If input coordinates are not all equal length

        Returns
        -------
        tuple of float or list of float.

        """
        if precision is not None:
            warnings.warn(
                "The precision parameter is unused, deprecated, and will be removed in 2.0.0.",
                RasterioDeprecationWarning,
            )

        AS_ARR = True if hasattr(xs, "__iter__") else False
        xs, ys, zs = self._ensure_arr_input(xs, ys, zs=zs)

        try:
            new_cols, new_rows = self._transform(
                xs, ys, zs, transform_direction=TransformDirection.reverse)

            if len(new_rows) == 1 and not AS_ARR:
                return (op(new_rows[0]), op(new_cols[0]))
            else:
                return ([op(r) for r in new_rows], [op(c) for c in new_cols])
        except TypeError:
            raise TransformError("Invalid inputs")
Exemplo n.º 5
0
    def xy(self, rows, cols, zs=None, offset='center'):
        """
        Returns geographic coordinates given dataset rows and cols coordinates

        Parameters
        ----------
        rows, cols : int or list of int
            Image pixel coordinates
        zs : float or list of float, optional
            Height associated with coordinates. Primarily used for RPC based 
            coordinate transformations. Ignored for affine based 
            transformations. Default: 0.
        offset : str, optional
            Determines if the returned coordinates are for the center of the
            pixel or for a corner.
        Raises
        ------
        ValueError
            If input coordinates are not all equal length

        Returns
        -------
        tuple of float or list of float

        """
        AS_ARR = True if hasattr(rows, "__iter__") else False
        rows, cols, zs = self._ensure_arr_input(rows, cols, zs=zs)

        if offset == 'center':
            coff, roff = (0.5, 0.5)
        elif offset == 'ul':
            coff, roff = (0, 0)
        elif offset == 'ur':
            coff, roff = (1, 0)
        elif offset == 'll':
            coff, roff = (0, 1)
        elif offset == 'lr':
            coff, roff = (1, 1)
        else:
            raise TransformError("Invalid offset")

        # shift input coordinates according to offset
        T = IDENTITY.translation(coff, roff)
        temp_rows = []
        temp_cols = []
        try:
            for pt in zip(cols, rows):
                y, x = T * pt
                temp_rows.append(y)
                temp_cols.append(x)

            new_ys, new_xs = self._transform(
                temp_rows,
                temp_cols,
                zs,
                transform_direction=TransformDirection.forward)

            if len(new_ys) == 1 and not AS_ARR:
                return (new_ys[0], new_xs[0])
            else:
                return (new_ys, new_xs)
        except TypeError:
            raise TransformError("Invalid inputs")