Ignore:
Timestamp:
2018-04-05T19:03:04+02:00 (6 years ago)
Author:
Don-vip
Message:

see #16129 - add new projections and support for new format of ESRI file

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/scripts/BuildProjectionDefinitions.java

    r13583 r13598  
    77import java.io.OutputStreamWriter;
    88import java.nio.charset.StandardCharsets;
    9 import java.util.HashMap;
     9import java.util.Arrays;
    1010import java.util.LinkedHashMap;
     11import java.util.List;
     12import java.util.Locale;
    1113import java.util.Map;
     14import java.util.TreeMap;
    1215
    1316import org.openstreetmap.josm.data.projection.CustomProjection;
     17import org.openstreetmap.josm.data.projection.CustomProjection.Param;
    1418import org.openstreetmap.josm.data.projection.ProjectionConfigurationException;
    1519import org.openstreetmap.josm.data.projection.Projections;
     
    2327public class BuildProjectionDefinitions {
    2428
    25     private static final String JOSM_EPSG_FILE = "data_nodist/projection/josm-epsg";
    26     private static final String PROJ4_EPSG_FILE = "data_nodist/projection/epsg";
    27     private static final String PROJ4_ESRI_FILE = "data_nodist/projection/esri";
     29    private static final String PROJ_DIR = "data_nodist/projection";
     30    private static final String JOSM_EPSG_FILE = "josm-epsg";
     31    private static final String PROJ4_EPSG_FILE = "epsg";
     32    private static final String PROJ4_ESRI_FILE = "esri";
    2833    private static final String OUTPUT_EPSG_FILE = "data/projection/custom-epsg";
    2934
     
    4045    private static int noGeocent = 0;
    4146    private static int noBaseProjection = 0;
    42     private static final Map<String, Integer> baseProjectionMap = new HashMap<>();
     47    private static int noEllipsoid = 0;
     48    private static int noNadgrid = 0;
    4349    private static int noDatumgrid = 0;
    4450    private static int noJosm = 0;
     
    4753    private static int noOmercNoBounds = 0;
    4854    private static int noEquatorStereo = 0;
     55
     56    private static final Map<String, Integer> baseProjectionMap = new TreeMap<>();
     57    private static final Map<String, Integer> ellipsoidMap = new TreeMap<>();
     58    private static final Map<String, Integer> nadgridMap = new TreeMap<>();
     59    private static final Map<String, Integer> datumgridMap = new TreeMap<>();
     60
     61    private static List<String> knownGeoidgrids;
     62    private static List<String> knownNadgrids;
    4963
    5064    /**
     
    5771    }
    5872
     73    static List<String> initList(String baseDir, String ext) {
     74        return Arrays.asList(new File(baseDir + File.separator + PROJ_DIR)
     75                .list((dir, name) -> !name.contains(".") || name.toLowerCase(Locale.ENGLISH).endsWith(ext)));
     76    }
     77
    5978    static void initMap(String baseDir, String file, Map<String, ProjectionDefinition> map) throws IOException {
    60         for (ProjectionDefinition pd : Projections.loadProjectionDefinitions(baseDir + File.separator + file)) {
     79        for (ProjectionDefinition pd : Projections.loadProjectionDefinitions(
     80                baseDir + File.separator + PROJ_DIR + File.separator + file)) {
    6181            map.put(pd.code, pd);
    6282        }
     
    6787        initMap(baseDir, PROJ4_EPSG_FILE, epsgProj4);
    6888        initMap(baseDir, PROJ4_ESRI_FILE, esriProj4);
     89
     90        knownGeoidgrids = initList(baseDir, ".gtx");
     91        knownNadgrids = initList(baseDir, ".gsb");
    6992
    7093        try (FileOutputStream output = new FileOutputStream(baseDir + File.separator + OUTPUT_EPSG_FILE);
     
    104127            System.out.println("some entries from proj.4 have not been included:");
    105128            System.out.println(String.format(" * already in the maintained JOSM list: %d entries", noInJosm));
    106             System.out.println(String.format(" * ESRI already in the standard EPSG list: %d entries", noInProj4));
     129            if (noInProj4 > 0) {
     130                System.out.println(String.format(" * ESRI already in the standard EPSG list: %d entries", noInProj4));
     131            }
    107132            System.out.println(String.format(" * deprecated: %d entries", noDeprecated));
    108133            System.out.println(String.format(" * using +proj=geocent, which is 3D (X,Y,Z) and not useful in JOSM: %d entries", noGeocent));
    109             System.out.println(String.format(" * unsupported base projection: %d entries", noBaseProjection));
    110             System.out.println("   in particular: " + baseProjectionMap);
    111             System.out.println(String.format(" * requires data file for datum conversion: %d entries", noDatumgrid));
     134            if (noEllipsoid > 0) {
     135                System.out.println(String.format(" * unsupported ellipsoids: %d entries", noEllipsoid));
     136                System.out.println("   in particular: " + ellipsoidMap);
     137            }
     138            if (noBaseProjection > 0) {
     139                System.out.println(String.format(" * unsupported base projection: %d entries", noBaseProjection));
     140                System.out.println("   in particular: " + baseProjectionMap);
     141            }
     142            if (noDatumgrid > 0) {
     143                System.out.println(String.format(" * requires data file for vertical datum conversion: %d entries", noDatumgrid));
     144                System.out.println("   in particular: " + datumgridMap);
     145            }
     146            if (noNadgrid > 0) {
     147                System.out.println(String.format(" * requires data file for datum conversion: %d entries", noNadgrid));
     148                System.out.println("   in particular: " + nadgridMap);
     149            }
    112150            if (noOmercNoBounds > 0) {
    113151                System.out.println(String.format(" * projection is Oblique Mercator (requires bounds), but no bounds specified: %d entries", noOmercNoBounds));
     
    147185        }
    148186
    149         // exclude deprecated projections
     187        // exclude deprecated/discontinued projections
    150188        // EPSG:4296 is also deprecated, but this is not mentioned in the name
    151         if (pd.name.contains("deprecated") || pd.code.equals("EPSG:4296")) {
     189        String lowName = pd.name.toLowerCase(Locale.ENGLISH);
     190        if (lowName.contains("deprecated") || lowName.contains("discontinued") || pd.code.equals("EPSG:4296")) {
    152191            result = false;
    153192            noDeprecated++;
     
    176215        }
    177216
    178         // requires datum conversion database
    179         if (parameters.containsKey("geoidgrids")) {
     217        // requires vertical datum conversion database (.gtx)
     218        String geoidgrids = parameters.get("geoidgrids");
     219        if (geoidgrids != null && !"@null".equals(geoidgrids) && !knownGeoidgrids.contains(geoidgrids)) {
    180220            result = false;
    181221            noDatumgrid++;
     222            incMap(datumgridMap, geoidgrids);
     223        }
     224
     225        // requires datum conversion database (.gsb)
     226        String nadgrids = parameters.get("nadgrids");
     227        if (nadgrids != null && !"@null".equals(nadgrids) && !knownNadgrids.contains(nadgrids)) {
     228            result = false;
     229            noNadgrid++;
     230            incMap(nadgridMap, nadgrids);
    182231        }
    183232
     
    188237            noBaseProjection++;
    189238            if (!"geocent".equals(proj)) {
    190                 if (!baseProjectionMap.containsKey(proj)) {
    191                     baseProjectionMap.put(proj, 0);
     239                incMap(baseProjectionMap, proj);
     240            }
     241        }
     242
     243        // exclude entries where we don't support the base ellipsoid
     244        String ellps = parameters.get("ellps");
     245        if (result && ellps != null && Projections.getEllipsoid(ellps) == null) {
     246            result = false;
     247            noEllipsoid++;
     248            incMap(ellipsoidMap, ellps);
     249        }
     250
     251        if (result && "omerc".equals(proj) && !parameters.containsKey(CustomProjection.Param.bounds.key)) {
     252            result = false;
     253            noOmercNoBounds++;
     254        }
     255
     256        final double EPS10 = 1.e-10;
     257
     258        String lat0 = parameters.get("lat_0");
     259        if (lat0 != null) {
     260            try {
     261                final double latitudeOfOrigin = Math.toRadians(CustomProjection.parseAngle(lat0, Param.lat_0.key));
     262                // TODO: implement equatorial stereographic, see https://josm.openstreetmap.de/ticket/15970
     263                if (result && "stere".equals(proj) && Math.abs(latitudeOfOrigin) < EPS10) {
     264                    result = false;
     265                    noEquatorStereo++;
    192266                }
    193                 baseProjectionMap.put(proj, baseProjectionMap.get(proj)+1);
    194             }
    195         }
    196 
    197         if (result && "omerc".equals(proj) && !parameters.containsKey(CustomProjection.Param.bounds.key)) {
    198             result = false;
    199             noOmercNoBounds++;
    200         }
    201         // TODO: implement equatorial stereographic, see https://josm.openstreetmap.de/ticket/15970
    202         if (result && "stere".equals(proj) && "0".equals(parameters.get(CustomProjection.Param.lat_0.key))) {
    203             result = false;
    204             noEquatorStereo++;
     267
     268                // exclude entries which need geodesic computation (equatorial/oblique azimuthal equidistant)
     269                if (result && "aeqd".equals(proj)) {
     270                    final double HALF_PI = Math.PI / 2;
     271                    if (Math.abs(latitudeOfOrigin - HALF_PI) >= EPS10 &&
     272                        Math.abs(latitudeOfOrigin + HALF_PI) >= EPS10) {
     273                        // See https://josm.openstreetmap.de/ticket/16129#comment:21
     274                        result = false;
     275                    }
     276                }
     277            } catch (NumberFormatException | ProjectionConfigurationException e) {
     278                e.printStackTrace();
     279                result = false;
     280            }
     281        }
     282
     283        if (result && "0.0".equals(parameters.get("rf"))) {
     284            // Proj fails with "reciprocal flattening (1/f) = 0" for
     285            result = false; // FIXME Only for some projections?
     286        }
     287
     288        String k_0 = parameters.get("k_0");
     289        if (result && k_0 != null && k_0.startsWith("-")) {
     290            // Proj fails with "k <= 0" for ESRI:102470
     291            result = false;
    205292        }
    206293
    207294        return result;
    208295    }
     296
     297    private static void incMap(Map<String, Integer> map, String key) {
     298        map.putIfAbsent(key, 0);
     299        map.put(key, map.get(key)+1);
     300    }
    209301}
Note: See TracChangeset for help on using the changeset viewer.