/*
* Geotoolkit.org - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2010-2012, Open Source Geospatial Foundation (OSGeo)
* (C) 2010-2012, Geomatys
*
* 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.geotoolkit.referencing.operation.transform;
import org.opengis.util.FactoryException;
import org.opengis.referencing.crs.ProjectedCRS;
import org.opengis.referencing.operation.TransformException;
import org.apache.sis.referencing.CRS;
import org.opengis.test.CalculationType;
import org.opengis.test.referencing.TransformTestCase;
import org.apache.sis.internal.system.DataDirectory;
import org.apache.sis.referencing.crs.AbstractCRS;
import org.apache.sis.referencing.cs.AxesConvention;
import org.junit.Test;
import static org.apache.sis.test.Assume.*;
import static java.lang.StrictMath.*;
/**
* Tests {@link NTv2Transform} with RGF93 data.
*
* @author Simon Reynard (Geomatys)
* @author Martin Desruisseaux (Geomatys)
*/
public final strictfp class RGF93TransformTest extends TransformTestCase {
/**
* The test points, as (Easting, Northing) ordinates.
* <ol>
* <li>The two first columns are the source points expressed in the EPSG:27572 projected CRS.</li>
* <li>The two next columns are the expected points expressed in the EPSG:2154 projected CRS,
* as computed by IGN using the NTv2 grid.</li>
* <li>The two last columns are the same expected points, but computed using CIRCE (the
* reference software) instead than the NTv2 grid.</li>
* </ol>
*/
private static final double[] POINTS = {
// EPSG:27572 EPSG:2154 using NTv2 EPSG:2154 using CIRCE
// ------------------------- ------------------------- -------------------------
565767.9060, 2669005.7300, 619119.4605, 7102502.9796, 619119.4610, 7102502.9800, // [ 1]
586916.3540, 2685313.9090, 640394.2192, 7118626.5017, 640394.2190, 7118626.5010, // [ 2]
586809.9010, 2640699.4610, 639914.1894, 7074034.8467, 639914.1890, 7074034.8460, // [ 3]
523456.3190, 2558732.7240, 575909.3038, 6992641.1077, 575909.3040, 6992641.1070, // [ 4]
595226.2980, 2558214.3740, 647634.5864, 6991523.7515, 647634.5870, 6991523.7510, // [ 5]
731608.0030, 2558633.7960, 783942.7495, 6990790.2512, 783942.7500, 6990790.2510, // [ 6]
305468.5890, 2525760.9710, 357778.7906, 6961484.3559, 357778.7910, 6961484.3560, // [ 7]
435389.8080, 2492660.2280, 487347.6920, 6927337.7626, 487347.6920, 6927337.7620, // [ 8]
579906.7800, 2488093.9460, 631736.5407, 6921573.1749, 631736.5410, 6921573.1750, // [ 9]
696204.1960, 2486642.3370, 747948.8340, 6919142.1958, 747948.8340, 6919142.1960, // [10]
784124.9120, 2466527.7250, 835641.6226, 6898291.5327, 835641.6230, 6898291.5320, // [11]
856998.3680, 2470446.3390, 908500.6340, 6901582.5244, 908500.6340, 6901582.5240, // [12]
929226.5610, 2485290.9830, 980808.8597, 6915794.5771, 980808.8600, 6915794.5770, // [13]
55824.4970, 2394454.2120, 107242.8306, 6832277.1818, 107242.8310, 6832277.1820, // [14]
207039.4390, 2376909.4780, 258206.9875, 6813532.5659, 258206.9870, 6813532.5660, // [15]
347675.8820, 2364112.2710, 398636.7673, 6799599.5673, 398636.7680, 6799599.5670, // [16]
472921.7110, 2347471.9370, 523653.0866, 6781938.7375, 523653.0870, 6781938.7370, // [17]
615208.4710, 2410068.4940, 666360.5365, 6843302.7284, 666360.5360, 6843302.7280, // [18]
774255.1110, 2336781.9170, 824671.2851, 6768721.5295, 824671.2850, 6768721.5290, // [19]
885696.8330, 2354069.8220, 936176.9432, 6785041.1104, 936176.9430, 6785041.1100, // [20]
1023838.2710, 2347294.3570, 1074154.7208, 6777074.0950, 1074154.7210, 6777074.0950, // [21]
245930.1080, 2231287.2200, 295884.5626, 6667708.0689, 295884.5620, 6667708.0690, // [22]
482536.2450, 2234288.2340, 532320.5569, 6668763.5434, 532320.5570, 6668763.5430, // [23]
571772.5460, 2243869.7100, 621562.9560, 6677593.5695, 621562.9560, 6677593.5690, // [24]
808477.9260, 2213860.5740, 857816.7872, 6645607.2826, 857816.7870, 6645607.2820, // [25]
962154.8710, 2238672.8090, 1011577.0899, 6669076.0321, 1011577.0900, 6669076.0320, // [26]
335739.3040, 2178572.4910, 385188.6949, 6614304.9039, 385188.6950, 6614304.9030, // [27]
710424.8050, 2124204.1250, 759087.4114, 6556864.5922, 759087.4110, 6556864.5920, // [28]
804996.0320, 2099634.2940, 853362.4078, 6531513.0948, 853362.4080, 6531513.0940, // [29]
917801.8930, 2141421.2140, 966422.5862, 6572293.1866, 966422.5860, 6572293.1870, // [30]
311927.5700, 2013416.1660, 360048.3633, 6449497.6594, 360048.3630, 6449497.6590, // [31]
443131.7830, 2000469.2590, 491014.8595, 6435484.9121, 491014.8590, 6435484.9120, // [32]
589087.0090, 2008609.2550, 636891.9741, 6442402.4429, 636891.9740, 6442402.4430, // [33]
712291.5080, 1982263.3390, 759750.0629, 6415045.6523, 759750.0630, 6415045.6520, // [34]
816457.4380, 2009601.8830, 864043.4959, 6441470.2490, 864043.4960, 6441470.2490, // [35]
951557.8200, 2000101.9410, 998925.0808, 6430818.4617, 998925.0810, 6430818.4620, // [36]
335588.3720, 1925554.7010, 382965.7020, 6361532.7761, 382965.7020, 6361532.7760, // [37]
466953.3130, 1895363.0580, 513941.6034, 6330291.1939, 513941.6030, 6330291.1930, // [38]
591523.5580, 1888624.7270, 638321.3307, 6322522.3676, 638321.3300, 6322522.3680, // [39]
716320.1410, 1914162.4660, 763198.2973, 6346981.7959, 763198.2970, 6346981.7960, // [40]
814149.5290, 1887019.7680, 860690.8052, 6319036.8495, 860690.8040, 6319036.8490, // [41]
969601.4270, 1903012.3120, 1016109.8027, 6333675.7251, 1016109.8030, 6333675.7250, // [42]
278246.3650, 1832443.1700, 324925.5421, 6268991.6779, 324925.5420, 6268991.6780, // [43]
418920.7800, 1814754.9160, 465295.7475, 6250169.6075, 465295.7470, 6250169.6080, // [44]
590413.4980, 1791602.8840, 636400.3102, 6225618.8552, 636400.3100, 6225618.8550, // [45]
1162613.7590, 1765373.2060, 1207701.1362, 6194512.5764, 1207701.1360, 6194512.5760 // [46]
};
/**
* Returns source or expected test points.
*
* @param type 0 for the source points, 1 for the expected destination points (NTv2),
* or 2 for the expected destination points (CIRCE).
* @return The test points.
*/
private static double[] getPoints(final int type) {
final double[] points = new double[POINTS.length / 3];
int srcOff = type*2;
int dstOff = 0;
while (dstOff < points.length) {
System.arraycopy(POINTS, srcOff, points, dstOff, 2);
srcOff += 6;
dstOff += 2;
}
return points;
}
/**
* Test the transformation of some points givens in the test set of
* <a href="http://lambert93.ign.fr/index.php?id=30">"Notice explicative"</a>
* from IGN lambert93 website.
*
* @throws FactoryException Should never happen.
* @throws TransformException Should never happen.
*/
@Test
@org.junit.Ignore
public void testTransform() throws FactoryException, TransformException {
assumeDataExists(DataDirectory.DATUM_CHANGES, "gr3df97a.txt");
assumeTrue(false /*Commons.isEpsgFactoryAvailable()*/);
/*
* Get the transform, which will use the NTv2 grid since
* we are transforming between two-dimensional CRS.
*/
final ProjectedCRS sourceCRS = (ProjectedCRS) AbstractCRS.castOrCopy(CRS.forCode("EPSG:27572")).forConvention(AxesConvention.RIGHT_HANDED); // Lambert zone II etendu
final ProjectedCRS targetCRS = (ProjectedCRS) AbstractCRS.castOrCopy(CRS.forCode("EPSG:2154")).forConvention(AxesConvention.RIGHT_HANDED); // RGF93 / lambert93
transform = CRS.findOperation(sourceCRS, targetCRS, null).getMathTransform();
/*
* Test the transform. It is normal to have a difference compared with CIRCE, since the
* NTv2 grid is an approximation. However the difference compared to the expected values
* for the NTv2 grid is more complex. In a previous version (were we performed all steps
* by hand, including the conversion from grad to degrees and the longitude shift), we
* had the same result (tolerance = 1E-4). By letting the referencing module doing the
* transform concatenation by itself, we have a slight difference (less than 4E-4 metre).
* It may be related to different rounding errors, since the referencing module performs
* more aggressive usage and concatenation of affine transforms.
*/
final double[] sourcePts = getPoints(0);
final double[] expectedPts = getPoints(1);
final double[] actualPts = new double[sourcePts.length];
transform.transform(sourcePts, 0, actualPts, 0, sourcePts.length / 2);
tolerance = 4E-4;
assertCoordinatesEqual("RGF93 transform (compared to NTv2)",
2, expectedPts, 0, actualPts, 0, expectedPts.length/2, CalculationType.DIRECT_TRANSFORM);
tolerance = 2E-3;
final double[] circePts = getPoints(2);
assertCoordinatesEqual("RGF93 transform (compared to CIRCE)",
2, circePts, 0, actualPts, 0, circePts.length/2, CalculationType.DIRECT_TRANSFORM);
/*
* Optional statistics for comparing our errors with the ones reported by IGN. We perform
* equal or better than IGN in 42% of cases, and we perform worst in the remaining 58% of
* cases. The differences however are very small: 0.5 millimetre.
*/
if (false) {
int pass = 0;
double s1=0, s2=0;
for (int i=0; i<circePts.length; i++) {
final double d1 = abs(actualPts [i] - circePts[i]);
final double d2 = abs(expectedPts[i] - circePts[i]);
s1 += d1;
s2 += d2;
if (d1 <= d2) {
pass++;
}
}
System.out.println("Mean error (Geotk): " + s1 / circePts.length);
System.out.println("Mean error (IGN): " + s2 / circePts.length);
System.out.println("No regression for " + round(pass*100f / circePts.length) + "% of ordinates.");
}
}
}