Package org.geotools.referencing.operation.builder

Source Code of org.geotools.referencing.operation.builder.WarpGridBuilder

/*
*    GeoTools - The Open Source Java GIS Toolkit
*    http://geotools.org
*
*    (C) 2007-2008, Open Source Geospatial Foundation (OSGeo)
*
*    This library is free software; you can redistribute it and/or
*    modify it under the terms of the GNU Lesser General Public
*    License as published by the Free Software Foundation;
*    version 2.1 of the License.
*
*    This library is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
*    Lesser General Public License for more details.
*/
package org.geotools.referencing.operation.builder;

import java.awt.Point;
import java.awt.image.DataBuffer;
import java.awt.image.WritableRaster;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;

import javax.media.jai.RasterFactory;
import javax.vecmath.MismatchedSizeException;

import org.geotools.geometry.DirectPosition2D;
import org.geotools.referencing.crs.DefaultEngineeringCRS;
import org.geotools.referencing.operation.DefaultMathTransformFactory;
import org.geotools.referencing.operation.builder.algorithm.AbstractInterpolation;
import org.geotools.referencing.operation.matrix.GeneralMatrix;
import org.geotools.referencing.operation.transform.AffineTransform2D;
import org.geotools.referencing.operation.transform.ConcatenatedTransform;
import org.geotools.referencing.operation.transform.ProjectiveTransform;
import org.geotools.referencing.operation.transform.WarpGridTransform2D;
import org.geotools.resources.i18n.ErrorKeys;
import org.geotools.resources.i18n.Errors;
import org.opengis.geometry.DirectPosition;
import org.opengis.geometry.Envelope;
import org.opengis.geometry.MismatchedDimensionException;
import org.opengis.geometry.MismatchedReferenceSystemException;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.NoSuchIdentifierException;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.TransformException;

/**
* Provides a basic implementation for
* {@linkplain WarpGridTransform2D warp grid math transform} builders.
*
* @see <A
*      HREF="http://java.sun.com/products/java-media/jai/forDevelopers/jai-apidocs/javax/media/jai/WarpGrid.html">WarpGrid
*      at JAI </A>
*
* @source $URL:
*         http://svn.geotools.org/geotools/trunk/spike/jan/gsoc-transformations/src/main/java/org/geotools/referencing/operation/builder/WarpGridBuilder.java $
* @version $Id$
* @author jezekjan
*
*/
public abstract class WarpGridBuilder extends MathTransformBuilder {
  /**
   * Grid width
   */
  private int width;

  /**
   * Grid height
   */
  private int height;

  /**
   * Envelope for generated Grid
   */
  protected final Envelope envelope;

  /** RealToGrid Math Transform */
  protected final MathTransform worldToGrid;

  /**
   * List of Mapped Positions in local coordinates (transformed by worldToGrid
   * transformation)
   */
  private List<MappedPosition> localpositions;

  // List /*<MappedPosition>*/ worldpositions ;

  /** GridValues like maxx maxt dx dy etc.. */
  protected GridParameters gridParameters;

  /** Grid of x shifts */
  private float[][] dxgrid;

  /** Grid of y shifts */
  private float[][] dygrid;

  /** Warp positions - target position of each point (not delta) */
  private float[] warpPositions;

  /** Raster of interpolated values */
  private WritableRaster xRaster;

  /** Raster of interpolated values */
  private WritableRaster yRaster;

  /**
   * Constructs Builder with proper worldToGrid math transform with integer
   * values for generated grid. This constructor is useful for calculating
   * transformation for image in image coordinate system.
   *
   * @param vectors
   *            Mapped positions ground control points
   * @param dx
   *            The horizontal spacing between grid cells.
   * @param dy
   *            The vertical spacing between grid cells.
   * @param envelope
   *            Envelope of generated grid.
   * @throws MismatchedSizeException
   * @throws MismatchedDimensionException
   * @throws MismatchedReferenceSystemException
   * @throws NoSuchIdentifierException
   */
  public WarpGridBuilder(List<MappedPosition> vectors, double dx, double dy,
      Envelope envelope, MathTransform worldToGrid)
      throws MismatchedSizeException, MismatchedDimensionException,
      MismatchedReferenceSystemException, TransformException,
      NoSuchIdentifierException {

    this.worldToGrid = worldToGrid;
    this.envelope = envelope;
    this.gridParameters = GridParameters.createGridParameters(envelope, dx,
        dy, (AffineTransform2D) worldToGrid, true);
    super.setMappedPositions(vectors);
    localpositions = transformMPToGrid(vectors, worldToGrid);
  }

