[5072] | 1 | // License: GPL. For details, see LICENSE file.
|
---|
| 2 | package org.openstreetmap.josm.data.projection;
|
---|
| 3 |
|
---|
| 4 | import static org.openstreetmap.josm.tools.I18n.tr;
|
---|
| 5 |
|
---|
| 6 | import java.util.ArrayList;
|
---|
[5227] | 7 | import java.util.Arrays;
|
---|
[5072] | 8 | import java.util.HashMap;
|
---|
[5227] | 9 | import java.util.HashSet;
|
---|
[5072] | 10 | import java.util.List;
|
---|
| 11 | import java.util.Map;
|
---|
[5227] | 12 | import java.util.Set;
|
---|
[5072] | 13 | import java.util.regex.Matcher;
|
---|
| 14 | import java.util.regex.Pattern;
|
---|
| 15 |
|
---|
| 16 | import org.openstreetmap.josm.data.Bounds;
|
---|
| 17 | import org.openstreetmap.josm.data.coor.LatLon;
|
---|
[5227] | 18 | import org.openstreetmap.josm.data.projection.CustomProjection.Param;
|
---|
[5072] | 19 | import org.openstreetmap.josm.data.projection.datum.CentricDatum;
|
---|
| 20 | import org.openstreetmap.josm.data.projection.datum.Datum;
|
---|
[5226] | 21 | import org.openstreetmap.josm.data.projection.datum.NTV2Datum;
|
---|
| 22 | import org.openstreetmap.josm.data.projection.datum.NTV2GridShiftFileWrapper;
|
---|
[5072] | 23 | import org.openstreetmap.josm.data.projection.datum.SevenParameterDatum;
|
---|
| 24 | import org.openstreetmap.josm.data.projection.datum.ThreeParameterDatum;
|
---|
[5226] | 25 | import org.openstreetmap.josm.data.projection.datum.WGS84Datum;
|
---|
[5072] | 26 | import org.openstreetmap.josm.data.projection.proj.Proj;
|
---|
| 27 | import org.openstreetmap.josm.data.projection.proj.ProjParameters;
|
---|
| 28 | import org.openstreetmap.josm.tools.Utils;
|
---|
| 29 |
|
---|
| 30 | /**
|
---|
| 31 | * Custom projection
|
---|
| 32 | *
|
---|
| 33 | * Inspired by PROJ.4 and Proj4J.
|
---|
| 34 | */
|
---|
[5226] | 35 | public class CustomProjection extends AbstractProjection {
|
---|
[5072] | 36 |
|
---|
[5226] | 37 | /**
|
---|
| 38 | * pref String that defines the projection
|
---|
| 39 | *
|
---|
| 40 | * null means fall back mode (Mercator)
|
---|
| 41 | */
|
---|
[5234] | 42 | protected String pref;
|
---|
[5228] | 43 | protected Bounds bounds;
|
---|
[5072] | 44 |
|
---|
[5227] | 45 | protected static class Param {
|
---|
| 46 | public String key;
|
---|
| 47 | public boolean hasValue;
|
---|
| 48 |
|
---|
| 49 | public final static Param x_0 = new Param("x_0", true);
|
---|
| 50 | public final static Param y_0 = new Param("y_0", true);
|
---|
| 51 | public final static Param lon_0 = new Param("lon_0", true);
|
---|
| 52 | public final static Param k_0 = new Param("k_0", true);
|
---|
| 53 | public final static Param ellps = new Param("ellps", true);
|
---|
| 54 | public final static Param a = new Param("a", true);
|
---|
| 55 | public final static Param es = new Param("es", true);
|
---|
| 56 | public final static Param rf = new Param("rf", true);
|
---|
| 57 | public final static Param f = new Param("f", true);
|
---|
| 58 | public final static Param b = new Param("b", true);
|
---|
| 59 | public final static Param datum = new Param("datum", true);
|
---|
| 60 | public final static Param towgs84 = new Param("towgs84", true);
|
---|
| 61 | public final static Param nadgrids = new Param("nadgrids", true);
|
---|
| 62 | public final static Param proj = new Param("proj", true);
|
---|
| 63 | public final static Param lat_0 = new Param("lat_0", true);
|
---|
| 64 | public final static Param lat_1 = new Param("lat_1", true);
|
---|
| 65 | public final static Param lat_2 = new Param("lat_2", true);
|
---|
[5228] | 66 | public final static Param wktext = new Param("wktext", false); // ignored
|
---|
| 67 | public final static Param units = new Param("units", true); // ignored
|
---|
| 68 | public final static Param no_defs = new Param("no_defs", false);
|
---|
| 69 | public final static Param init = new Param("init", true);
|
---|
| 70 | // JOSM extension, not present in PROJ.4
|
---|
| 71 | public final static Param bounds = new Param("bounds", true);
|
---|
[5227] | 72 |
|
---|
| 73 | public final static Set<Param> params = new HashSet<Param>(Arrays.asList(
|
---|
| 74 | x_0, y_0, lon_0, k_0, ellps, a, es, rf, f, b, datum, towgs84,
|
---|
[5228] | 75 | nadgrids, proj, lat_0, lat_1, lat_2, wktext, units, no_defs,
|
---|
| 76 | init, bounds
|
---|
[5227] | 77 | ));
|
---|
| 78 |
|
---|
| 79 | public final static Map<String, Param> paramsByKey = new HashMap<String, Param>();
|
---|
| 80 | static {
|
---|
| 81 | for (Param p : params) {
|
---|
| 82 | paramsByKey.put(p.key, p);
|
---|
| 83 | }
|
---|
| 84 | }
|
---|
| 85 |
|
---|
| 86 | public Param(String key, boolean hasValue) {
|
---|
| 87 | this.key = key;
|
---|
| 88 | this.hasValue = hasValue;
|
---|
| 89 | }
|
---|
| 90 | }
|
---|
| 91 |
|
---|
[5234] | 92 | public CustomProjection() {
|
---|
| 93 | this.pref = null;
|
---|
| 94 | }
|
---|
| 95 |
|
---|
| 96 | public CustomProjection(String pref) {
|
---|
| 97 | try {
|
---|
| 98 | this.pref = pref;
|
---|
| 99 | update(pref);
|
---|
| 100 | } catch (ProjectionConfigurationException ex) {
|
---|
| 101 | try {
|
---|
| 102 | update(null);
|
---|
| 103 | } catch (ProjectionConfigurationException ex1) {
|
---|
| 104 | throw new RuntimeException();
|
---|
| 105 | }
|
---|
| 106 | }
|
---|
| 107 | }
|
---|
| 108 |
|
---|
[5226] | 109 | public void update(String pref) throws ProjectionConfigurationException {
|
---|
[5228] | 110 | this.pref = pref;
|
---|
[5226] | 111 | if (pref == null) {
|
---|
| 112 | ellps = Ellipsoid.WGS84;
|
---|
| 113 | datum = WGS84Datum.INSTANCE;
|
---|
| 114 | proj = new org.openstreetmap.josm.data.projection.proj.Mercator();
|
---|
[5228] | 115 | bounds = new Bounds(
|
---|
| 116 | new LatLon(-85.05112877980659, -180.0),
|
---|
| 117 | new LatLon(85.05112877980659, 180.0));
|
---|
[5226] | 118 | } else {
|
---|
[5228] | 119 | Map<String, String> parameters = parseParameterList(pref);
|
---|
[5072] | 120 | ellps = parseEllipsoid(parameters);
|
---|
| 121 | datum = parseDatum(parameters, ellps);
|
---|
| 122 | proj = parseProjection(parameters, ellps);
|
---|
[5227] | 123 | String s = parameters.get(Param.x_0.key);
|
---|
[5072] | 124 | if (s != null) {
|
---|
[5227] | 125 | this.x_0 = parseDouble(s, Param.x_0.key);
|
---|
[5072] | 126 | }
|
---|
[5227] | 127 | s = parameters.get(Param.y_0.key);
|
---|
[5072] | 128 | if (s != null) {
|
---|
[5228] | 129 | this.y_0 = parseDouble(s, Param.y_0.key);
|
---|
[5072] | 130 | }
|
---|
[5227] | 131 | s = parameters.get(Param.lon_0.key);
|
---|
[5072] | 132 | if (s != null) {
|
---|
[5228] | 133 | this.lon_0 = parseAngle(s, Param.lon_0.key);
|
---|
[5072] | 134 | }
|
---|
[5227] | 135 | s = parameters.get(Param.k_0.key);
|
---|
[5072] | 136 | if (s != null) {
|
---|
[5228] | 137 | this.k_0 = parseDouble(s, Param.k_0.key);
|
---|
[5072] | 138 | }
|
---|
[5228] | 139 | s = parameters.get(Param.bounds.key);
|
---|
| 140 | if (s != null) {
|
---|
| 141 | this.bounds = parseBounds(s);
|
---|
| 142 | }
|
---|
[5072] | 143 | }
|
---|
| 144 | }
|
---|
| 145 |
|
---|
[5228] | 146 | private Map<String, String> parseParameterList(String pref) throws ProjectionConfigurationException {
|
---|
| 147 | Map<String, String> parameters = new HashMap<String, String>();
|
---|
| 148 | String[] parts = pref.trim().split("\\s+");
|
---|
| 149 | if (pref.trim().isEmpty()) {
|
---|
| 150 | parts = new String[0];
|
---|
| 151 | }
|
---|
| 152 | for (int i = 0; i < parts.length; i++) {
|
---|
| 153 | String part = parts[i];
|
---|
| 154 | if (part.isEmpty() || part.charAt(0) != '+')
|
---|
| 155 | throw new ProjectionConfigurationException(tr("Parameter must begin with a ''+'' character (found ''{0}'')", part));
|
---|
| 156 | Matcher m = Pattern.compile("\\+([a-zA-Z0-9_]+)(=(.*))?").matcher(part);
|
---|
| 157 | if (m.matches()) {
|
---|
| 158 | String key = m.group(1);
|
---|
| 159 | // alias
|
---|
| 160 | if (key.equals("k")) {
|
---|
| 161 | key = Param.k_0.key;
|
---|
| 162 | }
|
---|
| 163 | String value = null;
|
---|
| 164 | if (m.groupCount() >= 3) {
|
---|
| 165 | value = m.group(3);
|
---|
| 166 | // same aliases
|
---|
| 167 | if (key.equals(Param.proj.key)) {
|
---|
| 168 | if (value.equals("longlat") || value.equals("latlon") || value.equals("latlong")) {
|
---|
| 169 | value = "lonlat";
|
---|
| 170 | }
|
---|
| 171 | }
|
---|
| 172 | }
|
---|
| 173 | if (!Param.paramsByKey.containsKey(key))
|
---|
| 174 | throw new ProjectionConfigurationException(tr("Unkown parameter: ''{0}''.", key));
|
---|
| 175 | if (Param.paramsByKey.get(key).hasValue && value == null)
|
---|
| 176 | throw new ProjectionConfigurationException(tr("Value expected for parameter ''{0}''.", key));
|
---|
| 177 | if (!Param.paramsByKey.get(key).hasValue && value != null)
|
---|
| 178 | throw new ProjectionConfigurationException(tr("No value expected for parameter ''{0}''.", key));
|
---|
| 179 | parameters.put(key, value);
|
---|
| 180 | } else
|
---|
| 181 | throw new ProjectionConfigurationException(tr("Unexpected parameter format (''{0}'')", part));
|
---|
| 182 | }
|
---|
| 183 | // recursive resolution of +init includes
|
---|
| 184 | String initKey = parameters.get(Param.init.key);
|
---|
| 185 | if (initKey != null) {
|
---|
| 186 | String init = Projections.getInit(initKey);
|
---|
| 187 | if (init == null)
|
---|
| 188 | throw new ProjectionConfigurationException(tr("Value ''{0}'' for option +init not supported.", initKey));
|
---|
| 189 | Map<String, String> initp = null;
|
---|
| 190 | try {
|
---|
| 191 | initp = parseParameterList(init);
|
---|
| 192 | } catch (ProjectionConfigurationException ex) {
|
---|
| 193 | throw new ProjectionConfigurationException(tr(initKey+": "+ex.getMessage()));
|
---|
| 194 | }
|
---|
| 195 | for (Map.Entry<String, String> e : parameters.entrySet()) {
|
---|
| 196 | initp.put(e.getKey(), e.getValue());
|
---|
| 197 | }
|
---|
| 198 | return initp;
|
---|
| 199 | }
|
---|
| 200 | return parameters;
|
---|
| 201 | }
|
---|
| 202 |
|
---|
[5072] | 203 | public Ellipsoid parseEllipsoid(Map<String, String> parameters) throws ProjectionConfigurationException {
|
---|
[5227] | 204 | String code = parameters.get(Param.ellps.key);
|
---|
[5072] | 205 | if (code != null) {
|
---|
| 206 | Ellipsoid ellipsoid = Projections.getEllipsoid(code);
|
---|
| 207 | if (ellipsoid == null) {
|
---|
| 208 | throw new ProjectionConfigurationException(tr("Ellipsoid ''{0}'' not supported.", code));
|
---|
| 209 | } else {
|
---|
| 210 | return ellipsoid;
|
---|
| 211 | }
|
---|
| 212 | }
|
---|
[5227] | 213 | String s = parameters.get(Param.a.key);
|
---|
[5072] | 214 | if (s != null) {
|
---|
[5227] | 215 | double a = parseDouble(s, Param.a.key);
|
---|
| 216 | if (parameters.get(Param.es.key) != null) {
|
---|
| 217 | double es = parseDouble(parameters, Param.es.key);
|
---|
[5072] | 218 | return Ellipsoid.create_a_es(a, es);
|
---|
| 219 | }
|
---|
[5227] | 220 | if (parameters.get(Param.rf.key) != null) {
|
---|
| 221 | double rf = parseDouble(parameters, Param.rf.key);
|
---|
[5072] | 222 | return Ellipsoid.create_a_rf(a, rf);
|
---|
| 223 | }
|
---|
[5227] | 224 | if (parameters.get(Param.f.key) != null) {
|
---|
| 225 | double f = parseDouble(parameters, Param.f.key);
|
---|
[5072] | 226 | return Ellipsoid.create_a_f(a, f);
|
---|
| 227 | }
|
---|
[5227] | 228 | if (parameters.get(Param.b.key) != null) {
|
---|
| 229 | double b = parseDouble(parameters, Param.b.key);
|
---|
[5072] | 230 | return Ellipsoid.create_a_b(a, b);
|
---|
| 231 | }
|
---|
| 232 | }
|
---|
[5227] | 233 | if (parameters.containsKey(Param.a.key) ||
|
---|
| 234 | parameters.containsKey(Param.es.key) ||
|
---|
| 235 | parameters.containsKey(Param.rf.key) ||
|
---|
| 236 | parameters.containsKey(Param.f.key) ||
|
---|
| 237 | parameters.containsKey(Param.b.key))
|
---|
[5072] | 238 | throw new ProjectionConfigurationException(tr("Combination of ellipsoid parameters is not supported."));
|
---|
[5228] | 239 | if (parameters.containsKey(Param.no_defs.key))
|
---|
| 240 | throw new ProjectionConfigurationException(tr("Ellipsoid required (+ellps=* or +a=*, +b=*)"));
|
---|
[5072] | 241 | // nothing specified, use WGS84 as default
|
---|
| 242 | return Ellipsoid.WGS84;
|
---|
| 243 | }
|
---|
| 244 |
|
---|
| 245 | public Datum parseDatum(Map<String, String> parameters, Ellipsoid ellps) throws ProjectionConfigurationException {
|
---|
[5227] | 246 | String nadgridsId = parameters.get(Param.nadgrids.key);
|
---|
[5226] | 247 | if (nadgridsId != null) {
|
---|
[5228] | 248 | NTV2GridShiftFileWrapper nadgrids = Projections.getNTV2Grid(nadgridsId);
|
---|
[5226] | 249 | if (nadgrids == null)
|
---|
| 250 | throw new ProjectionConfigurationException(tr("Grid shift file ''{0}'' for option +nadgrids not supported.", nadgridsId));
|
---|
| 251 | return new NTV2Datum(nadgridsId, null, ellps, nadgrids);
|
---|
| 252 | }
|
---|
| 253 |
|
---|
[5227] | 254 | String towgs84 = parameters.get(Param.towgs84.key);
|
---|
[5072] | 255 | if (towgs84 != null)
|
---|
| 256 | return parseToWGS84(towgs84, ellps);
|
---|
| 257 |
|
---|
[5227] | 258 | String datumId = parameters.get(Param.datum.key);
|
---|
[5072] | 259 | if (datumId != null) {
|
---|
| 260 | Datum datum = Projections.getDatum(datumId);
|
---|
| 261 | if (datum == null) throw new ProjectionConfigurationException(tr("Unkown datum identifier: ''{0}''", datumId));
|
---|
| 262 | return datum;
|
---|
[5228] | 263 | }
|
---|
| 264 | if (parameters.containsKey(Param.no_defs.key))
|
---|
| 265 | throw new ProjectionConfigurationException(tr("Datum required (+datum=*, +towgs84=* or +nadgirds=*)"));
|
---|
| 266 | return new CentricDatum(null, null, ellps);
|
---|
[5072] | 267 | }
|
---|
| 268 |
|
---|
| 269 | public Datum parseToWGS84(String paramList, Ellipsoid ellps) throws ProjectionConfigurationException {
|
---|
| 270 | String[] numStr = paramList.split(",");
|
---|
| 271 |
|
---|
| 272 | if (numStr.length != 3 && numStr.length != 7)
|
---|
| 273 | throw new ProjectionConfigurationException(tr("Unexpected number of arguments for parameter ''towgs84'' (must be 3 or 7)"));
|
---|
| 274 | List<Double> towgs84Param = new ArrayList<Double>();
|
---|
| 275 | for (int i = 0; i < numStr.length; i++) {
|
---|
| 276 | try {
|
---|
| 277 | towgs84Param.add(Double.parseDouble(numStr[i]));
|
---|
| 278 | } catch (NumberFormatException e) {
|
---|
| 279 | throw new ProjectionConfigurationException(tr("Unable to parse value of parameter ''towgs84'' (''{0}'')", numStr[i]));
|
---|
| 280 | }
|
---|
| 281 | }
|
---|
| 282 | boolean is3Param = true;
|
---|
| 283 | for (int i = 3; i<towgs84Param.size(); i++) {
|
---|
| 284 | if (towgs84Param.get(i) != 0.0) {
|
---|
| 285 | is3Param = false;
|
---|
| 286 | break;
|
---|
| 287 | }
|
---|
| 288 | }
|
---|
| 289 | Datum datum = null;
|
---|
| 290 | if (is3Param) {
|
---|
| 291 | datum = new ThreeParameterDatum(null, null, ellps,
|
---|
| 292 | towgs84Param.get(0),
|
---|
| 293 | towgs84Param.get(1),
|
---|
| 294 | towgs84Param.get(2)
|
---|
| 295 | );
|
---|
| 296 | } else {
|
---|
| 297 | datum = new SevenParameterDatum(null, null, ellps,
|
---|
| 298 | towgs84Param.get(0),
|
---|
| 299 | towgs84Param.get(1),
|
---|
| 300 | towgs84Param.get(2),
|
---|
| 301 | towgs84Param.get(3),
|
---|
| 302 | towgs84Param.get(4),
|
---|
| 303 | towgs84Param.get(5),
|
---|
| 304 | towgs84Param.get(6)
|
---|
| 305 | );
|
---|
| 306 | }
|
---|
| 307 | return datum;
|
---|
| 308 | }
|
---|
| 309 |
|
---|
| 310 | public Proj parseProjection(Map<String, String> parameters, Ellipsoid ellps) throws ProjectionConfigurationException {
|
---|
[5227] | 311 | String id = (String) parameters.get(Param.proj.key);
|
---|
[5072] | 312 | if (id == null) throw new ProjectionConfigurationException(tr("Projection required (+proj=*)"));
|
---|
| 313 |
|
---|
[5227] | 314 | Proj proj = Projections.getBaseProjection(id);
|
---|
[5072] | 315 | if (proj == null) throw new ProjectionConfigurationException(tr("Unkown projection identifier: ''{0}''", id));
|
---|
| 316 |
|
---|
| 317 | ProjParameters projParams = new ProjParameters();
|
---|
| 318 |
|
---|
| 319 | projParams.ellps = ellps;
|
---|
| 320 |
|
---|
| 321 | String s;
|
---|
[5227] | 322 | s = parameters.get(Param.lat_0.key);
|
---|
[5072] | 323 | if (s != null) {
|
---|
[5227] | 324 | projParams.lat_0 = parseAngle(s, Param.lat_0.key);
|
---|
[5072] | 325 | }
|
---|
[5227] | 326 | s = parameters.get(Param.lat_1.key);
|
---|
[5072] | 327 | if (s != null) {
|
---|
[5227] | 328 | projParams.lat_1 = parseAngle(s, Param.lat_1.key);
|
---|
[5072] | 329 | }
|
---|
[5227] | 330 | s = parameters.get(Param.lat_2.key);
|
---|
[5072] | 331 | if (s != null) {
|
---|
[5227] | 332 | projParams.lat_2 = parseAngle(s, Param.lat_2.key);
|
---|
[5072] | 333 | }
|
---|
| 334 | proj.initialize(projParams);
|
---|
| 335 | return proj;
|
---|
[5228] | 336 | }
|
---|
[5072] | 337 |
|
---|
[5228] | 338 | public Bounds parseBounds(String boundsStr) throws ProjectionConfigurationException {
|
---|
| 339 | String[] numStr = boundsStr.split(",");
|
---|
| 340 | if (numStr.length != 4)
|
---|
| 341 | throw new ProjectionConfigurationException(tr("Unexpected number of arguments for parameter ''+bounds'' (must be 4)"));
|
---|
| 342 | return new Bounds(parseAngle(numStr[1], "minlat (+bounds)"),
|
---|
| 343 | parseAngle(numStr[0], "minlon (+bounds)"),
|
---|
| 344 | parseAngle(numStr[3], "maxlat (+bounds)"),
|
---|
| 345 | parseAngle(numStr[2], "maxlon (+bounds)"));
|
---|
[5072] | 346 | }
|
---|
| 347 |
|
---|
| 348 | public double parseDouble(Map<String, String> parameters, String parameterName) throws ProjectionConfigurationException {
|
---|
| 349 | String doubleStr = parameters.get(parameterName);
|
---|
| 350 | if (doubleStr == null && parameters.containsKey(parameterName))
|
---|
| 351 | throw new ProjectionConfigurationException(
|
---|
| 352 | tr("Expected number argument for parameter ''{0}''", parameterName));
|
---|
| 353 | return parseDouble(doubleStr, parameterName);
|
---|
| 354 | }
|
---|
| 355 |
|
---|
| 356 | public double parseDouble(String doubleStr, String parameterName) throws ProjectionConfigurationException {
|
---|
| 357 | try {
|
---|
| 358 | return Double.parseDouble(doubleStr);
|
---|
| 359 | } catch (NumberFormatException e) {
|
---|
| 360 | throw new ProjectionConfigurationException(
|
---|
[5202] | 361 | tr("Unable to parse value ''{1}'' of parameter ''{0}'' as number.", parameterName, doubleStr));
|
---|
[5072] | 362 | }
|
---|
| 363 | }
|
---|
| 364 |
|
---|
| 365 | public double parseAngle(String angleStr, String parameterName) throws ProjectionConfigurationException {
|
---|
| 366 | String s = angleStr;
|
---|
| 367 | double value = 0;
|
---|
| 368 | boolean neg = false;
|
---|
| 369 | Matcher m = Pattern.compile("^-").matcher(s);
|
---|
| 370 | if (m.find()) {
|
---|
| 371 | neg = true;
|
---|
| 372 | s = s.substring(m.end());
|
---|
| 373 | }
|
---|
| 374 | final String FLOAT = "(\\d+(\\.\\d*)?)";
|
---|
| 375 | boolean dms = false;
|
---|
| 376 | // degrees
|
---|
| 377 | m = Pattern.compile("^"+FLOAT+"d").matcher(s);
|
---|
| 378 | if (m.find()) {
|
---|
| 379 | s = s.substring(m.end());
|
---|
| 380 | value += Double.parseDouble(m.group(1));
|
---|
| 381 | dms = true;
|
---|
| 382 | }
|
---|
| 383 | // minutes
|
---|
| 384 | m = Pattern.compile("^"+FLOAT+"'").matcher(s);
|
---|
| 385 | if (m.find()) {
|
---|
| 386 | s = s.substring(m.end());
|
---|
| 387 | value += Double.parseDouble(m.group(1)) / 60.0;
|
---|
| 388 | dms = true;
|
---|
| 389 | }
|
---|
| 390 | // seconds
|
---|
| 391 | m = Pattern.compile("^"+FLOAT+"\"").matcher(s);
|
---|
| 392 | if (m.find()) {
|
---|
| 393 | s = s.substring(m.end());
|
---|
| 394 | value += Double.parseDouble(m.group(1)) / 3600.0;
|
---|
| 395 | dms = true;
|
---|
| 396 | }
|
---|
| 397 | // plain number (in degrees)
|
---|
| 398 | if (!dms) {
|
---|
| 399 | m = Pattern.compile("^"+FLOAT).matcher(s);
|
---|
| 400 | if (m.find()) {
|
---|
| 401 | s = s.substring(m.end());
|
---|
| 402 | value += Double.parseDouble(m.group(1));
|
---|
| 403 | }
|
---|
| 404 | }
|
---|
| 405 | m = Pattern.compile("^(N|E)", Pattern.CASE_INSENSITIVE).matcher(s);
|
---|
| 406 | if (m.find()) {
|
---|
| 407 | s = s.substring(m.end());
|
---|
| 408 | } else {
|
---|
| 409 | m = Pattern.compile("^(S|W)", Pattern.CASE_INSENSITIVE).matcher(s);
|
---|
| 410 | if (m.find()) {
|
---|
| 411 | s = s.substring(m.end());
|
---|
| 412 | neg = !neg;
|
---|
| 413 | }
|
---|
| 414 | }
|
---|
| 415 | if (neg) {
|
---|
| 416 | value = -value;
|
---|
| 417 | }
|
---|
| 418 | if (!s.isEmpty()) {
|
---|
| 419 | throw new ProjectionConfigurationException(
|
---|
[5202] | 420 | tr("Unable to parse value ''{1}'' of parameter ''{0}'' as coordinate value.", parameterName, angleStr));
|
---|
[5072] | 421 | }
|
---|
| 422 | return value;
|
---|
| 423 | }
|
---|
| 424 |
|
---|
| 425 | public void dump() {
|
---|
| 426 | System.err.println("x_0="+x_0);
|
---|
| 427 | System.err.println("y_0="+y_0);
|
---|
| 428 | System.err.println("lon_0="+lon_0);
|
---|
| 429 | System.err.println("k_0="+k_0);
|
---|
| 430 | System.err.println("ellps="+ellps);
|
---|
| 431 | System.err.println("proj="+proj);
|
---|
| 432 | System.err.println("datum="+datum);
|
---|
| 433 | }
|
---|
| 434 |
|
---|
| 435 | @Override
|
---|
| 436 | public Integer getEpsgCode() {
|
---|
| 437 | return null;
|
---|
| 438 | }
|
---|
| 439 |
|
---|
| 440 | @Override
|
---|
| 441 | public String toCode() {
|
---|
[5226] | 442 | return "proj:" + (pref == null ? "ERROR" : pref);
|
---|
[5072] | 443 | }
|
---|
| 444 |
|
---|
| 445 | @Override
|
---|
| 446 | public String getCacheDirectoryName() {
|
---|
[5226] | 447 | return "proj-"+Utils.md5Hex(pref == null ? "" : pref).substring(0, 4);
|
---|
[5072] | 448 | }
|
---|
| 449 |
|
---|
| 450 | @Override
|
---|
| 451 | public Bounds getWorldBoundsLatLon() {
|
---|
[5228] | 452 | if (bounds != null) return bounds;
|
---|
[5072] | 453 | return new Bounds(
|
---|
[5228] | 454 | new LatLon(-90.0, -180.0),
|
---|
| 455 | new LatLon(90.0, 180.0));
|
---|
[5072] | 456 | }
|
---|
| 457 |
|
---|
| 458 | @Override
|
---|
| 459 | public String toString() {
|
---|
[5227] | 460 | return tr("Custom Projection");
|
---|
[5072] | 461 | }
|
---|
| 462 | }
|
---|