Changeset 10870 in josm for trunk


Ignore:
Timestamp:
2016-08-21T23:46:58+02:00 (8 years ago)
Author:
Don-vip
Message:

fix #13408 - Clean up CustomProjection (patch by michael2402) - gsoc-core

Location:
trunk
Files:
1 added
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/data/projection/CustomProjection.java

    r10748 r10870  
    55
    66import java.util.ArrayList;
     7import java.util.Arrays;
    78import java.util.EnumMap;
    89import java.util.HashMap;
     
    3233import org.openstreetmap.josm.data.projection.proj.ProjParameters;
    3334import org.openstreetmap.josm.tools.Utils;
     35import org.openstreetmap.josm.tools.bugreport.BugReport;
    3436
    3537/**
     
    6365    private double metersPerUnitWMTS;
    6466    private String axis = "enu"; // default axis orientation is East, North, Up
     67
     68    private static final List<String> LON_LAT_VALUES = Arrays.asList("longlat", "latlon", "latlong");
    6569
    6670    /**
     
    155159                paramsByKey.put(p.key, p);
    156160            }
     161            // alias
     162            paramsByKey.put("k", Param.k_0);
    157163        }
    158164
     
    163169    }
    164170
    165     private enum Polarity { NORTH, SOUTH }
     171    private enum Polarity {
     172        NORTH(LatLon.NORTH_POLE),
     173        SOUTH(LatLon.SOUTH_POLE);
     174
     175        private final LatLon latlon;
     176
     177        Polarity(LatLon latlon) {
     178            this.latlon = latlon;
     179        }
     180
     181        private LatLon getLatLon() {
     182            return latlon;
     183        }
     184    }
    166185
    167186    private EnumMap<Polarity, EastNorth> polesEN;
    168     private EnumMap<Polarity, LatLon> polesLL;
    169     {
    170         polesLL = new EnumMap<>(Polarity.class);
    171         polesLL.put(Polarity.NORTH, LatLon.NORTH_POLE);
    172         polesLL.put(Polarity.SOUTH, LatLon.SOUTH_POLE);
    173     }
    174187
    175188    /**
     
    209222                update(null);
    210223            } catch (ProjectionConfigurationException ex1) {
    211                 throw new RuntimeException(ex1);
     224                throw BugReport.intercept(ex1).put("name", name).put("code", code).put("pref", pref);
    212225            }
    213226        }
     
    240253            if ("utm".equals(parameters.get(Param.proj.key))) {
    241254                String zoneStr = parameters.get(Param.zone.key);
    242                 Integer zone;
    243255                if (zoneStr == null)
    244256                    throw new ProjectionConfigurationException(tr("UTM projection (''+proj=utm'') requires ''+zone=...'' parameter."));
     257                Integer zone;
    245258                try {
    246259                    zone = Integer.valueOf(zoneStr);
     
    332345    public static Map<String, String> parseParameterList(String pref, boolean ignoreUnknownParameter) throws ProjectionConfigurationException {
    333346        Map<String, String> parameters = new HashMap<>();
     347        if (pref.trim().isEmpty()) {
     348            return parameters;
     349        }
     350
     351        Pattern keyPattern = Pattern.compile("\\+(?<key>[a-zA-Z0-9_]+)(=(?<value>.*))?");
    334352        String[] parts = Utils.WHITE_SPACES_PATTERN.split(pref.trim());
    335         if (pref.trim().isEmpty()) {
    336             parts = new String[0];
    337         }
    338353        for (String part : parts) {
    339             if (part.isEmpty() || part.charAt(0) != '+')
    340                 throw new ProjectionConfigurationException(tr("Parameter must begin with a ''+'' character (found ''{0}'')", part));
    341             Matcher m = Pattern.compile("\\+([a-zA-Z0-9_]+)(=(.*))?").matcher(part);
     354            Matcher m = keyPattern.matcher(part);
    342355            if (m.matches()) {
    343                 String key = m.group(1);
    344                 // alias
    345                 if ("k".equals(key)) {
    346                     key = Param.k_0.key;
     356                String key = m.group("key");
     357                String value = m.group("value");
     358                // some aliases
     359                if (key.equals(Param.proj.key) && LON_LAT_VALUES.contains(value)) {
     360                    value = "lonlat";
    347361                }
    348                 String value = null;
    349                 if (m.groupCount() >= 3) {
    350                     value = m.group(3);
    351                     // some aliases
    352                     if (key.equals(Param.proj.key)) {
    353                         if ("longlat".equals(value) || "latlon".equals(value) || "latlong".equals(value)) {
    354                             value = "lonlat";
    355                         }
    356                     }
    357                 }
    358                 if (!Param.paramsByKey.containsKey(key)) {
     362                Param param = Param.paramsByKey.get(key);
     363                if (param == null) {
    359364                    if (!ignoreUnknownParameter)
    360365                        throw new ProjectionConfigurationException(tr("Unknown parameter: ''{0}''.", key));
    361366                } else {
    362                     if (Param.paramsByKey.get(key).hasValue && value == null)
     367                    if (param.hasValue && value == null)
    363368                        throw new ProjectionConfigurationException(tr("Value expected for parameter ''{0}''.", key));
    364                     if (!Param.paramsByKey.get(key).hasValue && value != null)
     369                    if (!param.hasValue && value != null)
    365370                        throw new ProjectionConfigurationException(tr("No value expected for parameter ''{0}''.", key));
     371                    key = param.key; // To be really sure, we might have an alias.
    366372                }
    367373                parameters.put(key, value);
    368             } else
     374            } else if (!part.startsWith("+")) {
     375                throw new ProjectionConfigurationException(tr("Parameter must begin with a ''+'' character (found ''{0}'')", part));
     376            } else {
    369377                throw new ProjectionConfigurationException(tr("Unexpected parameter format (''{0}'')", part));
     378            }
    370379        }
    371380        return parameters;
     
    401410    }
    402411
     412    /**
     413     * Gets the ellipsoid
     414     * @param parameters The parameters to get the value from
     415     * @return The Ellipsoid as specified with the parameters
     416     * @throws ProjectionConfigurationException in case of invalid parameters
     417     */
    403418    public Ellipsoid parseEllipsoid(Map<String, String> parameters) throws ProjectionConfigurationException {
    404419        String code = parameters.get(Param.ellps.key);
     
    440455    }
    441456
     457    /**
     458     * Gets the datum
     459     * @param parameters The parameters to get the value from
     460     * @param ellps The ellisoid that was previously computed
     461     * @return The Datum as specified with the parameters
     462     * @throws ProjectionConfigurationException in case of invalid parameters
     463     */
    442464    public Datum parseDatum(Map<String, String> parameters, Ellipsoid ellps) throws ProjectionConfigurationException {
    443465        String datumId = parameters.get(Param.datum.key);
     
    519541    }
    520542
     543    /**
     544     * Gets a projection using the given ellipsoid
     545     * @param parameters Additional parameters
     546     * @param ellps The {@link Ellipsoid}
     547     * @return The projection
     548     * @throws ProjectionConfigurationException in case of invalid parameters
     549     */
    521550    public Proj parseProjection(Map<String, String> parameters, Ellipsoid ellps) throws ProjectionConfigurationException {
    522551        String id = parameters.get(Param.proj.key);
     
    578607    }
    579608
     609    /**
     610     * Converts a string to a bounds object
     611     * @param boundsStr The string as comma separated list of angles.
     612     * @return The bounds.
     613     * @throws ProjectionConfigurationException in case of invalid parameter
     614     * @see {@link CustomProjection#parseAngle(String, String)}
     615     */
    580616    public static Bounds parseBounds(String boundsStr) throws ProjectionConfigurationException {
    581617        String[] numStr = boundsStr.split(",");
     
    607643    }
    608644
     645    /**
     646     * Convert an angle string to a double value
     647     * @param angleStr The string. e.g. -1.1 or 50d 10' 3"
     648     * @param parameterName Only for error message.
     649     * @return The angle value, in degrees.
     650     * @throws ProjectionConfigurationException in case of invalid parameter
     651     */
    609652    public static double parseAngle(String angleStr, String parameterName) throws ProjectionConfigurationException {
    610         String s = angleStr;
    611         double value = 0;
    612         boolean neg = false;
    613         Matcher m = Pattern.compile("^-").matcher(s);
    614         if (m.find()) {
    615             neg = true;
    616             s = s.substring(m.end());
    617         }
    618653        final String floatPattern = "(\\d+(\\.\\d*)?)";
    619         boolean dms = false;
    620         double deg = 0.0, min = 0.0, sec = 0.0;
    621         // degrees
    622         m = Pattern.compile("^"+floatPattern+"d").matcher(s);
    623         if (m.find()) {
    624             s = s.substring(m.end());
    625             deg = Double.parseDouble(m.group(1));
    626             dms = true;
    627         }
    628         // minutes
    629         m = Pattern.compile("^"+floatPattern+"'").matcher(s);
    630         if (m.find()) {
    631             s = s.substring(m.end());
    632             min = Double.parseDouble(m.group(1));
    633             dms = true;
    634         }
    635         // seconds
    636         m = Pattern.compile("^"+floatPattern+"\"").matcher(s);
    637         if (m.find()) {
    638             s = s.substring(m.end());
    639             sec = Double.parseDouble(m.group(1));
    640             dms = true;
    641         }
    642         // plain number (in degrees)
    643         if (dms) {
    644             value = deg + (min/60.0) + (sec/3600.0);
    645         } else {
    646             m = Pattern.compile("^"+floatPattern).matcher(s);
    647             if (m.find()) {
    648                 s = s.substring(m.end());
    649                 value += Double.parseDouble(m.group(1));
    650             }
    651         }
    652         m = Pattern.compile("^(N|E)", Pattern.CASE_INSENSITIVE).matcher(s);
    653         if (m.find()) {
    654             s = s.substring(m.end());
    655         } else {
    656             m = Pattern.compile("^(S|W)", Pattern.CASE_INSENSITIVE).matcher(s);
    657             if (m.find()) {
    658                 s = s.substring(m.end());
    659                 neg = !neg;
    660             }
    661         }
    662         if (neg) {
    663             value = -value;
    664         }
    665         if (!s.isEmpty()) {
     654        // pattern does all error handling.
     655        Matcher in = Pattern.compile("^(?<neg1>-)?"
     656                + "(?=\\d)(?:(?<single>" + floatPattern + ")|"
     657                + "((?<degree>" + floatPattern + ")d)?"
     658                + "((?<minutes>" + floatPattern + ")\')?"
     659                + "((?<seconds>" + floatPattern + ")\")?)"
     660                + "(?:[NE]|(?<neg2>[SW]))?$").matcher(angleStr);
     661
     662        if (!in.find()) {
    666663            throw new ProjectionConfigurationException(
    667664                    tr("Unable to parse value ''{1}'' of parameter ''{0}'' as coordinate value.", parameterName, angleStr));
     665        }
     666
     667        double value = 0;
     668        if (in.group("single") != null) {
     669            value += Double.parseDouble(in.group("single"));
     670        }
     671        if (in.group("degree") != null) {
     672            value += Double.parseDouble(in.group("degree"));
     673        }
     674        if (in.group("minutes") != null) {
     675            value += Double.parseDouble(in.group("minutes")) / 60;
     676        }
     677        if (in.group("seconds") != null) {
     678            value += Double.parseDouble(in.group("seconds")) / 3600;
     679        }
     680
     681        if (in.group("neg1") != null ^ in.group("neg2") != null) {
     682            value = -value;
    668683        }
    669684        return value;
     
    684699    @Override
    685700    public String toCode() {
    686         return code != null ? code : "proj:" + (pref == null ? "ERROR" : pref);
     701        if (code != null) {
     702            return code;
     703        } else if (pref != null) {
     704            return "proj:" + pref;
     705        } else {
     706            return "proj:ERROR";
     707        }
    687708    }
    688709
    689710    @Override
    690711    public String getCacheDirectoryName() {
    691         return cacheDir != null ? cacheDir : "proj-"+Utils.md5Hex(pref == null ? "" : pref).substring(0, 4);
     712        if (cacheDir != null) {
     713            return cacheDir;
     714        } else {
     715            return "proj-" + Utils.md5Hex(pref == null ? "" : pref).substring(0, 4);
     716        }
    692717    }
    693718
    694719    @Override
    695720    public Bounds getWorldBoundsLatLon() {
    696         if (bounds != null) return bounds;
    697         Bounds ab = proj.getAlgorithmBounds();
    698         if (ab != null) {
    699             double minlon = Math.max(ab.getMinLon() + lon0 + pm, -180);
    700             double maxlon = Math.min(ab.getMaxLon() + lon0 + pm, 180);
    701             return new Bounds(ab.getMinLat(), minlon, ab.getMaxLat(), maxlon, false);
    702         } else {
    703             return new Bounds(
    704                 new LatLon(-90.0, -180.0),
    705                 new LatLon(90.0, 180.0));
    706         }
     721        if (bounds == null) {
     722            Bounds ab = proj.getAlgorithmBounds();
     723            if (ab != null) {
     724                double minlon = Math.max(ab.getMinLon() + lon0 + pm, -180);
     725                double maxlon = Math.min(ab.getMaxLon() + lon0 + pm, 180);
     726                bounds = new Bounds(ab.getMinLat(), minlon, ab.getMaxLat(), maxlon, false);
     727            } else {
     728                bounds = new Bounds(
     729                    new LatLon(-90.0, -180.0),
     730                    new LatLon(90.0, 180.0));
     731            }
     732        }
     733        return bounds;
    707734    }
    708735
     
    805832            for (Polarity p : Polarity.values()) {
    806833                polesEN.put(p, null);
    807                 LatLon ll = polesLL.get(p);
     834                LatLon ll = p.getLatLon();
    808835                try {
    809836                    EastNorth enPole = latlon2eastNorth(ll);
     
    853880            EastNorth pole = getPole(p);
    854881            if (pole != null && r.contains(pole)) {
    855                 result.extend(polesLL.get(p));
     882                result.extend(p.getLatLon());
    856883            }
    857884        }
Note: See TracChangeset for help on using the changeset viewer.