Class LocalizationGridBuilder

Object
TransformBuilder
LocalizationGridBuilder

public class LocalizationGridBuilder extends TransformBuilder
Creates an "almost linear" transform mapping the given source points to the given target points. The transform is backed by a grid of localization, a two-dimensional array of coordinate tuples. Grid size is width × height and input coordinates are (i,j) indices in the grid, where i must be in the [0…width-1] range and j in the [0…height-1] range inclusive. Output coordinates are the values stored in the grid of localization at the specified index. After a Localization­Grid­Builder instance has been fully populated (i.e. real world coordinates have been specified for all grid cells), a transformation from grid coordinates to "real world" coordinates can be obtained with the create(Math­Transform­Factory) method. If this transform is close enough to an affine transform, then an instance of Linear­Transform is returned. Otherwise, a transform backed by the localization grid is returned.

This builder performs the following steps:

  1. Compute a linear approximation of the transformation using Linear­Transform­Builder.
  2. Compute Datum­Shift­Grid with the residuals.
  3. Create a Interpolated­Transform with the above shift grid.
  4. If a linearizer has been applied, concatenate the inverse transform of that linearizer.
Builders are not thread-safe. Builders can be used only once; points cannot be added or modified after create(Math­Transform­Factory) has been invoked.

Linearizers

