001/* 002 * GeoAPI - Java interfaces for OGC/ISO standards 003 * http://www.geoapi.org 004 * 005 * Copyright (C) 2011-2019 Open Geospatial Consortium, Inc. 006 * All Rights Reserved. http://www.opengeospatial.org/ogc/legal 007 * 008 * Permission to use, copy, and modify this software and its documentation, with 009 * or without modification, for any purpose and without fee or royalty is hereby 010 * granted, provided that you include the following on ALL copies of the software 011 * and documentation or portions thereof, including modifications, that you make: 012 * 013 * 1. The full text of this NOTICE in a location viewable to users of the 014 * redistributed or derivative work. 015 * 2. Notice of any changes or modifications to the OGC files, including the 016 * date changes were made. 017 * 018 * THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE 019 * NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 020 * TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT 021 * THE USE OF THE SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY 022 * PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. 023 * 024 * COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR 025 * CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE SOFTWARE OR DOCUMENTATION. 026 * 027 * The name and trademarks of copyright holders may NOT be used in advertising or 028 * publicity pertaining to the software without specific, written prior permission. 029 * Title to copyright in this software and any associated documentation will at all 030 * times remain with copyright holders. 031 */ 032package org.opengis.test.referencing; 033 034import java.util.Set; 035import java.util.Map; 036import java.util.HashMap; 037import java.util.Collections; 038import java.util.Objects; 039import javax.measure.Unit; 040import javax.measure.quantity.Angle; 041import javax.measure.quantity.Length; 042 043import org.opengis.parameter.*; 044import org.opengis.referencing.*; 045import org.opengis.referencing.cs.*; 046import org.opengis.referencing.crs.*; 047import org.opengis.referencing.datum.*; 048import org.opengis.referencing.operation.*; 049import org.opengis.metadata.citation.Citation; 050import org.opengis.util.FactoryException; 051import org.opengis.util.InternationalString; 052import org.opengis.test.util.PseudoFactory; 053import org.opengis.test.ValidatorContainer; 054import org.opengis.test.Units; 055 056import static org.junit.Assert.*; 057import static org.junit.Assume.*; 058 059 060/** 061 * Creates referencing objects for a limited set of hard-coded EPSG codes 062 * using {@link ObjectFactory} and {@link MathTransformFactory}. This pseudo-factory 063 * can be used with implementation that do not support (or don't want to test) a "real" 064 * {@link CRSAuthorityFactory} for the EPSG database. 065 * 066 * @author Martin Desruisseaux (Geomatys) 067 * @author Johann Sorel (Geomatys) 068 * @version 3.1 069 * @since 3.1 070 */ 071public strictfp class PseudoEpsgFactory extends PseudoFactory implements DatumAuthorityFactory, 072 CSAuthorityFactory, CRSAuthorityFactory 073{ 074 /** 075 * The reciprocal of the conversion from US feets to metres. 076 */ 077 static final double R_US_FEET = 3.2808333333333333333; 078 079 /** 080 * Conversion from Clarke's 1865 feet to metres. 081 */ 082 static final double CLARKE_KEET = 0.3047972654; 083 084 /** 085 * Conversion from feets to metres. 086 */ 087 static final double FEET = 0.3048; 088 089 /** 090 * Conversion from links to metres 091 */ 092 static final double LINKS = 0.66 * FEET; 093 094 /** 095 * Provider of pre-defined {@link Unit} instances (degree, metre, second, <i>etc</i>). 096 */ 097 protected final Units units; 098 099 /** 100 * Factory to use for building {@link Datum} instances, or {@code null} if none. 101 */ 102 protected final DatumFactory datumFactory; 103 104 /** 105 * Factory to use for building {@link CoordinateSystem} instances, or {@code null} if none. 106 */ 107 protected final CSFactory csFactory; 108 109 /** 110 * Factory to use for building {@link CoordinateReferenceSystem} instances, or {@code null} if none. 111 */ 112 protected final CRSFactory crsFactory; 113 114 /** 115 * Factory to use for building {@link Conversion} instances, or {@code null} if none. 116 */ 117 protected final CoordinateOperationFactory copFactory; 118 119 /** 120 * Factory to use for building {@link MathTransform} instances, or {@code null} if none. 121 */ 122 protected final MathTransformFactory mtFactory; 123 124 /** 125 * The set of validators to use for verifying objects conformance (never {@code null}). 126 */ 127 protected final ValidatorContainer validators; 128 129 /** 130 * Creates a new pseudo-factory which will use the given factories. 131 * 132 * @param units provider of pre-defined {@link Unit} instances. 133 * @param datumFactory factory for creating {@link Datum} instances. 134 * @param csFactory factory for creating {@link CoordinateSystem} instances. 135 * @param crsFactory factory for creating {@link CoordinateReferenceSystem} instances. 136 * @param copFactory factory for creating {@link Conversion} instances. 137 * @param mtFactory factory for creating {@link MathTransform} instances. 138 * @param validators the set of validators to use for verifying objects conformance, 139 * Can not be {@code null}; if there is no particular validators, 140 * use {@link org.opengis.test.Validators#DEFAULT}. 141 */ 142 public PseudoEpsgFactory( 143 final Units units, 144 final DatumFactory datumFactory, 145 final CSFactory csFactory, 146 final CRSFactory crsFactory, 147 final CoordinateOperationFactory copFactory, 148 final MathTransformFactory mtFactory, 149 final ValidatorContainer validators) 150 { 151 this.units = Objects.requireNonNull(units, "The units can not be null. Do you mean Units.getDefault()?"); 152 this.datumFactory = datumFactory; 153 this.csFactory = csFactory; 154 this.crsFactory = crsFactory; 155 this.copFactory = copFactory; 156 this.mtFactory = mtFactory; 157 this.validators = Objects.requireNonNull(validators, "The validators can not be null. Do you mean Validators.DEFAULT?"); 158 } 159 160 /** 161 * Returns the given EPSG code as an integer. 162 * 163 * @param code the EPSG code to parse. 164 * @return the EPSG code as an integer. 165 * @throws NoSuchAuthorityCodeException if the given code can not be parsed as an integer. 166 */ 167 private static int parseCode(String code) throws NoSuchAuthorityCodeException { 168 final int s = code.lastIndexOf(':'); 169 if (s >= 0) { 170 final String authority = code.substring(0, s).trim(); 171 if (!authority.equalsIgnoreCase("EPSG")) { 172 throw new NoSuchAuthorityCodeException("Unsupported \"" + authority + "\" authority.", "EPSG", code); 173 } 174 code = code.substring(s+1).trim(); 175 } 176 try { 177 return Integer.parseInt(code); 178 } catch (NumberFormatException cause) { 179 NoSuchAuthorityCodeException e = new NoSuchAuthorityCodeException( 180 "Unparseable EPSG code: " + code, "EPSG", code); 181 e.initCause(cause); 182 throw e; 183 } 184 } 185 186 /** 187 * Creates the exception to be thrown when the given code has not been recognized. 188 * 189 * @param code the code which has been requested. 190 * @return the exception to throw. 191 */ 192 private static NoSuchAuthorityCodeException noSuchAuthorityCode(final int id, final String code) { 193 final String idAsText = String.valueOf(id); 194 return new NoSuchAuthorityCodeException("No case implemented for EPSG:" + idAsText, 195 "EPSG", idAsText, code); 196 } 197 198 /** 199 * The default implementation returns {@code null}. 200 */ 201 @Override 202 public Citation getAuthority() { 203 return null; 204 } 205 206 /** 207 * The default implementation returns an empty set. 208 * 209 * @throws FactoryException if this method can not provide the requested information. 210 * 211 * @todo Needs to be implemented. 212 */ 213 @Override 214 public Set<String> getAuthorityCodes(final Class<? extends IdentifiedObject> type) throws FactoryException { 215 return Collections.emptySet(); 216 } 217 218 /** 219 * The default implementation returns {@code null}. 220 * 221 * @throws FactoryException if this method can not provide the requested information. 222 */ 223 @Override 224 public InternationalString getDescriptionText(final String code) throws FactoryException { 225 return null; 226 } 227 228 /** 229 * Builds a map of properties for a referencing object to be build. The map shall contains 230 * at least the {@link IdentifiedObject#NAME_KEY} identifier associated to the given value. 231 * Subclasses can override this method in order to provide more information if they wish. 232 * 233 * @param code The EPSG code of the object being built. 234 * @param name The name of the object being built. 235 * @return a map containing the properties for the object to create. 236 */ 237 protected Map<String,Object> createPropertiesMap(final int code, final String name) { 238 final Map<String,Object> properties = new HashMap<>(4); 239 assertNull(properties.put(IdentifiedObject.NAME_KEY, name)); 240 assertNull(properties.put(IdentifiedObject.IDENTIFIERS_KEY, new EPSGIdentifier(code))); 241 return properties; 242 } 243 244 /** 245 * Returns an arbitrary object from a code. 246 * 247 * <table class="ogc"> 248 * <caption>Supported codes</caption> 249 * <tr><th>Code</th> <th>Name</th></tr> 250 * <tr><td>4326</td> <td>WGS 84</td></tr> 251 * <tr><td>6326</td> <td>World Geodetic System 1984</td></tr> 252 * <tr><td>6422</td> <td>Ellipsoidal 2D CS. Axes: latitude, longitude. Orientations: north, east. UoM: degree</td></tr> 253 * </table> 254 * 255 * @param code value allocated by authority. 256 * @return the datum for the given code. 257 * @throws FactoryException if the object creation failed. 258 */ 259 @Override 260 public IdentifiedObject createObject(final String code) throws FactoryException { 261 final int id = parseCode(code); 262 switch (id) { 263 case 6326: return createDatum(code); 264 case 6422: return createCoordinateSystem(code); 265 case 4326: return createCoordinateReferenceSystem(code); 266 default: throw noSuchAuthorityCode(id, code); 267 } 268 } 269 270 271 272 273 /////////////////////////////////////////////////////////////////////////////////////////////// 274 /////////////////////////////// /////////////////////////////// 275 /////////////////////////////// D A T U M F A C T O R Y /////////////////////////////// 276 /////////////////////////////// /////////////////////////////// 277 /////////////////////////////////////////////////////////////////////////////////////////////// 278 279 /** 280 * Returns an arbitrary {@linkplain Datum datum} from a code. 281 * 282 * <table class="ogc"> 283 * <caption>Supported codes</caption> 284 * <tr><th>Code</th> <th>Name</th></tr> 285 * <tr><td>6326</td> <td>World Geodetic System 1984</td></tr> 286 * </table> 287 * 288 * @param code value allocated by authority. 289 * @return the datum for the given code. 290 * @throws FactoryException if the object creation failed. 291 */ 292 @Override 293 public Datum createDatum(final String code) throws FactoryException { 294 final int id = parseCode(code); 295 switch (id) { 296 case 6326: return createGeodeticDatum(code); 297 default: throw noSuchAuthorityCode(id, code); 298 } 299 } 300 301 /** 302 * The default implementation throws {@link NoSuchAuthorityCodeException} unconditionally. 303 * 304 * @throws FactoryException if this method can not provide the requested information. 305 */ 306 @Override 307 public EngineeringDatum createEngineeringDatum(String code) throws FactoryException { 308 final int id = parseCode(code); 309 switch (id) { 310 default: throw noSuchAuthorityCode(id, code); 311 } 312 } 313 314 /** 315 * The default implementation throws {@link NoSuchAuthorityCodeException} unconditionally. 316 * 317 * @throws FactoryException if this method can not provide the requested information. 318 */ 319 @Override 320 public ImageDatum createImageDatum(String code) throws FactoryException { 321 final int id = parseCode(code); 322 switch (id) { 323 default: throw noSuchAuthorityCode(id, code); 324 } 325 } 326 327 /** 328 * The default implementation throws {@link NoSuchAuthorityCodeException} unconditionally. 329 * 330 * @throws FactoryException if this method can not provide the requested information. 331 */ 332 @Override 333 public VerticalDatum createVerticalDatum(String code) throws FactoryException { 334 final int id = parseCode(code); 335 switch (id) { 336 default: throw noSuchAuthorityCode(id, code); 337 } 338 } 339 340 /** 341 * The default implementation throws {@link NoSuchAuthorityCodeException} unconditionally. 342 * 343 * @throws FactoryException if this method can not provide the requested information. 344 */ 345 @Override 346 public TemporalDatum createTemporalDatum(String code) throws FactoryException { 347 final int id = parseCode(code); 348 switch (id) { 349 default: throw noSuchAuthorityCode(id, code); 350 } 351 } 352 353 /** 354 * The default implementation throws {@link NoSuchAuthorityCodeException} unconditionally. 355 * 356 * @throws FactoryException if this method can not provide the requested information. 357 */ 358 @Override 359 public ParametricDatum createParametricDatum(String code) throws FactoryException { 360 final int id = parseCode(code); 361 switch (id) { 362 default: throw noSuchAuthorityCode(id, code); 363 } 364 } 365 366 /** 367 * Returns a {@linkplain GeodeticDatum geodetic datum} from a code. 368 * 369 * <table class="ogc"> 370 * <caption>Supported codes</caption> 371 * <tr><th>Code</th> <th>Name</th></tr> 372 * <tr><td>6326</td> <td>World Geodetic System 1984</td></tr> 373 * <tr><td>6284</td> <td>Pulkovo 1942</td></tr> 374 * </table> 375 * 376 * @param code value allocated by authority. 377 * @return the datum for the given code. 378 * @throws FactoryException if the object creation failed. 379 */ 380 @Override 381 public GeodeticDatum createGeodeticDatum(final String code) throws FactoryException { 382 final String name; 383 final int ellipsoid; 384 final int primeMeridian; 385 final int id = parseCode(code); 386 switch (id) { 387 case 6326: name="World Geodetic System 1984"; ellipsoid=7030; primeMeridian=8901; break; 388 case 6284: name="Pulkovo 1942"; ellipsoid=7024; primeMeridian=8901; break; 389 default: throw noSuchAuthorityCode(id, code); 390 } 391 assumeNotNull(datumFactory); 392 final GeodeticDatum object = datumFactory.createGeodeticDatum(createPropertiesMap(id, name), 393 createEllipsoid (String.valueOf(ellipsoid)), 394 createPrimeMeridian(String.valueOf(primeMeridian))); 395 validators.validate(object); 396 return object; 397 } 398 399 /** 400 * Returns an {@linkplain Ellipsoid ellipsoid} from a code. 401 * 402 * <table class="ogc"> 403 * <caption>Supported codes</caption> 404 * <tr><th>Code</th> <th>Name</th></tr> 405 * <tr><td>7001</td> <td>Airy 1830</td></tr> 406 * <tr><td>7004</td> <td>Bessel 1841</td></tr> 407 * <tr><td>7011</td> <td>Clarke 1880 (IGN)</td></tr> 408 * <tr><td>7019</td> <td>GRS 1980</td></tr> 409 * <tr><td>7022</td> <td>International 1924</td></tr> 410 * <tr><td>7024</td> <td>Krassowsky 1940</td></tr> 411 * <tr><td>7030</td> <td>WGS 84</td></tr> 412 * </table> 413 * 414 * @param code value allocated by authority. 415 * @return the ellipsoid for the given code. 416 * @throws FactoryException if the object creation failed. 417 */ 418 @Override 419 public Ellipsoid createEllipsoid(final String code) throws FactoryException { 420 final String name; 421 final double semiMajorAxis; 422 double semiMinorAxis = Double.NaN; 423 double inverseFlattening = Double.NaN; 424 int unitCode = 9001; // Default unit is metre. 425 final int id = parseCode(code); 426 switch (id) { 427 case 7030: name="WGS 84"; semiMajorAxis=6378137; inverseFlattening=298.257223563; break; 428 case 7019: name="GRS 1980"; semiMajorAxis=6378137; inverseFlattening=298.2572221; break; 429 case 7001: name="Airy 1830"; semiMajorAxis=6377563.396; inverseFlattening=299.3249646; break; 430 case 7004: name="Bessel 1841"; semiMajorAxis=6377397.155; inverseFlattening=299.1528128; break; 431 case 7024: name="Krassowsky 1940"; semiMajorAxis=6378245; inverseFlattening=298.3; break; 432 case 7022: name="International 1924"; semiMajorAxis=6378388; inverseFlattening=297; break; 433 case 7011: name="Clarke 1880 (IGN)"; semiMajorAxis=6378249.2; semiMinorAxis=6356515; break; 434 default: throw noSuchAuthorityCode(id, code); 435 } 436 assumeNotNull(datumFactory); 437 final Map<String,?> properties = createPropertiesMap(id, name); 438 final Unit<Length> unit = createUnit(String.valueOf(unitCode)).asType(Length.class); 439 final Ellipsoid object; 440 if (Double.isNaN(inverseFlattening)) { 441 object = datumFactory.createEllipsoid(properties, semiMajorAxis, semiMinorAxis, unit); 442 } else { 443 object = datumFactory.createFlattenedSphere(properties, semiMajorAxis, inverseFlattening, unit); 444 } 445 validators.validate(object); 446 return object; 447 } 448 449 /** 450 * Returns a {@linkplain PrimeMeridian prime meridian} from a EPSG code. 451 * 452 * <table class="ogc"> 453 * <caption>Supported codes</caption> 454 * <tr><th>Code</th> <th>Name</th></tr> 455 * <tr><td>8901</td> <td>Greenwich</td></tr> 456 * <tr><td>8903</td> <td>Paris</td></tr> 457 * <tr><td>8908</td> <td>Jakarta</td></tr> 458 * </table> 459 * 460 * @param code value allocated by authority. 461 * @return the prime meridian for the given code. 462 * @throws FactoryException if the object creation failed. 463 */ 464 @Override 465 public PrimeMeridian createPrimeMeridian(final String code) throws FactoryException { 466 final String name; 467 final double longitude; 468 final int unit; 469 final int id = parseCode(code); 470 switch (id) { 471 case 8901: name="Greenwich"; longitude= 0.0; unit=9102; break; 472 case 8903: name="Paris"; longitude= 2.5969213; unit=9105; break; 473 case 8908: name="Jakarta"; longitude=106.80771944444444; unit=9102; break; 474 default: throw noSuchAuthorityCode(id, code); 475 } 476 assumeNotNull(datumFactory); 477 final PrimeMeridian object = datumFactory.createPrimeMeridian(createPropertiesMap(id, name), 478 longitude, createUnit(String.valueOf(unit)).asType(Angle.class)); 479 validators.validate(object); 480 return object; 481 } 482 483 484 485 486 /////////////////////////////////////////////////////////////////////////////////////////////// 487 /////////////////// /////////////////// 488 /////////////////// C O O R D I N A T E S Y S T E M F A C T O R Y /////////////////// 489 /////////////////// /////////////////// 490 /////////////////////////////////////////////////////////////////////////////////////////////// 491 492 /** 493 * Returns an arbitrary {@linkplain CoordinateSystem coordinate system} from a code. 494 * 495 * <table class="ogc"> 496 * <caption>Supported codes</caption> 497 * <tr><th>Code</th> <th>Name</th></tr> 498 * <tr><td>6422</td> <td>Ellipsoidal 2D CS. Axes: latitude, longitude. Orientations: north, east. UoM: degree</td></tr> 499 * </table> 500 * 501 * @param code value allocated by authority. 502 * @return the coordinate system for the given code. 503 * @throws FactoryException if the object creation failed. 504 */ 505 @Override 506 public CoordinateSystem createCoordinateSystem(final String code) throws FactoryException { 507 final int id = parseCode(code); 508 switch (id) { 509 case 6422: return createEllipsoidalCS(code); 510 default: throw noSuchAuthorityCode(id, code); 511 } 512 } 513 514 /** 515 * Creates a Cartesian coordinate system from a code. 516 * 517 * <table class="ogc"> 518 * <caption>Supported codes</caption> 519 * <tr><th>Code</th> <th>Name</th></tr> 520 * <tr><td>6500</td> <td>Earth centred, earth fixed, righthanded 3D coordinate system, consisting of 3 orthogonal axes with X and Y axes in the equatorial plane, positive Z-axis parallel to mean earth rotation axis and pointing towards North Pole. UoM: m</td></tr> 521 * </table> 522 * 523 * @param code value allocated by authority. 524 * @return the coordinate system for the given code. 525 * @throws FactoryException if the object creation failed. 526 */ 527 @Override 528 public CartesianCS createCartesianCS(final String code) throws FactoryException { 529 final String name; 530 final int axisCode0; 531 final int axisCode1; 532 final int axisCode2; 533 final int id = parseCode(code); 534 switch (id) { 535 case 6500: { 536 name = "Earth centred, earth fixed, righthanded 3D coordinate system, " 537 + "consisting of 3 orthogonal axes with X and Y axes in the equatorial plane, " 538 + "positive Z-axis parallel to mean earth rotation axis and pointing towards North Pole. " 539 + "UoM: m"; 540 axisCode0 = 115; // Geocentric X 541 axisCode1 = 116; // Geocentric Y 542 axisCode2 = 117; // Geocentric Z 543 break; 544 } 545 default: throw noSuchAuthorityCode(id, code); 546 } 547 assumeNotNull(csFactory); 548 final Map<String,?> properties = createPropertiesMap(id, name); 549 final CoordinateSystemAxis axis0 = createCoordinateSystemAxis(String.valueOf(axisCode0)); 550 final CoordinateSystemAxis axis1 = createCoordinateSystemAxis(String.valueOf(axisCode1)); 551 final CartesianCS object; 552 if (axisCode2 == 0) { 553 object = csFactory.createCartesianCS(properties, axis0, axis1); 554 } else { 555 object = csFactory.createCartesianCS(properties, axis0, axis1, 556 createCoordinateSystemAxis(String.valueOf(axisCode2))); 557 } 558 validators.validate(object); 559 return object; 560 } 561 562 /** 563 * The default implementation throws {@link NoSuchAuthorityCodeException} unconditionally. 564 * 565 * @throws FactoryException if this method can not provide the requested information. 566 */ 567 @Override 568 public PolarCS createPolarCS(final String code) throws FactoryException { 569 final int id = parseCode(code); 570 switch (id) { 571 default: throw noSuchAuthorityCode(id, code); 572 } 573 } 574 575 /** 576 * The default implementation throws {@link NoSuchAuthorityCodeException} unconditionally. 577 * 578 * @throws FactoryException if this method can not provide the requested information. 579 */ 580 @Override 581 public CylindricalCS createCylindricalCS(final String code) throws FactoryException { 582 final int id = parseCode(code); 583 switch (id) { 584 default: throw noSuchAuthorityCode(id, code); 585 } 586 } 587 588 /** 589 * The default implementation throws {@link NoSuchAuthorityCodeException} unconditionally. 590 * 591 * @throws FactoryException if this method can not provide the requested information. 592 */ 593 @Override 594 public SphericalCS createSphericalCS(final String code) throws FactoryException { 595 final int id = parseCode(code); 596 switch (id) { 597 default: throw noSuchAuthorityCode(id, code); 598 } 599 } 600 601 /** 602 * Creates an ellipsoidal coordinate system from a code. 603 * 604 * <table class="ogc"> 605 * <caption>Supported codes</caption> 606 * <tr><th>Code</th> <th>Name</th></tr> 607 * <tr><td>6403</td> <td>Ellipsoidal 2D CS. Axes: latitude, longitude. Orientations: north, east. UoM: grads.</td></tr> 608 * <tr><td>6422</td> <td>Ellipsoidal 2D CS. Axes: latitude, longitude. Orientations: north, east. UoM: degree</td></tr> 609 * <tr><td>6423</td> <td>Ellipsoidal 3D CS. Axes: latitude, longitude, ellipsoidal height. Orientations: north, east, up. UoM: degree, degree, metre.</td></tr> 610 * <tr><td>6424</td> <td>Ellipsoidal 2D CS. Axes: longitude, latitude. Orientations: east, north. UoM: degree</td></tr> 611 * </table> 612 * 613 * @param code value allocated by authority. 614 * @return the coordinate system for the given code. 615 * @throws FactoryException if the object creation failed. 616 */ 617 @Override 618 public EllipsoidalCS createEllipsoidalCS(final String code) throws FactoryException { 619 final String name; 620 final int axisCode0; 621 final int axisCode1; 622 int axisCode2 = 0; 623 final int id = parseCode(code); 624 switch (id) { 625 case 6403: { 626 name = "Ellipsoidal 2D CS. Axes: latitude, longitude. " 627 + "Orientations: north, east. " 628 + "UoM: grads. "; 629 axisCode0 = 58; // Geodetic latitude 630 axisCode1 = 59; // Geodetic longitude 631 break; 632 } 633 case 6422: { 634 name = "Ellipsoidal 2D CS. Axes: latitude, longitude. " 635 + "Orientations: north, east. " 636 + "UoM: degree"; 637 axisCode0 = 106; // Geodetic latitude 638 axisCode1 = 107; // Geodetic longitude 639 break; 640 } 641 case 6423: { 642 name = "Ellipsoidal 3D CS. Axes: latitude, longitude, ellipsoidal height. " 643 + "Orientations: north, east, up. " 644 + "UoM: degree, degree, metre."; 645 axisCode0 = 108; // Geodetic latitude 646 axisCode1 = 109; // Geodetic longitude 647 axisCode2 = 110; // Ellipsoidal height 648 break; 649 } 650 case 6424: { 651 name = "Ellipsoidal 2D CS. Axes: longitude, latitude. " 652 + "Orientations: east, north. " 653 + "UoM: degree"; 654 axisCode0 = 220; // Geodetic longitude 655 axisCode1 = 221; // Geodetic latitude 656 break; 657 } 658 default: throw noSuchAuthorityCode(id, code); 659 } 660 assumeNotNull(csFactory); 661 final Map<String,?> properties = createPropertiesMap(id, name); 662 final CoordinateSystemAxis axis0 = createCoordinateSystemAxis(String.valueOf(axisCode0)); 663 final CoordinateSystemAxis axis1 = createCoordinateSystemAxis(String.valueOf(axisCode1)); 664 final EllipsoidalCS object; 665 if (axisCode2 == 0) { 666 object = csFactory.createEllipsoidalCS(properties, axis0, axis1); 667 } else { 668 object = csFactory.createEllipsoidalCS(properties, axis0, axis1, 669 createCoordinateSystemAxis(String.valueOf(axisCode2))); 670 } 671 validators.validate(object); 672 return object; 673 } 674 675 /** 676 * The default implementation throws {@link NoSuchAuthorityCodeException} unconditionally. 677 * 678 * @throws FactoryException if this method can not provide the requested information. 679 */ 680 @Override 681 public VerticalCS createVerticalCS(final String code) throws FactoryException { 682 final int id = parseCode(code); 683 switch (id) { 684 default: throw noSuchAuthorityCode(id, code); 685 } 686 } 687 688 /** 689 * The default implementation throws {@link NoSuchAuthorityCodeException} unconditionally. 690 * 691 * @throws FactoryException if this method can not provide the requested information. 692 */ 693 @Override 694 public TimeCS createTimeCS(final String code) throws FactoryException { 695 final int id = parseCode(code); 696 switch (id) { 697 default: throw noSuchAuthorityCode(id, code); 698 } 699 } 700 701 /** 702 * The default implementation throws {@link NoSuchAuthorityCodeException} unconditionally. 703 * 704 * @throws FactoryException if this method can not provide the requested information. 705 */ 706 @Override 707 public ParametricCS createParametricCS(String code) throws FactoryException { 708 final int id = parseCode(code); 709 switch (id) { 710 default: throw noSuchAuthorityCode(id, code); 711 } 712 } 713 714 /** 715 * Returns a {@linkplain CoordinateSystemAxis coordinate system axis} from a code. 716 * 717 * <table class="ogc"> 718 * <caption>Supported codes</caption> 719 * <tr><th>Code</th> <th>Name</th> <th>Unit</th></tr> 720 * <tr><td>58</td> <td>Geodetic latitude</td> <td>grad</td></tr> 721 * <tr><td>59</td> <td>Geodetic longitude</td> <td>grad</td></tr> 722 * <tr><td>106, 108, 221</td> <td>Geodetic latitude</td> <td>degree</td></tr> 723 * <tr><td>107, 109, 220</td> <td>Geodetic longitude</td> <td>degree</td></tr> 724 * <tr><td>110</td> <td>Ellipsoidal height</td> <td>metre</td></tr> 725 * <tr><td>115</td> <td>Geocentric X</td> <td>metre</td></tr> 726 * <tr><td>116</td> <td>Geocentric Y</td> <td>metre</td></tr> 727 * <tr><td>117</td> <td>Geocentric Z</td> <td>metre</td></tr> 728 * </table> 729 * 730 * @param code value allocated by authority. 731 * @return the axis for the given code. 732 * @throws FactoryException if the object creation failed. 733 */ 734 @Override 735 public CoordinateSystemAxis createCoordinateSystemAxis(final String code) throws FactoryException { 736 final String name; 737 final String abbreviation; 738 final AxisDirection direction; 739 final int unit; 740 final int id = parseCode(code); 741 switch (id) { 742 case 108: case 221: 743 case 106: name="Geodetic latitude"; abbreviation="Lat"; direction=AxisDirection.NORTH; unit=9122; break; 744 case 58: name="Geodetic latitude"; abbreviation="Lat"; direction=AxisDirection.NORTH; unit=9105; break; 745 case 109: case 220: 746 case 107: name="Geodetic longitude"; abbreviation="Long"; direction=AxisDirection.EAST; unit=9122; break; 747 case 59: name="Geodetic longitude"; abbreviation="Long"; direction=AxisDirection.EAST; unit=9105; break; 748 case 110: name="Ellipsoidal height"; abbreviation="h"; direction=AxisDirection.UP; unit=9001; break; 749 case 115: name="Geocentric X"; abbreviation="X"; direction=AxisDirection.GEOCENTRIC_X; unit=9001; break; 750 case 116: name="Geocentric Y"; abbreviation="Y"; direction=AxisDirection.GEOCENTRIC_Y; unit=9001; break; 751 case 117: name="Geocentric Z"; abbreviation="Z"; direction=AxisDirection.GEOCENTRIC_Z; unit=9001; break; 752 default: throw noSuchAuthorityCode(id, code); 753 } 754 assumeNotNull(csFactory); 755 final CoordinateSystemAxis object = csFactory.createCoordinateSystemAxis(createPropertiesMap(id, name), 756 abbreviation, direction, createUnit(String.valueOf(unit))); 757 validators.validate(object); 758 return object; 759 } 760 761 /** 762 * Returns an {@linkplain Unit unit} from a code. 763 * 764 * <table class="ogc"> 765 * <caption>Supported codes</caption> 766 * <tr><th>Code</th> <th>Name</th></tr> 767 * <tr><td>9001</td> <td>metre</td></tr> 768 * <tr><td>9102</td> <td>degree</td></tr> 769 * <tr><td>9105</td> <td>grad</td></tr> 770 * <tr><td>9122</td> <td>degree (supplier to define representation)</td></tr> 771 * </table> 772 * 773 * @param code value allocated by authority. 774 * @return the unit for the given code. 775 * @throws FactoryException if the object creation failed. 776 */ 777 @Override 778 public Unit<?> createUnit(final String code) throws FactoryException { 779 final int id = parseCode(code); 780 switch (id) { 781 case 9001: return units.metre(); 782 case 9122: // Fall through 783 case 9102: return units.degree(); 784 case 9105: return units.grad(); 785 default: throw noSuchAuthorityCode(id, code); 786 } 787 } 788 789 790 791 792 /////////////////////////////////////////////////////////////////////////////////////////////// 793 ///////// ///////// 794 ///////// C O O R D I N A T E R E F E R E N C E S Y S T E M F A C T O R Y ///////// 795 ///////// ///////// 796 /////////////////////////////////////////////////////////////////////////////////////////////// 797 798 /** 799 * Returns an arbitrary {@linkplain CoordinateReferenceSystem coordinate reference system} from a code. 800 * 801 * <table class="ogc"> 802 * <caption>Supported codes</caption> 803 * <tr><th>Code</th> <th>Name</th></tr> 804 * <tr><td>4326</td> <td>WGS 84</td></tr> 805 * </table> 806 * 807 * @param code value allocated by authority. 808 * @return the coordinate reference system for the given code. 809 * @throws FactoryException if the object creation failed. 810 */ 811 @Override 812 public CoordinateReferenceSystem createCoordinateReferenceSystem(final String code) throws FactoryException { 813 final int id = parseCode(code); 814 switch (id) { 815 case 4326: return createGeographicCRS(code); 816 default: throw noSuchAuthorityCode(id, code); 817 } 818 } 819 820 /** 821 * The default implementation throws {@link NoSuchAuthorityCodeException} unconditionally. 822 * 823 * @throws FactoryException if this method can not provide the requested information. 824 */ 825 @Override 826 public CompoundCRS createCompoundCRS(String code) throws FactoryException { 827 final int id = parseCode(code); 828 switch (id) { 829 default: throw noSuchAuthorityCode(id, code); 830 } 831 } 832 833 /** 834 * The default implementation throws {@link NoSuchAuthorityCodeException} unconditionally. 835 * 836 * @throws FactoryException if this method can not provide the requested information. 837 */ 838 @Override 839 public DerivedCRS createDerivedCRS(String code) throws FactoryException { 840 final int id = parseCode(code); 841 switch (id) { 842 default: throw noSuchAuthorityCode(id, code); 843 } 844 } 845 846 /** 847 * The default implementation throws {@link NoSuchAuthorityCodeException} unconditionally. 848 * 849 * @throws FactoryException if this method can not provide the requested information. 850 */ 851 @Override 852 public EngineeringCRS createEngineeringCRS(String code) throws FactoryException { 853 final int id = parseCode(code); 854 switch (id) { 855 default: throw noSuchAuthorityCode(id, code); 856 } 857 } 858 859 /** 860 * Returns a {@linkplain GeographicCRS geographic coordinate reference system} from a code. 861 * 862 * <table class="ogc"> 863 * <caption>Supported codes</caption> 864 * <tr><th>Code</th> <th>Name</th></tr> 865 * <tr><td>4326</td> <td>WGS 84</td></tr> 866 * <tr><td>4284</td> <td>Pulkovo 1942</td></tr> 867 * </table> 868 * 869 * @param code value allocated by authority. 870 * @return the coordinate reference system for the given code. 871 * @throws FactoryException if the object creation failed. 872 */ 873 @Override 874 public GeographicCRS createGeographicCRS(final String code) throws FactoryException { 875 final String name; 876 final int datum; 877 final int coordinateSystem; 878 final int id = parseCode(code); 879 switch (id) { 880 case 4326: name="WGS 84"; datum=6326; coordinateSystem=6422; break; 881 case 4284: name="Pulkovo 1942"; datum=6284; coordinateSystem=6422; break; 882 default: throw noSuchAuthorityCode(id, code); 883 } 884 assumeNotNull(crsFactory); 885 final GeographicCRS object = crsFactory.createGeographicCRS(createPropertiesMap(id, name), 886 createGeodeticDatum(String.valueOf(datum)), 887 createEllipsoidalCS(String.valueOf(coordinateSystem))); 888 validators.validate(object); 889 return object; 890 } 891 892 /** 893 * The default implementation throws {@link NoSuchAuthorityCodeException} unconditionally. 894 * 895 * @throws FactoryException if this method can not provide the requested information. 896 */ 897 @Override 898 public GeocentricCRS createGeocentricCRS(String code) throws FactoryException { 899 final int id = parseCode(code); 900 switch (id) { 901 default: throw noSuchAuthorityCode(id, code); 902 } 903 } 904 905 /** 906 * The default implementation throws {@link NoSuchAuthorityCodeException} unconditionally. 907 * 908 * @throws FactoryException if this method can not provide the requested information. 909 */ 910 @Override 911 public ImageCRS createImageCRS(String code) throws FactoryException { 912 final int id = parseCode(code); 913 switch (id) { 914 default: throw noSuchAuthorityCode(id, code); 915 } 916 } 917 918 /** 919 * The default implementation throws {@link NoSuchAuthorityCodeException} unconditionally. 920 * 921 * @throws FactoryException if this method can not provide the requested information. 922 */ 923 @Override 924 public ProjectedCRS createProjectedCRS(String code) throws FactoryException { 925 final int id = parseCode(code); 926 switch (id) { 927 default: throw noSuchAuthorityCode(id, code); 928 } 929 } 930 931 /** 932 * The default implementation throws {@link NoSuchAuthorityCodeException} unconditionally. 933 * 934 * @throws FactoryException if this method can not provide the requested information. 935 */ 936 @Override 937 public TemporalCRS createTemporalCRS(String code) throws FactoryException { 938 final int id = parseCode(code); 939 switch (id) { 940 default: throw noSuchAuthorityCode(id, code); 941 } 942 } 943 944 /** 945 * The default implementation throws {@link NoSuchAuthorityCodeException} unconditionally. 946 * 947 * @throws FactoryException if this method can not provide the requested information. 948 */ 949 @Override 950 public VerticalCRS createVerticalCRS(String code) throws FactoryException { 951 final int id = parseCode(code); 952 switch (id) { 953 default: throw noSuchAuthorityCode(id, code); 954 } 955 } 956 957 /** 958 * The default implementation throws {@link NoSuchAuthorityCodeException} unconditionally. 959 * 960 * @throws FactoryException if this method can not provide the requested information. 961 */ 962 @Override 963 public ParametricCRS createParametricCRS(String code) throws FactoryException { 964 final int id = parseCode(code); 965 switch (id) { 966 default: throw noSuchAuthorityCode(id, code); 967 } 968 } 969 970 971 972 /////////////////////////////////////////////////////////////////////////////////////////////// 973 //////////////// //////////////// 974 //////////////// C O O R D I N A T E O P E R A T I O N F A C T O R Y //////////////// 975 //////////////// //////////////// 976 /////////////////////////////////////////////////////////////////////////////////////////////// 977 978 /** 979 * Returns the parameters to use for creating the {@linkplain CoordinateOperation coordinate 980 * operation} identified by the given EPSG code. The coordinate operation is typically a map 981 * projection used by exactly one {@linkplain ProjectedCRS projected CRS}, which is listed in 982 * the second column for information purpose. 983 * 984 * <p>The supported codes are determined from the set of examples published in the EPSG guidance 985 * document, augmented with other sources (IGNF). 986 * The following table lists the supported codes. 987 * <i>Codes in italics are not official EPSG codes.</i></p> 988 * 989 * <table class="ogc"> 990 * <caption>Supported codes</caption> 991 * <tr><th>Code</th> <th>Used by CRS</th><th>CRS or transformation name</th> <th>Operation method</th></tr> 992 * <tr><td>19905</td> <td>3002</td> <td>Makassar / NEIEZ</td> <td>Mercator (variant A)</td></tr> 993 * <tr><td>19884</td> <td>3388</td> <td>Pulkovo 1942 / Caspian Sea Mercator</td> <td>Mercator (variant B)</td></tr> 994 * <tr><td>3856</td> <td>3857</td> <td>WGS 84 / Pseudo-Mercator</td> <td>Popular Visualisation Pseudo Mercator</td></tr> 995 * <tr><td><i>310642901</i></td> <td><i>310642901</i></td> <td>IGNF:MILLER</td> <td><i>Miller_Cylindrical</i></td></tr> 996 * <tr><td>19958</td> <td>29873</td> <td>Timbalai 1948 / RSO Borneo (m)</td> <td>Hotine Oblique Mercator (variant B)</td></tr> 997 * <tr><td>19916</td> <td>27700</td> <td>OSGB 1936 / British National Grid</td> <td>Transverse Mercator</td></tr> 998 * <tr><td>17529</td> <td>2053</td> <td>South African Survey Grid zone 29</td> <td>Transverse Mercator</td></tr> 999 * <tr><td>19975</td> <td>2314</td> <td>Trinidad 1903 / Trinidad Grid</td> <td>Cassini-Soldner</td></tr> 1000 * <tr><td>19910</td> <td>24200</td> <td>JAD69 / Jamaica National Grid</td> <td>Lambert Conic Conformal (1SP)</td></tr> 1001 * <tr><td>14204</td> <td>32040</td> <td>NAD27 / Texas South Central</td> <td>Lambert Conic Conformal (2SP)</td></tr> 1002 * <tr> <td>6198</td> <td>6201</td> <td>Michigan CS27 Central zone</td> <td>Lambert Conic Conformal (2SP Michigan)</td></tr> 1003 * <tr><td>19902</td> <td>31300</td> <td>Belge 1972 / Belge Lambert 72</td> <td>Lambert Conic Conformal (2SP Belgium)</td></tr> 1004 * <tr><td>19986</td> <td>3035</td> <td>ETRS89 / LAEA Europe</td> <td>Lambert Azimuthal Equal Area</td></tr> 1005 * <tr><td>16061</td> <td>5041</td> <td>WGS 84 / UPS North (E,N)</td> <td>Polar Stereographic (variant A)</td></tr> 1006 * <tr><td>19993</td> <td>3032</td> <td>WGS 84 / Australian Antarctic Polar</td> <td>Polar Stereographic (variant B)</td></tr> 1007 * <tr><td>19983</td> <td>2985</td> <td>Petrels 1972 / Terre Adelie Polar Stereographic</td> <td>Polar Stereographic (variant C)</td></tr> 1008 * <tr><td>19914</td> <td>28992</td> <td>Amersfoort / RD New</td> <td>Oblique Stereographic</td></tr> 1009 * <tr><td><i>9818</i></td> <td><i>9818</i></td> <td><i>Polyconic</i></td> <td><i>Polyconic</i></td></tr> 1010 * <tr><td>19952</td> <td>2065</td> <td>CRS S-JTSK (Ferro) / Krovak</td> <td>Krovak</td></tr> 1011 * <tr><td><i>9605</i></td> <td>4230</td> <td>ED50 to WGS 84</td> <td>Abridged Molodensky</td></tr> 1012 * </table> 1013 * 1014 * @param code the EPSG code of the {@linkplain CoordinateOperation coordinate operation} to create. 1015 * @return the coordinate operation (typically a map projection) parameters. 1016 * @throws FactoryException if the given EPSG code is unknown to this factory. 1017 * 1018 * @see ParameterizedTransformTest 1019 * @see AuthorityFactoryTest 1020 */ 1021 protected ParameterValueGroup createParameters(final int code) throws FactoryException { 1022 final ParameterValueGroup parameters = createParameters(mtFactory, code); 1023 validators.validate(parameters); 1024 return parameters; 1025 } 1026 1027 /** 1028 * Implementation of the above {@link #createParameters(int)} method, 1029 * as a static method for direct access by {@link ParameterizedTransformTest}. 1030 */ 1031 static ParameterValueGroup createParameters(final MathTransformFactory factory, final int code) 1032 throws FactoryException 1033 { 1034 final ParameterValueGroup parameters; 1035 switch (code) { 1036 case 19905: { // "Makassar / NEIEZ" using operation method 9804 1037 parameters = factory.getDefaultParameters("Mercator (variant A)"); // Alias "Mercator (1SP)" 1038 parameters.parameter("semi_major").setValue(6377397.155); // Bessel 1841 1039 parameters.parameter("semi_minor").setValue(6377397.155 * (1 - 1/299.1528128)); 1040 parameters.parameter("Latitude of natural origin") .setValue( 0.0); 1041 parameters.parameter("Longitude of natural origin") .setValue(110.0); 1042 parameters.parameter("Scale factor at natural origin").setValue(0.997); 1043 parameters.parameter("False easting").setValue(3900000.0); 1044 parameters.parameter("False northing").setValue(900000.0); 1045 break; 1046 } 1047 case 19884: { // "Pulkovo 1942 / Caspian Sea Mercator" using operation method 9805 1048 parameters = factory.getDefaultParameters("Mercator (variant B) "); // Alias "Mercator (2SP)" 1049 parameters.parameter("semi_major").setValue(6378245.0); // Krassowski 1940 1050 parameters.parameter("semi_minor").setValue(6378245.0 * (1 - 1/298.3)); 1051 parameters.parameter("Latitude of 1st standard parallel").setValue(42.0); 1052 parameters.parameter("Longitude of natural origin") .setValue(51.0); 1053 break; 1054 } 1055 case 3856: { // "WGS 84 / Pseudo-Mercator" using operation method 1024 1056 parameters = factory.getDefaultParameters("Popular Visualisation Pseudo Mercator"); 1057 parameters.parameter("semi_major").setValue(6378137.0); // WGS 84 1058 parameters.parameter("semi_minor").setValue(6378137.0 * (1 - 1/298.2572236)); 1059 break; 1060 } 1061 case 310642901: { // "IGNF:MILLER" (not an official EPSG code) 1062 parameters = factory.getDefaultParameters("Miller_Cylindrical"); 1063 parameters.parameter("semi_major").setValue(6378137.0); 1064 parameters.parameter("semi_minor").setValue(6378137.0); 1065 break; 1066 } 1067 case 19958: { // "Rectified Skew Orthomorphic Borneo Grid (metres)" using operation method 9815 1068 parameters = factory.getDefaultParameters("Hotine Oblique Mercator (variant B)"); 1069 parameters.parameter("semi_major").setValue(6377298.556); // Everest 1830 1070 parameters.parameter("semi_minor").setValue(6377298.556 * (1 - 1/300.8017)); 1071 parameters.parameter("Latitude of projection centre") .setValue( 4.0); // 4°00'00"N 1072 parameters.parameter("Longitude of projection centre").setValue(115.0); // 115°00'00"E 1073 parameters.parameter("Azimuth of initial line").setValue(53 + (18 + 56.9537/60)/60); // 53°18'56.9537" 1074 parameters.parameter("Angle from Rectified to Skew Grid").setValue(53 + (7 + 48.3685/60)/60); // 53°07'48.3685" 1075 parameters.parameter("Scale factor on initial line") .setValue(0.99984); 1076 parameters.parameter("Easting at projection centre") .setValue(590476.87); 1077 parameters.parameter("Northing at projection centre").setValue(442857.65); 1078 break; 1079 } 1080 case 19916: { // "British National Grid" using operation method 9807 1081 parameters = factory.getDefaultParameters("Transverse Mercator"); 1082 parameters.parameter("semi_major").setValue(6377563.396); // Airy 1083 parameters.parameter("semi_minor").setValue(6377563.396 * (1 - 1/299.32496)); 1084 parameters.parameter("Latitude of natural origin") .setValue(49.0); 1085 parameters.parameter("Longitude of natural origin").setValue(-2.0); 1086 parameters.parameter("Scale factor at natural origin").setValue(0.9996012717); 1087 parameters.parameter("False easting") .setValue( 400000.00); 1088 parameters.parameter("False northing").setValue(-100000.00); 1089 break; 1090 } 1091 case 17529: { // "South African Survey Grid zone 29" using operation method 9808 1092 parameters = factory.getDefaultParameters("Transverse Mercator (South Orientated)"); 1093 parameters.parameter("semi_major").setValue(6378137.0); // WGS 84 1094 parameters.parameter("semi_minor").setValue(6378137.0 * (1 - 1/298.2572236)); 1095 parameters.parameter("Latitude of natural origin").setValue(0.0); 1096 parameters.parameter("Longitude of natural origin").setValue(29.0); 1097 parameters.parameter("Scale factor at natural origin").setValue(1.0); 1098 parameters.parameter("False easting") .setValue(0.0); 1099 parameters.parameter("False northing").setValue(0.0); 1100 break; 1101 } 1102 case 19975: { // "Trinidad 1903 / Trinidad Grid" using operation method 9806 1103 parameters = factory.getDefaultParameters("Cassini-Soldner"); 1104 parameters.parameter("semi_major").setValue(20926348.0 * FEET); // Clarke 1858 1105 parameters.parameter("semi_minor").setValue(20855233.0 * FEET); 1106 parameters.parameter("Latitude of natural origin") .setValue(10 + (26 + 30.0/60)/60); // 10°26'30"N 1107 parameters.parameter("Longitude of natural origin").setValue(-(61 + 20.0/60)); // 61°20'00"W 1108 parameters.parameter("False easting") .setValue(430000.00 * LINKS); 1109 parameters.parameter("False northing").setValue(325000.00 * LINKS); 1110 break; 1111 } 1112 case 19910: { // "JAD69 / Jamaica National Grid" using operation method 9801 1113 parameters = factory.getDefaultParameters("Lambert Conic Conformal (1SP)"); 1114 parameters.parameter("semi_major").setValue(6378206.4); // Clarke 1866 1115 parameters.parameter("semi_minor").setValue(6356583.8); 1116 parameters.parameter("Latitude of natural origin") .setValue( 18.0); 1117 parameters.parameter("Longitude of natural origin") .setValue(-77.0); 1118 parameters.parameter("Scale factor at natural origin").setValue( 1.0); 1119 parameters.parameter("False easting") .setValue(250000.00); 1120 parameters.parameter("False northing").setValue(150000.00); 1121 break; 1122 } 1123 case 14204: { // "NAD27 / Texas South Central" using operation method 9802 1124 parameters = factory.getDefaultParameters("Lambert Conic Conformal (2SP)"); 1125 parameters.parameter("semi_major").setValue(6378206.4); // Clarke 1866 1126 parameters.parameter("semi_minor").setValue(6356583.8); 1127 parameters.parameter("Latitude of 1st standard parallel").setValue(28 + 23.0/60); // 28°23'00"N 1128 parameters.parameter("Latitude of 2nd standard parallel").setValue(30 + 17.0/60); // 30°17'00"N 1129 parameters.parameter("Latitude of false origin") .setValue(27 + 50.0/60); // 27°50'00"N 1130 parameters.parameter("Longitude of false origin") .setValue(-99.0); // 99°00'00"W 1131 parameters.parameter("Easting at false origin") .setValue(2000000 / R_US_FEET); 1132 parameters.parameter("Northing at false origin").setValue( 0 / R_US_FEET); 1133 break; 1134 } 1135 case 6198: { // "Michigan CS27 Central zone" using operation method 1051 1136 parameters = factory.getDefaultParameters("Lambert Conic Conformal (2SP Michigan)"); 1137 parameters.parameter("semi_major").setValue(6378206.4); // Clarke 1866 1138 parameters.parameter("semi_minor").setValue(6356583.8); 1139 parameters.parameter("Latitude of 1st standard parallel").setValue( 44 + 11.0/60); // 44°11' N 1140 parameters.parameter("Latitude of 2nd standard parallel").setValue( 45 + 42.0/60); // 45°42' N 1141 parameters.parameter("Latitude of false origin") .setValue( 43 + 19.0/60); // 43°19' N 1142 parameters.parameter("Longitude of false origin") .setValue(-84 - 20.0/60); // 84°20' W 1143 parameters.parameter("Easting at false origin") .setValue(2000000 / R_US_FEET); 1144 parameters.parameter("Northing at false origin").setValue( 0 / R_US_FEET); 1145 parameters.parameter("Ellipsoid scaling factor").setValue(1.0000382); 1146 break; 1147 } 1148 case 19902: { // "Belge 1972 / Belge Lambert 72" using operation method 9803 1149 parameters = factory.getDefaultParameters("Lambert Conic Conformal (2SP Belgium)"); 1150 parameters.parameter("semi_major").setValue(6378388.0); // International 1924 1151 parameters.parameter("semi_minor").setValue(6378388.0 * (1 - 1/297.0)); 1152 parameters.parameter("Latitude of 1st standard parallel").setValue(49 + 50.0/60); // 49°50'00.000"N 1153 parameters.parameter("Latitude of 2nd standard parallel").setValue(51 + 10.0/60); // 51°10'00.000"N 1154 parameters.parameter("Latitude of false origin") .setValue(90.0); // 90°00'00.000"N 1155 parameters.parameter("Longitude of false origin").setValue(4 + (21 + 24.983/60)/60); // 4°21'24.983"E 1156 parameters.parameter("Easting at false origin") .setValue( 150000.01); 1157 parameters.parameter("Northing at false origin").setValue(5400088.44); 1158 break; 1159 } 1160 case 19986: { // "Europe Equal Area 2001" using operation method 9820 1161 parameters = factory.getDefaultParameters("Lambert Azimuthal Equal Area"); 1162 parameters.parameter("semi_major").setValue(6378137.0); 1163 parameters.parameter("semi_minor").setValue(6378137.0 * (1 - 1/298.2572221)); 1164 parameters.parameter("Latitude of natural origin") .setValue(52.0); 1165 parameters.parameter("Longitude of natural origin").setValue(10.0); 1166 parameters.parameter("False easting") .setValue(4321000.00); 1167 parameters.parameter("False northing").setValue(3210000.00); 1168 break; 1169 } 1170 case 16061: { // "Universal Polar Stereographic North" using operation method 9810 1171 parameters = factory.getDefaultParameters("Polar Stereographic (variant A)"); 1172 parameters.parameter("semi_major").setValue(6378137.0); // WGS84 1173 parameters.parameter("semi_minor").setValue(6378137.0 * (1 - 1/298.2572236)); 1174 parameters.parameter("Latitude of natural origin").setValue(90.0); 1175 parameters.parameter("Longitude of natural origin").setValue(0.0); 1176 parameters.parameter("Scale factor at natural origin").setValue(0.994); 1177 parameters.parameter("False easting") .setValue(2000000.00); 1178 parameters.parameter("False northing").setValue(2000000.00); 1179 break; 1180 } 1181 case 19993: { // "Australian Antarctic Polar Stereographic" using operation method 9829 1182 parameters = factory.getDefaultParameters("Polar Stereographic (variant B)"); 1183 parameters.parameter("semi_major").setValue(6378137.0); // WGS84 1184 parameters.parameter("semi_minor").setValue(6378137.0 * (1 - 1/298.2572236)); 1185 parameters.parameter("Latitude of standard parallel").setValue(-71.0); 1186 parameters.parameter("Longitude of origin").setValue(70.0); 1187 parameters.parameter("False easting") .setValue(6000000.00); 1188 parameters.parameter("False northing").setValue(6000000.00); 1189 break; 1190 } 1191 case 19983: { // "Petrels 1972 / Terre Adelie Polar Stereographic" using operation method 9830 1192 parameters = factory.getDefaultParameters("Polar Stereographic (variant C)"); 1193 parameters.parameter("semi_major").setValue(6378388.0); // International 1924 1194 parameters.parameter("semi_minor").setValue(6378388.0 * (1 - 1/297.0)); 1195 parameters.parameter("Latitude of standard parallel").setValue(-67.0); 1196 parameters.parameter("Longitude of origin").setValue(140.0); 1197 parameters.parameter("Easting at false origin") .setValue(300000.00); 1198 parameters.parameter("Northing at false origin").setValue(200000.00); 1199 break; 1200 } 1201 case 19914: { // "RD New" using operation method 9809 1202 parameters = factory.getDefaultParameters("Oblique Stereographic"); 1203 parameters.parameter("semi_major").setValue(6377397.155); // Bessel 1841 1204 parameters.parameter("semi_minor").setValue(6377397.155 * (1 - 1/299.15281)); 1205 parameters.parameter("Latitude of natural origin").setValue(52 + ( 9 + 22.178/60)/60); // 52°09'22.178"N 1206 parameters.parameter("Longitude of natural origin").setValue(5 + (23 + 15.500/60)/60); // 5°23'15.500"E 1207 parameters.parameter("Scale factor at natural origin").setValue(0.9999079); 1208 parameters.parameter("False easting") .setValue(155000.00); 1209 parameters.parameter("False northing").setValue(463000.00); 1210 break; 1211 } 1212 case 9818: { // (not an official EPSG code) using operation method 9818 1213 parameters = factory.getDefaultParameters("Polyconic"); 1214 parameters.parameter("semi_major").setValue(6378206.4); 1215 parameters.parameter("semi_minor").setValue(6356583.8); 1216 parameters.parameter("Latitude of natural origin") .setValue(0.0); 1217 parameters.parameter("Longitude of natural origin").setValue(0.0); 1218 parameters.parameter("False easting") .setValue(0.0); 1219 parameters.parameter("False northing").setValue(0.0); 1220 break; 1221 } 1222 case 19952: { // "CRS S-JTSK (Ferro) / Krovak" using operation method 9819 1223 parameters = factory.getDefaultParameters("Krovak"); 1224 parameters.parameter("semi_major").setValue(6377397.155); // Bessel 1225 parameters.parameter("semi_minor").setValue(6377397.155 * (1 - 1/299.15281)); 1226 parameters.parameter("Latitude of projection centre").setValue(49.5); // 49°30'00"N 1227 parameters.parameter("Longitude of origin").setValue(24 + 50.0/60); // 24°30'00"E 1228 parameters.parameter("Co-latitude of cone axis").setValue(30 + (17 + 17.3031/60)/60); 1229 parameters.parameter("Latitude of pseudo standard parallel").setValue(78.5); 1230 parameters.parameter("Scale factor on pseudo standard parallel").setValue(0.99990); 1231 break; 1232 } 1233 case 9605: { // (not an official EPSG code) using operation method 9605 1234 parameters = factory.getDefaultParameters("Abridged Molodensky"); 1235 parameters.parameter("dim").setValue(3); // Parameter defined by OGC 01-009 1236 parameters.parameter("src_semi_major").setValue(6378137.0); // WGS84 1237 parameters.parameter("src_semi_minor").setValue(6378137.0 * (1 - 1/298.2572236)); 1238 parameters.parameter("X-axis translation").setValue( 84.87); 1239 parameters.parameter("Y-axis translation").setValue( 96.49); 1240 parameters.parameter("Z-axis translation").setValue(116.95); 1241 parameters.parameter("Semi-major axis length difference").setValue(251); 1242 parameters.parameter("Flattening difference").setValue(1.41927E-05); 1243 break; 1244 } 1245 default: { 1246 throw noSuchAuthorityCode(code, String.valueOf(code)); 1247 } 1248 } 1249 return parameters; 1250 } 1251}