Class ResamplingGrid

All Implemented Interfaces:
Parameterized, LenientComparable, org.opengis.referencing.operation.MathTransform, org.opengis.referencing.operation.MathTransform2D

final class ResamplingGrid extends AbstractMathTransform2D
A grid of precomputed pixel coordinates in source images. This grid is used during image resampling operations for avoiding to project the coordinates of every pixels when a bilinear interpolation between nearby pixels would be sufficient. Coordinate conversions applied by this class are from target grid cell centers to source grid cell centers.

ResamplingGrid operates on a delimited space specified by a Rectangle. This space is subdivided into "tiles" (not necessarily coincident with image tiles) where each tile provides its own coefficients for bilinear interpolations. All coordinates inside the same tile are interpolated using the same coefficients.

ResampledImage implements MathTransform2D for allowing usage by ResampledImage but is not a full featured transform. For example, it does not support the AbstractMathTransform2D.inverse() operation. For this reason this class should not be public and instance of this class should not be accessible outside ResampledImage.

Since:
1.1
Version:
1.1
  • Field Details

    • MIN_TILE_SIZE

      private static final int MIN_TILE_SIZE
      The minimal tile width and height in pixels. If a tile width or height is less than this threshold, then this class abandons the attempt to create a ResamplingGrid instance.
      See Also:
    • TOLERANCE

      static final double TOLERANCE
      The maximal error allowed, in pixel units. This is the maximal difference allowed between a coordinate transformed using the original transform and the same coordinate transformed using this grid. This maximum is honored on a best-effort basis; it may happen that for some pixels the error is slightly higher.
      See Also:
    • CACHE

      private static final Cache<ResamplingGrid.Key,org.opengis.referencing.operation.MathTransform2D> CACHE
      Cache of previously computed ResamplingGrid instances. The cache may retain up to 256 kb (32 kb × 8) of grids by strong references. After that amount, grids are retained by weak references.
    • numXTiles

      final int numXTiles
      Number of tiles in this grid. A ResamplingGrid tile is a rectangular region inside which bilinear interpolations can be used with acceptable errors. ResamplingGrid tiles are not necessarily coincident with image tiles.
    • numYTiles

      final int numYTiles
      Number of tiles in this grid. A ResamplingGrid tile is a rectangular region inside which bilinear interpolations can be used with acceptable errors. ResamplingGrid tiles are not necessarily coincident with image tiles.
    • tileWidth

      private final double tileWidth
      Number of pixels in a tile row or column. Those values are integers, but stored as double values for avoiding type conversions.
    • tileHeight

      private final double tileHeight
      Number of pixels in a tile row or column. Those values are integers, but stored as double values for avoiding type conversions.
    • xmin

      private final double xmin
      The (x,y) coordinates of the pixel in the upper-left corner of the target image. The coordinate system is the one of inputs given to transform(…) methods. Those values are integers, but stored as double values for avoiding type conversions.
    • ymin

      private final double ymin
      The (x,y) coordinates of the pixel in the upper-left corner of the target image. The coordinate system is the one of inputs given to transform(…) methods. Those values are integers, but stored as double values for avoiding type conversions.
    • coordinates

      private final double[] coordinates
      Sequence of (x,y) grid coordinates for all tiles in this grid, stored in row-major fashion. The coordinate system is the one of outputs computed by transform(…) methods.
  • Constructor Details

    • ResamplingGrid

      ResamplingGrid(org.opengis.referencing.operation.MathTransform2D toSourceCenter, Rectangle bounds, Dimension depth) throws org.opengis.referencing.operation.TransformException
      Creates a new grid of precomputed values using the given transform applied on the specified region. The region is subdivided into a number of sub-regions. The number of sub-divisions is specified by the depth argument. A value of 1 means that the region is splitted in two parts. A value of 2 means that each part is itself splitted in 2 smaller parts (so the original grid is splitted in 4), etc. with recursive splits like a QuadTree.

      Determining an optimal value of depth argument is the most tricky part of this class. This work is done by create(MathTransform2D, Rectangle) static method which expects the toSourceCenter and bounds arguments and computes the depth one.

      Parameters:
      toSourceCenter - conversion from target cell centers to source cell centers.
      bounds - pixel coordinates of target images for which to create a grid of source coordinates.
      depth - number of recursive divisions by 2.
      Throws:
      org.opengis.referencing.operation.TransformException
  • Method Details

    • transform

      public org.opengis.referencing.operation.Matrix transform(double[] srcPts, int srcOff, double[] dstPts, int dstOff, boolean derivate) throws org.opengis.referencing.operation.TransformException
      Interpolates a single grid coordinate tuple. This method is required by parent class but its implementation just delegates to transform(double[], int, double[], int, int). Since this method is not invoked by ResampledImage, its performance does not matter.
      Specified by:
      transform in class AbstractMathTransform
      Parameters:
      srcPts - the array containing the source coordinates (cannot be null).
      srcOff - the offset to the point to be transformed in the source array.
      dstPts - the array into which the transformed coordinates is returned. May be the same than srcPts. May be null if only the derivative matrix is desired.
      dstOff - the offset to the location of the transformed point that is stored in the destination array.
      derivate - true for computing the derivative, or false if not needed.
      Returns:
      the matrix of the transform derivative at the given source position, or null if the derivate argument is false.
      Throws:
      org.opengis.referencing.operation.TransformException - if the point cannot be transformed or if a problem occurred while calculating the derivative.
      See Also:
    • transform

      public void transform(double[] srcPts, int srcOff, double[] dstPts, int dstOff, int numPts) throws org.opengis.referencing.operation.TransformException
      Interpolates a sequence of grid coordinate tuples. Input and output values are pixel coordinates with integer values located in pixel centers. When this method is invoked by ResampledImage, input coordinates are always integers but output coordinates are generally fractional. All input coordinates must be inside the region specified to constructor.
      Specified by:
      transform in interface org.opengis.referencing.operation.MathTransform
      Overrides:
      transform in class AbstractMathTransform
      Parameters:
      srcPts - the array containing the source point coordinates.
      srcOff - the offset to the first point to be transformed in the source array.
      dstPts - the array into which the transformed point coordinates are returned. May be the same than srcPts.
      dstOff - the offset to the location of the first transformed point that is stored in the destination array.
      numPts - the number of point objects to be transformed.
      Throws:
      org.opengis.referencing.operation.TransformException - if an input coordinate is outside the domain of this transform.
    • getOrCreate

      static org.opengis.referencing.operation.MathTransform2D getOrCreate(org.opengis.referencing.operation.MathTransform2D toSourceCenter, Rectangle bounds) throws org.opengis.referencing.operation.TransformException
      Creates a grid for the given domain of validity. The toSourceCenter argument is the transform used for computing the coordinate values in the grid. The toSourceCorner variable is the transform used for computing derivatives (Jacobian matrices) in order to determine when the grid has enough tiles.
      Parameters:
      toSourceCenter - transform from target grid center to source grid center.
      bounds - pixel coordinates of target images for which to create a grid of source coordinates.
      Returns:
      a precomputed grid for the given transform.
      Throws:
      org.opengis.referencing.operation.TransformException - if a derivative cannot be computed or a point cannot be transformed.
      ImagingOpException - if the grid would be too big for being useful.
    • create

      static org.opengis.referencing.operation.MathTransform2D create(org.opengis.referencing.operation.MathTransform2D toSourceCenter, Rectangle bounds) throws org.opengis.referencing.operation.TransformException
      Implementation of getOrCreate(MathTransform2D, Rectangle) but without using cached instances. Non-private for testing purpose only.
      Throws:
      org.opengis.referencing.operation.TransformException
    • depth

      private static Dimension depth(org.opengis.referencing.operation.MathTransform2D toSourceCorner, Point2D.Double point, Point2D.Double tolerance, double xmin, double xmax, double ymin, double ymax, Matrix2 upperLeft, Matrix2 upperRight, Matrix2 lowerLeft, Matrix2 lowerRight) throws org.opengis.referencing.operation.TransformException
      Computes the number of subdivisions (in power of 2) to apply in order to get a good ResamplingGrid approximation. The width and height fields in the returned value have the following meaning:
      • 0 means that the transform is approximately affine in the region of interest.
      • 1 means that we should split the grid in two parts horizontally and/or vertically.
      • 2 means that we should split the grid in four parts horizontally and/or vertically.
      • etc.
      Parameters:
      toSourceCorner - the transform for which to compute the depth.
      point - any Point2D.Double instance, to be written by this method. This is provided in argument only for reducing object allocations.
      tolerance - the tolerance value to use in comparisons of matrix coefficients, along the X axis and along the Y axis. The distance between the location of the matrix being compared is half the size of the region of interest.
      xmin - the minimal x ordinate.
      xmax - the maximal x ordinate.
      ymin - the minimal y ordinate.
      ymax - the maximal y ordinate.
      upperLeft - the transform derivative at (xmin,ymax).
      upperRight - the transform derivative at (xmax,ymax).
      lowerLeft - the transform derivative at (xmin,ymin).
      lowerRight - the transform derivative at (xmax,ymin).
      Returns:
      the number of subdivision along each axis.
      Throws:
      org.opengis.referencing.operation.TransformException - if a derivative cannot be computed.
      ImagingOpException - if the grid would be too big for being useful.
    • incrementNonAffineDimension

      private static void incrementNonAffineDimension(boolean he, boolean ve, Dimension depth)
      Increments the width, the height or both values in the given dimension, depending on which dimension are not affine. This method must be invoked using the following pattern, where center is the matrix of the transform derivative in the center of the region of interest. Note: the order of operations in the if statement matter! java he = center.equals(matrixOnTheSameHorizontalLine, tolerance); ve = center.equals(matrixOnTheSameVerticalLine, tolerance); if (!((he & ve) && center.equals(matrixOnADiagonal, tolerance))) { incrementNonAffineDimension(he, ve, depth); }
      Parameters:
      he - true if the matrix on the horizontal line are equal.
      ve - true if the matrix on the vertical line are equal.
      depth - the dimension in which to increment the width, height or both.
    • derivative

      private static Matrix2 derivative(org.opengis.referencing.operation.MathTransform2D toSourceCenter, Point2D point) throws org.opengis.referencing.operation.TransformException
      Computes the derivative of the given transform at the given location and returns the result as a 2×2 matrix. This method invokes the MathTransform2D.derivative(Point2D) and converts or casts the result to a Matrix2 instance.

      In Apache SIS implementations, matrices returned by derivative(Point2D) methods are already instances of Matrix2. Consequently, in most cases this method will just cast the result.

      Parameters:
      toSourceCenter - the transform for which to compute the derivative.
      point - the location where to compute the derivative.
      Returns:
      the derivative at the given location as a 2×2 matrix.
      Throws:
      org.opengis.referencing.operation.TransformException - if the derivative cannot be computed.
    • equals

      private static boolean equals(Matrix2 center, Matrix2 corner, Point2D.Double tolerance)
      Returns true if the given matrices are equal, up to the given tolerance thresholds. The thresholds can be different for the X and Y axes. This allows to break the loop sooner (resulting in smaller grids) inside the depth(…) method.
    • formatTo

      protected String formatTo(Formatter formatter)
      Formats a pseudo-WKT representation of this transform for debugging purpose.
      Overrides:
      formatTo in class AbstractMathTransform
      Parameters:
      formatter - the formatter to use.
      Returns:
      the WKT element name, which is "Param_MT" in the default implementation.
      See Also: