1 | // License: GPL. For details, see LICENSE file.
|
---|
2 | package org.openstreetmap.josm.data.projection;
|
---|
3 |
|
---|
4 | import java.io.BufferedReader;
|
---|
5 | import java.io.FileInputStream;
|
---|
6 | import java.io.FileNotFoundException;
|
---|
7 | import java.io.IOException;
|
---|
8 | import java.io.InputStreamReader;
|
---|
9 | import java.nio.charset.StandardCharsets;
|
---|
10 | import java.util.Collection;
|
---|
11 | import java.util.HashMap;
|
---|
12 | import java.util.Map;
|
---|
13 | import java.util.Map.Entry;
|
---|
14 |
|
---|
15 | import org.junit.Test;
|
---|
16 | import org.openstreetmap.josm.data.coor.EastNorth;
|
---|
17 | import org.openstreetmap.josm.data.coor.LatLon;
|
---|
18 | import org.openstreetmap.josm.gui.preferences.projection.ProjectionChoice;
|
---|
19 | import org.openstreetmap.josm.gui.preferences.projection.ProjectionPreference;
|
---|
20 |
|
---|
21 | /**
|
---|
22 | * Test projections using reference data. (Currently provided by proj.4)
|
---|
23 | *
|
---|
24 | * The data file data_nodist/projection-reference-data.csv can be created like this:
|
---|
25 | * Fist run this file's main method to collect epsg codes and bounds data.
|
---|
26 | * Then pipe the result into test/generate-proj-data.pl.
|
---|
27 | */
|
---|
28 | public class ProjectionRefTest {
|
---|
29 |
|
---|
30 | /**
|
---|
31 | * create a list of epsg codes and bounds to be used by the perl script
|
---|
32 | * @param args program main arguments
|
---|
33 | */
|
---|
34 | public static void main(String[] args) {
|
---|
35 | Map<String, Projection> allCodes = new HashMap<>();
|
---|
36 | for (ProjectionChoice pc : ProjectionPreference.getProjectionChoices()) {
|
---|
37 | for (String code : pc.allCodes()) {
|
---|
38 | Collection<String> pref = pc.getPreferencesFromCode(code);
|
---|
39 | pc.setPreferences(pref);
|
---|
40 | Projection p = pc.getProjection();
|
---|
41 | allCodes.put(code, p);
|
---|
42 | }
|
---|
43 | }
|
---|
44 | for (Entry<String, Projection> e : allCodes.entrySet()) {
|
---|
45 | System.out.println(String.format("%s %s", e.getKey(), e.getValue().getWorldBoundsLatLon()));
|
---|
46 | }
|
---|
47 | }
|
---|
48 |
|
---|
49 | @Test
|
---|
50 | public void test() throws IOException, FileNotFoundException {
|
---|
51 | try (BufferedReader in = new BufferedReader(new InputStreamReader(
|
---|
52 | new FileInputStream("data_nodist/projection-reference-data.csv"), StandardCharsets.UTF_8))) {
|
---|
53 | StringBuilder fail = new StringBuilder();
|
---|
54 | String line;
|
---|
55 | while ((line = in.readLine()) != null) {
|
---|
56 | if (line.startsWith("#")) {
|
---|
57 | continue;
|
---|
58 | }
|
---|
59 | String[] f = line.split(",");
|
---|
60 | String code = f[0];
|
---|
61 | double lat = Double.parseDouble(f[1]);
|
---|
62 | double lon = Double.parseDouble(f[2]);
|
---|
63 | double east = Double.parseDouble(f[3]);
|
---|
64 | double north = Double.parseDouble(f[4]);
|
---|
65 | Projection p = Projections.getProjectionByCode(code);
|
---|
66 | EastNorth en = p.latlon2eastNorth(new LatLon(lat, lon));
|
---|
67 | String errorEN = String.format("%s (%s): Projecting latlon(%s,%s):%n" +
|
---|
68 | " expected: eastnorth(%s,%s),%n" +
|
---|
69 | " but got: eastnorth(%s,%s)!%n",
|
---|
70 | p.toString(), code, lat, lon, east, north, en.east(), en.north());
|
---|
71 | final double EPSILON_EN = SwissGridTest.SWISS_EPSG_CODE.equals(code)
|
---|
72 | ? SwissGridTest.EPSILON_APPROX
|
---|
73 | : 1e-3; // 1 mm accuracy
|
---|
74 | if (Math.abs(east - en.east()) > EPSILON_EN || Math.abs(north - en.north()) > EPSILON_EN) {
|
---|
75 | fail.append(errorEN);
|
---|
76 | }
|
---|
77 | LatLon ll = p.eastNorth2latlon(new EastNorth(east, north));
|
---|
78 | String errorLL = String.format("%s (%s): Inverse projecting eastnorth(%s,%s):%n" +
|
---|
79 | " expected: latlon(%s,%s),%n" +
|
---|
80 | " but got: latlon(%s,%s)!%n",
|
---|
81 | p.toString(), code, east, north, lat, lon, ll.lat(), ll.lon());
|
---|
82 | final double EPSILON_LL = Math.toDegrees(EPSILON_EN / 6378137); // 1 mm accuracy (or better)
|
---|
83 | if (Math.abs(lat - ll.lat()) > EPSILON_LL || Math.abs(lon - ll.lon()) > EPSILON_LL) {
|
---|
84 | if (!("yes".equals(System.getProperty("suppressPermanentFailure")) && code.equals("EPSG:21781"))) {
|
---|
85 | fail.append(errorLL);
|
---|
86 | }
|
---|
87 | }
|
---|
88 | }
|
---|
89 | if (fail.length() > 0) {
|
---|
90 | System.err.println(fail.toString());
|
---|
91 | throw new AssertionError(fail.toString());
|
---|
92 | }
|
---|
93 | }
|
---|
94 | }
|
---|
95 | }
|
---|