Author: desruisseaux Date: Thu Dec 3 12:11:45 2015 New Revision: 1717746 URL: http://svn.apache.org/viewvc?rev=1717746&view=rev Log: Add IP review for NADCON. Applies also indirectly to DatumShiftGridLoader and InterpolatedTransform. Added: sis/ip-review/NADCON.xhtml (with props) sis/ip-review/rev/07843/NADCON.xhtml (with props) sis/ip-review/rev/09131/NADCON.xhtml (with props) sis/ip-review/rev/10796/NADCON.xhtml (with props) sis/ip-review/rev/20874/NADCON.xhtml (with props) Added: sis/ip-review/NADCON.xhtml URL: http://svn.apache.org/viewvc/sis/ip-review/NADCON.xhtml?rev=1717746&view=auto ============================================================================== --- sis/ip-review/NADCON.xhtml (added) +++ sis/ip-review/NADCON.xhtml Thu Dec 3 12:11:45 2015 @@ -0,0 +1,77 @@ + + + + + NADCON history + + + +
+

NADCON history

+

Click on the commit message for inspecting the diff and how the code has been rewritten.

+

Command line:

+
svn log -r31996:1 http://svn.osgeo.org/geotools/trunk/modules/library/referencing/src/main/java/org/geotools/referencing/operation/transform/NADCONTransform.java
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Rev.DateAuthorMessage
306412008-06-12acusterCopyright headers: lib/referencing, this time with feeling (and the el in Toolkit)
306392008-06-12acusterCopyright headers: cleanup library/referencing
305212008-06-05acusterCopyright: Update referencing headers
302582008-05-08acusterReshuffle the top level repo: drop uDig, move up trunk, tags, and branches.
302572008-05-08acusterMove trunk/gt/ directory contents up to trunk/ and drop gt
298252008-04-07desruisseauxAdded synchronized statements. While the old approach was not exactly the deprecated double-check idiom, it was too close of that. A few unsynchronized blocks still exist which may need to be revisited later.
291002008-02-06desruisseauxMoved LocalizationGrid to builder package for consistency with other builders.
289222008-01-24acusterBump the (at)since version to 2.5 since WKTParser was cut from 2.4
288462008-01-20desruisseauxCovariant return type for inverse() method in MathTransform1D and MathTransform2D. Also javadoc fixes and Java 5 type safety. Changed ViewType to an enum and initial implementation of GridCoverageViews (not yet connected to GridCoverage2D).
285402007-12-29acusterHide buttons which are not yet used
285202007-12-27desruisseauxAdded @Override annotation for safety.
280812007-11-27desruisseauxJava 5 constructs: replaced some StringBuffer by StringBuilder in order to avoid unecessary synchronisation; rely on auto-boxing in order to give a chance to the JVM to reuse its cached values.
243842007-02-14desruisseauxGEOT-1160: First working implementation of AbstractAuthorityFactory.find(IdentifiedObject). This includes a package-privated AuthorityFactoryProxy class, together with many fix in the code base in order to get CRS.equalsIgnoreCase to work in the ProjectedCRS case.
223272006-10-23desruisseauxGEOT-982: regroup 'module', 'plugin', 'ext' and 'unsupported' in a common directory.
223152006-10-22desruisseauxReorganisation of directory tree structure (GEOT-982) phase 1: moved 'src' to 'src/main/java'.
221262006-10-14desruisseauxRolled back to non-static inner classes, now that the Clover bug has been fixed (as for maven-clover-plugin 2.3, released recently).
208742006-08-07jgarnettip review
207562006-07-30aaimeClover in, PMD out since nobody is using it. Also changed a few classes to make them compatible with Clover (workaround for a Clover bug, see http://www.cenqua.com/forums/thread.jspa?forumID=1&threadID=2333)
197692006-06-02desruisseauxJavadoc fix: replaced 'degrees' by 'decimal degrees' when relevant (GEOT-855)
176722006-01-19desruisseauxAdded @source tag.
176602006-01-18desruisseauxFixed SVN attributes, including the addition of URL attribute.
169832005-11-25desruisseauxReplaced references to static fields and methods of CitationImpl.* by Citations.*
153502005-08-16desruisseauxMerged the 'split-main' branch to trunk (GEOT-662)
152562005-08-09desruisseauxExtraction of referencing module from main
152552005-08-09desruisseauxPrepare branch for splitting main
148342005-07-20desruisseauxReorganized I18N resources
146102005-06-26desruisseauxCoordinateOperationFactory is now backed by an EPSG authority when available (GEOT-592)
145812005-06-22desruisseauxImplemented South-Orientated transverse mercator / more GEOT-589 work
139252005-05-30desruisseauxAdded @since javadoc tag
139222005-05-29desruisseauxRenaming of remainding GeoAPI implementations. Renaming is now finished.
139072005-05-28desruisseauxMore additions of 'Default' prefix in CRS package
138532005-05-26desruisseauxBug fix: arrays must be NamedIndentifier[], because it implements two interfaces
138362005-05-26desruisseauxAdded 'Default' suffix to some CRS implementations: partial work
137732005-05-24desruisseauxRemoved old metadata implementations (they are now renamed with 'Impl' suffix) / Use OGC citation instead of OPEN_GIS
137522005-05-23desruisseauxAdded the 'Impl' suffix to direct implementations of all metadata interfaces; deprecated the old implementations (not yet deleted).
117182005-03-01desruisseauxReplaced system preferences by user preferences, as of GEOT-450
110742005-02-03desruisseauxRevisited CRSFactory.createProjectedCRS(...) API
107962005-01-28dzwiersimports cleaned
104692005-01-11desruisseauxReplaced calls to 'getDim[Source|Target]' by 'get[Source|Target]Dimensions
102282005-01-04desruisseauxRenamed 'getDimSource' as 'getSourceDimension'
92662004-11-23desruisseauxLast WKT tuning; parsing and formatting should now be functional
91312004-11-16rschulzupdated parameter and math transform aliases (GEOT-337)
91182004-11-14desruisseauxMercator projection port completed (but untested) as a use case for other projection ports
91172004-11-13desruisseauxAdded the capability to list all available MathTransforms
91042004-11-12desruisseauxFirst prototype of a MapProjection implementation
91032004-11-12desruisseauxFixed and enabled test cases
90922004-11-11desruisseauxSlight modification in the protected API for handling parameters
87262004-10-21desruisseauxVarious bug fixes in parameter handling
78432004-09-08jgarnettFirst round of resync with geoapi
77072004-08-31jgarnettChange over to parameter descriptor.
73342004-08-01rschulzfirst commit for NADCONTransform
+
+ + Propchange: sis/ip-review/NADCON.xhtml ------------------------------------------------------------------------------ svn:eol-style = native Propchange: sis/ip-review/NADCON.xhtml ------------------------------------------------------------------------------ svn:mime-type = text/html Added: sis/ip-review/rev/07843/NADCON.xhtml URL: http://svn.apache.org/viewvc/sis/ip-review/rev/07843/NADCON.xhtml?rev=1717746&view=auto ============================================================================== --- sis/ip-review/rev/07843/NADCON.xhtml (added) +++ sis/ip-review/rev/07843/NADCON.xhtml Thu Dec 3 12:11:45 2015 @@ -0,0 +1,1036 @@ + + + + + NADCON changes for revisions 7333:7843 + + + +
+

NADCON changes for revisions 7333:7843

+

This class has been fully rewritten in Apache SIS:

+ + +

Command line:

+
svn diff --extensions "--unified --ignore-space-change --ignore-all-space --ignore-eol-style" -r7333:7843 http://svn.osgeo.org/geotools/trunk/modules/library/referencing/src/main/java/org/geotools/referencing/operation/transform/NADCONTransform.java
+ + + + +
Revision 7843
/*
+ *    Geotools 2 - OpenSource mapping toolkit
+ *    http://www.geotools.org
+ *    (C) 2004 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; either
+ *    version 2.1 of the License, or (at your option) any later version.
+ *
+ *    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.
+ *
+ *    You should have received a copy of the GNU Lesser General Public
+ *    License along with this library; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *
+ *    This package contains documentation from OpenGIS specifications.
+ *    OpenGIS consortium's work is fully acknowledged here.
+ */
+package org.geotools.referencing.operation.transform;
+
+// Geotools dependencies
+import org.geotools.metadata.citation.Citation;
+import org.geotools.referencing.Identifier;
+import org.geotools.referencing.operation.MathTransformProvider;
+import org.geotools.resources.Arguments;
+import org.geotools.resources.cts.ResourceKeys;
+import org.geotools.resources.cts.Resources;
+import org.opengis.parameter.GeneralParameterValue;
+import org.opengis.parameter.ParameterDescriptor;
+import org.opengis.parameter.ParameterDescriptorGroup;
+import org.opengis.parameter.ParameterNotFoundException;
+
+// OpenGIS dependencies
+import org.opengis.parameter.ParameterValue;
+import org.opengis.parameter.ParameterValueGroup;
+import org.opengis.referencing.FactoryException;
+import org.opengis.referencing.operation.MathTransform;
+import org.opengis.referencing.operation.TransformException;
+
+// J2SE dependencies
+import java.io.BufferedReader;
+import java.io.EOFException;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.ObjectInputStream;
+import java.io.PrintWriter;
+import java.io.Serializable;
+import java.net.URL;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import java.util.StringTokenizer;
+import java.util.prefs.Preferences;
+
+
+/**
+ * The North American Datum Conversion (NADCON) Transform (EPSG code 9613) is a
+ * two dimentional datum shift method, created by the National Geodetic Survey
+ * (NGS), that uses interpolated values from two grid shift files. This
+ * method is used  to transform NAD27 (EPSG code 4267) datum coordinates (and
+ * some others) to  NAD83 (EPSG code 4267) within the United States. There are
+ * two sent of grid  shift files: NADCON and High Accuracy Reference Networks
+ * (HARN).  NADCON shfts from NAD27 (and some others) to NAD83 while HARN
+ * shifts from  the NADCON NAD83 to an improved NAD83. Both sets of grid shift
+ * files may be  downloaded from  <a href="http://www.ngs.noaa.gov/PC_PROD/NADCON/">www.ngs.noaa.gov/PC_PROD/NADCON/</a>.
+ * <br><br>
+ *
+ * Some of the NADCON grids, their areas of use, and source datums are shown
+ * in the following table.
+ * <br><br>
+ *
+ * <table>
+ *   <tr><th>Shift File Name</td><th>Area</td><th>Source Datum</td><th>Accuracy at 67% confidence (m)</td></tr>
+ *   <tr><td>CONUS</td><td>Conterminous U S (lower 48 states)</td><td>NAD27</td><td>0.15</td></tr>
+ *   <tr><td>ALASKA</td><td>Alaska, incl. Aleutian Islands</td><td>NAD27</td><td>0.5</td></tr>
+ *   <tr><td>HAWAII</td><td>Hawaiian Islands</td><td>Old Hawaiian (4135)</td><td>0.2</td></tr>
+ *   <tr><td>STLRNC</td><td>St. Lawrence Is., AK</td><td>St. Lawrence Island (4136)</td><td>--</td></tr>
+ *   <tr><td>STPAUL </td><td>St. Paul Is., AK</td><td>St. Paul Island (4137)</td><td>--</td></tr>
+ *   <tr><td>STGEORGE</td><td>St. George Is., AK</td><td>St. George Island (4138)</td><td>--</td></tr>
+ *   <tr><td>PRVI</td><td>Puerto Rico and the Virgin Islands</td><td>Puerto Rico (4139)</td><td>0.05</td></tr>
+ * </table>
+ * <br><br>
+ *
+ * Grid shift files come in two formats: binary and text. The files from  the
+ * NGS are binary and have .las (latitude shift) and .los (longitude shift)
+ * extentions. Text grids may be created with the NGS nadgrd program and have
+ * .laa (latitude shift) and .loa (longitude shift) file extentions. Both
+ * types of  files may be used here.
+ * <br><br>
+ *
+ * The grid names to use for transforming are parameters of this
+ * MathTransform.  This parameter may be the full name and path to the grids
+ * or just the name  of the grids if the default location of the grids was set
+ * as a preference.  This preference may be set with the main method of this
+ * class. <br><br>
+ *
+ * Transformations here have been tested to be within 0.00001 seconds of
+ * values  given by the NGS ndcon210 program for NADCON grids. American Samoa
+ * and HARN  shifts have not yet been tested.  <strong>References:</strong>
+ *
+ * <ul>
+ *   <li><a href="http://www.ngs.noaa.gov/PC_PROD/NADCON/Readme.htm">NADCONreadme</a></li>
+ *   <li>American Samoa Grids for NADCON - Samoa_Readme.txt</li>
+ *   <li><a href="http://www.ngs.noaa.gov/PUBS_LIB/NGS50.pdf">NADCON - The
+ *       Application of Minimum-Curvature-Derived  Surfaces in the Transformation of
+ *       Positional Data From the North American  Datum of 1927 to the North
+ *       American Datum of 1983</a> - NOAA TM.</li>
+ *   <li>ndcon210.for - NGS fortran source code for NADCON conversions. See the
+ *       following subroutines: TRANSF, TO83, FGRID, INTRP, COEFF and SURF</li>
+ *   <li>nadgrd.for - NGS fortran source code to export/import binary and text grid
+ *       formats</li>
+ *   <li>EPSG Geodesy Parameters database version 6.5</li>
+ * </ul>
+ *
+ * @see <a href="http://www.ngs.noaa.gov/TOOLS/Nadcon/Nadcon.html"> NADCON -
+ *      North American Datum Conversion Utility</a>
+ *
+ * @version $Id$
+ * @author Rueben Schulz
+ *
+ * @TODO the transform code does not deal with the case where grids
+ *       cross +- 180 degrees
+ */
+public class NADCONTransform extends AbstractMathTransform implements Serializable {
+
+    /** Serial number for interoperability with different versions. */
+    private static final long serialVersionUID = -4707304160205218546L;
+
+    /**
+     * Preference node for the grid shift file location, and its default value.
+     */
+    private static final String GRID_LOCATION = "Grid location";
+
+    /**
+     * Preference node for the grid shift file location, and its default value.
+     */
+    private static final String DEFAULT_GRID_LOCATION = ".";
+
+    /**
+     * Difference allowed in iterative computations. This is half the value
+     * used in the NGS fortran code (so all tests pass).
+     */
+    private static final double TOL = 5.0E-10;
+
+    /** Maximum number of itterations for iterative computations. */
+    private static final int MAX_ITER = 10;
+
+    /** Conversion factor from seconds to degrees. */
+    private static final double SEC_2_DEG = 3600.0;
+
+    /** latitude and longitude grid shift file names. Output in WKT. */
+    private final String latGridName;
+
+    /** latitude and longitude grid shift file names. Output in WKT. */
+    private final String longGridName;
+
+    /*
+     * the minimum longitude value covered by this grid (degrees)
+     */
+    private double xmin;
+
+    /*
+     * the minimum latiude value covered by this grid (degrees)
+     */
+    private double ymin;
+
+    /*
+     * the maximum longitude value covered by this grid (degrees)
+     */
+    private double xmax;
+
+    /*
+     * the maximum latitude value covered by this grid (degrees)
+     */
+    private double ymax;
+
+    /*
+     * the difference between longitude grid points (degrees)
+     */
+    private double dx;
+
+    /*
+     * the difference between latitude grid points (degrees)
+     */
+    private double dy;
+
+    /**
+     * longitude and latitude grid shift values. Values are organized from  low
+     * to high longitude (low x index to high) and low to high latitude (low y
+     * index to high).
+     */
+    private LocalizationGrid gridShift = null;
+
+    /**
+     * The {@link gridShift} values as a {@link LocalizationGridTransform2D}.
+     * Used for interpolating shift values.
+     */
+    private MathTransform gridShiftTransform = null;
+
+    /** The inverse of this transform. Will be created only when needed. */
+    private transient MathTransform inverse;
+
+    /**
+     * Constructs a NADCONTransform from the specified grid shift files.
+     *
+     * @param latGridName path and name (or just name if {@link GRID_LOCATION}
+     *        is set) to the latitude differenc file. This will have a .las or
+     *        .laa file extention.
+     * @param longGridName path and name (or just name if {@link GRID_LOCATION}
+     *        is set) to the longitude differenc file. This will have a .los
+     *        or .loa file extention.
+     *
+     * @throws ParameterNotFoundException if a math transform parameter cannot
+     *         be found.
+     * @throws FactoryException if there is a problem creating this math transform
+     *         (ie file extentions are unknown or there is an error reading the
+     *          grid files)
+     */
+    public NADCONTransform(String latGridName, String longGridName)
+            throws ParameterNotFoundException, FactoryException
+    {
+        this.latGridName = latGridName;
+        this.longGridName = longGridName;
+
+        //decide if text or binary grid will be used
+        try {
+            final URL latGridURL = makeURL(latGridName);
+            final URL longGridURL = makeURL(longGridName);
+
+            if ((latGridName.endsWith(".las") && longGridName.endsWith(".los"))
+                    || (latGridName.endsWith(".LAS") && longGridName.endsWith(".LOS"))) {
+                loadBinaryGrid(latGridURL, longGridURL);
+            } else if ((latGridName.endsWith(".laa") && longGridName.endsWith(".loa"))
+                    || (latGridName.endsWith(".LAA") && longGridName.endsWith(".LOA"))) {
+                loadTextGrid(latGridURL, longGridURL);
+            } else {
+                throw new FactoryException(Resources.format(
+                        ResourceKeys.ERROR_UNSUPPORTED_FILE_TYPE_$2,
+                        latGridName.substring(latGridName.lastIndexOf('.')),
+                        longGridName.substring(longGridName.lastIndexOf('.'))));
+            }
+
+            gridShiftTransform = gridShift.getMathTransform();
+        } catch (IOException exception) {
+            final Throwable cause = exception.getCause();
+            if (cause instanceof FactoryException) {
+                throw (FactoryException) cause;
+            }
+            throw new FactoryException(exception.getLocalizedMessage(),
+                exception);
+        }
+    }
+
+    /**
+     * Returns the parameter values for this math transform.
+     *
+     * @return A copy of the parameter values for this math transform.
+     */
+    public ParameterValueGroup getParameterValues() {
+        final ParameterValue lat_diff_file = new org.geotools.parameter.Parameter(Provider.LAT_DIFF_FILE);
+        lat_diff_file.setValue(latGridName);
+
+        final ParameterValue long_diff_file = new org.geotools.parameter.Parameter(Provider.LONG_DIFF_FILE);
+        long_diff_file.setValue(longGridName);
+
+        return new org.geotools.parameter.ParameterGroup(
+            Provider.PARAMETERS,
+            new GeneralParameterValue[] { lat_diff_file, long_diff_file }
+        );
+    }
+
+    /**
+     * Gets the dimension of input points (always 2).
+     *
+     * @return the source dimention.
+     */
+    public int getDimSource() {
+        return 2;
+    }
+
+    /**
+     * Gets the dimension of output points (always 2).
+     *
+     * @return the target dimention.
+     */
+    public int getDimTarget() {
+        return 2;
+    }
+
+    /**
+     * Returns a URL from the string representation. If the string has  no
+     * path, the default path preferece is added.
+     *
+     * @param str a string representation of a URL
+     * @return a URL created from the string representation
+     * @throws java.net.MalformedURLException if the URL cannot be created
+     */
+    private URL makeURL(String str) throws java.net.MalformedURLException {
+        //has '/' or '\' or ':', so probably full path to file
+        if ((str.indexOf("\\") != -1) || (str.indexOf("/") != -1)
+                || (str.indexOf(":") != -1)) {
+            return makeURLfromString(str);
+        } else {
+            //just a file name , prepend base location
+            final Preferences prefs = Preferences.systemNodeForPackage(NADCONTransform.class);
+            final String baseLocation = prefs.get(GRID_LOCATION,
+                    DEFAULT_GRID_LOCATION);
+            return makeURLfromString(baseLocation + "/" + str);
+        }
+    }
+
+    /**
+     * Returns a URL based on a string representation. If no protocol is given,
+     * it is assumed to be a local file.
+     *
+     * @param str a string representation of a URL
+     * @return a URL created from the string representation
+     * @throws java.net.MalformedURLException if the URL cannot be created
+     */
+    private URL makeURLfromString(String str)
+            throws java.net.MalformedURLException
+    {
+        try {
+            return new URL(str);
+        } catch (java.net.MalformedURLException e) {
+            //try making this with a file protocal
+            return new URL("file", "", str);
+        }
+    }
+
+    /**
+     * Reads latitude and longitude binary grid shift file data into {@link
+     * grid}.  The file is organized into records, with the first record
+     * containing the  header information, followed by the shift data. The
+     * header values are: text describing grid (64 bytes), num. columns (int),
+     * num. rows (int),  num. z (int), min x (float), delta x (float), min y
+     * (float), delta y (float)  and angle (float). Each record is num.
+     * columns  4 bytes + 4 byte separator long and the file contains num.
+     * rows + 1 (for the header) records. The data records (with the grid
+     * shift values) are all floats and have a 4 byte  separator (0's) before
+     * the data. Row records are organized from low  y (latitude) to high and
+     * columns are orderd from low longitude to high.  Everything is written
+     * in low byte order.
+     *
+     * @param latGridUrl URL to the binary latitude shift file (.las
+     *        extention).
+     * @param longGridUrl URL to the binary longitude shift file (.los
+     *        extention).
+     * @throws IOException if the data files cannot be read.
+     * @throws FactoryException if there is an inconsistency in the data
+     */
+    private void loadBinaryGrid(URL latGridUrl, URL longGridUrl)
+            throws IOException, FactoryException
+    {
+        final int HEADER_BYTES = 96;
+        final int SEPARATOR_BYTES = 4;
+        final int DESCRIPTION_LENGTH = 64;
+        ReadableByteChannel latChannel;
+        ReadableByteChannel longChannel;
+        ByteBuffer latBuffer;
+        ByteBuffer longBuffer;
+
+        ////////////////////////
+        //setup
+        ////////////////////////
+        latChannel = getReadChannel(latGridUrl);
+        latBuffer = fillBuffer(latChannel, HEADER_BYTES);
+
+        longChannel = getReadChannel(longGridUrl);
+        longBuffer = fillBuffer(longChannel, HEADER_BYTES);
+
+        ////////////////////////
+        //read header info
+        ////////////////////////
+        //skip the header description
+        latBuffer.position(latBuffer.position() + DESCRIPTION_LENGTH);
+
+        int nc = latBuffer.getInt();
+        int nr = latBuffer.getInt();
+        int nz = latBuffer.getInt();
+
+        xmin = latBuffer.getFloat();
+        dx = latBuffer.getFloat();
+        ymin = latBuffer.getFloat();
+        dy = latBuffer.getFloat();
+
+        float angle = latBuffer.getFloat();
+        xmax = xmin + ((nc - 1) * dx);
+        ymax = ymin + ((nr - 1) * dy);
+
+        //skip the longitude header description
+        longBuffer.position(longBuffer.position() + DESCRIPTION_LENGTH);
+
+        //check that latitude grid header is the same as for latitude grid
+        if ((nc != longBuffer.getInt()) || (nr != longBuffer.getInt())
+                || (nz != longBuffer.getInt())
+                || (xmin != longBuffer.getFloat())
+                || (dx != longBuffer.getFloat())
+                || (ymin != longBuffer.getFloat())
+                || (dy != longBuffer.getFloat())
+                || (angle != longBuffer.getFloat())) {
+            throw new FactoryException(Resources.format(
+                    ResourceKeys.ERROR_GRID_LOCATIONS_UNEQUAL));
+        }
+
+        ////////////////////////
+        //read grid shift data into LocalizationGrid
+        ////////////////////////
+        final int RECORD_LENGTH = (nc * 4) + SEPARATOR_BYTES;
+        final int NUM_BYTES_LEFT = ((nr + 1) * RECORD_LENGTH) - HEADER_BYTES;
+        final int START_OF_DATA = RECORD_LENGTH - HEADER_BYTES;
+
+        latBuffer = fillBuffer(latChannel, NUM_BYTES_LEFT);
+        latBuffer.position(START_OF_DATA); //start of second record (data)
+
+        longBuffer = fillBuffer(longChannel, NUM_BYTES_LEFT);
+        longBuffer.position(START_OF_DATA);
+
+        gridShift = new LocalizationGrid(nc, nr);
+
+        int i = 0;
+        int j = 0;
+        for (i = 0; i < nr; i++) {
+            latBuffer.position(latBuffer.position() + SEPARATOR_BYTES); //skip record separator
+            longBuffer.position(longBuffer.position() + SEPARATOR_BYTES);
+
+            for (j = 0; j < nc; j++) {
+                gridShift.setLocalizationPoint(j, i,
+                    (new Float(longBuffer.getFloat())).doubleValue(),
+                    (new Float(latBuffer.getFloat())).doubleValue());
+            }
+        }
+
+        assert i == nr : i;
+        assert j == nc : j;
+    }
+
+    /**
+     * Returns a new bytebuffer, of numBytes length and little endian byte
+     * order, filled from the channel.
+     *
+     * @param channel the channel to fill the buffer from
+     * @param numBytes number of bytes to read
+     * @return a new bytebuffer filled from the channel
+     * @throws IOException if there is a problem reading the channel
+     * @throws EOFException if the end of the channel is reached
+     */
+    private ByteBuffer fillBuffer(ReadableByteChannel channel, int numBytes)
+        throws IOException {
+        ByteBuffer buf = ByteBuffer.allocateDirect(numBytes);
+
+        if (fill(buf, channel) == -1) {
+            throw new EOFException(Resources.format(
+                    ResourceKeys.ERROR_END_OF_DATA_FILE));
+        }
+
+        buf.flip();
+        buf.order(ByteOrder.LITTLE_ENDIAN);
+
+        return buf;
+    }
+
+    /**
+     * Fills the bytebuffer from the channel. Code was lifted from
+     * ShapefileDataStore.
+     *
+     * @param buffer bytebuffer to fill from the channel
+     * @param channel channel to fill the buffer from
+     * @return number of bytes read
+     * @throws IOException if there is a problem reading the channel
+     */
+    private int fill(ByteBuffer buffer, ReadableByteChannel channel)
+        throws IOException {
+        int r = buffer.remaining();
+
+        // channel reads return -1 when EOF or other error
+        // because they a non-blocking reads, 0 is a valid return value!!
+        while ((buffer.remaining() > 0) && (r != -1)) {
+            r = channel.read(buffer);
+        }
+
+        if (r == -1) {
+            buffer.limit(buffer.position());
+        }
+
+        return r;
+    }
+
+    /**
+     * Obtain a ReadableByteChannel from the given URL. If the url protocol is
+     * file, a FileChannel will be returned. Otherwise a generic channel will
+     * be obtained from the urls input stream. Code swiped from
+     * ShapefileDataStore.
+     *
+     * @param url URL to create the channel from
+     * @return a new PeadableByteChannel from the input url
+     * @throws IOException if there is a problem creating the channel
+     */
+    private ReadableByteChannel getReadChannel(URL url)
+        throws IOException {
+        ReadableByteChannel channel = null;
+
+        if (url.getProtocol().equals("file")) {
+            File file = new File(url.getFile());
+
+            if (!file.exists() || !file.canRead()) {
+                throw new IOException(Resources.format(
+                        ResourceKeys.ERROR_FILE_DOES_NOT_EXIST_$1, file));
+            }
+
+            FileInputStream in = new FileInputStream(file);
+            channel = in.getChannel();
+        } else {
+            InputStream in = url.openConnection().getInputStream();
+            channel = Channels.newChannel(in);
+        }
+
+        return channel;
+    }
+
+    /**
+     * Reads latitude and longitude text grid shift file data into {@link
+     * grid}.    The first two lines of the shift data file contain the
+     * header, with the first being a description of the grid. The second line
+     * contains 8 values separated by spaces: num. columns, num. rows, num. z,
+     * min x, delta x, min y, delta y and angle. Shift data values follow this
+     * and are also  separated by spaces. Row records are organized from low y
+     * (latitude) to  high and columns are orderd from low longitude to high.
+     *
+     * @param latGridUrl URL to the text latitude shift file (.laa extention).
+     * @param longGridUrl URL to the text longitude shift file (.loa
+     *        extention).
+     * @throws IOException if the data files cannot be read.
+     * @throws FactoryException if there is an inconsistency in the data
+     */
+    private void loadTextGrid(URL latGridUrl, URL longGridUrl)
+        throws IOException, FactoryException {
+        String latLine;
+        String longLine;
+        StringTokenizer latSt;
+        StringTokenizer longSt;
+
+        ////////////////////////
+        //setup
+        ////////////////////////
+        InputStreamReader latIsr = new InputStreamReader(latGridUrl.openStream());
+        BufferedReader latBr = new BufferedReader(latIsr);
+
+        InputStreamReader longIsr = new InputStreamReader(longGridUrl.openStream());
+        BufferedReader longBr = new BufferedReader(longIsr);
+
+        ////////////////////////
+        //read header info
+        ////////////////////////
+        latLine = latBr.readLine(); //skip header description
+        latLine = latBr.readLine();
+        latSt = new StringTokenizer(latLine, " ");
+
+        if (latSt.countTokens() != 8) {
+            throw new FactoryException(Resources.format(
+                    ResourceKeys.ERROR_HEADER_UNEXPECTED_LENGTH_$1,
+                    String.valueOf(latSt.countTokens())));
+        }
+
+        int nc = Integer.parseInt(latSt.nextToken());
+        int nr = Integer.parseInt(latSt.nextToken());
+        int nz = Integer.parseInt(latSt.nextToken());
+
+        xmin = Float.parseFloat(latSt.nextToken());
+        dx = Float.parseFloat(latSt.nextToken());
+        ymin = Float.parseFloat(latSt.nextToken());
+        dy = Float.parseFloat(latSt.nextToken());
+
+        float angle = Float.parseFloat(latSt.nextToken());
+        xmax = xmin + ((nc - 1) * dx);
+        ymax = ymin + ((nr - 1) * dy);
+
+        //now read long shift grid
+        longLine = longBr.readLine(); //skip header description
+        longLine = longBr.readLine();
+        longSt = new StringTokenizer(longLine, " ");
+
+        if (longSt.countTokens() != 8) {
+            throw new FactoryException(Resources.format(
+                    ResourceKeys.ERROR_HEADER_UNEXPECTED_LENGTH_$1,
+                    String.valueOf(longSt.countTokens())));
+        }
+
+        //check that latitude grid header is the same as for latitude grid
+        if ((nc != Integer.parseInt(longSt.nextToken()))
+                || (nr != Integer.parseInt(longSt.nextToken()))
+                || (nz != Integer.parseInt(longSt.nextToken()))
+                || (xmin != Float.parseFloat(longSt.nextToken()))
+                || (dx != Float.parseFloat(longSt.nextToken()))
+                || (ymin != Float.parseFloat(longSt.nextToken()))
+                || (dy != Float.parseFloat(longSt.nextToken()))
+                || (angle != Float.parseFloat(longSt.nextToken()))) {
+            throw new FactoryException(Resources.format(
+                    ResourceKeys.ERROR_GRID_LOCATIONS_UNEQUAL));
+        }
+
+        ////////////////////////
+        //read grid shift data into LocalizationGrid
+        ////////////////////////
+        gridShift = new LocalizationGrid(nc, nr);
+
+        int i = 0;
+        int j = 0;
+        for (i = 0; i < nr; i++) {
+            for (j = 0; j < nc;) {
+                latLine = latBr.readLine();
+                latSt = new StringTokenizer(latLine, " ");
+                longLine = longBr.readLine();
+                longSt = new StringTokenizer(longLine, " ");
+
+                while (latSt.hasMoreTokens() && longSt.hasMoreTokens()) {
+                    gridShift.setLocalizationPoint(j, i,
+                        (double) Float.parseFloat(longSt.nextToken()),
+                        (double) Float.parseFloat(latSt.nextToken()));
+                    ++j;
+                }
+            }
+        }
+
+        assert i == nr : i;
+        assert j == nc : j;
+    }
+
+    /**
+     * Transforms a list of coordinate point ordinal values. This method is
+     * provided for efficiently transforming many points. The supplied array
+     * of ordinal values will contain packed ordinal values.  For example, if
+     * the source dimension is 3, then the ordinals will be packed in this
+     * order:
+     * (<var>x<sub>0</sub></var>,<var>y<sub>0</sub></var>,<var>z<sub>0</sub></var>,
+     *
+     * <var>x<sub>1</sub></var>,<var>y<sub>1</sub></var>,<var>z<sub>1</sub></var>
+     * ...).  All input and output values are in degrees.
+     *
+     * @param srcPts the array containing the source point coordinates.
+     * @param srcOff the offset to the first point to be transformed in the
+     *        source array.
+     * @param dstPts the array into which the transformed point coordinates are
+     *        returned. May be the same than <code>srcPts</code>.
+     * @param dstOff the offset to the location of the first transformed point
+     *        that is stored in the destination array.
+     * @param numPts the number of point objects to be transformed.
+     *
+     * @throws TransformException if the input point is outside the area
+     *         covered by this grid.
+     */
+    public void transform(final double[] srcPts, int srcOff,
+        final double[] dstPts, int dstOff, int numPts)
+        throws TransformException {
+        int step = 0;
+
+        if ((srcPts == dstPts) && (srcOff < dstOff)
+                && ((srcOff + (numPts * getDimSource())) > dstOff)) {
+            step = -getDimSource();
+            srcOff -= ((numPts - 1) * step);
+            dstOff -= ((numPts - 1) * step);
+        }
+
+        while (--numPts >= 0) {
+            double x = srcPts[srcOff++];
+            double y = srcPts[srcOff++];
+
+            //check bounding box
+//issue of bbox crossing +- 180 degrees (ie input point of -188 longitude);
+//abs(x - xmin) > 0 , rollLongitude() ???
+            if (((x < xmin) || (x > xmax)) || ((y < ymin) || (y > ymax))) {
+                throw new TransformException(Resources.format(
+                        ResourceKeys.ERROR_POINT_OUTSIDE_GRID));
+            }
+
+            //find the grid the point is in (index is 0 based)
+            final double xgrid = (x - xmin) / dx;
+            final double ygrid = (y - ymin) / dy;
+            double[] array = new double[] { xgrid, ygrid };
+
+            //use the LocalizationGridTransform2D transform method (bilineal interpolation)
+            //returned shift values are in seconds, longitude shift values are + west
+            gridShiftTransform.transform(array, 0, array, 0, 1);
+
+            dstPts[dstOff++] = x - (array[0] / SEC_2_DEG);
+            dstPts[dstOff++] = y + (array[1] / SEC_2_DEG);
+            srcOff += step;
+            dstOff += step;
+        }
+    }
+
+    /**
+     * Transforms nad83 values to nad27. Input and output values are in
+     * degrees.  This is done by itteratively finding a nad27 value that
+     * shifts to the  input nad83 value. The input nad83 value is used as the
+     * first  approximation.
+     *
+     * @param srcPts the array containing the source point coordinates.
+     * @param srcOff the offset to the first point to be transformed in the
+     *        source array.
+     * @param dstPts the array into which the transformed point coordinates are
+     *        returned. May be the same than <code>srcPts</code>.
+     * @param dstOff the offset to the location of the first transformed point
+     *        that is stored in the destination array.
+     * @param numPts the number of point objects to be transformed.
+     *
+     * @throws TransformException if the input point is outside the area
+     *         covered by this grid.
+     */
+    public void inverseTransform(final double[] srcPts, int srcOff,
+        final double[] dstPts, int dstOff, int numPts)
+        throws TransformException {
+        int step = 0;
+
+        if ((srcPts == dstPts) && (srcOff < dstOff)
+                && ((srcOff + (numPts * getDimSource())) > dstOff)) {
+            step = -getDimSource();
+            srcOff -= ((numPts - 1) * step);
+            dstOff -= ((numPts - 1) * step);
+        }
+
+        while (--numPts >= 0) {
+            final double x = srcPts[srcOff++];
+            final double y = srcPts[srcOff++];
+            double xtemp = x;
+            double ytemp = y;
+
+            for (int i = MAX_ITER;;) {
+                double[] array = { xtemp, ytemp };
+                transform(array, 0, array, 0, 1);
+                double xdif = array[0] - x;
+                double ydif = array[1] - y;
+
+                if (Math.abs(xdif) > TOL) {
+                    xtemp = xtemp - xdif;
+                }
+                if (Math.abs(ydif) > TOL) {
+                    ytemp = ytemp - ydif;
+                }
+
+                if ((Math.abs(xdif) <= TOL) && (Math.abs(ydif) <= TOL)) {
+                    dstPts[dstOff++] = xtemp;
+                    dstPts[dstOff++] = ytemp;
+                    break;
+                }
+                if (--i < 0) {
+                    throw new TransformException(Resources.format(
+                            ResourceKeys.ERROR_NO_CONVERGENCE));
+                }
+            }
+
+            srcOff += step;
+            dstOff += step;
+        }
+    }
+
+    /**
+     * Returns the inverse of this transform.
+     *
+     * @return the inverse of this transform
+     */
+    public MathTransform inverse() {
+        if (inverse == null) {
+            // No need to synchronize; this is not a big deal if this object is created twice.
+            inverse = new Inverse();
+        }
+
+        return inverse;
+    }
+
+    /**
+     * Returns a hash value for this transform. To make this faster it does not
+     * check the grid values.
+     *
+     * @return a hash value for this transform.
+     */
+    public final int hashCode() {
+        final long code = Double.doubleToLongBits(xmin)
+            + (37 * (Double.doubleToLongBits(ymin)
+            + (37 * (Double.doubleToLongBits(xmax)
+            + (37 * (Double.doubleToLongBits(ymax)
+            + (37 * (Double.doubleToLongBits(dx)
+            + (37 * (Double.doubleToLongBits(dy)))))))))));
+
+        return (int) code ^ (int) (code >>> 32);
+    }
+
+    /**
+     * Compares the specified object with this math transform for equality.
+     *
+     * @param object the object to compare to
+     * @return <code>true</code> if the objects are equal.
+     */
+    public final boolean equals(final Object object) {
+        if (object == this) {
+            // Slight optimization
+            return true;
+        }
+
+        if (super.equals(object)) {
+            final NADCONTransform that = (NADCONTransform) object;
+
+            return (Double.doubleToLongBits(this.xmin) == Double.doubleToLongBits(that.xmin))
+                && (Double.doubleToLongBits(this.ymin) == Double.doubleToLongBits(that.ymin))
+                && (Double.doubleToLongBits(this.xmax) == Double.doubleToLongBits(that.xmax))
+                && (Double.doubleToLongBits(this.ymax) == Double.doubleToLongBits(that.ymax))
+                && (Double.doubleToLongBits(this.dx) == Double.doubleToLongBits(that.dx))
+                && (Double.doubleToLongBits(this.dy) == Double.doubleToLongBits(that.dy))
+                && (this.gridShiftTransform).equals(that.gridShiftTransform);
+        }
+
+        return false;
+    }
+
+    /**
+     * Used to set the preference for the default grid shift file location.
+     * This allows grids parameters to be specified by name only, without the
+     * full path. This needs to be done only once, by the superuser (root or
+     * admin). Path values may be simple file system paths or more complex
+     * text  representations of a url. A value of "default" resets this
+     * preference to its default value.
+     * <br><br>
+     *
+     * Example:
+     * <blockquote>
+     * <pre>
+     * java org.geotools.referencing.operation.transform.NADCONTransform file:///home/rschulz/GIS/NADCON/data
+     * </pre>
+     * </blockquote>
+     *
+     * @param args a single argument for the defualt location of grid shift
+     *        files
+     */
+    public static void main(String[] args) {
+        final Arguments arguments = new Arguments(args);
+        final PrintWriter out = arguments.out;
+        final Preferences prefs = Preferences.systemNodeForPackage(NADCONTransform.class);
+
+        if (args.length == 1) {
+            if (args[0].equalsIgnoreCase("default")) {
+                prefs.remove(GRID_LOCATION);
+            } else {
+                prefs.put(GRID_LOCATION, args[0]);
+            }
+
+            return;
+        } else {
+            final String location = prefs.get(GRID_LOCATION,
+                    DEFAULT_GRID_LOCATION);
+            out.println(
+                "Usage: java org.geotools.referencing.operation.transform.NADCONTransform "
+                + "<defalult grid file location (path)>");
+            out.print("Grid location: \"");
+            out.print(location);
+            out.println('"');
+
+            return;
+        }
+    }
+
+    /**
+     * Inverse of a {@link NADCONTransform}.
+     *
+     * @version $Id$
+     * @author Rueben Schulz
+     */
+    private final class Inverse extends AbstractMathTransform.Inverse implements Serializable {
+        /** Serial number for interoperability with different versions. */
+        private static final long serialVersionUID = -4707304160205218546L;
+
+        /**
+         * Default constructor.
+         */
+        public Inverse() {
+            NADCONTransform.this.super();
+        }
+
+        /**
+         * Returns the parameter values for this math transform.
+         *
+         * @return A copy of the parameter values for this math transform.
+         */
+        public ParameterValueGroup getParameterValues() {
+            return null;
+        }
+
+        /**
+         * Inverse transform an array of points.
+         *
+         * @param source
+         * @param srcOffset
+         * @param dest
+         * @param dstOffset
+         * @param length
+         *
+         * @throws TransformException if the input point is outside the area
+         *         covered by this grid.
+         */
+        public void transform(final double[] source, final int srcOffset,
+            final double[] dest, final int dstOffset, final int length)
+            throws TransformException {
+            NADCONTransform.this.inverseTransform(source, srcOffset, dest,
+                dstOffset, length);
+        }
+
+        /**
+         * Restore reference to this object after deserialization.
+         *
+         * @param in DOCUMENT ME!
+         * @throws IOException DOCUMENT ME!
+         * @throws ClassNotFoundException DOCUMENT ME!
+         */
+        private void readObject(ObjectInputStream in)
+            throws IOException, ClassNotFoundException {
+            in.defaultReadObject();
+            NADCONTransform.this.inverse = this;
+        }
+    }
+
+    /**
+     * The provider for {@link NADCONTransform}. This provider will construct
+     * transforms from {@linkPlain org.geotools.referencing.crs.GeographicCRS
+     * geographic} to {@linkPlain org.geotools.referencing.crs.GeographicCRS
+     * geographic} coordinate reference systems.
+     *
+     * @version $Id$
+     * @author Rueben Schulz
+     */
+    public static class Provider extends MathTransformProvider {
+        /** Serial number for interoperability with different versions. */
+        private static final long serialVersionUID = -4707304160205218546L;
+
+        /**
+         * The operation parameter descriptor for the "Latitude_difference_file"
+         * parameter value. The default value is "conus.las".
+         */
+        public static final ParameterDescriptor LAT_DIFF_FILE
+            = new org.geotools.parameter.ParameterDescriptor(
+                "Latitude_difference_file", "".getClass(), null, "conus.las");
+
+        /**
+         * The operation parameter descriptor for the "Longitude_difference_file"
+         * parameter value. The default value is "conus.los".
+         */
+        public static final ParameterDescriptor LONG_DIFF_FILE
+            = new org.geotools.parameter.ParameterDescriptor(
+                "Longitude_difference_file", new String().getClass(), null, "conus.los");
+
+        /** The parameters group. */
+        static final ParameterDescriptorGroup PARAMETERS = group(new Identifier[] {
+                    new Identifier(Citation.OPEN_GIS, null, "NADCON"),
+                    new Identifier(Citation.EPSG, "EPSG", "9613")
+                }, new ParameterDescriptor[] { LAT_DIFF_FILE, LONG_DIFF_FILE });
+
+        /**
+         * Constructs a provider.
+         */
+        public Provider() {
+            super(2, 2, PARAMETERS);
+        }
+
+        /**
+         * Returns the resources key for {@linkPlain #getName localized name}.
+         * This method is for internal purpose by Geotools implementation
+         * only.
+         *
+         * @return the resource key for this math transform
+         */
+        protected int getLocalizationKey() {
+            return ResourceKeys.NADCON_TRANSFORM;
+        }
+
+        /**
+         * Creates a math transform from the specified group of parameter
+         * values.
+         *
+         * @param values The group of parameter values.
+         * @return The created math transform.
+         * @throws ParameterNotFoundException if a required parameter was not
+         *         found.
+         * @throws FactoryException if there is a problem creating this
+         *         math transform.
+         */
+        protected MathTransform createMathTransform(ParameterValueGroup values)
+            throws ParameterNotFoundException, FactoryException {
+            return new NADCONTransform(
+                stringValue(values, LAT_DIFF_FILE),
+                stringValue(values, LONG_DIFF_FILE));
+        }
+    }
+}
+
+ + Propchange: sis/ip-review/rev/07843/NADCON.xhtml ------------------------------------------------------------------------------ svn:eol-style = native Propchange: sis/ip-review/rev/07843/NADCON.xhtml ------------------------------------------------------------------------------ svn:mime-type = text/html Added: sis/ip-review/rev/09131/NADCON.xhtml URL: http://svn.apache.org/viewvc/sis/ip-review/rev/09131/NADCON.xhtml?rev=1717746&view=auto ============================================================================== --- sis/ip-review/rev/09131/NADCON.xhtml (added) +++ sis/ip-review/rev/09131/NADCON.xhtml Thu Dec 3 12:11:45 2015 @@ -0,0 +1,35 @@ + + + + + NADCON changes for revisions 9130:9131 + + + +
+

NADCON changes for revisions 9130:9131

+

The same information has been fetched independently from the EPSG database.

+ +

Command line:

+
svn diff --extensions "--unified --ignore-space-change --ignore-all-space --ignore-eol-style" -r9130:9131 http://svn.osgeo.org/geotools/trunk/modules/library/referencing/src/main/java/org/geotools/referencing/operation/transform/NADCONTransform.java
+ + + + +
Revision 9130Revision 9131
 */
+static final ParameterDescriptorGroup PARAMETERS = createDescriptorGroup(new Identifier[] {
+        new Identifier(Citation.OPEN_GIS, "NADCON"),
+        new Identifier(Citation.EPSG,     "9613"),
+        new Identifier(Citation.GEOTOOLS, Resources.formatInternational(
+                                          ResourceKeys.NADCON_TRANSFORM))
 */
+static final ParameterDescriptorGroup PARAMETERS = createDescriptorGroup(new Identifier[] {
+        new Identifier(Citation.OPEN_GIS, "NADCON"),
+        new Identifier(Citation.EPSG,     "NADCON"),
+        new Identifier(Citation.EPSG,     "9613"),
+        new Identifier(Citation.GEOTOOLS, Resources.formatInternational(
+                                          ResourceKeys.NADCON_TRANSFORM))
+
+ + Propchange: sis/ip-review/rev/09131/NADCON.xhtml ------------------------------------------------------------------------------ svn:eol-style = native Propchange: sis/ip-review/rev/09131/NADCON.xhtml ------------------------------------------------------------------------------ svn:mime-type = text/html Added: sis/ip-review/rev/10796/NADCON.xhtml URL: http://svn.apache.org/viewvc/sis/ip-review/rev/10796/NADCON.xhtml?rev=1717746&view=auto ============================================================================== --- sis/ip-review/rev/10796/NADCON.xhtml (added) +++ sis/ip-review/rev/10796/NADCON.xhtml Thu Dec 3 12:11:45 2015 @@ -0,0 +1,85 @@ + + + + + NADCON changes for revisions 10795:10796 + + + +
+

NADCON changes for revisions 10795:10796

+

Changes in this commit seem to be the result of some "auto reformat" tool execution. +The Java - GeoAPI - GeoTools import ordering is altered, +imports used only in Javadoc are lost and the encoding of non-ASCII characters is broken. +This commit has been reverted, except for the removal of really unused imports which are keep removed.

+

Command line:

+
svn diff --extensions "--unified --ignore-space-change --ignore-all-space --ignore-eol-style" -r10795:10796 http://svn.osgeo.org/geotools/trunk/modules/library/referencing/src/main/java/org/geotools/referencing/operation/transform/NADCONTransform.java
+ + + + + + +
Revision 10795Revision 10796
package org.geotools.referencing.operation.transform;
+
+// Geotools dependencies
+import org.geotools.metadata.citation.Citation;
+import org.geotools.referencing.Identifier;
+import org.geotools.referencing.operation.MathTransformProvider;
+import org.geotools.resources.Arguments;
+import org.geotools.resources.cts.ResourceKeys;
+import org.geotools.resources.cts.Resources;
+import org.opengis.parameter.GeneralParameterValue;
+import org.opengis.parameter.ParameterDescriptor;
+import org.opengis.parameter.ParameterDescriptorGroup;
+import org.opengis.parameter.ParameterNotFoundException;
+
+// OpenGIS dependencies
+import org.opengis.parameter.ParameterValue;
+import org.opengis.parameter.ParameterValueGroup;
+import org.opengis.referencing.FactoryException;
+import org.opengis.referencing.operation.MathTransform;
+import org.opengis.referencing.operation.TransformException;
+
+// J2SE dependencies
+import java.io.BufferedReader;
+import java.io.EOFException;
+import java.io.File;
package org.geotools.referencing.operation.transform;
+
+// Geotools dependencies
+import java.io.BufferedReader;
+import java.io.EOFException;
+import java.io.File;
import java.util.StringTokenizer;
+import java.util.prefs.Preferences;
+
+
+/**
+ * The North American Datum Conversion (NADCON) Transform (EPSG code 9613) is a
+ * two dimentional datum shift method, created by the National Geodetic Survey
import java.util.StringTokenizer;
+import java.util.prefs.Preferences;
+
+import org.geotools.metadata.citation.Citation;
+import org.geotools.referencing.Identifier;
+import org.geotools.referencing.operation.MathTransformProvider;
+import org.geotools.resources.Arguments;
+import org.geotools.resources.cts.ResourceKeys;
+import org.geotools.resources.cts.Resources;
+import org.opengis.parameter.GeneralParameterValue;
+import org.opengis.parameter.ParameterDescriptor;
+import org.opengis.parameter.ParameterDescriptorGroup;
+import org.opengis.parameter.ParameterNotFoundException;
+import org.opengis.parameter.ParameterValue;
+import org.opengis.parameter.ParameterValueGroup;
+import org.opengis.referencing.FactoryException;
+import org.opengis.referencing.operation.MathTransform;
+import org.opengis.referencing.operation.TransformException;
+
+
+/**
+ * The North American Datum Conversion (NADCON) Transform (EPSG code 9613) is a
+ * two dimentional datum shift method, created by the National Geodetic Survey
+
+ + Propchange: sis/ip-review/rev/10796/NADCON.xhtml ------------------------------------------------------------------------------ svn:eol-style = native Propchange: sis/ip-review/rev/10796/NADCON.xhtml ------------------------------------------------------------------------------ svn:mime-type = text/html