  /**
   * Constructs builder to be used in real world system with Float values as
   * parameters.
   *
   * @param vectors
   * @param params
   * @param envelope
   */
  protected WarpGridBuilder(List<MappedPosition> vectors,
      GridParameters params, Envelope envelope) {

    super.setMappedPositions(vectors);
    localpositions = vectors;
    this.envelope = envelope;
    this.gridParameters = params;
    DefaultMathTransformFactory s = new DefaultMathTransformFactory();
    this.worldToGrid = this.getIdntityTransform();
  }

  /*
   * public WarpGridBuilder(List<MappedPosition> vectors, double dx, double
   * dy, Envelope envelope) throws MismatchedSizeException,
   * MismatchedDimensionException, MismatchedReferenceSystemException,
   * TransformException, NoSuchIdentifierException { this(vectors, dx, dy,
   * envelope, getIdntityTransform());
   *  }
   */

  private static MathTransform getIdntityTransform() {
    GeneralMatrix M = new GeneralMatrix(3, 3);
    double[] m0 = { 1, 0, 0 };
    double[] m1 = { 0, 1, 0 };
    double[] m2 = { 0, 0, 1 };
    M.setRow(0, m0);
    M.setRow(1, m1);
    M.setRow(2, m2);
    return ProjectiveTransform.create(M);
  }

  public List<MappedPosition> getGridMappedPositions()
      throws MismatchedDimensionException, TransformException {
    if (localpositions == null) {
      localpositions = transformMPToGrid(getMappedPositions(),
          worldToGrid);
    }

    return localpositions;
  }

  protected HashMap<DirectPosition, Float> buildPositionsMap(int dim)
      throws TransformException {
    return buildPositionsMap(dim, 1);
  }

  /**
   * Converts MappedPosition to HashMap where Source Points are key and delta
   * in proper dimension is value
   *
   * @param dim
   *            delta dimension (0 - dx, 1 - dy)
   * @param k
   *            coefficient for multiplying point value (For example 3600 to
   *            get difference in degree seconds).
   * @return Map
   * @throws TransformException
   */
  protected HashMap<DirectPosition, Float> buildPositionsMap(int dim, float k)
      throws TransformException {
    HashMap<DirectPosition, Float> poitnsToDeltas = new HashMap<DirectPosition, Float>();

    for (Iterator<MappedPosition> i = this.getGridMappedPositions()
        .iterator(); i.hasNext();) {
      MappedPosition mp = ((MappedPosition) i.next());
      poitnsToDeltas.put(mp.getSource(), k
          * new Float(mp.getSource().getCoordinate()[dim]
              - mp.getTarget().getCoordinate()[dim]));
    }

    return poitnsToDeltas;
  }

  /**
   * Transforms MappedPostions to grid system
   *
   */
  private List<MappedPosition> transformMPToGrid(
      List<MappedPosition> MappedPositions, MathTransform trans)
      throws MismatchedDimensionException, TransformException {
    List<MappedPosition> gridmp = new ArrayList<MappedPosition>();

    for (Iterator<MappedPosition> i = MappedPositions.iterator(); i
        .hasNext();) {
      MappedPosition mp = (MappedPosition) i.next();

      DirectPosition2D gridSource = new DirectPosition2D();
      DirectPosition2D gridTarget = new DirectPosition2D();
      trans.transform(mp.getSource(), gridSource);
      gridSource
          .setCoordinateReferenceSystem(DefaultEngineeringCRS.CARTESIAN_2D);

      trans.transform(mp.getTarget(), gridTarget);
      gridTarget
          .setCoordinateReferenceSystem(DefaultEngineeringCRS.CARTESIAN_2D);

      gridmp.add(new MappedPosition(gridSource, gridTarget));
    }

    return gridmp;
  }

