/*
* Geotoolkit.org - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2002-2012, Open Source Geospatial Foundation (OSGeo)
* (C) 2009-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.factory.epsg;
import java.util.Map;
import java.util.HashMap;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.awt.geom.Point2D;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.crs.ProjectedCRS;
import org.apache.sis.math.Statistics;
import org.apache.sis.referencing.CRS;
import org.apache.sis.geometry.DirectPosition2D;
import org.apache.sis.referencing.CommonCRS;
import org.apache.sis.referencing.factory.GeodeticAuthorityFactory;
import static org.junit.Assert.*;
import static java.lang.StrictMath.*;
import static org.apache.sis.util.collection.Containers.hashMapCapacity;
/**
* A thread which will perform many coordinate transformations between different pairs of CRS.
* The results are compared with previous results for consistency.
* <p>
* The {@link StressTest} class starts many instances of this class in order to test concurrency.
*
* @author Jody Garnett (Refractions)
* @author Martin Desruisseaux (Geomatys)
* @version 3.17
*
* @since 2.4
*/
final strictfp class ClientThread extends Thread {
/**
* The tolerance (in decimal degrees) between the results of transformation
* to geographic coordinates.
*/
private static final double ANGLE_TOLERANCE = 1E-12;
/**
* The squared value of the maximal distance (in metres) allowed between a point
* in UTM 84 and its transform in UTM 72, or conversely.
*/
private static final double UTM_TOLERANCE = 20 * 20;
/**
* Thread identifier.
*/
final int id;
/**
* The result of the {@link #testGeographicToRandom()} method.
* Keys are EPSG code of the source CRS. Values are the transformed coordinates.
*/
final Map<Integer, Point2D.Double> result;
/**
* The first exception that occurred, or {@code null} if everything was successful.
*/
Throwable exception;
/**
* The code of the CRS that caused the exception, or {@code null} if none.
*/
String badCode;
/**
* Test metrics.
*/
final Statistics statistics;
/**
* Random number generator.
*/
private final Random random;
/**
* The factory to test.
*/
private final GeodeticAuthorityFactory factory;
/**
* Used in order to wait until every threads are ready to process.
*/
private final CountDownLatch lock;
/**
* Creates a client thread for the given factory to test.
*
* @param id Thread identifier.
* @param factory The factory to test.
*/
public ClientThread(final int id, final GeodeticAuthorityFactory factory, final CountDownLatch lock) {
super("ClientThread" + (id < 10 ? " 0" : " ") + id);
this.id = id;
this.factory = factory;
this.random = new Random(179702531L + id);
this.statistics = new Statistics(null);
this.lock = lock;
this.result = createEmptyResultMap();
}
/**
* Creates an initially empty map which will hold the result of
* {@link #testGeographicToRandom()}.
*/
static Map<Integer, Point2D.Double> createEmptyResultMap() {
return new HashMap<>(hashMapCapacity(CODES.length));
}
/**
* Gets random CRS and apply a map projection from that CRS to WGS84 for each of them.
*/
@Override
public void run() {
final CoordinateReferenceSystem sourceCRS = CommonCRS.WGS84.normalizedGeographic();
final DirectPosition2D sourcePt = new DirectPosition2D(104800, 273914); // Random coordinate
final DirectPosition2D targetPt = new DirectPosition2D();
final DirectPosition2D coordUTM = new DirectPosition2D();
/*
* Wait until every threads are ready to process.
*/
try {
lock.await();
} catch (InterruptedException e) {
// Consider that as a failure.
exception = e;
return;
}
for (int i=0; i<StressTest.ITERATIONS; i++) {
/*
* Test the transformations from a random CRS to WGS84. This test uses a
* fixed coordinates so we can verify that every thread produce the same
* result for the same source CRS.
*/
final int crsCode = CODES[random.nextInt(CODES.length)];
String code = String.valueOf(crsCode);
long startTime = System.nanoTime();
try {
/*
* Random CRS --> WGS84
* The result will be saved for comparison with the results from other threads.
*/
final CoordinateReferenceSystem targetCRS = factory.createCoordinateReferenceSystem(code);
MathTransform transform = CRS.findOperation(sourceCRS, targetCRS, null).getMathTransform();
assertSame(targetPt, transform.inverse().transform(sourcePt, targetPt));
statistics.accept(System.nanoTime() - startTime);
assertFalse("x=NaN", Double.isNaN(targetPt.x));
assertFalse("y=NaN", Double.isNaN(targetPt.y));
assertConsistent(result, crsCode, targetPt);
/*
* UTM 72 --> UTM 84 (or conversely)
* The distance should be small.
*/
int zone = random.nextInt(60) + 1;
if (random.nextBoolean()) {
zone += 100; // Switch from zone North to zone South.
}
final ProjectedCRS sourceUTM = factory.createProjectedCRS(code = String.valueOf(32200 + zone));
final ProjectedCRS targetUTM = factory.createProjectedCRS(code = String.valueOf(32600 + zone));
transform = CRS.findOperation(sourceUTM, targetUTM, null).getMathTransform();
if (random.nextBoolean()) {
transform = transform.inverse();
}
assertFalse("Expected at datum shift.", transform.isIdentity());
final double x = coordUTM.x = random.nextDouble() * 300000 + 100000;
final double y = coordUTM.y = random.nextDouble() * 5000000 + 2500000;
assertSame(coordUTM, transform.transform(coordUTM, coordUTM));
final double distSq = coordUTM.distanceSq(x, y);
if (!(distSq <= UTM_TOLERANCE)) { // Use '!' for catching NaN.
fail("UTM tolerance error: " + sqrt(distSq));
}
} catch (Throwable e) {
exception = e;
badCode = code;
break;
}
}
}
/**
* Asserts that the given result of a coordinate transformation is consistent with previous
* result.
*/
static void assertConsistent(final Map<Integer, Point2D.Double> result,
final Integer code, final Point2D.Double point)
{
final Point2D.Double previous = result.put(code, new Point2D.Double(point.x, point.y));
if (previous != null) {
assertEquals("x", previous.x, point.x, ANGLE_TOLERANCE);
assertEquals("y", previous.y, point.y, ANGLE_TOLERANCE);
}
}
/**
* A selection of CRS codes for UTM and NAD zones.
*/
static final int[] CODES = {
2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022, 2023, 2024, 2025, 2026, 2027, 2028, 2029, 2030, 2031,
2032, 2033, 2034, 2035, 2040, 2041, 2042, 2043, 2058, 2059, 2060, 2061,
2063, 2064, 2067, 2077, 2078, 2079, 2080, 2084, 2085, 2086, 2089, 2090,
2095, 2133, 2134, 2135, 2138, 2156, 2158, 2161, 2162, 2188, 2189, 2190,
2195, 2201, 2202, 2203, 2204, 2205, 2215, 2216, 2217, 2219, 2220, 2222,
2223, 2224, 2225, 2226, 2227, 2228, 2229, 2230, 2231, 2232, 2233, 2234,
2235, 2236, 2237, 2238, 2239, 2240, 2241, 2242, 2243, 2244, 2245, 2246,
2247, 2248, 2249, 2250, 2251, 2252, 2253, 2254, 2255, 2256, 2257, 2258,
2259, 2260, 2261, 2262, 2263, 2264, 2265, 2266, 2267, 2268, 2269, 2270,
2271, 2272, 2273, 2274, 2275, 2276, 2277, 2278, 2279, 2280, 2281, 2282,
2283, 2284, 2285, 2286, 2287, 2288, 2289, 2291, 2312, 2313, 2315, 2316,
2736, 2737, 2759, 2760, 2761, 2762, 2763, 2764, 2765, 2766, 2767, 2768,
2769, 2770, 2771, 2772, 2773, 2774, 2775, 2776, 2777, 2778, 2779, 2780,
2781, 2782, 2783, 2784, 2785, 2786, 2787, 2788, 2789, 2790, 2791, 2792,
2793, 2794, 2795, 2796, 2797, 2798, 2799, 2800, 2801, 2802, 2803, 2804,
2805, 2806, 2807, 2808, 2809, 2810, 2811, 2812, 2813, 2814, 2815, 2816,
2817, 2818, 2819, 2820, 2821, 2822, 2823, 2824, 2825, 2826, 2827, 2828,
2829, 2830, 2831, 2832, 2833, 2834, 2835, 2836, 2837, 2838, 2839, 2840,
2841, 2842, 2843, 2844, 2845, 2846, 2847, 2848, 2849, 2850, 2851, 2852,
2853, 2854, 2855, 2856, 2857, 2858, 2859, 2860, 2861, 2862, 2863, 2864,
2865, 2866, 2867, 2868, 2869, 2870, 2871, 2872, 2873, 2874, 2875, 2876,
2877, 2878, 2879, 2880, 2881, 2882, 2883, 2884, 2885, 2886, 2887, 2888,
2889, 2890, 2891, 2892, 2893, 2894, 2895, 2896, 2897, 2898, 2899, 2900,
2901, 2902, 2903, 2904, 2905, 2906, 2907, 2908, 2909, 2910, 2911, 2912,
2913, 2914, 2915, 2916, 2917, 2918, 2919, 2920, 2921, 2922, 2923, 2924,
2925, 2926, 2927, 2928, 2929, 2930, 2933, 2936, 2942, 2943, 2944, 2945,
2946, 2947, 2948, 2949, 2950, 2951, 2952, 2953, 2954, 2955, 2956, 2957,
2958, 2959, 2960, 2961, 2962, 2964, 2965, 2966, 2967, 2968, 2969, 2970,
2971, 2972, 2973, 2975, 2976, 2977, 2978, 2979, 2980, 2981, 2983, 2987,
2988, 2989, 2991, 2992, 2993, 2994, 2995, 2996, 2997, 2998, 2999, 3005,
3036, 3037, 3054, 3055, 3056, 3060, 3061, 3062, 3063, 3064, 3065, 3148,
3149, 3439, 3440, 3920, 4152, 4267, 4268, 4269, 4608, 4609, 4617, 20135,
20136, 20137, 20138, 20437, 20438, 20439, 20538, 20539, 20822, 20823, 20824, 20934,
20935, 20936, 21035, 21036, 21037, 21095, 21096, 21097, 21148, 21149, 21150, 21817,
21818, 22032, 22033, 22234, 22235, 22236, 22332, 22523, 22524, 23028, 23029, 23030,
23031, 23032, 23033, 23034, 23035, 23036, 23037, 23038, 23239, 23240, 23846, 23847,
23848, 23849, 23850, 23851, 23852, 23853, 23886, 23887, 23888, 23889, 23890, 23891,
23892, 23893, 23894, 23946, 23947, 23948, 24047, 24048, 24305, 24306, 24311, 24312,
24313, 24342, 24343, 24344, 24345, 24346, 24347, 24547, 24548, 24718, 24719, 24720,
24818, 24819, 24820, 24821, 24877, 24878, 24879, 24880, 24882, 25231, 25828, 25829,
25830, 25831, 25832, 25833, 25834, 25835, 25836, 25837, 25838, 25932, 26237, 26331,
26332, 26432, 26632, 26692, 26703, 26704, 26705, 26706, 26707, 26708, 26709, 26710,
26711, 26712, 26713, 26714, 26715, 26716, 26717, 26718, 26719, 26720, 26721, 26722,
26729, 26730, 26731, 26732, 26733, 26734, 26735, 26736, 26737, 26738, 26739, 26740,
26741, 26742, 26743, 26744, 26745, 26746, 26747, 26748, 26749, 26750, 26751, 26752,
26753, 26754, 26755, 26756, 26757, 26758, 26759, 26760, 26766, 26767, 26768, 26769,
26770, 26771, 26772, 26773, 26774, 26775, 26776, 26777, 26778, 26779, 26780, 26781,
26782, 26783, 26784, 26785, 26786, 26787, 26791, 26792, 26793, 26794, 26795, 26796,
26797, 26798, 26801, 26802, 26803, 26811, 26812, 26813, 26903, 26904, 26905, 26906,
26907, 26908, 26909, 26910, 26911, 26912, 26913, 26914, 26915, 26916, 26917, 26918,
26919, 26920, 26921, 26922, 26923, 26929, 26930, 26931, 26932, 26933, 26934, 26935,
26936, 26937, 26938, 26939, 26940, 26941, 26942, 26943, 26944, 26945, 26946, 26948,
26949, 26950, 26951, 26952, 26953, 26954, 26955, 26956, 26957, 26958, 26959, 26960,
26961, 26962, 26963, 26964, 26965, 26966, 26967, 26968, 26969, 26970, 26971, 26972,
26973, 26974, 26975, 26976, 26977, 26978, 26979, 26980, 26981, 26982, 26983, 26984,
26985, 26986, 26987, 26988, 26989, 26990, 26991, 26992, 26993, 26994, 26995, 26996,
26997, 26998, 27038, 27039, 27040, 27120, 27258, 27259, 27260, 27429, 28232, 29168,
29169, 29170, 29171, 29172, 29187, 29188, 29189, 29190, 29191, 29192, 29193, 29194,
29195, 29220, 29221, 29333, 29738, 29739, 29849, 29850, 30339, 30340, 30729, 30730,
30731, 30732, 31028, 31121, 31528, 31529, 31838, 31839, 31986, 31987, 31988, 31989,
31990, 31991, 31992, 31993, 31994, 31995, 31996, 31997, 31998, 31999, 32000, 32001,
32002, 32003, 32005, 32006, 32007, 32008, 32009, 32010, 32011, 32012, 32013, 32014,
32015, 32016, 32017, 32018, 32019, 32020, 32021, 32022, 32023, 32024, 32025, 32026,
32027, 32028, 32029, 32030, 32031, 32033, 32034, 32035, 32036, 32037, 32038, 32039,
32040, 32041, 32042, 32043, 32044, 32045, 32046, 32047, 32048, 32049, 32050, 32051,
32052, 32053, 32054, 32055, 32056, 32057, 32058, 32061, 32062, 32064, 32065, 32066,
32067, 32074, 32075, 32076, 32077, 32081, 32082, 32083, 32084, 32085, 32086, 32098,
32100, 32104, 32107, 32108, 32109, 32110, 32111, 32112, 32113, 32114, 32115, 32116,
32117, 32118, 32119, 32120, 32121, 32122, 32123, 32124, 32125, 32126, 32127, 32128,
32129, 32130, 32133, 32134, 32135, 32136, 32137, 32138, 32139, 32140, 32141, 32142,
32143, 32144, 32145, 32146, 32147, 32148, 32149, 32150, 32151, 32152, 32153, 32154,
32155, 32156, 32157, 32158, 32161, 32180, 32181, 32182, 32183, 32184, 32185, 32186,
32187, 32188, 32189, 32190, 32191, 32192, 32193, 32194, 32195, 32196, 32197, 32198,
32201, 32202, 32203, 32204, 32205, 32206, 32207, 32208, 32209, 32210, 32211, 32212,
32213, 32214, 32215, 32216, 32217, 32218, 32219, 32220, 32221, 32222, 32223, 32224,
32225, 32226, 32227, 32228, 32229, 32230, 32231, 32232, 32233, 32234, 32235, 32236,
32237, 32238, 32239, 32240, 32241, 32242, 32243, 32244, 32245, 32246, 32247, 32248,
32249, 32250, 32251, 32252, 32253, 32254, 32255, 32256, 32257, 32258, 32259, 32260,
32301, 32302, 32303, 32304, 32305, 32306, 32307, 32308, 32309, 32310, 32311, 32312,
32313, 32314, 32315, 32316, 32317, 32318, 32319, 32320, 32321, 32322, 32323, 32324,
32325, 32326, 32327, 32328, 32329, 32330, 32331, 32332, 32333, 32334, 32335, 32336,
32337, 32338, 32339, 32340, 32341, 32342, 32343, 32344, 32345, 32346, 32347, 32348,
32349, 32350, 32351, 32352, 32353, 32354, 32355, 32356, 32357, 32358, 32359, 32360,
32401, 32402, 32403, 32404, 32405, 32406, 32407, 32408, 32409, 32410, 32411, 32412,
32413, 32414, 32415, 32416, 32417, 32418, 32419, 32420, 32421, 32422, 32423, 32424,
32425, 32426, 32427, 32428, 32429, 32430, 32431, 32432, 32433, 32434, 32435, 32436,
32437, 32438, 32439, 32440, 32441, 32442, 32443, 32444, 32445, 32446, 32447, 32448,
32449, 32450, 32451, 32452, 32453, 32454, 32455, 32456, 32457, 32458, 32459, 32460,
32501, 32502, 32503, 32504, 32505, 32506, 32507, 32508, 32509, 32510, 32511, 32512,
32513, 32514, 32515, 32516, 32517, 32518, 32519, 32520, 32521, 32522, 32523, 32524,
32525, 32526, 32527, 32528, 32529, 32530, 32531, 32532, 32533, 32534, 32535, 32536,
32537, 32538, 32539, 32540, 32541, 32542, 32543, 32544, 32545, 32546, 32547, 32548,
32549, 32550, 32551, 32552, 32553, 32554, 32555, 32556, 32557, 32558, 32559, 32560,
32601, 32602, 32603, 32604, 32605, 32606, 32607, 32608, 32609, 32610, 32611, 32612,
32613, 32614, 32615, 32616, 32617, 32618, 32619, 32620, 32621, 32622, 32623, 32624,
32625, 32626, 32627, 32628, 32629, 32630, 32631, 32632, 32633, 32634, 32635, 32636,
32637, 32638, 32639, 32640, 32641, 32642, 32643, 32644, 32645, 32646, 32647, 32648,
32649, 32650, 32651, 32652, 32653, 32654, 32655, 32656, 32657, 32658, 32659, 32660,
32701, 32702, 32703, 32704, 32705, 32706, 32707, 32708, 32709, 32710, 32711, 32712,
32713, 32714, 32715, 32716, 32717, 32718, 32719, 32720, 32721, 32722, 32723, 32724,
32725, 32726, 32727, 32728, 32729, 32730, 32731, 32732, 32733, 32734, 32735, 32736,
32737, 32738, 32739, 32740, 32741, 32742, 32743, 32744, 32745, 32746, 32747, 32748,
32749, 32750, 32751, 32752, 32753, 32754, 32755, 32756, 32757, 32758, 32759, 32760
};
}