001/* 002 * GeoAPI - Java interfaces for OGC/ISO standards 003 * http://www.geoapi.org 004 * 005 * Copyright (C) 2009-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.List; 036import java.awt.geom.Rectangle2D; 037 038import org.opengis.util.Factory; 039import org.opengis.util.FactoryException; 040import org.opengis.referencing.cs.*; 041import org.opengis.referencing.crs.*; 042import org.opengis.referencing.datum.*; 043import org.opengis.referencing.IdentifiedObject; 044import org.opengis.referencing.AuthorityFactory; 045import org.opengis.referencing.NoSuchAuthorityCodeException; 046import org.opengis.referencing.operation.TransformException; 047import org.opengis.referencing.operation.MathTransform; 048import org.opengis.referencing.operation.Conversion; 049import org.opengis.metadata.extent.Extent; 050import org.opengis.metadata.extent.GeographicExtent; 051import org.opengis.metadata.extent.GeographicBoundingBox; 052import org.opengis.test.CalculationType; 053import org.opengis.test.ToleranceModifier; 054import org.opengis.test.Configuration; 055 056import org.junit.Test; 057import org.junit.runner.RunWith; 058import org.junit.runners.Parameterized; 059 060import static org.junit.Assume.*; 061import static org.opengis.test.Assert.*; 062import static org.opengis.test.Validator.DEFAULT_TOLERANCE; 063 064 065/** 066 * Tests the creation of referencing objects from the {@linkplain AuthorityFactory authority 067 * factories} given at construction time. 068 * 069 * <p>Many {@link ProjectedCRS} instances tested in this class use the same projections than the 070 * {@link MathTransform} instances tested in {@link ParameterizedTransformTest}. However the later 071 * test class expects (λ,φ) input ordinates in degrees and (<var>x</var>,<var>y</var>) 072 * output ordinates in metres, while this {@code AuthorityFactoryTest} class expects input and 073 * output ordinates in CRS-dependent units and axis order.</p> 074 * 075 * <div class="note"><b>Usage example:</b> 076 * in order to specify their factories and run the tests in a JUnit framework, implementors can 077 * define a subclass in their own test suite as in the example below: 078 * 079 * <blockquote><pre>import org.junit.runner.RunWith; 080 *import org.junit.runners.JUnit4; 081 *import org.opengis.test.referencing.AuthorityFactoryTest; 082 * 083 *@RunWith(JUnit4.class) 084 *public class MyTest extends AuthorityFactoryTest { 085 * public MyTest() { 086 * super(new MyCRSAuthorityFactory(), new MyCSAuthorityFactory(), new MyDatumAuthorityFactory()); 087 * } 088 *}</pre></blockquote> 089 * </div> 090 * 091 * @see ObjectFactoryTest 092 * @see ParameterizedTransformTest 093 * @see org.opengis.test.TestSuite 094 * 095 * @author Cédric Briançon (Geomatys) 096 * @author Martin Desruisseaux (Geomatys) 097 * @version 3.1 098 * @since 2.3 099 */ 100@RunWith(Parameterized.class) 101public strictfp class AuthorityFactoryTest extends ReferencingTestCase { 102 /** 103 * Factory to use for building {@link CoordinateReferenceSystem} instances, or {@code null} if none. 104 */ 105 protected final CRSAuthorityFactory crsAuthorityFactory; 106 107 /** 108 * Factory to use for building {@link CoordinateSystem} instances, or {@code null} if none. 109 */ 110 protected final CSAuthorityFactory csAuthorityFactory; 111 112 /** 113 * Factory to use for building {@link Datum} instances, or {@code null} if none. 114 */ 115 protected final DatumAuthorityFactory datumAuthorityFactory; 116 117 /** 118 * The identified object (typically a {@link CoordinateReferenceSystem}) being tested. 119 * Every test methods in this class will set this field to a non-null value. 120 * Implementors can use this value for their own assertions after any test has been run. 121 * 122 * @since 3.1 123 */ 124 protected IdentifiedObject object; 125 126 /** 127 * {@code true} if the longitude and latitude axes shall be swapped. This flag applies 128 * only to geographic coordinates. 129 * 130 * <p><b>Default value:</b> {@code true}, since the majority of {@link GeographicCRS} 131 * defined in the EPSG database uses the (φλ) axis order.</p> 132 * 133 * @since 3.1 134 */ 135 protected boolean swapλφ = true; 136 137 /** 138 * {@code true} if the easting and northing axes shall be swapped. This flag applies only 139 * to projected coordinates. 140 * 141 * <p><b>Default value:</b> {@code false}, since the majority of {@link ProjectedCRS} defined 142 * in the EPSG database uses the (<var>x</var>,<var>y</var>) axis order.</p> 143 * 144 * @since 3.1 145 */ 146 protected boolean swapxy = false; 147 148 /** 149 * {@code true} if the sign of ordinate values shall be reversed in both projected axes. 150 * This flag applies only to projected coordinates. This flag is set to {@code true} for 151 * <cite>South Oriented</cite> {@link ProjectedCRS}. 152 * 153 * <p><b>Default value:</b> {@code false}.</p> 154 * 155 * @since 3.1 156 */ 157 private boolean flipxy = false; 158 159 /** 160 * {@code true} if the {@linkplain CoordinateReferenceSystem Coordinate Reference System} being 161 * tested is a polar CRS. Such CRS have axis orientation like <cite>"South along 90°E"</cite> 162 * instead than {@linkplain AxisDirection#EAST East} or {@linkplain AxisDirection#NORTH North}. 163 * 164 * <p><b>Default value:</b> {@code false}.</p> 165 * 166 * @since 3.1 167 */ 168 private boolean isPolar = false; 169 170 /** 171 * The expected prime meridian of the CRS being tested, in decimal degrees from Greenwich. 172 * 173 * <p><b>Default value:</b> {@code 0.0}.</p> 174 * 175 * @since 3.1 176 */ 177 protected double primeMeridian = 0.0; 178 179 /** 180 * Conversion factor from degrees to the CRS-specific angular units. This value is different 181 * than one when the latitude or longitude angles need to be converted from degrees before to 182 * run a test. 183 * 184 * <p><b>Default value:</b> {@code 1.0}.</p> 185 * 186 * @since 3.1 187 */ 188 protected double toAngularUnit = 1.0; 189 190 /** 191 * Conversion factor from metres to the CRS-specific linear units. This value is different 192 * than one when the easting or northing values need to be converted from metres before to 193 * run a test. 194 * 195 * <p><b>Default value:</b> {@code 1.0}.</p> 196 * 197 * @since 3.1 198 */ 199 protected double toLinearUnit = 1.0; 200 201 /** 202 * {@code true} if {@link #crsAuthorityFactory} and {@link #csAuthorityFactory} supports the 203 * creation of coordinate system with (<var>y</var>,<var>x</var>) axis order. If this field is 204 * set to {@code false}, then the tests that would normally expect (<var>y</var>,<var>x</var>) 205 * axis order or <cite>South Oriented</cite> CRS will rather use the (<var>x</var>,<var>y</var>) 206 * axis order and <cite>North Oriented</cite> CRS in their test. 207 * 208 * @since 3.1 209 */ 210 protected boolean isAxisSwappingSupported; 211 212 /** 213 * A helper class to use for running the tests. The {@link #runProjectionTest(int)} method 214 * will use the following {@code ParameterizedTransformTest} package-private methods: 215 * 216 * <ul> 217 * <li>{@link ParameterizedTransformTest#verifyKnownSamplePoints}</li> 218 * <li>{@link ParameterizedTransformTest#verifyInDomainOfValidity}</li> 219 * </ul> 220 */ 221 private final ParameterizedTransformTest test; 222 223 /** 224 * Returns a default set of factories to use for running the tests. Those factories are given 225 * in arguments to the constructor when this test class is instantiated directly by JUnit (for 226 * example as a {@linkplain org.junit.runners.Suite.SuiteClasses suite} element), instead than 227 * subclassed by the implementor. The factories are fetched as documented in the 228 * {@link #factories(Class[])} javadoc. 229 * 230 * @return the default set of arguments to be given to the {@code AuthorityFactoryTest} constructor. 231 * 232 * @since 3.1 233 */ 234 @Parameterized.Parameters 235 @SuppressWarnings("unchecked") 236 public static List<Factory[]> factories() { 237 return factories(CRSAuthorityFactory.class, CSAuthorityFactory.class, DatumAuthorityFactory.class); 238 } 239 240 /** 241 * Creates a new test using the given factories. If a given factory is {@code null}, 242 * then the tests which depend on it will be skipped. 243 * 244 * @param crsFactory factory for creating {@link CoordinateReferenceSystem} instances. 245 * @param csFactory factory for creating {@link CoordinateSystem} instances. 246 * @param datumFactory factory for creating {@link Datum} instances. 247 */ 248 public AuthorityFactoryTest(final CRSAuthorityFactory crsFactory, 249 final CSAuthorityFactory csFactory, final DatumAuthorityFactory datumFactory) 250 { 251 super(crsFactory, csFactory, datumFactory); 252 crsAuthorityFactory = crsFactory; 253 csAuthorityFactory = csFactory; 254 datumAuthorityFactory = datumFactory; 255 final Configuration.Key<Boolean>[] keys = ParameterizedTransformTest.getEnabledKeys(1); 256 final int offset = keys.length - 1; // First free slot for our keys. 257 keys[offset] = Configuration.Key.isAxisSwappingSupported; 258 final boolean[] isEnabled = getEnabledFlags(keys); 259 test = new ParameterizedTransformTest(isEnabled); 260 isAxisSwappingSupported = isEnabled[offset]; 261 } 262 263 /** 264 * Returns information about the configuration of the test which has been run. 265 * This method returns a map containing: 266 * 267 * <ul> 268 * <li>All the entries defined in the {@link ParameterizedTransformTest#configuration() 269 * ParameterizedTransformTest} class except {@code mtFactory}.</li> 270 * <li>All the following values associated to the {@link org.opengis.test.Configuration.Key} of the same name: 271 * <ul> 272 * <li>{@link #isAxisSwappingSupported}</li> 273 * <li>{@link #crsAuthorityFactory}</li> 274 * <li>{@link #csAuthorityFactory}</li> 275 * <li>{@link #datumAuthorityFactory}</li> 276 * </ul> 277 * </li> 278 * </ul> 279 * 280 * @return the configuration of the test being run, or an empty map if none. 281 * 282 * @since 3.1 283 */ 284 @Override 285 public Configuration configuration() { 286 final Configuration op = test.configuration(); 287 assertNull(op.remove(Configuration.Key.mtFactory)); 288 assertNull(op.put(Configuration.Key.isAxisSwappingSupported, isAxisSwappingSupported)); 289 assertNull(op.put(Configuration.Key.crsAuthorityFactory, crsAuthorityFactory)); 290 assertNull(op.put(Configuration.Key.csAuthorityFactory, csAuthorityFactory)); 291 assertNull(op.put(Configuration.Key.datumAuthorityFactory, datumAuthorityFactory)); 292 return op; 293 } 294 295 /** 296 * Returns the longitude value relative to the Greenwich Meridian, expressed in decimal degrees. 297 * 298 * @param pm the prime meridian from which to get the Greenwich longitude, or {@code null}. 299 * @return the prime meridian in the given units, or 0 if the given prime meridian was null. 300 */ 301 private double getGreenwichLongitude(final PrimeMeridian pm) { 302 return (pm != null) ? pm.getAngularUnit().getConverterTo(units.degree()).convert(pm.getGreenwichLongitude()) : 0; 303 } 304 305 /** 306 * Tests the creation of the EPSG:4326 {@link GeographicCRS}. 307 * 308 * @throws NoSuchAuthorityCodeException if the specified code is not found among the ones present in the database. 309 * @throws FactoryException if the creation of the {@link CoordinateReferenceSystem} failed for an other raison. 310 */ 311 @Test 312 public void testWGS84() throws NoSuchAuthorityCodeException, FactoryException { 313 assumeNotNull(crsAuthorityFactory); 314 final GeographicCRS crs = crsAuthorityFactory.createGeographicCRS("EPSG:4326"); 315 assertNotNull("CRSAuthorityFactory.createGeographicCRS()", crs); 316 object = crs; 317 validators.validate(crs); 318 verifyIdentification(crs, "WGS 84", null); 319 /* 320 * Coordinate system validation. In theory, the coordinate system is mandatory. 321 * This is verified by the above call to validate(crs). However the user could 322 * have set the Validator.requireMandatoryAttributes to 'false', in which case 323 * we need to be lenient as the user wish. 324 */ 325 final EllipsoidalCS cs = crs.getCoordinateSystem(); 326 if (cs != null) { 327 verifyCoordinateSystem(cs, EllipsoidalCS.class, 328 new AxisDirection[] { 329 AxisDirection.NORTH, 330 AxisDirection.EAST 331 }, units.degree()); 332 verifyIdentification(cs.getAxis(0), "Geodetic latitude", null); 333 verifyIdentification(cs.getAxis(1), "Geodetic longitude", null); 334 } 335 /* 336 * Datum validation. Same rational about 'null' value as for the coordinate system. 337 */ 338 final GeodeticDatum datum = crs.getDatum(); 339 if (datum != null) { 340 verifyIdentification(datum, "World Geodetic System 1984", null); 341 verifyPrimeMeridian(datum.getPrimeMeridian(), "Greenwich", 0.0, units.degree()); 342 } 343 } 344 345 /** 346 * Verifies the horizontal axis direction of the given coordinate system. The standard 347 * directions are (East,North), but the boolean argument allows to swap and flip those 348 * directions. 349 * 350 * @param cs the coordinate system to check, or {@code null}. 351 * @param swap {@code true} if the the easting and northing axes should be interchanged. 352 * @param flip {@code true} if the sign of both axes should be reversed. 353 */ 354 private static void verifyAxisDirection(final String message, final CoordinateSystem cs, 355 final boolean swap, final boolean flip) 356 { 357 if (cs != null) { 358 AxisDirection X,Y; 359 if (flip) { 360 X = AxisDirection.WEST; 361 Y = AxisDirection.SOUTH; 362 } else { 363 X = AxisDirection.EAST; 364 Y = AxisDirection.NORTH; 365 } 366 if (swap) { 367 final AxisDirection t = X; 368 X=Y; Y=t; 369 } 370 assertAxisDirectionsEqual(message, cs, X, Y); 371 } 372 } 373 374 /** 375 * Creates a {@link ProjectedCRS} identified by the given EPSG code, and tests its 376 * math transform. The set of allowed codes is documented in second column of the 377 * {@link PseudoEpsgFactory#createParameters(int)} method. 378 * 379 * @param code the EPSG code of a target Coordinate Reference System. 380 * @throws FactoryException if the math transform can not be created. 381 * @throws TransformException if a point can not be transformed. 382 */ 383 private void runProjectionTest(final int code) throws FactoryException, TransformException { 384 if (!isAxisSwappingSupported) { 385 swapλφ = swapxy = flipxy = false; 386 } 387 assumeNotNull(crsAuthorityFactory); 388 final ProjectedCRS crs; 389 try { 390 crs = crsAuthorityFactory.createProjectedCRS("EPSG:" + code); 391 } catch (NoSuchAuthorityCodeException e) { 392 // If a code was not found, ensure that the factory does not declare that it was 393 // a supported code. If the code was unsupported, then the test will be ignored. 394 final Set<String> authorityCodes = crsAuthorityFactory.getAuthorityCodes(ProjectedCRS.class); 395 if (authorityCodes == null || !authorityCodes.contains(String.valueOf(code))) { 396 assumeNoException(e); // Will mark the test as "ignored". 397 } 398 throw e; // Will mark the test as "failed". 399 } 400 assertNotNull("CRSAuthorityFactory.createProjectedCRS()", crs); 401 object = crs; 402 validators.validate(crs); 403 /* 404 * Coordinate system validation. In theory, the coordinate system is mandatory. 405 * This is verified by the above call to validate(crs). However the user could 406 * have set the Validator.requireMandatoryAttributes to 'false', in which case 407 * we need to be lenient as the user wishes. 408 */ 409 final GeographicCRS baseCRS = crs.getBaseCRS(); 410 if (baseCRS != null) { 411 verifyAxisDirection("BaseCRS", baseCRS.getCoordinateSystem(), swapλφ, false); 412 final GeodeticDatum datum = baseCRS.getDatum(); 413 if (datum != null) { 414 assertEquals("PrimeMeridian.greenwichLongitude", primeMeridian, 415 getGreenwichLongitude(datum.getPrimeMeridian()), DEFAULT_TOLERANCE); 416 } 417 } 418 /* 419 * Verifies axis direction only if the CRS is not polar. Polar CRS has unusual 420 * axis directions like "South along 90°E". Since there is no GeoAPI code list 421 * for such direction, we consider them as implementation-dependent. 422 */ 423 if (!isPolar) { 424 verifyAxisDirection("ProjectedCRS", crs.getCoordinateSystem(), swapxy, flipxy); 425 } 426 /* 427 * Test the projection of sample point values. 428 */ 429 final Conversion conversion = crs.getConversionFromBase(); 430 if (conversion != null) { 431 final MathTransform projection = conversion.getMathTransform(); 432 if (projection != null) { 433 test.description = Utilities.getName(crs); 434 test.transform = projection; 435 validators.validate(projection); 436 /* 437 * Get the sample points and swap ordinate values if needed. 438 * Finally apply a unit conversion if the CRS doesn't use the usual units. 439 */ 440 final SamplePoints sample = SamplePoints.forCRS(code); 441 if (primeMeridian != 0) sample.rotateLongitude(primeMeridian); 442 if (swapλφ) SamplePoints.swap(sample.sourcePoints); 443 if (swapxy) SamplePoints.swap(sample.targetPoints); 444 if (flipxy) SamplePoints.flip(sample.targetPoints); 445 test.setTolerance(swapλφ ? ToleranceModifier.PROJECTION_FROM_φλ : ToleranceModifier.PROJECTION); 446 if (toLinearUnit != 1) test.applyUnitConversion(CalculationType.DIRECT_TRANSFORM, sample.targetPoints, toLinearUnit); 447 if (toAngularUnit != 1) test.applyUnitConversion(CalculationType.INVERSE_TRANSFORM, sample.sourcePoints, toAngularUnit); 448 test.verifyTransform(sample.sourcePoints, sample.targetPoints); 449 /* 450 * Tests random points in every domains of validity declared in the CRS. 451 * If the CRS does not declare any domain of validity, then we will use 452 * the one which is hard-coded in the SamplePoints class. 453 */ 454 boolean tested = false; 455 final Rectangle2D areaOfValidity = sample.areaOfValidity; 456 double λmin = areaOfValidity.getMinX(); 457 double λmax = areaOfValidity.getMaxX(); 458 double φmin = areaOfValidity.getMinY(); 459 double φmax = areaOfValidity.getMaxY(); 460 final Extent extent = crs.getDomainOfValidity(); 461 validators.validate(extent); 462 if (extent != null) { 463 for (final GeographicExtent element : extent.getGeographicElements()) { 464 if (element instanceof GeographicBoundingBox && Boolean.TRUE.equals(element.getInclusion())) { 465 final GeographicBoundingBox bbox = (GeographicBoundingBox) element; 466 λmin = bbox.getWestBoundLongitude(); 467 λmax = bbox.getEastBoundLongitude(); 468 φmin = bbox.getSouthBoundLatitude(); 469 φmax = bbox.getNorthBoundLatitude(); 470 setRect(areaOfValidity, λmin, φmin, λmax, φmax, swapλφ, toAngularUnit); 471 assertFalse("Empty geographic bounding box.", areaOfValidity.isEmpty()); 472 test.verifyInDomainOfValidity(areaOfValidity); 473 tested = true; 474 } 475 } 476 } 477 if (!tested) { 478 setRect(areaOfValidity, λmin, φmin, λmax, φmax, swapλφ, toAngularUnit); 479 test.verifyInDomainOfValidity(areaOfValidity); 480 } 481 } 482 } 483 } 484 485 /** 486 * Sets the area of validity, swapping axis and converting units if necessary. 487 */ 488 private static void setRect(final Rectangle2D areaOfValidity, 489 double λmin, double φmin, double λmax, double φmax, 490 final boolean swapλφ, final double toAngularUnit) 491 { 492 λmin *= toAngularUnit; 493 λmax *= toAngularUnit; 494 φmin *= toAngularUnit; 495 φmax *= toAngularUnit; 496 if (swapλφ) { 497 double t; 498 t=λmin; λmin=φmin; φmin=t; 499 t=λmax; λmax=φmax; φmax=t; 500 } 501 areaOfValidity.setRect(λmin, φmin, λmax-λmin, φmax-φmin); 502 } 503 504 /** 505 * Tests the EPSG:3002 (<cite>Makassar / NEIEZ</cite>) projected CRS. 506 * 507 * <table class="ogc"> 508 * <caption>CRS characteristics</caption> 509 * <tr><td>Projection method:</td> <td>Mercator (variant A)</td></tr> 510 * <tr><td>Prime meridian:</td> <td>Greenwich</td></tr> 511 * <tr><td>Source ordinates:</td> <td>(φ,λ) in degrees</td></tr> 512 * <tr><td>Output ordinates:</td> <td>(<var>x</var>,<var>y</var>) in metres</td></tr> 513 * </table> 514 * 515 * @throws FactoryException if the math transform can not be created. 516 * @throws TransformException if the example point can not be transformed. 517 * 518 * @see ParameterizedTransformTest#testMercator1SP() 519 */ 520 @Test 521 public void testEPSG_3002() throws FactoryException, TransformException { 522 runProjectionTest(3002); 523 } 524 525 /** 526 * Tests the EPSG:3388 (<cite>Pulkovo 1942 / Caspian Sea Mercator</cite>) projected CRS. 527 * 528 * <table class="ogc"> 529 * <caption>CRS characteristics</caption> 530 * <tr><td>Projection method:</td> <td>Mercator (variant B)</td></tr> 531 * <tr><td>Prime meridian:</td> <td>Greenwich</td></tr> 532 * <tr><td>Source ordinates:</td> <td>(φ,λ) in degrees</td></tr> 533 * <tr><td>Output ordinates:</td> <td>(<var>y</var>,<var>x</var>) in metres - <strong>note the axis order!</strong></td></tr> 534 * </table> 535 * 536 * @throws FactoryException if the math transform can not be created. 537 * @throws TransformException if the example point can not be transformed. 538 * 539 * @see ParameterizedTransformTest#testMercator2SP() 540 */ 541 @Test 542 public void testEPSG_3388() throws FactoryException, TransformException { 543 swapxy = true; 544 runProjectionTest(3388); 545 } 546 547 /** 548 * Tests the EPSG:3857 (<cite>WGS 84 / Pseudo-Mercator</cite>) projected CRS. 549 * 550 * <table class="ogc"> 551 * <caption>CRS characteristics</caption> 552 * <tr><td>Projection method:</td> <td>Mercator Popular Visualisation Pseudo Mercator</td></tr> 553 * <tr><td>Prime meridian:</td> <td>Greenwich</td></tr> 554 * <tr><td>Source ordinates:</td> <td>(φ,λ) in degrees</td></tr> 555 * <tr><td>Output ordinates:</td> <td>(<var>x</var>,<var>y</var>) in metres</td></tr> 556 * </table> 557 * 558 * @throws FactoryException if the math transform can not be created. 559 * @throws TransformException if the example point can not be transformed. 560 * 561 * @see ParameterizedTransformTest#testPseudoMercator() 562 */ 563 @Test 564 public void testEPSG_3857() throws FactoryException, TransformException { 565 runProjectionTest(3857); 566 } 567 568 /** 569 * Tests the IGNF:MILLER (unofficial EPSG:310642901 code) projected CRS. 570 * 571 * <table class="ogc"> 572 * <caption>CRS characteristics</caption> 573 * <tr><td>Projection method:</td> <td>Miller</td></tr> 574 * <tr><td>Prime meridian:</td> <td>Greenwich</td></tr> 575 * <tr><td>Source ordinates:</td> <td>(φ,λ) in degrees</td></tr> 576 * <tr><td>Output ordinates:</td> <td>(<var>x</var>,<var>y</var>) in metres</td></tr> 577 * </table> 578 * 579 * @throws FactoryException if the math transform can not be created. 580 * @throws TransformException if the example point can not be transformed. 581 * 582 * @see ParameterizedTransformTest#testMiller() 583 */ 584 @Test 585 public void testIGNF_MILLER() throws FactoryException, TransformException { 586 runProjectionTest(310642901); 587 } 588 589 /** 590 * Tests the EPSG:29873 (<cite>Timbalai 1948 / RSO Borneo (m)</cite>) projected CRS. 591 * 592 * <table class="ogc"> 593 * <caption>CRS characteristics</caption> 594 * <tr><td>Projection method:</td> <td>Hotine Oblique Mercator (variant B)</td></tr> 595 * <tr><td>Prime meridian:</td> <td>Greenwich</td></tr> 596 * <tr><td>Source ordinates:</td> <td>(φ,λ) in degrees</td></tr> 597 * <tr><td>Output ordinates:</td> <td>(<var>x</var>,<var>y</var>) in metres</td></tr> 598 * </table> 599 * 600 * @throws FactoryException if the math transform can not be created. 601 * @throws TransformException if the example point can not be transformed. 602 * 603 * @see ParameterizedTransformTest#testHotineObliqueMercator() 604 */ 605 @Test 606 public void testEPSG_29873() throws FactoryException, TransformException { 607 runProjectionTest(29873); 608 } 609 610 /** 611 * Tests the EPSG:27700 (<cite>OSGB 1936 / British National Grid</cite>) projected CRS. 612 * 613 * <table class="ogc"> 614 * <caption>CRS characteristics</caption> 615 * <tr><td>Projection method:</td> <td>Transverse Mercator</td></tr> 616 * <tr><td>Prime meridian:</td> <td>Greenwich</td></tr> 617 * <tr><td>Source ordinates:</td> <td>(φ,λ) in degrees</td></tr> 618 * <tr><td>Output ordinates:</td> <td>(<var>x</var>,<var>y</var>) in metres</td></tr> 619 * </table> 620 * 621 * @throws FactoryException if the math transform can not be created. 622 * @throws TransformException if the example point can not be transformed. 623 * 624 * @see ParameterizedTransformTest#testTransverseMercator() 625 */ 626 @Test 627 public void testEPSG_27700() throws FactoryException, TransformException { 628 runProjectionTest(27700); 629 } 630 631 /** 632 * Tests the EPSG:2314 (<cite>Trinidad 1903 / Trinidad Grid</cite>) projected CRS. 633 * 634 * <table class="ogc"> 635 * <caption>CRS characteristics</caption> 636 * <tr><td>Projection method:</td> <td>Cassini-Soldner</td></tr> 637 * <tr><td>Prime meridian:</td> <td>Greenwich</td></tr> 638 * <tr><td>Source ordinates:</td> <td>(φ,λ) in degrees</td></tr> 639 * <tr><td>Output ordinates:</td> <td>(<var>x</var>,<var>y</var>) in Clarke's foot - <strong>note the units!</strong></td></tr> 640 * </table> 641 * 642 * @throws FactoryException if the math transform can not be created. 643 * @throws TransformException if the example point can not be transformed. 644 * 645 * @see ParameterizedTransformTest#testCassiniSoldner() 646 */ 647 @Test 648 public void testEPSG_2314() throws FactoryException, TransformException { 649 toLinearUnit = 1/PseudoEpsgFactory.CLARKE_KEET; 650 runProjectionTest(2314); 651 } 652 653 /** 654 * Tests the EPSG:24200 (<cite>JAD69 / Jamaica National Grid</cite>) projected CRS. 655 * 656 * <table class="ogc"> 657 * <caption>CRS characteristics</caption> 658 * <tr><td>Projection method:</td> <td>Lambert Conic Conformal (1SP)</td></tr> 659 * <tr><td>Prime meridian:</td> <td>Greenwich</td></tr> 660 * <tr><td>Source ordinates:</td> <td>(φ,λ) in degrees</td></tr> 661 * <tr><td>Output ordinates:</td> <td>(<var>x</var>,<var>y</var>) in metres</td></tr> 662 * </table> 663 * 664 * @throws FactoryException if the math transform can not be created. 665 * @throws TransformException if the example point can not be transformed. 666 * 667 * @see ParameterizedTransformTest#testLambertConicConformal1SP() 668 */ 669 @Test 670 public void testEPSG_24200() throws FactoryException, TransformException { 671 runProjectionTest(24200); 672 } 673 674 /** 675 * Tests the EPSG:32040 (<cite>NAD27 / Texas South Central</cite>) projected CRS. 676 * 677 * <table class="ogc"> 678 * <caption>CRS characteristics</caption> 679 * <tr><td>Projection method:</td> <td>Lambert Conic Conformal (2SP)</td></tr> 680 * <tr><td>Prime meridian:</td> <td>Greenwich</td></tr> 681 * <tr><td>Source ordinates:</td> <td>(φ,λ) in degrees</td></tr> 682 * <tr><td>Output ordinates:</td> <td>(<var>x</var>,<var>y</var>) in US feet - <strong>note the units!</strong></td></tr> 683 * </table> 684 * 685 * @throws FactoryException if the math transform can not be created. 686 * @throws TransformException if the example point can not be transformed. 687 * 688 * @see ParameterizedTransformTest#testLambertConicConformal2SP() 689 */ 690 @Test 691 public void testEPSG_32040() throws FactoryException, TransformException { 692 toLinearUnit = PseudoEpsgFactory.R_US_FEET; 693 runProjectionTest(32040); 694 } 695 696 /** 697 * Tests the EPSG:31300 (<cite>Belge 1972 / Belge Lambert 72</cite>) projected CRS. 698 * 699 * <table class="ogc"> 700 * <caption>CRS characteristics</caption> 701 * <tr><td>Projection method:</td> <td>Lambert Conic Conformal (2SP Belgium)</td></tr> 702 * <tr><td>Prime meridian:</td> <td>Greenwich</td></tr> 703 * <tr><td>Source ordinates:</td> <td>(φ,λ) in degrees</td></tr> 704 * <tr><td>Output ordinates:</td> <td>(<var>x</var>,<var>y</var>) in metres</td></tr> 705 * </table> 706 * 707 * @throws FactoryException if the math transform can not be created. 708 * @throws TransformException if the example point can not be transformed. 709 * 710 * @see ParameterizedTransformTest#testLambertConicConformalBelgium() 711 */ 712 @Test 713 public void testEPSG_31300() throws FactoryException, TransformException { 714 runProjectionTest(31300); 715 } 716 717 /** 718 * Tests the EPSG:3035 (<cite>ETRS89 / LAEA Europe</cite>) projected CRS. 719 * 720 * <table class="ogc"> 721 * <caption>CRS characteristics</caption> 722 * <tr><td>Projection method:</td> <td>Lambert Azimuthal Equal Area</td></tr> 723 * <tr><td>Prime meridian:</td> <td>Greenwich</td></tr> 724 * <tr><td>Source ordinates:</td> <td>(φ,λ) in degrees</td></tr> 725 * <tr><td>Output ordinates:</td> <td>(<var>y</var>,<var>x</var>) in metres - <strong>note the axis order!</strong></td></tr> 726 * </table> 727 * 728 * @throws FactoryException if the math transform can not be created. 729 * @throws TransformException if the example point can not be transformed. 730 * 731 * @see ParameterizedTransformTest#testLambertAzimuthalEqualArea() 732 */ 733 @Test 734 public void testEPSG_3035() throws FactoryException, TransformException { 735 swapxy = true; 736 runProjectionTest(3035); 737 } 738 739 /** 740 * Tests the EPSG:5041 (<cite>WGS 84 / UPS North (E,N)</cite>) projected CRS. 741 * 742 * <table class="ogc"> 743 * <caption>CRS characteristics</caption> 744 * <tr><td>Projection method:</td> <td>Polar Stereographic (variant A)</td></tr> 745 * <tr><td>Prime meridian:</td> <td>Greenwich</td></tr> 746 * <tr><td>Source ordinates:</td> <td>(φ,λ) in degrees</td></tr> 747 * <tr><td>Output ordinates:</td> <td>(<var>x</var>,<var>y</var>) in metres</td></tr> 748 * </table> 749 * 750 * @throws FactoryException if the math transform can not be created. 751 * @throws TransformException if the example point can not be transformed. 752 * 753 * @see ParameterizedTransformTest#testPolarStereographicA() 754 */ 755 @Test 756 public void testEPSG_5041() throws FactoryException, TransformException { 757 isPolar = true; 758 runProjectionTest(5041); 759 } 760 761 /** 762 * Tests the EPSG:32661 (<cite>WGS 84 / UPS North (N,E)</cite>) projected CRS. 763 * This CRS is identical to EPSG:5041 except for axis order. 764 * 765 * <table class="ogc"> 766 * <caption>CRS characteristics</caption> 767 * <tr><td>Projection method:</td> <td>Polar Stereographic (variant A)</td></tr> 768 * <tr><td>Prime meridian:</td> <td>Greenwich</td></tr> 769 * <tr><td>Source ordinates:</td> <td>(φ,λ) in degrees</td></tr> 770 * <tr><td>Output ordinates:</td> <td>(<var>y</var>,<var>x</var>) in metres - <strong>note the axis order!</strong></td></tr> 771 * </table> 772 * 773 * @throws FactoryException if the math transform can not be created. 774 * @throws TransformException if the example point can not be transformed. 775 * 776 * @see ParameterizedTransformTest#testPolarStereographicA() 777 */ 778 @Test 779 public void testEPSG_32661() throws FactoryException, TransformException { 780 isPolar = true; 781 swapxy = true; 782 runProjectionTest(32661); 783 } 784 785 /** 786 * Tests the EPSG:3032 (<cite>WGS 84 / Australian Antarctic Polar Stereographic</cite>) projected CRS. 787 * 788 * <table class="ogc"> 789 * <caption>CRS characteristics</caption> 790 * <tr><td>Projection method:</td> <td>Polar Stereographic (variant B)</td></tr> 791 * <tr><td>Prime meridian:</td> <td>Greenwich</td></tr> 792 * <tr><td>Source ordinates:</td> <td>(φ,λ) in degrees</td></tr> 793 * <tr><td>Output ordinates:</td> <td>(<var>x</var>,<var>y</var>) in metres</td></tr> 794 * </table> 795 * 796 * @throws FactoryException if the math transform can not be created. 797 * @throws TransformException if the example point can not be transformed. 798 * 799 * @see ParameterizedTransformTest#testPolarStereographicB() 800 */ 801 @Test 802 public void testEPSG_3032() throws FactoryException, TransformException { 803 isPolar = true; 804 runProjectionTest(3032); 805 } 806 807 /** 808 * Tests the EPSG:28992 (<cite>Amersfoort / RD New</cite>) projected CRS. 809 * 810 * <table class="ogc"> 811 * <caption>CRS characteristics</caption> 812 * <tr><td>Projection method:</td> <td>Oblique Stereographic</td></tr> 813 * <tr><td>Prime meridian:</td> <td>Greenwich</td></tr> 814 * <tr><td>Source ordinates:</td> <td>(φ,λ) in degrees</td></tr> 815 * <tr><td>Output ordinates:</td> <td>(<var>x</var>,<var>y</var>) in metres</td></tr> 816 * </table> 817 * 818 * @throws FactoryException if the math transform can not be created. 819 * @throws TransformException if the example point can not be transformed. 820 * 821 * @see ParameterizedTransformTest#testObliqueStereographic() 822 */ 823 @Test 824 public void testEPSG_28992() throws FactoryException, TransformException { 825 runProjectionTest(28992); 826 } 827 828 /** 829 * Tests the EPSG:2065 (<cite>CRS S-JTSK (Ferro) / Krovak</cite>) projected CRS. 830 * 831 * <table class="ogc"> 832 * <caption>CRS characteristics</caption> 833 * <tr><td>Projection method:</td> <td>Krovak</td></tr> 834 * <tr><td>Prime meridian:</td> <td>Ferro <strong>(17°40'W from Greenwich)</strong></td></tr> 835 * <tr><td>Source ordinates:</td> <td>(φ,λ) in degrees</td></tr> 836 * <tr><td>Output ordinates:</td> <td>(<var>y</var>,<var>x</var>) in metres, <strong>south oriented (S,W)</strong></td></tr> 837 * </table> 838 * 839 * @throws FactoryException if the math transform can not be created. 840 * @throws TransformException if the example point can not be transformed. 841 * 842 * @see ParameterizedTransformTest#testKrovak() 843 */ 844 @Test 845 public void testEPSG_2065() throws FactoryException, TransformException { 846 swapxy = true; 847 flipxy = true; 848 primeMeridian = -(17 + 40.0/60); 849 runProjectionTest(2065); 850 } 851}