  private void ensureVectorsInsideEnvelope() {
    /* @TODO - ensure that source MappedPositions are inside the envelope */
  }

  /*
   *
   * (non-Javadoc)
   *
   * @see org.geotools.referencing.operation.builder.MathTransformBuilder#computeMathTransform()
   */
  protected MathTransform computeMathTransform() throws FactoryException {
    // warpPositions = getWarpPositions();

    /** Add the last parameter - warp positions * */
    gridParameters.setWarpPositions(getWarpPositions());

    /** Use provider and values to get proper transformation * */
    WarpGridTransform2D wt = (WarpGridTransform2D) (new WarpGridTransform2D.Provider())
        .createMathTransform(gridParameters.getWarpGridParameters());

    wt.setWorldtoGridTransform(this.worldToGrid);

    MathTransform trans = null;

    try {
      trans = ConcatenatedTransform.create(ConcatenatedTransform.create(
          this.worldToGrid, wt), this.worldToGrid.inverse());
    } catch (TransformException e) {
      throw new FactoryException(Errors
          .format(ErrorKeys.NONINVERTIBLE_TRANSFORM), e);
    }

    return wt;
  }

  /*
   * (non-Javadoc)
   *
   * @see org.geotools.referencing.operation.builder.MathTransformBuilder#getMinimumPointCount()
   */
  public int getMinimumPointCount() {
    return 1;
  }

  /**
   * Computes WarpGrid Positions.
   *
   * @throws TransformException
   *             when problems in world to grid system occurs
   *
   */
  abstract protected float[] computeWarpGrid(GridParameters parameters/*
                                     * ParameterValueGroup
                                     * values
                                     */)
      throws TransformException, FactoryException;

  /**
   * Convenience method for generating the grid by interpolation. This method
   * should be called from implementation of computeWarpGrid.
   *
   * @param WarpParams
   * @param dxInterp
   * @param dyInterp
   * @return
   * @throws TransformException
   */
  protected float[] interpolateWarpGrid(GridParameters gridParams,
      AbstractInterpolation dxInterp, AbstractInterpolation dyInterp)
      throws TransformException {
    float[] warpPositions = (float[]) gridParams.getWarpPositions();// .parameter("warpPositions").getValue();

    for (int i = 0; i <= gridParams.getYNumber(); i++) {
      for (int j = 0; j <= gridParams.getXNumber(); j++) {
        DirectPosition2D dp = new DirectPosition2D(gridParams
            .getXStart()
            + (j * gridParams.getXStep()), gridParams.getYStart()
            + (i * gridParams.getYStep()));

        double x = -dxInterp.getValue(dp) + (j * gridParams.getXStep())
            + gridParams.getXStart();
        double y = -dyInterp.getValue(dp) + (i * gridParams.getYStep())
            + gridParams.getYStart();

        warpPositions[(i * ((1 + gridParams.getXNumber()) * 2))
            + (2 * j)] = (float) x;

        warpPositions[(i * ((1 + gridParams.getXNumber()) * 2))
            + (2 * j) + 1] = (float) y;
      }
    }

    return warpPositions;
  }

  /**
   * Returns array of warp grid positions. The array contains target positions
   * to original grid. The cells are enumerated in row-major order, that is,
   * all the grid points along a row are enumerated first, then the grid
   * points for the next row are enumerated, and so on. As an example, suppose
   * xNumCells is equal to 2 and yNumCells is equal 1. Then the order of the
   * data in table would be: x00, y00, x10, y10, x20, y20, x01, y01, x11, y11,
   * x21, y21
   *
   * @see <A
   *      HREF="http://java.sun.com/products/java-media/jai/forDevelopers/jai-apidocs/javax/media/jai/WarpGrid.html">warpPositions
   *      at WarpGrid constructor at JAI </A>
   * @return warp positions
   *
   */
  private float[] getWarpPositions() throws FactoryException {
    if (warpPositions == null) {
      try {
        warpPositions = computeWarpGrid(gridParameters);
      } catch (TransformException e) {
        throw new FactoryException(Errors
            .format(ErrorKeys.CANT_TRANSFORM_VALID_POINTS), e);
      }

      return warpPositions;
    } else {
      return warpPositions;
    }
  }