If the localization grid is not close enough to a linear transform, Interpolated­Transform may not converge. To improve the speed and reliability of the transform, a non-linear step can be specified. Many candidates can be specified in case the exact form of that non-linear step is unknown; Localization­Grid­Builder will select the non-linear step that provides the best improvement, if any. See the Linearizers section in Linear­Transform­Builder for more discussion.
Since:
0.8
See Also:
  • Constructor Details

    • LocalizationGridBuilder

      public LocalizationGridBuilder(int width, int height)
      Creates a new, initially empty, builder for a localization grid of the given size.
      Parameters:
      width - the number of columns in the grid of target positions.
      height - the number of rows in the grid of target positions.
    • LocalizationGridBuilder

      public LocalizationGridBuilder(Vector sourceX, Vector sourceY)
      Creates a new, initially empty, builder for a localization grid of a size inferred from the given points. This constructor uses the given vectors for computing a grid size and the following initial conversion:
      (source­X, source­Y) → (grid­X, grid­Y)
      Above conversion can be obtained by get­Source­To­Grid().

      Values in the given vectors should be integers, but this constructor is tolerant to non-integer values if they have a constant offset (typically 0.5) relative to integer values. The two vectors do not need to have the same length (i.e. source­X[i] are not necessarily related to source­Y[i]).

      Parameters:
      source­X - all possible x inputs before conversion to grid coordinates.
      source­Y - all possible y inputs before conversion to grid coordinates.
      Throws:
      Arithmetic­Exception - if this constructor cannot infer a reasonable grid size from the given vectors.
    • LocalizationGridBuilder

      public LocalizationGridBuilder(LinearTransformBuilder localizations)
      Creates a new builder for a localization grid inferred from the given provider of control points. The number of source dimensions in the given localizations argument shall be 2. The localization can be used in two ways:
      • If the localizations instance has been created with a fixed grid size, then that instance is used as-is — it is not copied. It is okay to specify an empty instance and to provide control points later by calls to set­Control­Point(int, int, double...).
      • If the localizations instance has been created for a grid of unknown size, then this constructor tries to infer a grid size by inspection of the control points present in localizations at the time this constructor is invoked. Changes in localizations after construction will not be reflected in this new builder.
      The new builder inherits the linearizers of localizations.
      Parameters:
      localizations - the provider of control points for which to create a localization grid.
      Throws:
      Arithmetic­Exception - if this constructor cannot infer a reasonable grid size from the given localizations.
      Since:
      1.0
  • Method Details

    • setDesiredPrecision

      public void setDesiredPrecision(double precision)
      Sets the desired precision of inverse transformations, in units of source coordinates. If a conversion from "real world" to grid coordinates has been specified, then the given precision is in "real world" units. Otherwise the precision is in units of grid cells (i.e. a value of 1 is the size of one grid cell).
      Note: there is no method for setting the desired target precision because forward transformations precision (not to be confused with accuracy) are limited only by rounding errors. Of course the accuracy of both forward and inverse transformations still limited by the accuracy of given control points and the grid resolution.
      Parameters:
      precision - desired precision of the results of inverse transformations.
      Throws:
      Illegal­State­Exception - if create(…) has already been invoked.
      See Also:
    • getDesiredPrecision

      public double getDesiredPrecision()
      Returns the desired precision of inverse transformations, in units of source coordinates. This is the precision sets by the last call to set­Desired­Precision(double).
      Returns:
      desired precision of the results of inverse transformations.
    • setSourceToGrid

      public void setSourceToGrid(LinearTransform sourceToGrid)
      Defines relationship between "real-world" source coordinates and grid coordinates. The given transform is usually two-dimensional, in which case conversions from (x,y) source coordinates to (grid­X, grid­Y) indices can be done with the following formulas:
      • gridX = (x - x₀) / Δx
      • gridY = (y - y₀) / Δy
      where:
      • (x₀, y₀) is the coordinate of the center of the cell at grid index (0,0).
      • Δx and Δy are the distances between two cells on the x and y axes respectively, in the same unit of measurement than the one documented in the set­Desired­Precision(double) method.
      The coordinate­To­Grid transform for the above formulas can be represented by the following matrix:
         ┌                      ┐
         │ 1/Δx      0   -x₀/Δx │
         │    0   1/Δy   -y₀/Δy │
         │    0      0        1 │
         └                      ┘
      If this method is never invoked, then the default conversion is identity. If a desired precision has been specified before this method call, it is caller's responsibility to convert that value to new source units if needed.
      Parameters:
      source­To­Grid - conversion from the "real world" source coordinates to grid indices including fractional parts.
      Throws:
      Illegal­State­Exception - if create(…) has already been invoked.
      See Also:
    • getSourceToGrid

      public LinearTransform getSourceToGrid()
      Returns the current relationship between "real-world" source coordinates and grid coordinates. This is the value set by the last call to set­Source­To­Grid(Linear­Transform). If that setter method has never been invoked, then this is an automatically computed transform if the grid coordinates have been specified to the constructor, or the identity transform otherwise.
      Returns:
      the current relationship between "real-world" source coordinates and grid coordinates.
    • getSourceEnvelope

      public Envelope getSourceEnvelope(boolean fullArea) throws TransformException
      Returns the envelope of source coordinates. The full­Area argument control whether the returned envelope shall encompass full surface of every cells or only their centers:
      • If true, then the returned envelope encompasses full cell surfaces, from lower border to upper border. In other words, the returned envelope encompasses all cell corners.
      • If false, then the returned envelope encompasses only cell centers, inclusive.
      This is the envelope of the grid domain (i.e. the ranges of valid grid­X and grid­Y argument values in calls to get/set­Control­Point(…) methods) transformed as below:
      1. expanded by ½ cell on each side if full­Area is true
      2. transformed by the inverse of source to grid transform.
      Parameters:
      full­Area - whether the envelope shall encompass the full cell surfaces instead of only their centers.
      Returns:
      the envelope of grid points, from lower corner to upper corner.
      Throws:
      Illegal­State­Exception - if the grid points are not yet known.
      Transform­Exception - if the envelope cannot be calculated.
      Since:
      1.0
      See Also:
    • setControlPoints

      public void setControlPoints(Vector... coordinates)
      Sets all control points. The length of given vectors must be equal to the total number of cells in the grid. The first vector provides the x coordinates; the second vector provides the y coordinates, etc.. Coordinates are stored in row-major order (column index varies faster, followed by row index).
      Parameters:
      coordinates - coordinates in each target dimensions, stored in row-major order.
      Throws:
      Illegal­State­Exception - if create(…) has already been invoked.
      Since:
      1.0
    • setControlPoint

      public void setControlPoint(int gridX, int gridY, double... target)
      Sets a single matching control point pair. Source position is assumed precise and target position is assumed uncertain. If the given source position was already associated with another target position, then the old target position is discarded.

      If a source to grid conversion exists, it shall have been applied by the caller for computing the (grid­X, grid­Y) coordinates given to this method.

      Parameters:
      grid­X - the column index in the grid where to store the given target position.
      grid­Y - the row index in the grid where to store the given target position.
      target - the target coordinates, assumed uncertain.
      Throws:
      Illegal­State­Exception - if create(…) has already been invoked.
      Illegal­Argument­Exception - if the x or y coordinate value is out of grid range.
      Mismatched­Dimension­Exception - if the target position does not have the expected number of dimensions.
    • getControlPoint

      public double[] getControlPoint(int gridX, int gridY)
      Returns a single target coordinate for the given source coordinate, or null if none. If linearizers have been specified and create(…) has already been invoked, then the control points may be projected using one of the linearizers.
      Parameters:
      grid­X - the column index in the grid where to read the target position.
      grid­Y - the row index in the grid where to read the target position.
      Returns:
      the target coordinates associated to the given source, or null if none.
      Throws:
      Illegal­Argument­Exception - if the x or y coordinate value is out of grid range.
    • getRow

      public Vector getRow(int dimension, int row)
      Returns a row of coordinate values in the given dimension. The returned vector is a view; changes in the returned vector will be reflected in this builder.
      Parameters:
      dimension - the target dimension for which to get coordinate values.
      row - index of the row to get.
      Returns:
      coordinate values of the specified row in the specified dimension.
      Since:
      1.0
    • getColumn

      public Vector getColumn(int dimension, int column)
      Returns a column of coordinate values in the given dimension. The returned vector is a view; changes in the returned vector will be reflected in this builder.
      Parameters:
      dimension - the target dimension for which to get coordinate values.
      column - index of the column to get.
      Returns:
      coordinate values of the specified column in the specified dimension.
      Since:
      1.0
    • resolveWraparoundAxis

      public NumberRange<Double> resolveWraparoundAxis(int dimension, int direction, double period)
      Tries to remove discontinuities in coordinates values caused by anti-meridian crossing. This method can be invoked when the localization grid may cross the anti-meridian, where longitude values may suddenly jump from +180° to -180° or conversely. This method walks through the coordinate values of the given dimension (typically the longitudes dimension) in the given direction (grid rows or grid columns). If a difference greater than period/2 (typically 180°) is found between two consecutive values, then a multiple of period (typically 360°) is added or subtracted in order to make a value as close as possible from its previous value.

      This method needs a direction to be specified:

      • Direction 0 means that each value is compared with the value in the previous column, except the value in the first column which is compared to the value in previous row.
      • Direction 1 means that each value is compared with the value in the previous row, except the value in the first row which is compared to the value in previous column.
      The recommended value is the direction of most stable values. Typically, longitude values increase with column indices and are almost constant when increasing row indices. In such case, the recommended direction is 1 for comparing each value with the value in previous row, since that value should be closer than the value in previous column.

      Example

      for a grid of (longitude, latitude) values in decimal degrees where longitude values vary (increase or decrease) with increasing column indices and latitude values vary (increase or decrease) with increasing row indices, the following method should be invoked for protecting the grid against discontinuities on anti-meridian:
      grid.resolveWraparoundAxis(0, 1, 360);
      
      Parameters:
      dimension - the dimension to process. This is 0 for longitude dimension in a (longitudes, latitudes) grid.
      direction - the direction to walk through: 0 for columns or 1 for rows. The recommended direction is the direction of most stable values, typically 1 (rows) for longitudes.
      period - that wraparound range (typically 360° for longitudes). Must be strictly positive.
      Returns:
      the range of coordinate values in the specified dimension after correction for wraparound values.
      Throws:
      Illegal­State­Exception - if this method has already been invoked for the same dimension, or if create(…) has already been invoked.
      Since:
      1.0
    • addLinearizers

      public void addLinearizers(Map<String,MathTransform> projections, boolean compensate, int... projToGrid)
      Adds transforms to potentially apply on target control points before to compute the transform. This method can be invoked if the departure from a linear transform is too large, resulting in Interpolated­Transform to fail with "no convergence error" messages. If linearizers have been specified, then the create(Math­Transform­Factory) method will try to apply each transform on target coordinates and check which one results in the best correlation coefficients. Exactly one of the specified transforms will be selected. If applying no transform is an acceptable solution, then an identity transform should be included in the given projections map.

      The linearizers are specified as Math­Transforms from current target coordinates of control points to other spaces where sources to new targets transforms may be more linear. The keys in the map are arbitrary identifiers. The proj­To­Grid argument specifies which control point dimensions to use as projections source coordinates and can be null or omitted if the projections shall be applied on all target coordinates. It is possible to invoke this method many times with different dimensions argument values.

      The compensate argument tell whether the inverse of specified transform shall be concatenated to the final interpolated transform. If true, the projection effect will be cancelled in the final result, i.e. the target coordinates will be approximately the same as if no projection were applied. In such case, the advantage of applying a projection is to improve numerical stability with a better linear approximation in used by the coordinate transformation process.

      Parameters:
      projections - projections from current target coordinates to other spaces which may result in more linear transforms.
      compensate - whether the inverse of selected projection shall be concatenated to the final interpolated transform.
      proj­To­Grid - the target dimensions to project, or null or omitted for projecting all target dimensions. If non-null and non-empty, then all transforms in the projections map shall have a number of source and target dimensions equals to the length of this array.
      Throws:
      Illegal­State­Exception - if create(…) has already been invoked.
      Since:
      1.1
      See Also:
    • create

      public MathTransform create(MathTransformFactory factory) throws FactoryException
      Creates a transform from the source points to the target points. This method assumes that source points are precise and all uncertainty is in the target points. If this transform is close enough to an affine transform, then an instance of Linear­Transform is returned.

      If this method is invoked more than once, the previously created transform instance is returned.

      Specified by:
      create in class Transform­Builder
      Parameters:
      factory - the factory to use for creating the transform, or null for the default factory. The Math­Transform­Factory​.create­Affine­Transform(Matrix) method of that factory shall return Linear­Transform instances.
      Returns:
      the transform from source to target points.
      Throws:
      Factory­Exception - if the transform cannot be created, for example because the target points have not be specified.
    • linearizer

      public Optional<Map.Entry<String,MathTransform>> linearizer(boolean ifNotCompensated)
      Returns the linearizer applied on target control points. This method returns a non-empty value if add­Linearizers(Map, boolean, int...) has been invoked with a non-empty map, followed by a create(Math­Transform­Factory) call. In such case, Linear­Transform­Builder selects a linearizer identified by the returned key - value entry. The entry key is one of the keys of the maps given to add­Linearizers(…). The entry value is the associated Math­Transform, possibly modified as described in the axis order section below.

      All control points returned by get­Control­Point(int, int) are projected by the selected transform. Consequently, if the target coordinates of original control points are desired, then the transform computed by this builder needs to be concatenated with the inverse of the transform returned by this method. This is done automatically in the create(…) method if the compensate flag given to add­Linearizers(…) method was true. Otherwise the compensation, if desired, needs to be done by the caller.

      Axis order

      The returned transform will contain an operation step performing axis filtering and swapping implied by the proj­To­Grid argument that was given to the add­Linearizers(…, proj­To­Grid)} method. Consequently, if the proj­To­Grid argument was not an arithmetic progression, then the transform returned by this method will not be one of the instances given to add­Linearizers(…).
      Parameters:
      if­Not­Compensated - whether to return the transform only if not already compensated by create(…). A value of true is useful if the caller wants the transform only if it needs to compensate itself.
      Returns:
      the projection applied on target coordinates before to compute a linear transform.
      Since:
      1.1
      See Also:
    • errors

      public Statistics[] errors(boolean linear)
      Returns statistics of differences between values calculated by the transform and actual values. The tested transform is the one computed by create(Math­Transform­Factory) if the linear argument is false, or the transform computed by Linear­Transform­Builder if the linear argument is true. The returned statistics are:
      1. One Statistics instance for each target dimension, containing statistics about the differences between coordinates computed by the given transform and expected coordinates. For each (i,j) indices in this grid, the indices are transformed by a call to mt​.transform(…) and the result is compared with the coordinates given by get­Control­Point(i,j). Those statistics are identified by labels like “Δx” and “Δy”.
      2. One Statistics instance for each source dimension, containing statistics about the differences between coordinates computed by the inverse of the transform and expected coordinates. For each (x,y) control point in this grid, the points are transformed by a call to mt​.inverse()​.transform(…) and the result is compared with the pixel indices of that point. Those statistics are identified by labels like "Δi" and "Δj".
      Parameters:
      linear - false for computing errors using the complete transform, or true for using only the linear part.
      Returns:
      statistics of difference between computed values and expected values for each target dimension.
      Throws:
      Illegal­State­Exception - if create(Math­Transform­Factory) has not yet been invoked.
      Since:
      1.1
      See Also:
    • toString

      public String toString(boolean linear, Locale locale)
      Returns a string representation of this builder in the given locale. Current implementation shows the following information:
      • Number of points.
      • Linearizers and their correlation coefficients (if available).
      • The linear component of the transform.
      • Error statistics, as documented in the errors(boolean) method.
      The string representation may change in any future version.
      Parameters:
      linear - false for errors using the complete transform, or true for using only the linear part.
      locale - the locale for formatting messages and some numbers, or null for the default.
      Returns:
      a string representation of this builder.
      Since:
      1.1
      See Also:
    • toString

      public String toString()
      Returns a string representation of this builder for debugging purpose. The string representation is for debugging purpose and may change in any future version. The default implementation delegates to to­String(boolean, Locale) with a null locale.
      Overrides:
      to­String in class Object
      Returns:
      a string representation of this builder.
      Since:
      1.0