gt:             points[i] = target ? mp.getTarget() : mp.getSource();
context: /*
   *    Geotools2 - OpenSource mapping toolkit
   *    http://geotools.org
   *    (C) 2006, Geotools Project Managment Committee (PMC)
   *
   *    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.referencefork.referencing.operation.builder;
  
  import java.io.IOException;
  import java.io.StringWriter;
  import java.io.Writer;
  import java.util.ArrayList;
  import java.util.Collection;
  import java.util.Collections;
  import java.util.HashMap;
  import java.util.Iterator;
  import java.util.List;
  import java.util.Locale;
  import java.util.Map;
  import java.util.Set;
  
  import javax.vecmath.MismatchedSizeException;
  
  import org.geotools.referencefork.geometry.GeneralDirectPosition;
  import org.geotools.referencefork.math.Statistics;
  import org.gvsig.referencing.ReferencingUtil;
  import org.opengis.metadata.Identifier;
  import org.opengis.metadata.extent.Extent;
  import org.opengis.parameter.ParameterValueGroup;
  import org.opengis.referencing.FactoryException;
  import org.opengis.referencing.crs.CoordinateReferenceSystem;
  import org.opengis.referencing.crs.DerivedCRS;
  import org.opengis.referencing.crs.EngineeringCRS;
  import org.opengis.referencing.crs.GeographicCRS;
  import org.opengis.referencing.crs.ImageCRS;
  import org.opengis.referencing.crs.ProjectedCRS;
  import org.opengis.referencing.cs.CartesianCS;
  import org.opengis.referencing.cs.CoordinateSystem;
  import org.opengis.referencing.operation.Conversion;
  import org.opengis.referencing.operation.CoordinateOperationFactory;
  import org.opengis.referencing.operation.MathTransform;
  import org.opengis.referencing.operation.OperationMethod;
  import org.opengis.referencing.operation.TransformException;
  import org.opengis.referencing.operation.Transformation;
  import org.opengis.spatialschema.geometry.DirectPosition;
  import org.opengis.spatialschema.geometry.MismatchedDimensionException;
  import org.opengis.spatialschema.geometry.MismatchedReferenceSystemException;
  import org.opengis.util.InternationalString;
  
  
  /**
   * Provides a basic implementation for {@linkplain MathTransform math transform}
   * builders.
   * 
   * Math transform builders create {@link MathTransform} objects for transforming 
   * coordinates from a source CRS 
   * ({@linkplain CoordinateReferenceSystem Coordinate Reference System}) to
   * a target CRS using empirical parameters. Usually, one of those CRS is a
   * {@linkplain GeographicCRS geographic} or {@linkplain ProjectedCRS projected}
   * one with a well known relationship to the earth. The other CRS is often an
   * {@linkplain EngineeringCRS engineering} or {@linkplain ImageCRS image} one
   * tied to some ship. For example a remote sensing image <em>before</em>
   * georectification may be referenced by an {@linkplain ImageCRS image CRS}.
   *
   * <blockquote><p><font size=-1><strong>Design note:</strong>
   * It is technically possible to reference such remote sensing images with a
   * {@linkplain DerivedCRS CRS derived} from the geographic or projected CRS,
   * where the {@linkplain DerivedCRS#getConversionFromBase conversion from base}
   * is the math transform {@linkplain #getMathTransform computed by this builder}.
   * Such approach is advantageous for {@linkplain CoordinateOperationFactory
   * coordinate operation factory} implementations, since they can determine the
   * operation just by inspection of the {@link DerivedCRS} instance. However this
   * is conceptually incorrect since {@link DerivedCRS} can be related to an other
   * CRS only through {@linkplain Conversion conversions}, which by definition are
   * accurate up to rounding errors. The operations created by math transform
   * builders are rather {@linkplain Transformation transformations}, which can't
   * be used for {@link DerivedCRS} creation.
   * </font></p></blockquote>
   *
   * The math transform from {@linkplain #getSourceCRS source CRS} to {@linkplain
   * #getTargetCRS target CRS} is calculated by {@code MathTransformBuilder} from
   * a set of {@linkplain #getMappedPositions mapped positions} in both CRS.
   * <p>
   * Subclasses must implement at least the {@link #getMinimumPointCount()} and
   * {@link #computeMathTransform()} methods.
   *
   * @since 2.4
   * @source $URL: http://svn.geotools.org/geotools/trunk/gt/modules/library/referencing/src/main/java/org/geotools/referencing/operation/builder/MathTransformBuilder.java $
   * @version $Id: MathTransformBuilder.java 28984 2008-01-28 18:08:29Z acuster $
   * @author Jan Jezek
   * @author Martin Desruisseaux
   */
  public abstract class MathTransformBuilder {
      /**
       * The list of mapped positions.
       */
      private final List<MappedPosition> positions = new ArrayList<MappedPosition>();
  
      /**
       * An unmodifiable view of mapped positions to be returned by {@link #getMappedPositions}.
       */
      private final List<MappedPosition> unmodifiablePositions =
              Collections.unmodifiableList(positions);
  
      /**
       * Coordinate Reference System of the source and target points,
       * or {@code null} if unknown.
       */
      private CoordinateReferenceSystem sourceCRS, targetCRS;
  
      /**
       * The math transform. Will be computed only when first needed.
       */
      private transient MathTransform transform;
  
      /**
       * The transformation. Will be computed only when first needed.
       */
      private transient Transformation transformation;
  
      /**
       * The factory to use for creating {@link MathTransform math transform} instances.
       */
  //    protected final MathTransformFactory mtFactory;
  
      /**
       * The CRS factory to use for creating {@link EngineeringCRS} instances.
       */
  //    private final CRSFactory crsFactory;
  
      /**
       * The datum factory to use for creating {@link EngineeringCRS} instances.
       */
  //    private final DatumFactory datumFactory;    
  
      /**
       * Creates a builder with the default factories.
       */
      public MathTransformBuilder() {
  //        this(null);
      }
  
      /**
       * Creates a builder from the specified hints.
       */
  //    public MathTransformBuilder(final Hints hints) {
  //        mtFactory    = ReferencingFactoryFinder.getMathTransformFactory(hints);
  //        crsFactory   = ReferencingFactoryFinder.getCRSFactory          (hints);
  //        datumFactory = ReferencingFactoryFinder.getDatumFactory        (hints);
  //    }
  
      /**
       * Returns the name for the {@linkplain #getTransformation transformation} to
       * be created by this builder.
       */
      public String getName() {
  //        return Classes.getShortClassName(this) + " fit";
      	return this.toString();
      }
  
      /**
       * Returns the minimum number of points required by this builder. This minimum depends on the
       * algorithm used. For example {@linkplain AffineTransformBuilder affine transform builders}
       * require at least 3 points, while {@linkplain SimilarTransformBuilder similar transform
       * builders} requires only 2 points.
       */
      public abstract int getMinimumPointCount();
  
      /**
       * Returns the dimension for {@linkplain #getSourceCRS source} and
       * {@link #getTargetCRS target} CRS. The default value is 2.
       */
      public int getDimension() {
          return 2;
      }
  
      /**
       * Returns the list of mapped positions.
       */
      public List <MappedPosition> getMappedPositions() {
          return unmodifiablePositions;
      }
  
      /**
       * Set the list of mapped positions.
       *
       * @throws MismatchedSizeException if the list doesn't have the expected number of points.
       * @throws MismatchedDimensionException if some points doesn't have the
       *         {@linkplain #getDimension expected number of dimensions}.
       * @throws MismatchedReferenceSystemException if CRS is not the same for all points.
       */
      public void setMappedPositions(final List<MappedPosition> positions)
              throws MismatchedSizeException, MismatchedDimensionException,
                     MismatchedReferenceSystemException
      {
          final CoordinateReferenceSystem source, target;
          source = ensureValid(getPoints(positions, false), "sourcePoints");
          target = ensureValid(getPoints(positions, true ), "targetPoints");
          /*
           * Now stores the informations. Note that we set the source and target CRS
           * only after 'ensureValid' succeed for both CRS.
           */
          this.positions.clear();
          this.positions.addAll(positions);
          
  //        this.positions = positions;
          
          
          
          this.sourceCRS = source;
          this.targetCRS = target;
          this.transform = null;
      }
  
      /**
       * Extracts the source or target points from the specified list.
       *
       * @param positions The array where to take points from.
       * @param target {@code false} for extracting source points,
       *        or {@code true} for extracting target points.
       */
      private static DirectPosition[] getPoints(List <MappedPosition> positions, boolean target) {
          final DirectPosition[] points = new DirectPosition[positions.size()];
          for (int i=0; i<points.length; i++) {
              final MappedPosition mp = (MappedPosition) positions.get(i);
  