  /**
   * Returns array of Shifts. This method is useful to create Coverage2D
   * object.
   *
   * @return array of Shifts
   */
  public float[][] getDxGrid() throws FactoryException {
    if ((dxgrid == null) || (dxgrid.length == 0)) {
      // ParameterValueGroup WarpParams =
      // gridParameters.getWarpGridParameters();
      final int xNumCells = gridParameters.getXNumber();// WarpParams.parameter("xNumCells").intValue();
      final int yNumCells = gridParameters.getYNumber();// WarpParams.parameter("yNumCells").intValue();
      final double xStep = gridParameters.getXStep();// WarpParams.parameter("xStep").intValue();
      final double yStep = gridParameters.getYStep();// WarpParams.parameter("yStep").intValue();
      final double xStart = gridParameters.getXStart();// WarpParams.parameter("xStart").intValue();
      final double yStart = gridParameters.getYStart();// WarpParams.parameter("yStart").intValue();

      final float[] warpPositions;

      warpPositions = getWarpPositions();

      dxgrid = new float[yNumCells + 1][xNumCells + 1];

      for (int i = 0; i <= yNumCells; i++) {
        for (int j = 0; j <= xNumCells; j++) {
          dxgrid[yNumCells - i][j] = new Double(
              warpPositions[(int) ((i * (1 + xNumCells) * 2) + (2 * j))]
                  - (j * xStep) - xStart).floatValue();
        }
      }
    }

    return dxgrid;
  }

  /**
   * Returns array of Shifts. This method is useful to create Coverage2D
   * object.
   *
   * @return array of Shifts
   */
  public float[][] getDyGrid() throws FactoryException {
    if ((dygrid == null) || (dygrid.length == 0)) {
      /*
       * ParameterValueGroup WarpParams =
       * gridParameters.getWarpGridParameters(); final int xNumCells =
       * WarpParams.parameter("xNumCells").intValue(); final int yNumCells =
       * WarpParams.parameter("yNumCells").intValue(); final int xStep =
       * WarpParams.parameter("xStep").intValue(); final int yStep =
       * WarpParams.parameter("yStep").intValue(); final int xStart =
       * WarpParams.parameter("xStart").intValue(); final int yStart =
       * WarpParams.parameter("yStart").intValue();
       */
      final int xNumCells = gridParameters.getXNumber();// WarpParams.parameter("xNumCells").intValue();
      final int yNumCells = gridParameters.getYNumber();// WarpParams.parameter("yNumCells").intValue();
      final double xStep = gridParameters.getXStep();// WarpParams.parameter("xStep").intValue();
      final double yStep = gridParameters.getYStep();// WarpParams.parameter("yStep").intValue();
      final double xStart = gridParameters.getXStart();// WarpParams.parameter("xStart").intValue();
      final double yStart = gridParameters.getYStart();// WarpParams.parameter("yStart").intValue();

      final float[] warpPositions;

      warpPositions = getWarpPositions();

      dygrid = new float[yNumCells + 1][xNumCells + 1];

      for (int i = 0; i <= yNumCells; i++) {
        for (int j = 0; j <= xNumCells; j++) {
          dygrid[yNumCells - i][j] = new Double(
              warpPositions[(int) ((i * (1 + xNumCells) * 2)
                  + (2 * j) + 1)]
                  - (i * yStep) - yStart).floatValue();
        }
      }
    }

    return dygrid;
  }

