001/* 002 * GeoAPI - Java interfaces for OGC/ISO standards 003 * http://www.geoapi.org 004 * 005 * Copyright (C) 2014-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.wkt; 033 034import java.util.Date; 035import java.util.List; 036import javax.measure.Unit; 037import javax.measure.quantity.Angle; 038import javax.measure.quantity.Length; 039import javax.measure.quantity.Dimensionless; 040 041import org.opengis.util.Factory; 042import org.opengis.util.FactoryException; 043import org.opengis.referencing.IdentifiedObject; 044import org.opengis.referencing.crs.*; 045import org.opengis.referencing.cs.*; 046import org.opengis.referencing.datum.*; 047import org.opengis.parameter.ParameterValueGroup; 048import org.opengis.metadata.extent.Extent; 049import org.opengis.test.referencing.ReferencingTestCase; 050import org.opengis.test.Configuration; 051import org.junit.runner.RunWith; 052import org.junit.runners.Parameterized; 053import org.junit.Test; 054 055import static java.lang.Double.NaN; 056import static org.junit.Assume.assumeTrue; 057import static org.opengis.test.Assert.*; 058import static org.opengis.referencing.cs.AxisDirection.*; 059 060 061/** 062 * Tests the Well-Known Text (WKT) parser of Coordinate Reference System (CRS) objects. 063 * For running this test, vendors need to implement the {@link CRSFactory#createFromWKT(String)} method. 064 * That method will be given various WKT strings from the 065 * <a href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html">OGC 12-063r5 — 066 * Well-known text representation of coordinate reference systems</a> specification. 067 * The object returned by {@code createFromWKT(String)} will be checked for the following properties: 068 * 069 * <ul> 070 * <li>{@link IdentifiedObject#getName()} and {@link IdentifiedObject#getIdentifiers() getIdentifiers()} on the CRS and the datum</li> 071 * <li>{@link Ellipsoid#getSemiMajorAxis()} and {@link Ellipsoid#getInverseFlattening() getInverseFlattening()}</li> 072 * <li>{@link PrimeMeridian#getGreenwichLongitude()}</li> 073 * <li>{@link CoordinateSystem#getDimension()}</li> 074 * <li>{@link CoordinateSystemAxis#getAbbreviation()} when they were explicitly given in the WKT and do not need transliteration.</li> 075 * <li>{@link CoordinateSystemAxis#getDirection()} and {@link CoordinateSystemAxis#getUnit() getUnit()}</li> 076 * <li>{@link CoordinateReferenceSystem#getScope()} (optional – null allowed)</li> 077 * <li>{@link CoordinateReferenceSystem#getDomainOfValidity()} (optional – null allowed)</li> 078 * <li>{@link CoordinateReferenceSystem#getRemarks()} (optional – null allowed)</li> 079 * </ul> 080 * 081 * <div class="note"><b>Usage example:</b> 082 * in order to specify their factories and run the tests in a JUnit framework, implementors can 083 * define a subclass in their own test suite as in the example below: 084 * 085 * <blockquote><pre>import org.junit.runner.RunWith; 086 *import org.junit.runners.JUnit4; 087 *import org.opengis.test.wkt.CRSParserTest; 088 * 089 *@RunWith(JUnit4.class) 090 *public class MyTest extends CRSParserTest { 091 * public MyTest() { 092 * super(new MyCRSFactory()); 093 * } 094 *}</pre></blockquote> 095 * </div> 096 * 097 * @author Martin Desruisseaux (Geomatys) 098 * @author Johann Sorel (Geomatys) 099 * @version 3.1 100 * @since 3.1 101 * 102 * @see <a href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html">WKT 2 specification</a> 103 */ 104@RunWith(Parameterized.class) 105public strictfp class CRSParserTest extends ReferencingTestCase { 106 /** 107 * The factory to use for parsing WKT strings. The {@link CRSFactory#createFromWKT(String)} method 108 * of this factory will be invoked for each test defined in this {@code CRSParserTest} class. 109 */ 110 protected final CRSFactory crsFactory; 111 112 /** 113 * The instance returned by {@link CRSFactory#createFromWKT(String)} after parsing the WKT. 114 * Subclasses can use this field if they wish to verify additional properties after the 115 * verifications done by this {@code CRSParserTest} class. 116 */ 117 protected CoordinateReferenceSystem object; 118 119 /** 120 * {@code true} if the test methods can invoke a <code>{@linkplain #validators validators}.validate(…)}</code> 121 * method after parsing. Implementors can set this flag to {@code false} if their WKT parser is known to create 122 * CRS objects that differ from the ISO 19111 model. One of the main reasons for disabling validation is because 123 * the axis names specified by ISO 19162 differ from the axis names specified by ISO 19111. 124 */ 125 protected boolean isValidationEnabled; 126 127 /** 128 * Returns a default set of factories to use for running the tests. Those factories are given 129 * in arguments to the constructor when this test class is instantiated directly by JUnit (for 130 * example as a {@linkplain org.junit.runners.Suite.SuiteClasses suite} element), instead than 131 * sub-classed by the implementor. The factories are fetched as documented in the 132 * {@link #factories(Class[])} javadoc. 133 * 134 * @return the default set of arguments to be given to the {@code ObjectFactoryTest} constructor. 135 */ 136 @Parameterized.Parameters 137 @SuppressWarnings("unchecked") 138 public static List<Factory[]> factories() { 139 return factories(CRSFactory.class); 140 } 141 142 /** 143 * Creates a new test using the given factory. 144 * 145 * @param crsFactory factory for parsing {@link CoordinateReferenceSystem} instances. 146 */ 147 public CRSParserTest(final CRSFactory crsFactory) { 148 super(crsFactory); 149 this.crsFactory = crsFactory; 150 @SuppressWarnings("unchecked") 151 final boolean[] isEnabled = getEnabledFlags( 152 Configuration.Key.isValidationEnabled); 153 isValidationEnabled = isEnabled[0]; 154 } 155 156 /** 157 * Returns information about the configuration of the test which has been run. 158 * This method returns a map containing: 159 * 160 * <ul> 161 * <li>All the following values associated to the {@link org.opengis.test.Configuration.Key} of the same name: 162 * <ul> 163 * <li>{@link #isValidationEnabled}</li> 164 * <li>{@link #crsFactory}</li> 165 * </ul> 166 * </li> 167 * </ul> 168 * 169 * @return {@inheritDoc} 170 */ 171 @Override 172 public Configuration configuration() { 173 final Configuration op = super.configuration(); 174 assertNull(op.put(Configuration.Key.isValidationEnabled, isValidationEnabled)); 175 assertNull(op.put(Configuration.Key.crsFactory, crsFactory)); 176 return op; 177 } 178 179 /** 180 * Asserts that the given datum has the expected name. 181 * 182 * @param datum the datum to verify. 183 * @param name the string representation of the expected name (ignoring code space). 184 */ 185 private static void verifyDatum(final Datum datum, final String name) { 186 assertNotNull("SingleCRS.getDatum()", datum); 187 assertEquals("datum.getName().getCode()", name, datum.getName().getCode()); 188 } 189 190 /** 191 * Compares the abbreviations of coordinate system axes against the expected values. 192 * The comparison is case-sensitive, e.g. <var>h</var> (ellipsoidal height) is not the same than 193 * <var>H</var> (gravity-related height). 194 * 195 * <p>The GeoAPI conformance tests invoke this method only for abbreviations that should not need transliteration. 196 * For example the GeoAPI tests do not invoke this method for geodetic latitude and longitude axes, because some 197 * implementations may keep the Greek letters φ and λ as specified in ISO 19111 while other implementations may 198 * transliterate those Greek letters to the <var>P</var> and <var>L</var> Latin letters.</p> 199 * 200 * @param cs the coordinate system to verify. 201 * @param abbreviations the expected abbreviations. Null elements are considered unrestricted. 202 */ 203 private static void verifyAxisAbbreviations(final CoordinateSystem cs, final String... abbreviations) { 204 final int dimension = Math.min(abbreviations.length, cs.getDimension()); 205 for (int i=0; i<dimension; i++) { 206 final String expected = abbreviations[i]; 207 if (expected != null) { 208 assertEquals("CoordinateSystemAxis.getAbbreviation()", expected, cs.getAxis(i).getAbbreviation()); 209 } 210 } 211 } 212 213 /** 214 * Asserts the the given character sequence is either null or equals to the given value. 215 * This is used for optional elements like remarks. 216 * 217 * @param property the property being tested, for producing a message in case of assertion failure. 218 * @param expected the expected value. 219 * @param actual the actual value. 220 */ 221 private static void assertNullOrEquals(final String property, final String expected, final CharSequence actual) { 222 if (actual != null) { 223 assertEquals(property, expected, actual.toString()); 224 } 225 } 226 227 /** 228 * Pre-process the WKT string before parsing. 229 * The default implementation performs the following changes for strict ISO 19162 compliance: 230 * 231 * <ul> 232 * <li>Double the straight quotation marks {@code "} (U+0022).</li> 233 * <li>Replace the left quotation marks {@code “} (U+201C) and right quotation marks {@code ”} (U+201D) 234 * by straight quotation marks {@code "} (U+0022).</li> 235 * </ul> 236 * 237 * Subclasses can override this method if they wish to perform additional pre-processing. 238 * The use of left and right quotation marks is intended to make easier for subclasses to 239 * identify the beginning and end of quoted texts. 240 * 241 * @param wkt the Well-Known Text to pre-process. 242 * @return the Well-Known Text to parse. 243 */ 244 protected String preprocessWKT(final String wkt) { 245 final StringBuilder b = new StringBuilder(wkt); 246 for (int i = wkt.lastIndexOf('"'); i >= 0; i = wkt.lastIndexOf('"', i-1)) { 247 b.insert(i, '"'); 248 } 249 for (int i=0; i<b.length(); i++) { 250 final char c = b.charAt(i); 251 if (c == '“' || c == '”') { 252 b.setCharAt(i, '"'); 253 } 254 } 255 return b.toString(); 256 } 257 258 /** 259 * Parses the given WKT. 260 * 261 * @param type the expected object type. 262 * @param text the WKT string to parse. 263 * @return the parsed object. 264 * @throws FactoryException if an error occurred during the WKT parsing. 265 */ 266 private <T extends CoordinateReferenceSystem> T parse(final Class<T> type, final String text) throws FactoryException { 267 assumeTrue("No CRSFactory.", crsFactory != null); 268 object = crsFactory.createFromWKT(preprocessWKT(text)); 269 assertInstanceOf("CRSFactory.createFromWKT(String)", type, object); 270 return type.cast(object); 271 } 272 273 /** 274 * Parses a three-dimensional geodetic CRS. 275 * The WKT parsed by this test is (except for quote characters): 276 * 277 * <blockquote><pre>GEODCRS[“WGS 84”, 278 * DATUM[“World Geodetic System 1984”, 279 * ELLIPSOID[“WGS 84”, 6378137, 298.257223563, 280 * LENGTHUNIT[“metre”,1.0]]], 281 * CS[ellipsoidal,3], 282 * AXIS[“(lat)”,north,ANGLEUNIT[“degree”,0.0174532925199433]], 283 * AXIS[“(lon)”,east,ANGLEUNIT[“degree”,0.0174532925199433]], 284 * AXIS[“ellipsoidal height (h)”,up,LENGTHUNIT[“metre”,1.0]]]</pre></blockquote> 285 * 286 * @throws FactoryException if an error occurred during the WKT parsing. 287 * 288 * @see <a href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html#56">OGC 12-063r5 §8.4 example 2</a> 289 */ 290 @Test 291 public void testGeographic3D() throws FactoryException { 292 final GeodeticCRS crs = parse(GeodeticCRS.class, 293 "GEODCRS[“WGS 84”,\n" + 294 " DATUM[“World Geodetic System 1984”,\n" + 295 " ELLIPSOID[“WGS 84”, 6378137, 298.257223563,\n" + 296 " LENGTHUNIT[“metre”,1.0]]],\n" + 297 " CS[ellipsoidal,3],\n" + 298 " AXIS[“(lat)”,north,ANGLEUNIT[“degree”,0.0174532925199433]],\n" + 299 " AXIS[“(lon)”,east,ANGLEUNIT[“degree”,0.0174532925199433]],\n" + 300 " AXIS[“ellipsoidal height (h)”,up,LENGTHUNIT[“metre”,1.0]]]"); 301 302 if (isValidationEnabled) { 303 configurationTip = Configuration.Key.isValidationEnabled; 304 validators.validate(crs); 305 configurationTip = null; 306 } 307 verifyWGS84(crs, true, units.degree(), units.metre()); 308 verifyAxisAbbreviations(crs.getCoordinateSystem(), null, null, "h"); 309 } 310 311 /** 312 * Verifies the CRS name, datum and axes for {@code GEODCRS[“WGS 84”]}. 313 * This method does not verify axis abbreviations. 314 * 315 * @param crs the Coordinate Reference System which is expected to be WGS 84. 316 * @param is3D whether the CRS contains an ellipsoidal height axis. 317 * @param degree value of {@link org.opengis.test.Units#degree()} (for fetching it only once per test). 318 * @param metre value of {@link org.opengis.test.Units#metre()} (for fetching it only once per test). 319 */ 320 private void verifyWGS84(final GeodeticCRS crs, final boolean is3D, 321 final Unit<Angle> degree, final Unit<Length> metre) 322 { 323 final GeodeticDatum datum; 324 final AxisDirection[] directions; 325 326 verifyIdentification (crs, "WGS 84", null); 327 verifyDatum (datum = crs.getDatum(), "World Geodetic System 1984"); 328 verifyFlattenedSphere(datum.getEllipsoid(), "WGS 84", 6378137, 298.257223563, metre); 329 verifyPrimeMeridian (datum.getPrimeMeridian(), null, 0, degree); 330 directions = new AxisDirection[is3D ? 3 : 2]; 331 directions[0] = NORTH; 332 directions[1] = EAST; 333 if (is3D) { 334 directions[2] = UP; 335 } 336 verifyCoordinateSystem(crs.getCoordinateSystem(), EllipsoidalCS.class, directions, degree, degree, metre); 337 } 338 339 /** 340 * Parses a geodetic CRS which contain a remark written using non-ASCII characters. 341 * The WKT parsed by this test is (except for quote characters): 342 * 343 * <blockquote><pre>GEODCRS[“S-95”, 344 * DATUM[“Pulkovo 1995”, 345 * ELLIPSOID[“Krassowsky 1940”, 6378245, 298.3, 346 * LENGTHUNIT[“metre”,1.0]]], 347 * CS[ellipsoidal,2], 348 * AXIS[“latitude”,north,ORDER[1]], 349 * AXIS[“longitude”,east,ORDER[2]], 350 * ANGLEUNIT[“degree”,0.0174532925199433], 351 * REMARK[“Система Геодеэических Координвт года 1995(СК-95)”]]</pre></blockquote> 352 * 353 * @throws FactoryException if an error occurred during the WKT parsing. 354 * 355 * @see <a href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html#34">OGC 12-063r5 §7.3.5 example 3</a> 356 */ 357 @Test 358 public void testGeographicWithUnicode() throws FactoryException { 359 final GeodeticCRS crs = parse(GeodeticCRS.class, 360 "GEODCRS[“S-95”,\n" + 361 " DATUM[“Pulkovo 1995”,\n" + 362 " ELLIPSOID[“Krassowsky 1940”, 6378245, 298.3,\n" + 363 " LENGTHUNIT[“metre”,1.0]]],\n" + 364 " CS[ellipsoidal,2],\n" + 365 " AXIS[“latitude”,north,ORDER[1]],\n" + 366 " AXIS[“longitude”,east,ORDER[2]],\n" + 367 " ANGLEUNIT[“degree”,0.0174532925199433],\n" + 368 " REMARK[“Система Геодеэических Координвт года 1995(СК-95)”]]"); 369 370 if (isValidationEnabled) { 371 configurationTip = Configuration.Key.isValidationEnabled; 372 validators.validate(crs); 373 configurationTip = null; 374 } 375 final Unit<Angle> degree = units.degree(); 376 final Unit<Length> metre = units.metre(); 377 final GeodeticDatum datum; 378 379 verifyIdentification (crs, "S-95", null); 380 verifyDatum (datum = crs.getDatum(), "Pulkovo 1995"); 381 verifyFlattenedSphere (datum.getEllipsoid(), "Krassowsky 1940", 6378245, 298.3, metre); 382 verifyPrimeMeridian (datum.getPrimeMeridian(), null, 0, degree); 383 verifyCoordinateSystem(crs.getCoordinateSystem(), EllipsoidalCS.class, new AxisDirection[] {NORTH,EAST}, degree); 384 assertNullOrEquals("remark", "Система Геодеэических Координвт года 1995(СК-95)", crs.getRemarks()); 385 } 386 387 /** 388 * Parses a geodetic CRS which contains a remark and an identifier. 389 * The WKT parsed by this test is (except for quote characters): 390 * 391 * <blockquote><pre>GEODCRS[“NAD83”, 392 * DATUM[“North American Datum 1983”, 393 * ELLIPSOID[“GRS 1980”, 6378137, 298.257222101, LENGTHUNIT[“metre”,1.0]]], 394 * CS[ellipsoidal,2], 395 * AXIS[“latitude”,north], 396 * AXIS[“longitude”,east], 397 * ANGLEUNIT[“degree”,0.0174532925199433], 398 * ID[“EPSG”,4269], 399 * REMARK[“1986 realisation”]]</pre></blockquote> 400 * 401 * @throws FactoryException if an error occurred during the WKT parsing. 402 * 403 * @see <a href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html#56">OGC 12-063r5 §8.4 example 3</a> 404 */ 405 @Test 406 public void testGeographicWithIdentifier() throws FactoryException { 407 final GeodeticCRS crs = parse(GeodeticCRS.class, 408 "GEODCRS[“NAD83”,\n" + 409 " DATUM[“North American Datum 1983”,\n" + 410 " ELLIPSOID[“GRS 1980”, 6378137, 298.257222101, LENGTHUNIT[“metre”,1.0]]],\n" + 411 " CS[ellipsoidal,2],\n" + 412 " AXIS[“latitude”,north],\n" + 413 " AXIS[“longitude”,east],\n" + 414 " ANGLEUNIT[“degree”,0.0174532925199433],\n" + 415 " ID[“EPSG”,4269],\n" + 416 " REMARK[“1986 realisation”]]"); 417 418 if (isValidationEnabled) { 419 configurationTip = Configuration.Key.isValidationEnabled; 420 validators.validate(crs); 421 configurationTip = null; 422 } 423 verifyNAD23(crs, true, units.degree(), units.metre()); 424 assertNullOrEquals("remark", "1986 realisation", crs.getRemarks()); 425 } 426 427 /** 428 * Verifies the CRS name, datum and axes for {@code GEODCRS[“NAD83”]}. 429 * This method does not verify the remark, since it is not included in the components of {@code COMPOUNDCRS[…]}. 430 * 431 * @param degree value of {@link org.opengis.test.Units#degree()} (for fetching it only once per test). 432 * @param metre value of {@link org.opengis.test.Units#metre()} (for fetching it only once per test). 433 */ 434 private void verifyNAD23(final GeodeticCRS crs, final boolean hasIdentifier, 435 final Unit<Angle> degree, final Unit<Length> metre) 436 { 437 final GeodeticDatum datum; 438 439 verifyIdentification (crs, "NAD83", hasIdentifier ? "4269" : null); 440 verifyDatum (datum = crs.getDatum(), "North American Datum 1983"); 441 verifyFlattenedSphere (datum.getEllipsoid(), "GRS 1980", 6378137, 298.257222101, metre); 442 verifyPrimeMeridian (datum.getPrimeMeridian(), null, 0, degree); 443 verifyCoordinateSystem(crs.getCoordinateSystem(), EllipsoidalCS.class, new AxisDirection[] {NORTH,EAST}, degree); 444 } 445 446 /** 447 * Parses a geodetic CRS with a prime meridian other than Greenwich and all angular units in grads. 448 * The WKT parsed by this test is (except for quote characters): 449 * 450 * <blockquote><pre>GEODCRS[“NTF (Paris)”, 451 * DATUM[“Nouvelle Triangulation Francaise”, 452 * ELLIPSOID[“Clarke 1880 (IGN)”, 6378249.2, 293.4660213]], 453 * PRIMEM[“Paris”,2.5969213], 454 * CS[ellipsoidal,2], 455 * AXIS[“latitude”,north,ORDER[1]], 456 * AXIS[“longitude”,east,ORDER[2]], 457 * ANGLEUNIT[“grad”,0.015707963267949], 458 * REMARK[“Nouvelle Triangulation Française”]]</pre></blockquote> 459 * 460 * @throws FactoryException if an error occurred during the WKT parsing. 461 * 462 * @see <a href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html#56">OGC 12-063r5 §8.4 example 4</a> 463 */ 464 @Test 465 public void testGeographicWithGradUnits() throws FactoryException { 466 final GeodeticCRS crs = parse(GeodeticCRS.class, 467 "GEODCRS[“NTF (Paris)”,\n" + 468 " DATUM[“Nouvelle Triangulation Francaise”,\n" + 469 " ELLIPSOID[“Clarke 1880 (IGN)”, 6378249.2, 293.4660213]],\n" + 470 " PRIMEM[“Paris”,2.5969213],\n" + 471 " CS[ellipsoidal,2],\n" + 472 " AXIS[“latitude”,north,ORDER[1]],\n" + 473 " AXIS[“longitude”,east,ORDER[2]],\n" + 474 " ANGLEUNIT[“grad”,0.015707963267949],\n" + 475 " REMARK[“Nouvelle Triangulation Française”]]"); 476 477 if (isValidationEnabled) { 478 configurationTip = Configuration.Key.isValidationEnabled; 479 validators.validate(crs); 480 configurationTip = null; 481 } 482 final Unit<Angle> grad = units.grad(); 483 final Unit<Length> metre = units.metre(); 484 final GeodeticDatum datum; 485 486 verifyIdentification (crs, "NTF (Paris)", null); 487 verifyDatum (datum = crs.getDatum(), "Nouvelle Triangulation Francaise"); 488 verifyFlattenedSphere (datum.getEllipsoid(), "Clarke 1880 (IGN)", 6378249.2, 293.4660213, metre); 489 verifyPrimeMeridian (datum.getPrimeMeridian(), "Paris", 2.5969213, grad); 490 verifyCoordinateSystem(crs.getCoordinateSystem(), EllipsoidalCS.class, new AxisDirection[] {NORTH,EAST}, grad); 491 assertNullOrEquals("remark", "Nouvelle Triangulation Française", crs.getRemarks()); 492 } 493 494 /** 495 * Parses a geodetic CRS with Cartesian coordinate system. 496 * The WKT parsed by this test is (except for quote characters): 497 * 498 * <blockquote><pre>GEODETICCRS[“JGD2000”, 499 * DATUM[“Japanese Geodetic Datum 2000”, 500 * ELLIPSOID[“GRS 1980”, 6378137, 298.257222101]], 501 * CS[Cartesian,3], 502 * AXIS[“(X)”,geocentricX], 503 * AXIS[“(Y)”,geocentricY], 504 * AXIS[“(Z)”,geocentricZ], 505 * LENGTHUNIT[“metre”,1.0], 506 * SCOPE[“Geodesy, topographic mapping and cadastre”], 507 * AREA[“Japan”], 508 * BBOX[17.09,122.38,46.05,157.64], 509 * TIMEEXTENT[2002-04-01,2011-10-21], 510 * ID[“EPSG”,4946,URI[“urn:ogc:def:crs:EPSG::4946”]], 511 * REMARK[“注:JGD2000ジオセントリックは現在JGD2011に代わりました。”]]</pre></blockquote> 512 * 513 * @throws FactoryException if an error occurred during the WKT parsing. 514 * 515 * @see <a href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html#56">OGC 12-063r5 §8.4 example 1</a> 516 */ 517 @Test 518 public void testGeocentric() throws FactoryException { 519 final GeodeticCRS crs = parse(GeodeticCRS.class, 520 "GEODETICCRS[“JGD2000”,\n" + 521 " DATUM[“Japanese Geodetic Datum 2000”,\n" + 522 " ELLIPSOID[“GRS 1980”, 6378137, 298.257222101]],\n" + 523 " CS[Cartesian,3],\n" + 524 " AXIS[“(X)”,geocentricX],\n" + 525 " AXIS[“(Y)”,geocentricY],\n" + 526 " AXIS[“(Z)”,geocentricZ],\n" + 527 " LENGTHUNIT[“metre”,1.0],\n" + 528 " SCOPE[“Geodesy, topographic mapping and cadastre”],\n" + 529 " AREA[“Japan”],\n" + 530 " BBOX[17.09,122.38,46.05,157.64],\n" + 531 " TIMEEXTENT[2002-04-01,2011-10-21],\n" + 532 " ID[“EPSG”,4946,URI[“urn:ogc:def:crs:EPSG::4946”]],\n" + 533 " REMARK[“注:JGD2000ジオセントリックは現在JGD2011に代わりました。”]]"); 534 535 if (isValidationEnabled) { 536 configurationTip = Configuration.Key.isValidationEnabled; 537 validators.validate(crs); 538 configurationTip = null; 539 } 540 final Unit<Angle> degree = units.degree(); 541 final Unit<Length> metre = units.metre(); 542 final GeodeticDatum datum; 543 final CoordinateSystem cs; 544 final Extent extent; 545 546 verifyIdentification (crs, "JGD2000", "4946"); 547 verifyDatum (datum = crs.getDatum(), "Japanese Geodetic Datum 2000"); 548 verifyFlattenedSphere (datum.getEllipsoid(), "GRS 1980", 6378137, 298.257222101, metre); 549 verifyPrimeMeridian (datum.getPrimeMeridian(), null, 0, degree); 550 verifyAxisAbbreviations(cs = crs.getCoordinateSystem(), "X", "Y", "Z"); 551 verifyCoordinateSystem (cs, CartesianCS.class, new AxisDirection[] {GEOCENTRIC_X, GEOCENTRIC_Y, GEOCENTRIC_Z}, metre); 552 verifyGeographicExtent (extent = crs.getDomainOfValidity(), "Japan", 17.09, 122.38, 46.05, 157.64); 553 verifyTimeExtent (extent, new Date(1017619200000L), new Date(1319155200000L), 1); 554 assertNullOrEquals("scope", "Geodesy, topographic mapping and cadastre", crs.getScope()); 555 assertNullOrEquals("remark", "注:JGD2000ジオセントリックは現在JGD2011に代わりました。", crs.getRemarks()); 556 } 557 558 /** 559 * Parses a projected CRS with linear units in metres and axes in (<var>Y</var>,<var>X</var>) order. 560 * The WKT parsed by this test is (except for quote characters): 561 * 562 * <blockquote><pre>PROJCRS[“ETRS89 Lambert Azimuthal Equal Area CRS”, 563 * BASEGEODCRS[“ETRS89”, 564 * DATUM[“ETRS89”, 565 * ELLIPSOID[“GRS 80”, 6378137, 298.257222101, LENGTHUNIT[“metre”,1.0]]]], 566 * CONVERSION[“LAEA”, 567 * METHOD[“Lambert Azimuthal Equal Area”,ID[“EPSG”,9820]], 568 * PARAMETER[“Latitude of natural origin”, 52.0, ANGLEUNIT[“degree”,0.0174532925199433]], 569 * PARAMETER[“Longitude of natural origin”, 10.0, ANGLEUNIT[“degree”,0.0174532925199433]], 570 * PARAMETER[“False easting”, 4321000.0, LENGTHUNIT[“metre”,1.0]], 571 * PARAMETER[“False northing”, 3210000.0, LENGTHUNIT[“metre”,1.0]]], 572 * CS[Cartesian,2], 573 * AXIS[“(Y)”,north,ORDER[1]], 574 * AXIS[“(X)”,east,ORDER[2]], 575 * LENGTHUNIT[“metre”,1.0], 576 * SCOPE[“Description of a purpose”], 577 * AREA[“An area description”], 578 * ID[“EuroGeographics”,“ETRS-LAEA”]]</pre></blockquote> 579 * 580 * @throws FactoryException if an error occurred during the WKT parsing. 581 * 582 * @see <a href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html#68">OGC 12-063r5 §9.5 example 1</a> 583 */ 584 @Test 585 public void testProjectedYX() throws FactoryException { 586 final ProjectedCRS crs = parse(ProjectedCRS.class, 587 "PROJCRS[“ETRS89 Lambert Azimuthal Equal Area CRS”,\n" + 588 " BASEGEODCRS[“ETRS89”,\n" + 589 " DATUM[“ETRS89”,\n" + 590 " ELLIPSOID[“GRS 80”, 6378137, 298.257222101, LENGTHUNIT[“metre”,1.0]]]],\n" + 591 " CONVERSION[“LAEA”,\n" + 592 " METHOD[“Lambert Azimuthal Equal Area”,ID[“EPSG”,9820]],\n" + 593 " PARAMETER[“Latitude of natural origin”, 52.0, ANGLEUNIT[“degree”,0.0174532925199433]],\n" + 594 " PARAMETER[“Longitude of natural origin”, 10.0, ANGLEUNIT[“degree”,0.0174532925199433]],\n" + 595 " PARAMETER[“False easting”, 4321000.0, LENGTHUNIT[“metre”,1.0]],\n" + 596 " PARAMETER[“False northing”, 3210000.0, LENGTHUNIT[“metre”,1.0]]],\n" + 597 " CS[Cartesian,2],\n" + 598 " AXIS[“(Y)”,north,ORDER[1]],\n" + 599 " AXIS[“(X)”,east,ORDER[2]],\n" + 600 " LENGTHUNIT[“metre”,1.0],\n" + 601 " SCOPE[“Description of a purpose”],\n" + 602 " AREA[“An area description”],\n" + 603 " ID[“EuroGeographics”,“ETRS-LAEA”]]"); 604 605 if (isValidationEnabled) { 606 configurationTip = Configuration.Key.isValidationEnabled; 607 validators.validate(crs); 608 configurationTip = null; 609 } 610 final Unit<Angle> degree = units.degree(); 611 final Unit<Length> metre = units.metre(); 612 final GeodeticDatum datum; 613 final CoordinateSystem cs; 614 615 verifyIdentification (crs, "ETRS89 Lambert Azimuthal Equal Area CRS", "ETRS-LAEA"); 616 verifyIdentification (crs.getBaseCRS(), "ETRS89", null); 617 verifyIdentification (crs.getConversionFromBase(), "LAEA", null); 618 verifyDatum (datum = crs.getDatum(), "ETRS89"); 619 verifyFlattenedSphere (datum.getEllipsoid(), "GRS 80", 6378137, 298.257222101, metre); 620 verifyPrimeMeridian (datum.getPrimeMeridian(), null, 0, degree); 621 verifyAxisAbbreviations(cs = crs.getCoordinateSystem(), "Y", "X"); 622 verifyCoordinateSystem (cs, CartesianCS.class, new AxisDirection[] {NORTH,EAST}, metre); 623 624 final ParameterValueGroup group = crs.getConversionFromBase().getParameterValues(); 625 verifyParameter(group, "Latitude of natural origin", 52.0, degree); 626 verifyParameter(group, "Longitude of natural origin", 10.0, degree); 627 verifyParameter(group, "False easting", 4321000.0, metre); 628 verifyParameter(group, "False northing", 3210000.0, metre); 629 630 verifyGeographicExtent(crs.getDomainOfValidity(), "An area description", NaN, NaN, NaN, NaN); 631 assertNullOrEquals("scope", "Description of a purpose", crs.getScope()); 632 } 633 634 /** 635 * Parses a projected CRS with linear units in feet. 636 * The WKT parsed by this test is (except for quote characters): 637 * 638 * <blockquote><pre>PROJCRS[“NAD27 / Texas South Central”, 639 * BASEGEODCRS[“NAD27”, 640 * DATUM[“North American Datum 1927”, 641 * ELLIPSOID[“Clarke 1866”, 20925832.164, 294.97869821, 642 * LENGTHUNIT[“US survey foot”,0.304800609601219]]]], 643 * CONVERSION[“Texas South Central SPCS27”, 644 * METHOD[“Lambert Conic Conformal (2SP)”,ID[“EPSG”,9802]], 645 * PARAMETER[“Latitude of false origin”,27.83333333333333, 646 * ANGLEUNIT[“degree”,0.0174532925199433],ID[“EPSG”,8821]], 647 * PARAMETER[“Longitude of false origin”,-99.0, 648 * ANGLEUNIT[“degree”,0.0174532925199433],ID[“EPSG”,8822]], 649 * PARAMETER[“Latitude of 1st standard parallel”,28.383333333333, 650 * ANGLEUNIT[“degree”,0.0174532925199433],ID[“EPSG”,8823]], 651 * PARAMETER[“Latitude of 2nd standard parallel”,30.283333333333, 652 * ANGLEUNIT[“degree”,0.0174532925199433],ID[“EPSG”,8824]], 653 * PARAMETER[“Easting at false origin”,2000000.0, 654 * LENGTHUNIT[“US survey foot”,0.304800609601219],ID[“EPSG”,8826]], 655 * PARAMETER[“Northing at false origin”,0.0, 656 * LENGTHUNIT[“US survey foot”,0.304800609601219],ID[“EPSG”,8827]]], 657 * CS[Cartesian,2], 658 * AXIS[“(x)”,east], 659 * AXIS[“(y)”,north], 660 * LENGTHUNIT[“US survey foot”,0.304800609601219], 661 * REMARK[“Fundamental point: Meade’s Ranch KS, latitude 39°13'26.686"N, longitude 98°32'30.506"W.”]]</pre></blockquote> 662 * 663 * @throws FactoryException if an error occurred during the WKT parsing. 664 * 665 * @see <a href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html#68">OGC 12-063r5 §9.5 example 2</a> 666 */ 667 @Test 668 public void testProjectedWithFootUnits() throws FactoryException { 669 final ProjectedCRS crs = parse(ProjectedCRS.class, 670 "PROJCRS[“NAD27 / Texas South Central”,\n" + 671 " BASEGEODCRS[“NAD27”,\n" + 672 " DATUM[“North American Datum 1927”,\n" + 673 " ELLIPSOID[“Clarke 1866”, 20925832.164, 294.97869821,\n" + 674 " LENGTHUNIT[“US survey foot”,0.304800609601219]]]],\n" + 675 " CONVERSION[“Texas South Central SPCS27”,\n" + 676 " METHOD[“Lambert Conic Conformal (2SP)”,ID[“EPSG”,9802]],\n" + 677 " PARAMETER[“Latitude of false origin”,27.83333333333333,\n" + 678 " ANGLEUNIT[“degree”,0.0174532925199433],ID[“EPSG”,8821]],\n" + 679 " PARAMETER[“Longitude of false origin”,-99.0,\n" + 680 " ANGLEUNIT[“degree”,0.0174532925199433],ID[“EPSG”,8822]],\n" + 681 " PARAMETER[“Latitude of 1st standard parallel”,28.383333333333,\n" + 682 " ANGLEUNIT[“degree”,0.0174532925199433],ID[“EPSG”,8823]],\n" + 683 " PARAMETER[“Latitude of 2nd standard parallel”,30.283333333333,\n" + 684 " ANGLEUNIT[“degree”,0.0174532925199433],ID[“EPSG”,8824]],\n" + 685 " PARAMETER[“Easting at false origin”,2000000.0,\n" + 686 " LENGTHUNIT[“US survey foot”,0.304800609601219],ID[“EPSG”,8826]],\n" + 687 " PARAMETER[“Northing at false origin”,0.0,\n" + 688 " LENGTHUNIT[“US survey foot”,0.304800609601219],ID[“EPSG”,8827]]],\n" + 689 " CS[Cartesian,2],\n" + 690 " AXIS[“(X)”,east],\n" + 691 " AXIS[“(Y)”,north],\n" + 692 " LENGTHUNIT[“US survey foot”,0.304800609601219],\n" + 693 " REMARK[“Fundamental point: Meade’s Ranch KS, latitude 39°13'26.686\"N, longitude 98°32'30.506\"W.”]]"); 694 695 if (isValidationEnabled) { 696 configurationTip = Configuration.Key.isValidationEnabled; 697 validators.validate(crs); 698 configurationTip = null; 699 } 700 final Unit<Angle> degree = units.degree(); 701 final Unit<Length> footSurveyUS = units.footSurveyUS(); 702 final CoordinateSystem cs; 703 704 verifyAxisAbbreviations(cs = crs.getCoordinateSystem(), "X", "Y"); 705 verifyCoordinateSystem (cs, CartesianCS.class, new AxisDirection[] {EAST,NORTH}, footSurveyUS); 706 verifyTexasSouthCentral(crs, degree, footSurveyUS); 707 assertNullOrEquals("remark", "Fundamental point: Meade’s Ranch KS, latitude 39°13'26.686\"N, longitude 98°32'30.506\"W.", crs.getRemarks()); 708 } 709 710 /** 711 * Verifies the CRS name, datum and conversion parameters for {@code PROJCRS[“NAD27 / Texas South Central”]}. 712 * This method does not verify the axes and remark, since they are not specified in {@code BASEPROJCRS[…]}. 713 * 714 * @param degree value of {@link org.opengis.test.Units#degree()} (for fetching it only once per test). 715 * @param footSurveyUS value of {@link org.opengis.test.Units#footSurveyUS()}. 716 */ 717 private void verifyTexasSouthCentral(final ProjectedCRS crs, 718 final Unit<Angle> degree, final Unit<Length> footSurveyUS) 719 { 720 final GeodeticDatum datum; 721 722 verifyIdentification (crs, "NAD27 / Texas South Central", null); 723 verifyIdentification (crs.getBaseCRS(), "NAD27", null); 724 verifyIdentification (crs.getConversionFromBase(), "Texas South Central SPCS27", null); 725 verifyDatum (datum = crs.getDatum(), "North American Datum 1927"); 726 verifyFlattenedSphere (datum.getEllipsoid(), "Clarke 1866", 20925832.164, 294.97869821, footSurveyUS); 727 verifyPrimeMeridian (datum.getPrimeMeridian(), null, 0, degree); 728 729 final ParameterValueGroup group = crs.getConversionFromBase().getParameterValues(); 730 verifyParameter(group, "Latitude of false origin", 27.83333333333333, degree); 731 verifyParameter(group, "Longitude of false origin", -99.0, degree); 732 verifyParameter(group, "Latitude of 1st standard parallel", 28.383333333333, degree); 733 verifyParameter(group, "Latitude of 2nd standard parallel", 30.283333333333, degree); 734 verifyParameter(group, "Easting at false origin", 2000000.0, footSurveyUS); 735 verifyParameter(group, "Northing at false origin", 0.0, footSurveyUS); 736 } 737 738 /** 739 * Parses a projected CRS with implicit parameter units. 740 * The WKT parsed by this test is (except for quote characters and the line feed in {@code REMARK}): 741 * 742 * <blockquote><pre>PROJCRS[“NAD83 UTM 10”, 743 * BASEGEODCRS[“NAD83(86)”, 744 * DATUM[“North American Datum 1983”, 745 * ELLIPSOID[“GRS 1980”,6378137,298.257222101]], 746 * ANGLEUNIT[“degree”,0.0174532925199433], 747 * PRIMEM[“Greenwich”,0]], 748 * CONVERSION[“UTM zone 10N”,ID[“EPSG”,16010], 749 * METHOD[“Transverse Mercator”], 750 * PARAMETER[“Latitude of natural origin”,0.0], 751 * PARAMETER[“Longitude of natural origin”,-123.0], 752 * PARAMETER[“Scale factor”,0.9996], 753 * PARAMETER[“False easting”,500000.0], 754 * PARAMETER[“False northing”,0.0]], 755 * CS[Cartesian,2], 756 * AXIS[“(E)”,east,ORDER[1]], 757 * AXIS[“(N)”,north,ORDER[2]], 758 * LENGTHUNIT[“metre”,1.0], 759 * REMARK[“In this example units are implied. This is allowed for backward compatibility. 760 * It is recommended that units are explicitly given in the string, 761 * as in the previous two examples.”]]</pre></blockquote> 762 * 763 * @throws FactoryException if an error occurred during the WKT parsing. 764 * 765 * @see <a href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html#68">OGC 12-063r5 §9.5 example 3</a> 766 */ 767 @Test 768 public void testProjectedWithImplicitParameterUnits() throws FactoryException { 769 final ProjectedCRS crs = parse(ProjectedCRS.class, 770 "PROJCRS[“NAD83 UTM 10”,\n" + 771 " BASEGEODCRS[“NAD83(86)”,\n" + 772 " DATUM[“North American Datum 1983”,\n" + 773 " ELLIPSOID[“GRS 1980”, 6378137, 298.257222101]],\n" + 774 " ANGLEUNIT[“degree”,0.0174532925199433],\n" + 775 " PRIMEM[“Greenwich”,0]],\n" + 776 " CONVERSION[“UTM zone 10N”,ID[“EPSG”,16010],\n" + 777 " METHOD[“Transverse Mercator”],\n" + 778 " PARAMETER[“Latitude of natural origin”,0.0],\n" + 779 " PARAMETER[“Longitude of natural origin”,-123.0],\n" + 780 " PARAMETER[“Scale factor”,0.9996],\n" + 781 " PARAMETER[“False easting”,500000.0],\n" + 782 " PARAMETER[“False northing”,0.0]],\n" + 783 " CS[Cartesian,2],\n" + 784 " AXIS[“(E)”,east,ORDER[1]],\n" + 785 " AXIS[“(N)”,north,ORDER[2]],\n" + 786 " LENGTHUNIT[“metre”,1.0],\n" + 787 " REMARK[“In this example units are implied. This is allowed for backward compatibility." + 788 " It is recommended that units are explicitly given in the string," + 789 " as in the previous two examples.”]]"); 790 791 if (isValidationEnabled) { 792 configurationTip = Configuration.Key.isValidationEnabled; 793 validators.validate(crs); 794 configurationTip = null; 795 } 796 final Unit<Angle> degree = units.degree(); 797 final Unit<Length> metre = units.metre(); 798 final GeodeticDatum datum; 799 final CoordinateSystem cs; 800 801 verifyIdentification (crs, "NAD83 UTM 10", null); 802 verifyIdentification (crs.getBaseCRS(), "NAD83(86)", null); 803 verifyIdentification (crs.getConversionFromBase(), "UTM zone 10N", "16010"); 804 verifyDatum (datum = crs.getDatum(), "North American Datum 1983"); 805 verifyFlattenedSphere (datum.getEllipsoid(), "GRS 1980", 6378137, 298.257222101, metre); 806 verifyPrimeMeridian (datum.getPrimeMeridian(), null, 0, degree); 807 verifyAxisAbbreviations(cs = crs.getCoordinateSystem(), "E", "N"); 808 verifyCoordinateSystem (cs, CartesianCS.class, new AxisDirection[] {EAST,NORTH}, metre); 809 810 final ParameterValueGroup group = crs.getConversionFromBase().getParameterValues(); 811 verifyParameter(group, "Latitude of natural origin", 0.0, degree); 812 verifyParameter(group, "Longitude of natural origin", -123.0, degree); 813 verifyParameter(group, "Scale factor", 0.9996, units.one()); 814 verifyParameter(group, "False easting", 500000.0, metre); 815 verifyParameter(group, "False northing", 0.0, metre); 816 } 817 818 /** 819 * Parses a vertical CRS. 820 * The WKT parsed by this test is (except for quote characters): 821 * 822 * <blockquote><pre>VERTCRS[“NAVD88”, 823 * VDATUM[“North American Vertical Datum 1988”], 824 * CS[vertical,1], 825 * AXIS[“gravity-related height (H)”,up],LENGTHUNIT[“metre”,1.0]]</pre></blockquote> 826 * 827 * @throws FactoryException if an error occurred during the WKT parsing. 828 * 829 * @see <a href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html#73">OGC 12-063r5 §10.4</a> 830 */ 831 @Test 832 public void testVertical() throws FactoryException { 833 final VerticalCRS crs = parse(VerticalCRS.class, 834 "VERTCRS[“NAVD88”,\n" + 835 " VDATUM[“North American Vertical Datum 1988”],\n" + 836 " CS[vertical,1],\n" + 837 " AXIS[“gravity-related height (H)”,up],LENGTHUNIT[“metre”,1.0]]"); 838 839 if (isValidationEnabled) { 840 configurationTip = Configuration.Key.isValidationEnabled; 841 validators.validate(crs); 842 configurationTip = null; 843 } 844 verifyNAD28(crs, units.metre()); 845 } 846 847 /** 848 * Verifies the CRS name, datum and axis for {@code VERTCRS[“NAD88”]}. 849 * 850 * @param metre value of {@link org.opengis.test.Units#metre()} (for fetching it only once per test). 851 */ 852 private void verifyNAD28(final VerticalCRS crs, final Unit<Length> metre) { 853 verifyIdentification(crs, "NAVD88", null); 854 verifyDatum(crs.getDatum(), "North American Vertical Datum 1988"); 855 verifyCoordinateSystem (crs.getCoordinateSystem(), VerticalCS.class, new AxisDirection[] {UP}, metre); 856 verifyAxisAbbreviations(crs.getCoordinateSystem(), "H"); 857 } 858 859 /** 860 * Parses a temporal CRS. 861 * The WKT parsed by this test is (except for quote characters): 862 * 863 * <blockquote><pre>TIMECRS[“GPS Time”, 864 * TDATUM[“Time origin”,TIMEORIGIN[1980-01-01T00:00:00.0Z]], 865 * CS[temporal,1],AXIS[“time”,future],TIMEUNIT[“day”,86400.0]]</pre></blockquote> 866 * 867 * @throws FactoryException if an error occurred during the WKT parsing. 868 * 869 * @see <a href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html#92">OGC 12-063r5 §14.4</a> 870 */ 871 @Test 872 public void testTemporal() throws FactoryException { 873 final TemporalCRS crs = parse(TemporalCRS.class, 874 "TIMECRS[“GPS Time”,\n" + 875 " TDATUM[“Time origin”,TIMEORIGIN[1980-01-01T00:00:00.0Z]],\n" + 876 " CS[temporal,1],AXIS[“time”,future],TIMEUNIT[“day”,86400.0]]"); 877 878 if (isValidationEnabled) { 879 configurationTip = Configuration.Key.isValidationEnabled; 880 validators.validate(crs); 881 configurationTip = null; 882 } 883 verifyGPSTime(crs); 884 } 885 886 /** 887 * Verifies the CRS name, datum and axis for {@code TIMECRS[“GPS Time”]}. 888 */ 889 private void verifyGPSTime(final TemporalCRS crs) { 890 verifyIdentification (crs, "GPS Time", null); 891 verifyDatum (crs.getDatum(), "Time origin"); 892 verifyCoordinateSystem (crs.getCoordinateSystem(), TimeCS.class, new AxisDirection[] {FUTURE}, units.day()); 893 assertEquals("TimeOrigin", new Date(315532800000L), crs.getDatum().getOrigin()); 894 } 895 896 /** 897 * Parses a parametric CRS. 898 * The WKT parsed by this test is (except for quote characters): 899 * 900 * <blockquote><pre>PARAMETRICCRS[“WMO standard atmosphere layer 0”, 901 * PDATUM[“Mean Sea Level”,ANCHOR[“1013.25 hPa at 15°C”]], 902 * CS[parametric,1], 903 * AXIS[“pressure (hPa)”,up], 904 * PARAMETRICUNIT[“hPa”,100.0]]</pre></blockquote> 905 * 906 * @throws FactoryException if an error occurred during the WKT parsing. 907 * 908 * @see <a href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html#87">OGC 12-063r5 §13.4 example 1</a> 909 */ 910 @Test 911 public void testParametric() throws FactoryException { 912 final ParametricCRS crs = parse(ParametricCRS.class, 913 "PARAMETRICCRS[“WMO standard atmosphere layer 0”,\n" + 914 "PDATUM[“Mean Sea Level”,ANCHOR[“1013.25 hPa at 15°C”]],\n" + 915 "CS[parametric,1],\n" + 916 "AXIS[“pressure (hPa)”,up],PARAMETRICUNIT[“hPa”,100.0]]"); 917 918 if (isValidationEnabled) { 919 configurationTip = Configuration.Key.isValidationEnabled; 920 validators.validate(crs); 921 configurationTip = null; 922 } 923 verifyIdentification (crs, "WMO standard atmosphere layer 0", null); 924 verifyDatum (crs.getDatum(), "Mean Sea Level"); 925 verifyCoordinateSystem (crs.getCoordinateSystem(), ParametricCS.class, new AxisDirection[] {UP}, units.hectopascal()); 926 } 927 928 /** 929 * Parses an engineering CRS with North and West axis directions. 930 * The WKT parsed by this test is (except for quote characters): 931 * 932 * <blockquote><pre>ENGINEERINGCRS[“Astra Minas Grid”, 933 * ENGINEERINGDATUM[“Astra Minas”], 934 * CS[Cartesian,2], 935 * AXIS[“northing (X)”,north,ORDER[1]], 936 * AXIS[“westing (Y)”,west,ORDER[2]], 937 * LENGTHUNIT[“metre”,1.0], 938 * ID[“EPSG”,5800]]</pre></blockquote> 939 * 940 * @throws FactoryException if an error occurred during the WKT parsing. 941 * 942 * @see <a href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html#78">OGC 12-063r5 §11.4 example 2</a> 943 */ 944 @Test 945 public void testEngineering() throws FactoryException { 946 final EngineeringCRS crs = parse(EngineeringCRS.class, 947 "ENGINEERINGCRS[“Astra Minas Grid”,\n" + 948 " ENGINEERINGDATUM[“Astra Minas”],\n" + 949 " CS[Cartesian,2],\n" + 950 " AXIS[“northing (X)”,north,ORDER[1]],\n" + 951 " AXIS[“westing (Y)”,west,ORDER[2]],\n" + 952 " LENGTHUNIT[“metre”,1.0],\n" + 953 " ID[“EPSG”,5800]]"); 954 955 if (isValidationEnabled) { 956 configurationTip = Configuration.Key.isValidationEnabled; 957 validators.validate(crs); 958 configurationTip = null; 959 } 960 final Unit<Length> metre = units.metre(); 961 final CoordinateSystem cs; 962 963 verifyIdentification (crs, "Astra Minas Grid", "5800"); 964 verifyDatum (crs.getDatum(), "Astra Minas"); 965 verifyAxisAbbreviations(cs = crs.getCoordinateSystem(), "X", "Y"); 966 verifyCoordinateSystem (cs, CartesianCS.class, new AxisDirection[] {NORTH,WEST}, metre); 967 } 968 969 /** 970 * Parses an engineering CRS with South-West and South-East axis directions. 971 * The WKT parsed by this test is (except for quote characters): 972 * 973 * <blockquote><pre>ENGCRS[“A construction site CRS”, 974 * EDATUM[“P1”,ANCHOR[“Peg in south corner”]], 975 * CS[Cartesian,2], 976 * AXIS[“site east”,southWest,ORDER[1]], 977 * AXIS[“site north”,southEast,ORDER[2]], 978 * LENGTHUNIT[“metre”,1.0], 979 * TIMEEXTENT[“date/time t1”,“date/time t2”]]</pre></blockquote> 980 * 981 * @throws FactoryException if an error occurred during the WKT parsing. 982 * 983 * @see <a href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html#78">OGC 12-063r5 §11.4 example 1</a> 984 */ 985 @Test 986 public void testEngineeringRotated() throws FactoryException { 987 final EngineeringCRS crs = parse(EngineeringCRS.class, 988 "ENGCRS[“A construction site CRS”,\n" + 989 " EDATUM[“P1”,ANCHOR[“Peg in south corner”]],\n" + 990 " CS[Cartesian,2],\n" + 991 " AXIS[“site east”,southWest,ORDER[1]],\n" + 992 " AXIS[“site north”,southEast,ORDER[2]],\n" + 993 " LENGTHUNIT[“metre”,1.0],\n" + 994 " TIMEEXTENT[“date/time t1”,“date/time t2”]]"); 995 996 if (isValidationEnabled) { 997 configurationTip = Configuration.Key.isValidationEnabled; 998 validators.validate(crs); 999 configurationTip = null; 1000 } 1001 final Unit<Length> metre = units.metre(); 1002 1003 verifyIdentification (crs, "A construction site CRS", null); 1004 verifyDatum (crs.getDatum(), "P1"); 1005 assertNullOrEquals ("datum.anchor", "Peg in south corner", crs.getDatum().getAnchorPoint()); 1006 verifyCoordinateSystem (crs.getCoordinateSystem(), CartesianCS.class, new AxisDirection[] {SOUTH_WEST, SOUTH_EAST}, metre); 1007 } 1008 1009 /** 1010 * Parses an engineering CRS anchored to a ship. 1011 * The WKT parsed by this test is (except for quote characters): 1012 * 1013 * <blockquote><pre>ENGCRS[“A ship-centred CRS”, 1014 * EDATUM[“Ship reference point”,ANCHOR[“Centre of buoyancy”]], 1015 * CS[Cartesian,3], 1016 * AXIS[“(x)”,forward], 1017 * AXIS[“(y)”,starboard], 1018 * AXIS[“(z)”,down], 1019 * LENGTHUNIT[“metre”,1.0]]</pre></blockquote> 1020 * 1021 * @throws FactoryException if an error occurred during the WKT parsing. 1022 * 1023 * @see <a href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html#78">OGC 12-063r5 §11.4 example 2</a> 1024 */ 1025 @Test 1026 public void testEngineeringForShip() throws FactoryException { 1027 final EngineeringCRS crs = parse(EngineeringCRS.class, 1028 "ENGCRS[“A ship-centred CRS”,\n" + 1029 " EDATUM[“Ship reference point”,ANCHOR[“Centre of buoyancy”]],\n" + 1030 " CS[Cartesian,3],\n" + 1031 " AXIS[“(x)”,forward],\n" + 1032 " AXIS[“(y)”,starboard],\n" + 1033 " AXIS[“(z)”,down],\n" + 1034 " LENGTHUNIT[“metre”,1.0]]"); 1035 1036 if (isValidationEnabled) { 1037 configurationTip = Configuration.Key.isValidationEnabled; 1038 validators.validate(crs); 1039 configurationTip = null; 1040 } 1041 final Unit<Length> metre = units.metre(); 1042 final CoordinateSystem cs; 1043 1044 verifyIdentification (crs, "A ship-centred CRS", null); 1045 verifyDatum (crs.getDatum(), "Ship reference point"); 1046 assertNullOrEquals ("datum.anchor", "Centre of buoyancy", crs.getDatum().getAnchorPoint()); 1047 verifyAxisAbbreviations(cs = crs.getCoordinateSystem(), "x", "y", "z"); 1048 verifyCoordinateSystem (cs, CartesianCS.class, new AxisDirection[] {valueOf("forward"), valueOf("starboard"), DOWN}, metre); 1049 } 1050 1051 /** 1052 * Parses a derived geodetic CRS. 1053 * The WKT parsed by this test is (except for quote characters): 1054 * 1055 * <blockquote><pre>GEODCRS[“ETRS89 Lambert Azimuthal Equal Area CRS”, 1056 * BASEGEODCRS[“WGS 84”, 1057 * DATUM[“WGS 84”, 1058 * ELLIPSOID[“WGS 84”,6378137,298.2572236,LENGTHUNIT[“metre”,1.0]]]], 1059 * DERIVINGCONVERSION[“Atlantic pole”, 1060 * METHOD[“Pole rotation”,ID[“Authority”,1234]], 1061 * PARAMETER[“Latitude of rotated pole”,52.0, 1062 * ANGLEUNIT[“degree”,0.0174532925199433]], 1063 * PARAMETER[“Longitude of rotated pole”,-30.0, 1064 * ANGLEUNIT[“degree”,0.0174532925199433]], 1065 * PARAMETER[“Axis rotation”,-25.0, 1066 * ANGLEUNIT[“degree”,0.0174532925199433]]], 1067 * CS[ellipsoidal,2], 1068 * AXIS[“latitude”,north,ORDER[1]], 1069 * AXIS[“longitude”,east,ORDER[2]], 1070 * ANGLEUNIT[“degree”,0.0174532925199433]]</pre></blockquote> 1071 * 1072 * @throws FactoryException if an error occurred during the WKT parsing. 1073 * 1074 * @see <a href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html#103">OGC 12-063r5 §15.3.5 example 3</a> 1075 */ 1076 @Test 1077 public void testDerivedGeodetic() throws FactoryException { 1078 final DerivedCRS crs = parse(DerivedCRS.class, 1079 "GEODCRS[“ETRS89 Lambert Azimuthal Equal Area CRS”,\n" + 1080 " BASEGEODCRS[“WGS 84”,\n" + 1081 " DATUM[“WGS 84”,\n" + 1082 " ELLIPSOID[“WGS 84”, 6378137, 298.2572236, LENGTHUNIT[“metre”,1.0]]]],\n" + 1083 " DERIVINGCONVERSION[“Atlantic pole”,\n" + 1084 " METHOD[“Pole rotation”,ID[“Authority”,1234]],\n" + 1085 " PARAMETER[“Latitude of rotated pole”,52.0,\n" + 1086 " ANGLEUNIT[“degree”,0.0174532925199433]],\n" + 1087 " PARAMETER[“Longitude of rotated pole”,-30.0,\n" + 1088 " ANGLEUNIT[“degree”,0.0174532925199433]],\n" + 1089 " PARAMETER[“Axis rotation”,-25.0,\n" + 1090 " ANGLEUNIT[“degree”,0.0174532925199433]]],\n" + 1091 " CS[ellipsoidal,2],\n" + 1092 " AXIS[“latitude”,north,ORDER[1]],\n" + 1093 " AXIS[“longitude”,east,ORDER[2]],\n" + 1094 " ANGLEUNIT[“degree”,0.0174532925199433]]"); 1095 1096 if (isValidationEnabled) { 1097 configurationTip = Configuration.Key.isValidationEnabled; 1098 validators.validate(crs); 1099 configurationTip = null; 1100 } 1101 final Unit<Angle> degree = units.degree(); 1102 final Unit<Length> metre = units.metre(); 1103 final GeodeticDatum datum; 1104 1105 verifyIdentification (crs, "ETRS89 Lambert Azimuthal Equal Area CRS", null); 1106 verifyCoordinateSystem(crs.getCoordinateSystem(), EllipsoidalCS.class, new AxisDirection[] {NORTH,EAST}, degree); 1107 1108 assertInstanceOf("baseCRS", GeodeticCRS.class, crs.getBaseCRS()); 1109 verifyDatum (datum = ((GeodeticCRS) crs.getBaseCRS()).getDatum(), "WGS 84"); 1110 verifyFlattenedSphere (datum.getEllipsoid(), "WGS 84", 6378137, 298.2572236, metre); 1111 verifyPrimeMeridian (datum.getPrimeMeridian(), null, 0, degree); 1112 1113 final ParameterValueGroup group = crs.getConversionFromBase().getParameterValues(); 1114 verifyParameter(group, "Latitude of rotated pole", 52, degree); 1115 verifyParameter(group, "Longitude of rotated pole", -30, degree); 1116 verifyParameter(group, "Axis rotation", -25, degree); 1117 } 1118 1119 /** 1120 * Parses a derived engineering CRS having a base geodetic CRS. 1121 * The WKT parsed by this test is (except for quote characters): 1122 * 1123 * <blockquote><pre>ENGCRS[“Topocentric example A”, 1124 * BASEGEODCRS[“WGS 84”, 1125 * DATUM[“WGS 84”, 1126 * ELLIPSOID[“WGS 84”, 6378137, 298.2572236, LENGTHUNIT[“metre”,1.0]]]], 1127 * DERIVINGCONVERSION[“Topocentric example A”, 1128 * METHOD[“Geographic/topocentric conversions”,ID[“EPSG”,9837]], 1129 * PARAMETER[“Latitude of topocentric origin”,55.0, 1130 * ANGLEUNIT[“degree”,0.0174532925199433]], 1131 * PARAMETER[“Longitude of topocentric origin”,5.0, 1132 * ANGLEUNIT[“degree”,0.0174532925199433]], 1133 * PARAMETER[“Ellipsoidal height of topocentric origin”,0.0, 1134 * LENGTHUNIT[“metre”,1.0]]], 1135 * CS[Cartesian,3], 1136 * AXIS[“Topocentric East (U)”,east,ORDER[1]], 1137 * AXIS[“Topocentric North (V)”,north,ORDER[2]], 1138 * AXIS[“Topocentric height (W)”,up,ORDER[3]], 1139 * LENGTHUNIT[“metre”,1.0]]</pre></blockquote> 1140 * 1141 * @throws FactoryException if an error occurred during the WKT parsing. 1142 * 1143 * @see <a href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html#107">OGC 12-063r5 §15.5.2 example 2</a> 1144 */ 1145 @Test 1146 public void testDerivedEngineeringFromGeodetic() throws FactoryException { 1147 final DerivedCRS crs = parse(DerivedCRS.class, 1148 "ENGCRS[“Topocentric example A”,\n" + 1149 " BASEGEODCRS[“WGS 84”,\n" + 1150 " DATUM[“WGS 84”,\n" + 1151 " ELLIPSOID[“WGS 84”, 6378137, 298.2572236, LENGTHUNIT[“metre”,1.0]]]],\n" + 1152 " DERIVINGCONVERSION[“Topocentric example A”,\n" + 1153 " METHOD[“Geographic/topocentric conversions”,ID[“EPSG”,9837]],\n" + 1154 " PARAMETER[“Latitude of topocentric origin”,55.0,\n" + 1155 " ANGLEUNIT[“degree”,0.0174532925199433]],\n" + 1156 " PARAMETER[“Longitude of topocentric origin”,5.0,\n" + 1157 " ANGLEUNIT[“degree”,0.0174532925199433]],\n" + 1158 " PARAMETER[“Ellipsoidal height of topocentric origin”,0.0,\n" + 1159 " LENGTHUNIT[“metre”,1.0]]],\n" + 1160 " CS[Cartesian,3],\n" + 1161 " AXIS[“Topocentric East (U)”,east,ORDER[1]],\n" + 1162 " AXIS[“Topocentric North (V)”,north,ORDER[2]],\n" + 1163 " AXIS[“Topocentric height (W)”,up,ORDER[3]],\n" + 1164 " LENGTHUNIT[“metre”,1.0]]"); 1165 1166 if (isValidationEnabled) { 1167 configurationTip = Configuration.Key.isValidationEnabled; 1168 validators.validate(crs); 1169 configurationTip = null; 1170 } 1171 final Unit<Angle> degree = units.degree(); 1172 final Unit<Length> metre = units.metre(); 1173 final GeodeticDatum datum; 1174 1175 verifyIdentification (crs, "Topocentric example A", null); 1176 verifyCoordinateSystem (crs.getCoordinateSystem(), EllipsoidalCS.class, new AxisDirection[] {EAST,NORTH,UP}, metre); 1177 verifyAxisAbbreviations(crs.getCoordinateSystem(), "U", "V", "W"); 1178 1179 assertInstanceOf("baseCRS", GeodeticCRS.class, crs.getBaseCRS()); 1180 verifyDatum (datum = ((GeodeticCRS) crs.getBaseCRS()).getDatum(), "WGS 84"); 1181 verifyFlattenedSphere (datum.getEllipsoid(), "WGS 84", 6378137, 298.2572236, metre); 1182 verifyPrimeMeridian (datum.getPrimeMeridian(), null, 0, degree); 1183 1184 final ParameterValueGroup group = crs.getConversionFromBase().getParameterValues(); 1185 verifyParameter(group, "Latitude of topocentric origin", 55, degree); 1186 verifyParameter(group, "Longitude of topocentric origin", 5, degree); 1187 verifyParameter(group, "Ellipsoidal height of topocentric origin", 0, metre); 1188 } 1189 1190 /** 1191 * Parses a derived engineering CRS having a base projected CRS. 1192 * The WKT parsed by this test is (except for quote characters): 1193 * 1194 * <blockquote><pre>ENGCRS[“Gulf of Mexico speculative seismic survey bin grid”, 1195 * BASEPROJCRS[“NAD27 / Texas South Central”, 1196 * BASEGEODCRS[“NAD27”, 1197 * DATUM[“North American Datum 1927”, 1198 * ELLIPSOID[“Clarke 1866”,20925832.164,294.97869821, 1199 * LENGTHUNIT[“US survey foot”,0.304800609601219]]]], 1200 * CONVERSION[“Texas South CentralSPCS27”, 1201 * METHOD[“Lambert Conic Conformal (2SP)”,ID[“EPSG”,9802]], 1202 * PARAMETER[“Latitude of false origin”,27.83333333333333, 1203 * ANGLEUNIT[“degree”,0.0174532925199433],ID[“EPSG”,8821]], 1204 * PARAMETER[“Longitude of false origin”,-99.0, 1205 * ANGLEUNIT[“degree”,0.0174532925199433],ID[“EPSG”,8822]], 1206 * PARAMETER[“Latitude of 1st standard parallel”,28.383333333333, 1207 * ANGLEUNIT[“degree”,0.0174532925199433],ID[“EPSG”,8823]], 1208 * PARAMETER[“Latitude of 2nd standard parallel”,30.283333333333, 1209 * ANGLEUNIT[“degree”,0.0174532925199433],ID[“EPSG”,8824]], 1210 * PARAMETER[“Easting at false origin”,2000000.0, 1211 * LENGTHUNIT[“US survey foot”,0.304800609601219],ID[“EPSG”,8826]], 1212 * PARAMETER[“Northing at false origin”,0.0, 1213 * LENGTHUNIT[“US survey foot”,0.304800609601219],ID[“EPSG”,8827]]]], 1214 * DERIVINGCONVERSION[“Gulf of Mexico speculative survey bin grid”, 1215 * METHOD[“P6 (I = J-90°) seismic bin grid transformation”,ID[“EPSG”,1049]], 1216 * PARAMETER[“Bin grid origin I”,5000,SCALEUNIT[“Bin”,1.0],ID[“EPSG”,8733]], 1217 * PARAMETER[“Bin grid origin J”,0,SCALEUNIT[“Bin”,1.0],ID[“EPSG”,8734]], 1218 * PARAMETER[“Bin grid origin Easting”,871200, 1219 * LENGTHUNIT[“US survey foot”,0.304800609601219],ID[“EPSG”,8735]], 1220 * PARAMETER[“Bin grid origin Northing”, 10280160, 1221 * LENGTHUNIT[“US survey foot”,0.304800609601219],ID[“EPSG”,8736]], 1222 * PARAMETER[“Scale factor of bin grid”,1.0, 1223 * SCALEUNIT[“Unity”,1.0],ID[“EPSG”,8737]], 1224 * PARAMETER[“Bin width on I-axis”,82.5, 1225 * LENGTHUNIT[“US survey foot”,0.304800609601219],ID[“EPSG”,8738]], 1226 * PARAMETER[“Bin width on J-axis”,41.25, 1227 * LENGTHUNIT[“US survey foot”,0.304800609601219],ID[“EPSG”,8739]], 1228 * PARAMETER[“Map grid bearing of bin grid J-axis”,340, 1229 * ANGLEUNIT[“degree”,0.0174532925199433],ID[“EPSG”,8740]], 1230 * PARAMETER[“Bin node increment on I-axis”,1.0, 1231 * SCALEUNIT[“Bin”,1.0],ID[“EPSG”,8741]], 1232 * PARAMETER[“Bin node increment on J-axis”,1.0, 1233 * SCALEUNIT[“Bin”,1.0],ID[“EPSG”,8742]]], 1234 * CS[Cartesian,2], 1235 * AXIS[“(I)”,northNorthWest], 1236 * AXIS[“(J)”,westSouthWest], 1237 * SCALEUNIT[“Bin”,1.0]]</pre></blockquote> 1238 * 1239 * @throws FactoryException if an error occurred during the WKT parsing. 1240 * 1241 * @see <a href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html#107">OGC 12-063r5 §15.5.2 example 1</a> 1242 */ 1243 @Test 1244 public void testDerivedEngineeringFromProjected() throws FactoryException { 1245 final DerivedCRS crs = parse(DerivedCRS.class, 1246 "ENGCRS[“Gulf of Mexico speculative seismic survey bin grid”,\n" + 1247 " BASEPROJCRS[“NAD27 / Texas South Central”,\n" + 1248 " BASEGEODCRS[“NAD27”,\n" + 1249 " DATUM[“North American Datum 1927”,\n" + 1250 " ELLIPSOID[“Clarke 1866”,20925832.164,294.97869821,\n" + 1251 " LENGTHUNIT[“US survey foot”,0.304800609601219]]]],\n" + 1252 " CONVERSION[“Texas South CentralSPCS27”,\n" + 1253 " METHOD[“Lambert Conic Conformal (2SP)”,ID[“EPSG”,9802]],\n" + 1254 " PARAMETER[“Latitude of false origin”,27.83333333333333,\n" + 1255 " ANGLEUNIT[“degree”,0.0174532925199433],ID[“EPSG”,8821]],\n" + 1256 " PARAMETER[“Longitude of false origin”,-99.0,\n" + 1257 " ANGLEUNIT[“degree”,0.0174532925199433],ID[“EPSG”,8822]],\n" + 1258 " PARAMETER[“Latitude of 1st standard parallel”,28.383333333333,\n" + 1259 " ANGLEUNIT[“degree”,0.0174532925199433],ID[“EPSG”,8823]],\n" + 1260 " PARAMETER[“Latitude of 2nd standard parallel”,30.283333333333,\n" + 1261 " ANGLEUNIT[“degree”,0.0174532925199433],ID[“EPSG”,8824]],\n" + 1262 " PARAMETER[“Easting at false origin”,2000000.0,\n" + 1263 " LENGTHUNIT[“US survey foot”,0.304800609601219],ID[“EPSG”,8826]],\n" + 1264 " PARAMETER[“Northing at false origin”,0.0,\n" + 1265 " LENGTHUNIT[“US survey foot”,0.304800609601219],ID[“EPSG”,8827]]]],\n" + 1266 " DERIVINGCONVERSION[“Gulf of Mexico speculative survey bin grid”,\n" + 1267 " METHOD[“P6 (I = J-90°) seismic bin grid transformation”,ID[“EPSG”,1049]],\n" + 1268 " PARAMETER[“Bin grid origin I”,5000,SCALEUNIT[“Bin”,1.0],ID[“EPSG”,8733]],\n" + 1269 " PARAMETER[“Bin grid origin J”,0,SCALEUNIT[“Bin”,1.0],ID[“EPSG”,8734]],\n" + 1270 " PARAMETER[“Bin grid origin Easting”,871200,\n" + 1271 " LENGTHUNIT[“US survey foot”,0.304800609601219],ID[“EPSG”,8735]],\n" + 1272 " PARAMETER[“Bin grid origin Northing”, 10280160,\n" + 1273 " LENGTHUNIT[“US survey foot”,0.304800609601219],ID[“EPSG”,8736]],\n" + 1274 " PARAMETER[“Scale factor of bin grid”,1.0,\n" + 1275 " SCALEUNIT[“Unity”,1.0],ID[“EPSG”,8737]],\n" + 1276 " PARAMETER[“Bin width on I-axis”,82.5,\n" + 1277 " LENGTHUNIT[“US survey foot”,0.304800609601219],ID[“EPSG”,8738]],\n" + 1278 " PARAMETER[“Bin width on J-axis”,41.25,\n" + 1279 " LENGTHUNIT[“US survey foot”,0.304800609601219],ID[“EPSG”,8739]],\n" + 1280 " PARAMETER[“Map grid bearing of bin grid J-axis”,340,\n" + 1281 " ANGLEUNIT[“degree”,0.0174532925199433],ID[“EPSG”,8740]],\n" + 1282 " PARAMETER[“Bin node increment on I-axis”,1.0,\n" + 1283 " SCALEUNIT[“Bin”,1.0],ID[“EPSG”,8741]],\n" + 1284 " PARAMETER[“Bin node increment on J-axis”,1.0,\n" + 1285 " SCALEUNIT[“Bin”,1.0],ID[“EPSG”,8742]]],\n" + 1286 " CS[Cartesian,2],\n" + 1287 " AXIS[“(I)”,northNorthWest],\n" + 1288 " AXIS[“(J)”,westSouthWest],\n" + 1289 " SCALEUNIT[“Bin”,1.0]]"); 1290 1291 if (isValidationEnabled) { 1292 configurationTip = Configuration.Key.isValidationEnabled; 1293 validators.validate(crs); 1294 configurationTip = null; 1295 } 1296 final Unit<Angle> degree = units.degree(); 1297 final Unit<Length> footSurveyUS = units.footSurveyUS(); 1298 final Unit<Dimensionless> one = units.one(); 1299 final CoordinateSystem cs; 1300 1301 verifyIdentification (crs, "Gulf of Mexico speculative seismic survey bin grid", null); 1302 verifyAxisAbbreviations(cs = crs.getCoordinateSystem(), "I", "J"); 1303 verifyCoordinateSystem (cs, CartesianCS.class, new AxisDirection[] {NORTH_NORTH_WEST, WEST_SOUTH_WEST}, one); 1304 assertInstanceOf("baseCRS", ProjectedCRS.class, crs.getBaseCRS()); 1305 verifyTexasSouthCentral((ProjectedCRS) crs.getBaseCRS(), degree, footSurveyUS); 1306 1307 final ParameterValueGroup group = crs.getConversionFromBase().getParameterValues(); 1308 verifyParameter(group, "Bin grid origin I", 5000, one); 1309 verifyParameter(group, "Bin grid origin J", 0, one); 1310 verifyParameter(group, "Bin grid origin Easting", 871200, footSurveyUS); 1311 verifyParameter(group, "Bin grid origin Northing", 10280160, footSurveyUS); 1312 verifyParameter(group, "Scale factor of bin grid", 1, one); 1313 verifyParameter(group, "Bin width on I-axis", 82.50, footSurveyUS); 1314 verifyParameter(group, "Bin width on J-axis", 41.25, footSurveyUS); 1315 verifyParameter(group, "Map grid bearing of bin grid J-axis", 340, degree); 1316 verifyParameter(group, "Bin node increment on I-axis", 1, one); 1317 verifyParameter(group, "Bin node increment on J-axis", 1, one); 1318 } 1319 1320 /** 1321 * Parses a compound CRS with a vertical component. 1322 * The WKT parsed by this test is (except for quote characters): 1323 * 1324 * <blockquote><pre>COMPOUNDCRS[“NAD83 + NAVD88”, 1325 * GEODCRS[“NAD83”, 1326 * DATUM[“North American Datum 1983”, 1327 * ELLIPSOID[“GRS 1980”,6378137,298.257222101, 1328 * LENGTHUNIT[“metre”,1.0]]], 1329 * PRIMEMERIDIAN[“Greenwich”,0], 1330 * CS[ellipsoidal,2], 1331 * AXIS[“latitude”,north,ORDER[1]], 1332 * AXIS[“longitude”,east,ORDER[2]], 1333 * ANGLEUNIT[“degree”,0.0174532925199433]], 1334 * VERTCRS[“NAVD88”, 1335 * VDATUM[“North American Vertical Datum 1988”], 1336 * CS[vertical,1], 1337 * AXIS[“gravity-related height (H)”,up], 1338 * LENGTHUNIT[“metre”,1]]]</pre></blockquote> 1339 * 1340 * @throws FactoryException if an error occurred during the WKT parsing. 1341 * 1342 * @see <a href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html#112">OGC 12-063r5 §16.2 example 1</a> 1343 */ 1344 @Test 1345 public void testCompoundWithVertical() throws FactoryException { 1346 final CompoundCRS crs = parse(CompoundCRS.class, 1347 "COMPOUNDCRS[“NAD83 + NAVD88”,\n" + 1348 " GEODCRS[“NAD83”,\n" + 1349 " DATUM[“North American Datum 1983”,\n" + 1350 " ELLIPSOID[“GRS 1980”,6378137,298.257222101,\n" + 1351 " LENGTHUNIT[“metre”,1.0]]],\n" + 1352 " PRIMEMERIDIAN[“Greenwich”,0],\n" + 1353 " CS[ellipsoidal,2],\n" + 1354 " AXIS[“latitude”,north,ORDER[1]],\n" + 1355 " AXIS[“longitude”,east,ORDER[2]],\n" + 1356 " ANGLEUNIT[“degree”,0.0174532925199433]],\n" + 1357 " VERTCRS[“NAVD88”,\n" + 1358 " VDATUM[“North American Vertical Datum 1988”],\n" + 1359 " CS[vertical,1],\n" + 1360 " AXIS[“gravity-related height (H)”,up],\n" + 1361 " LENGTHUNIT[“metre”,1]]]"); 1362 1363 if (isValidationEnabled) { 1364 configurationTip = Configuration.Key.isValidationEnabled; 1365 validators.validate(crs); 1366 configurationTip = null; 1367 } 1368 final Unit<Angle> degree = units.degree(); 1369 final Unit<Length> metre = units.metre(); 1370 1371 verifyIdentification(crs, "NAD83 + NAVD88", null); 1372 final List<CoordinateReferenceSystem> components = crs.getComponents(); 1373 assertEquals("components.size()", 2, components.size()); 1374 assertInstanceOf("components[0]", GeodeticCRS.class, components.get(0)); 1375 assertInstanceOf("components[1]", VerticalCRS.class, components.get(1)); 1376 verifyNAD23((GeodeticCRS) components.get(0), false, degree, metre); 1377 verifyNAD28((VerticalCRS) components.get(1), metre); 1378 } 1379 1380 /** 1381 * Parses a compound CRS with a temporal component. 1382 * The WKT parsed by this test is (except for quote characters): 1383 * 1384 * <blockquote><pre>COMPOUNDCRS[“GPS position and time”, 1385 * GEODCRS[“WGS 84”, 1386 * DATUM[“World Geodetic System 1984”, 1387 * ELLIPSOID[“WGS 84”,6378137,298.257223563]], 1388 * CS[ellipsoidal,2], 1389 * AXIS[“(lat)”,north,ORDER[1]], 1390 * AXIS[“(lon)”,east,ORDER[2]], 1391 * ANGLEUNIT[“degree”,0.0174532925199433]], 1392 * TIMECRS[“GPS Time”, 1393 * TIMEDATUM[“Time origin”,TIMEORIGIN[1980-01-01]], 1394 * CS[temporal,1], 1395 * AXIS[“time (T)”,future], 1396 * TIMEUNIT[“day”,86400]]]</pre></blockquote> 1397 * 1398 * @throws FactoryException if an error occurred during the WKT parsing. 1399 * 1400 * @see <a href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html#112">OGC 12-063r5 §16.2 example 3</a> 1401 */ 1402 @Test 1403 public void testCompoundWithTime() throws FactoryException { 1404 final CompoundCRS crs = parse(CompoundCRS.class, 1405 "COMPOUNDCRS[“GPS position and time”,\n" + 1406 " GEODCRS[“WGS 84”,\n" + 1407 " DATUM[“World Geodetic System 1984”,\n" + 1408 " ELLIPSOID[“WGS 84”,6378137,298.257223563]],\n" + 1409 " CS[ellipsoidal,2],\n" + 1410 " AXIS[“(lat)”,north,ORDER[1]],\n" + 1411 " AXIS[“(lon)”,east,ORDER[2]],\n" + 1412 " ANGLEUNIT[“degree”,0.0174532925199433]],\n" + 1413 " TIMECRS[“GPS Time”,\n" + 1414 " TIMEDATUM[“Time origin”,TIMEORIGIN[1980-01-01]],\n" + 1415 " CS[temporal,1],\n" + 1416 " AXIS[“time (T)”,future],\n" + 1417 " TIMEUNIT[“day”,86400]]]"); 1418 1419 if (isValidationEnabled) { 1420 configurationTip = Configuration.Key.isValidationEnabled; 1421 validators.validate(crs); 1422 configurationTip = null; 1423 } 1424 final Unit<Angle> degree = units.degree(); 1425 final Unit<Length> metre = units.metre(); 1426 1427 verifyIdentification(crs, "GPS position and time", null); 1428 final List<CoordinateReferenceSystem> components = crs.getComponents(); 1429 assertEquals("components.size()", 2, components.size()); 1430 assertInstanceOf("components[0]", GeodeticCRS.class, components.get(0)); 1431 assertInstanceOf("components[1]", TemporalCRS.class, components.get(1)); 1432 verifyWGS84 ((GeodeticCRS) components.get(0), false, degree, metre); 1433 verifyGPSTime((TemporalCRS) components.get(1)); 1434 } 1435 1436 /** 1437 * Parses a compound CRS with a parametric component. 1438 * The WKT parsed by this test is (except for quote characters): 1439 * 1440 * <blockquote><pre>COMPOUNDCRS[“ICAO layer 0”, 1441 * GEODETICCRS[“WGS 84”, 1442 * DATUM[“World Geodetic System 1984”, 1443 * ELLIPSOID[“WGS 84”,6378137,298.257223563, 1444 * LENGTHUNIT[“metre”,1.0]]], 1445 * CS[ellipsoidal,2], 1446 * AXIS[“latitude”,north,ORDER[1]], 1447 * AXIS[“longitude”,east,ORDER[2]], 1448 * ANGLEUNIT[“degree”,0.0174532925199433]], 1449 * PARAMETRICCRS[“WMO standard atmosphere”, 1450 * PARAMETRICDATUM[“Mean Sea Level”, 1451 * ANCHOR[“Mean Sea Level = 1013.25 hPa”]], 1452 * CS[parametric,1], 1453 * AXIS[“pressure (P)”,unspecified], 1454 * PARAMETRICUNIT[“hPa”,100]]]</pre></blockquote> 1455 * 1456 * @throws FactoryException if an error occurred during the WKT parsing. 1457 * 1458 * @see <a href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html#112">OGC 12-063r5 §16.2 example 2</a> 1459 */ 1460 @Test 1461 public void testCompoundWithParametric() throws FactoryException { 1462 final CompoundCRS crs = parse(CompoundCRS.class, 1463 "COMPOUNDCRS[“ICAO layer 0”,\n" + 1464 " GEODETICCRS[“WGS 84”,\n" + 1465 " DATUM[“World Geodetic System 1984”,\n" + 1466 " ELLIPSOID[“WGS 84”,6378137,298.257223563,\n" + 1467 " LENGTHUNIT[“metre”,1.0]]],\n" + 1468 " CS[ellipsoidal,2],\n" + 1469 " AXIS[“latitude”,north,ORDER[1]],\n" + 1470 " AXIS[“longitude”,east,ORDER[2]],\n" + 1471 " ANGLEUNIT[“degree”,0.0174532925199433]],\n" + 1472 " PARAMETRICCRS[“WMO standard atmosphere”,\n" + 1473 " PARAMETRICDATUM[“Mean Sea Level”,\n" + 1474 " ANCHOR[“Mean Sea Level = 1013.25 hPa”]],\n" + 1475 " CS[parametric,1],\n" + 1476 " AXIS[“pressure (P)”,unspecified],\n" + 1477 " PARAMETRICUNIT[“hPa”,100]]]"); 1478 1479 if (isValidationEnabled) { 1480 configurationTip = Configuration.Key.isValidationEnabled; 1481 validators.validate(crs); 1482 configurationTip = null; 1483 } 1484 final Unit<Angle> degree = units.degree(); 1485 final Unit<Length> metre = units.metre(); 1486 1487 verifyIdentification(crs, "ICAO layer 0", null); 1488 final List<CoordinateReferenceSystem> components = crs.getComponents(); 1489 assertEquals("components.size()", 2, components.size()); 1490 assertInstanceOf("components[0]", GeodeticCRS.class, components.get(0)); 1491 assertInstanceOf("components[1]", ParametricCRS.class, components.get(1)); 1492 verifyWGS84((GeodeticCRS) components.get(0), false, degree, metre); 1493 1494 final ParametricCRS ps = (ParametricCRS) components.get(1); 1495 verifyIdentification(ps, "WMO standard atmosphere", null); 1496 verifyDatum(ps.getDatum(), "Mean Sea Level"); 1497 assertInstanceOf("coordinateSystem", ParametricCS.class, ps.getCoordinateSystem()); 1498 } 1499}