Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/data/projection/CustomProjection.java
r10748 r10870 5 5 6 6 import java.util.ArrayList; 7 import java.util.Arrays; 7 8 import java.util.EnumMap; 8 9 import java.util.HashMap; … … 32 33 import org.openstreetmap.josm.data.projection.proj.ProjParameters; 33 34 import org.openstreetmap.josm.tools.Utils; 35 import org.openstreetmap.josm.tools.bugreport.BugReport; 34 36 35 37 /** … … 63 65 private double metersPerUnitWMTS; 64 66 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"); 65 69 66 70 /** … … 155 159 paramsByKey.put(p.key, p); 156 160 } 161 // alias 162 paramsByKey.put("k", Param.k_0); 157 163 } 158 164 … … 163 169 } 164 170 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 } 166 185 167 186 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 }174 187 175 188 /** … … 209 222 update(null); 210 223 } catch (ProjectionConfigurationException ex1) { 211 throw new RuntimeException(ex1);224 throw BugReport.intercept(ex1).put("name", name).put("code", code).put("pref", pref); 212 225 } 213 226 } … … 240 253 if ("utm".equals(parameters.get(Param.proj.key))) { 241 254 String zoneStr = parameters.get(Param.zone.key); 242 Integer zone;243 255 if (zoneStr == null) 244 256 throw new ProjectionConfigurationException(tr("UTM projection (''+proj=utm'') requires ''+zone=...'' parameter.")); 257 Integer zone; 245 258 try { 246 259 zone = Integer.valueOf(zoneStr); … … 332 345 public static Map<String, String> parseParameterList(String pref, boolean ignoreUnknownParameter) throws ProjectionConfigurationException { 333 346 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>.*))?"); 334 352 String[] parts = Utils.WHITE_SPACES_PATTERN.split(pref.trim()); 335 if (pref.trim().isEmpty()) {336 parts = new String[0];337 }338 353 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); 342 355 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"; 347 361 } 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) { 359 364 if (!ignoreUnknownParameter) 360 365 throw new ProjectionConfigurationException(tr("Unknown parameter: ''{0}''.", key)); 361 366 } else { 362 if ( Param.paramsByKey.get(key).hasValue && value == null)367 if (param.hasValue && value == null) 363 368 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) 365 370 throw new ProjectionConfigurationException(tr("No value expected for parameter ''{0}''.", key)); 371 key = param.key; // To be really sure, we might have an alias. 366 372 } 367 373 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 { 369 377 throw new ProjectionConfigurationException(tr("Unexpected parameter format (''{0}'')", part)); 378 } 370 379 } 371 380 return parameters; … … 401 410 } 402 411 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 */ 403 418 public Ellipsoid parseEllipsoid(Map<String, String> parameters) throws ProjectionConfigurationException { 404 419 String code = parameters.get(Param.ellps.key); … … 440 455 } 441 456 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 */ 442 464 public Datum parseDatum(Map<String, String> parameters, Ellipsoid ellps) throws ProjectionConfigurationException { 443 465 String datumId = parameters.get(Param.datum.key); … … 519 541 } 520 542 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 */ 521 550 public Proj parseProjection(Map<String, String> parameters, Ellipsoid ellps) throws ProjectionConfigurationException { 522 551 String id = parameters.get(Param.proj.key); … … 578 607 } 579 608 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 */ 580 616 public static Bounds parseBounds(String boundsStr) throws ProjectionConfigurationException { 581 617 String[] numStr = boundsStr.split(","); … … 607 643 } 608 644 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 */ 609 652 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 }618 653 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()) { 666 663 throw new ProjectionConfigurationException( 667 664 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; 668 683 } 669 684 return value; … … 684 699 @Override 685 700 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 } 687 708 } 688 709 689 710 @Override 690 711 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 } 692 717 } 693 718 694 719 @Override 695 720 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; 707 734 } 708 735 … … 805 832 for (Polarity p : Polarity.values()) { 806 833 polesEN.put(p, null); 807 LatLon ll = p olesLL.get(p);834 LatLon ll = p.getLatLon(); 808 835 try { 809 836 EastNorth enPole = latlon2eastNorth(ll); … … 853 880 EastNorth pole = getPole(p); 854 881 if (pole != null && r.contains(pole)) { 855 result.extend(p olesLL.get(p));882 result.extend(p.getLatLon()); 856 883 } 857 884 }
Note:
See TracChangeset
for help on using the changeset viewer.