  /**
   *
   * @param dim
   * @param path
   * @return
   * @throws IOException
   */
  public File writeDeltaFile(int dim, String path) throws IOException,
      FactoryException {
    // ParameterValueGroup WarpParams =
    // gridParameters.getWarpGridParameters();
    final float[] warpPositions = (float[]) gridParameters
        .getWarpPositions();
    File file = new File(path);
    FileOutputStream fos = new FileOutputStream(file);
    OutputStreamWriter osw = new OutputStreamWriter(fos);
    /* Print the header */
    osw
        .write("NADCON EXTRACTED REGION                                 NADGRD ");
    osw.write("\n");

    /*
     * Print first row (number of columns, number of rows, number of
     * z–values (always one), minimum longitude, cell size, minimum
     * latitude, cell size, and not used. )
     */
    Locale.setDefault(Locale.UK);
    DecimalFormat format = new DecimalFormat();// NumberFormat.getInstance();

    format.setMinimumFractionDigits(5);
    format.setMaximumFractionDigits(5);
    format.setMinimumIntegerDigits(0);
    String space = " ";
    osw.write(" " + (gridParameters.getXNumber() + 1) + " "
        + (gridParameters.getYNumber() + 1) + "   " + "1" + "    "
        + format.format(gridParameters.getXStart()) + "      "
        + format.format(gridParameters.getXStep()) + "    "
        + format.format(gridParameters.getYStart()) + "      "
        + format.format(gridParameters.getYStep()) + "      "
        + format.format(0));

    // osw.write("\n");
    int ii = 0;

    format.setMinimumFractionDigits(6);
    format.setMaximumFractionDigits(6);

    switch (dim) {

    case 0:
      for (int i = getDxGrid().length - 1; i >= 0; i--) {

        osw.write(String.valueOf("\n"));

        int col = 0; // laa
        for (int j = 0; j < getDxGrid()[i].length; j++) {

          float val = -1 * /* 3600* */getDxGrid()[i][j]; // in
                                  // decimal
                                  // seconds
          osw.write("   " + format.format(val));
          col++;
          if (col >= 6) {
            osw.write(String.valueOf("\n"));
            col = 0;
          }
        }
      }
    break;
    case 1: {
      for (int i = getDyGrid().length - 1; i >= 0; i--) {

        osw.write(String.valueOf("\n"));

        int col = 0;// loa
        for (int j = 0; j < getDyGrid()[i].length; j++) {

          float val = /* 3600 */getDyGrid()[i][j];
          osw.write("    " + format.format(val));
          col++;
          if (col >= 6) {
            osw.write(String.valueOf("\n"));
            col = 0;
          }
        }
      }
    }
    break;
    }
    osw.close();

    return file;
  }

  /**
   * Converts warp positions from float[] containing target positions to
   * float[][] containing deltas.
   *
   */
  /*
   * public static void warpPosToDeltas(int xStart, int xStep, int xNumCells,
   * int yStart, int yStep, int yNumCells, float[][] yDeltas, float[][]
   * xDeltas) { /* @TODO
   */

  /**
   * Recalculates Deltas to Warp Positions (target position of each grid cell)
   *
   * @param xStart
   * @param xStep
   * @param xNumCells
   * @param yStart
   * @param yStep
   * @param yNumCells
   * @param yDeltas
   * @param xDeltas
   * @return
   */
  /*
   * public static float[] deltasToWarpPos(int xStart, int xStep, int
   * xNumCells, int yStart, int yStep, int yNumCells, float[][] yDeltas,
   * float[][] xDeltas) { float[] warpPos = new float[(xNumCells + 1) *
   * (yNumCells + 1) * 2];
   *
   * for (int i = 0; i < yNumCells; i++) { for (int j = 0; j < xNumCells; j++) {
   * warpPos[(2 * j) + (xNumCells * i * 2)] = xStart + (j * xStep) +
   * xDeltas[i][j]; warpPos[(2 * j) + (xNumCells * i * 2) + 1] = yStart + (i *
   * yStep) + yDeltas[i][j]; } }
   *
   * return warpPos; }
   */

  public WritableRaster getDxRaster() throws FactoryException {
    float[][] values;
    values = getDxGrid();
    WritableRaster raster = RasterFactory.createBandedRaster(
        DataBuffer.TYPE_FLOAT, values[0].length, values.length, 1,
        new Point(0, 0));
    for (int i = 0; i < values.length; i++) {
      for (int j = 0; j < values[0].length; j++) {

        raster.setSample(j, i, 0, values[i][j]);

      }
    }

    return raster;
  }

  public WritableRaster getDyRaster() throws FactoryException {
    float[][] values;
    values = getDyGrid();
    WritableRaster raster = RasterFactory.createBandedRaster(
        DataBuffer.TYPE_FLOAT, values[0].length, values.length, 1,
        new Point(0, 0));
    for (int i = 0; i < values.length; i++) {
      for (int j = 0; j < values[0].length; j++) {

        raster.setSample(j, i, 0, values[i][j]);

      }
    }

    return raster;
  }

  public WritableRaster getDxDyRaster() throws FactoryException {
    float[][] valuesDx;
    valuesDx = getDxGrid();
    float[][] valuesDy;
    valuesDy = getDyGrid();
    WritableRaster raster = RasterFactory.createBandedRaster(
        DataBuffer.TYPE_FLOAT, valuesDx[0].length, valuesDx.length, 2,
        new Point(0, 0));
    for (int i = 0; i < valuesDx.length; i++) {
      for (int j = 0; j < valuesDx[0].length; j++) {

        raster.setSample(j, i, 0, valuesDx[i][j]);
        raster.setSample(j, i, 1, valuesDy[i][j]);

      }
    }

    return raster;
  }

  /**
   *
   * @return Number of y Grid Cells
   */
  public int getHeight() {
    return gridParameters.getWarpGridParameters().parameter("yNumCells")
        .intValue();
  }

  /**
   * Sets grid height
   *
   * @param height
   *            grid height
   */
  public void setHeight(int height) {
    this.height = height;

    try {
      this.gridParameters = GridParameters.createGridParameters(envelope,
          this.envelope.getSpan(0) / width, this.envelope
              .getSpan(1)
              / height, (AffineTransform2D) worldToGrid, true);
    } catch (TransformException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }

    this.dxgrid = null;
    this.dygrid = null;
    this.warpPositions = null;
  }

  /**
   *
   * @return Number of grid cells width
   */
  public int getWidth() {
    return gridParameters.getWarpGridParameters().parameter("xNumCells")
        .intValue();
  }

  /**
   * Sets grid width
   *
   * @param width
   *            width of grid
   */
  public void setWidth(int width) {
    this.width = width;

    try {
      this.gridParameters = GridParameters.createGridParameters(envelope,
          this.envelope.getSpan(0) / width, this.envelope
              .getSpan(1)
              / height, (AffineTransform2D) worldToGrid, true);

    } catch (TransformException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }

    this.dxgrid = null;
    this.dygrid = null;
    this.warpPositions = null;
  }

  /**
   *
   * @return Envelope (in real world coordinates)
   */
  public Envelope getEnvelope() {
    return envelope;
  }

  public MathTransform getWorldToGrid() {
    MathTransform mt = null;

    mt = worldToGrid;// this.gridValues.getGridToCRS();

    return mt;
  }

  /*
   * public void setEnvelope(Envelope envelope) { cleanTransformationVars();
   * this.envelope = envelope; }
   */

  /**
   * Cleans all variable to force the recalculation of grid.
   */
  protected void cleanTransformationVars() {
    this.warpPositions = null;
    this.dxgrid = null;
    this.dygrid = null;
    this.localpositions = null;
  }

  public void setMappedPositions(List<MappedPosition> positions)
      throws MismatchedSizeException, MismatchedDimensionException,
      MismatchedReferenceSystemException {
    // TODO Auto-generated method stub
    cleanTransformationVars();

    super.setMappedPositions(positions);
  }

}
TOP

Related Classes of org.geotools.referencing.operation.builder.WarpGridBuilder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.