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.Map; 035import java.util.List; 036import java.util.Collections; 037import javax.measure.Unit; 038import javax.measure.quantity.Angle; 039import javax.measure.quantity.Length; 040 041import org.opengis.parameter.*; 042import org.opengis.referencing.cs.*; 043import org.opengis.referencing.crs.*; 044import org.opengis.referencing.datum.*; 045import org.opengis.referencing.operation.*; 046import org.opengis.referencing.IdentifiedObject; 047import org.opengis.referencing.ObjectFactory; 048import org.opengis.util.Factory; 049import org.opengis.util.FactoryException; 050import org.opengis.test.Units; 051 052import org.junit.Test; 053import org.junit.runner.RunWith; 054import org.junit.runners.Parameterized; 055 056import static org.junit.Assume.*; 057import static org.opengis.test.Assert.*; 058import static org.opengis.referencing.cs.AxisDirection.*; 059 060 061/** 062 * Tests the creation of referencing objects from the {@linkplain ObjectFactory object factories} 063 * given at construction time. 064 * 065 * <div class="note"><b>Usage example:</b> 066 * in order to specify their factories and run the tests in a JUnit framework, implementors can 067 * define a subclass in their own test suite as in the example below: 068 * 069 * <blockquote><pre>import org.junit.runner.RunWith; 070 *import org.junit.runners.JUnit4; 071 *import org.opengis.test.referencing.ObjectFactoryTest; 072 * 073 *@RunWith(JUnit4.class) 074 *public class MyTest extends ObjectFactoryTest { 075 * public MyTest() { 076 * super(new MyDatumFactory(), new MyCSFactory(), new MyCRSFactory(), new MyOpFactory()); 077 * } 078 *}</pre></blockquote> 079 * </div> 080 * 081 * @see AuthorityFactoryTest 082 * @see org.opengis.test.TestSuite 083 * 084 * @author Cédric Briançon (Geomatys) 085 * @author Martin Desruisseaux (Geomatys) 086 * @version 3.1 087 * @since 2.3 088 */ 089@RunWith(Parameterized.class) 090public strictfp class ObjectFactoryTest extends ReferencingTestCase { 091 /** 092 * Factory to use for building {@link Datum} instances, or {@code null} if none. 093 */ 094 protected final DatumFactory datumFactory; 095 096 /** 097 * Factory to use for building {@link CoordinateSystem} instances, or {@code null} if none. 098 */ 099 protected final CSFactory csFactory; 100 101 /** 102 * Factory to use for building {@link CoordinateReferenceSystem} instances, or {@code null} if none. 103 */ 104 protected final CRSFactory crsFactory; 105 106 /** 107 * Factory to use for building {@link Conversion} instances, or {@code null} if none. 108 */ 109 protected final CoordinateOperationFactory copFactory; 110 111 /** 112 * Returns a default set of factories to use for running the tests. Those factories are given 113 * in arguments to the constructor when this test class is instantiated directly by JUnit (for 114 * example as a {@linkplain org.junit.runners.Suite.SuiteClasses suite} element), instead than 115 * subclassed by the implementor. The factories are fetched as documented in the 116 * {@link #factories(Class[])} javadoc. 117 * 118 * @return the default set of arguments to be given to the {@code ObjectFactoryTest} constructor. 119 * 120 * @since 3.1 121 */ 122 @Parameterized.Parameters 123 @SuppressWarnings("unchecked") 124 public static List<Factory[]> factories() { 125 return factories(DatumFactory.class, CSFactory.class, CRSFactory.class, CoordinateOperationFactory.class); 126 } 127 128 /** 129 * Creates a new test using the given factories. If a given factory is {@code null}, 130 * then the tests which depend on it will be skipped. 131 * 132 * @param datumFactory factory for creating {@link Datum} instances. 133 * @param csFactory factory for creating {@link CoordinateSystem} instances. 134 * @param crsFactory factory for creating {@link CoordinateReferenceSystem} instances. 135 * @param copFactory factory for creating {@link Conversion} instances. 136 */ 137 public ObjectFactoryTest( 138 final DatumFactory datumFactory, 139 final CSFactory csFactory, 140 final CRSFactory crsFactory, 141 final CoordinateOperationFactory copFactory) 142 { 143 super(datumFactory, csFactory, crsFactory, copFactory); 144 this.datumFactory = datumFactory; 145 this.csFactory = csFactory; 146 this.crsFactory = crsFactory; 147 this.copFactory = copFactory; 148 } 149 150 /** 151 * Returns the authority factory tests backed by the object factories. 152 */ 153 private AuthorityFactoryTest createAuthorityFactoryTest() { 154 final PseudoEpsgFactory factory = new PseudoEpsgFactory(Units.getDefault(), 155 datumFactory, csFactory, crsFactory, copFactory, null, validators); 156 return new AuthorityFactoryTest(factory, factory, factory); 157 } 158 159 /** 160 * Builds a map containing only one value, composed by the {@link IdentifiedObject#NAME_KEY} 161 * identifier and the value specified. 162 * 163 * @param value the value for the name key. 164 * @return a map containing only the value specified for the name key. 165 */ 166 private static Map<String,String> name(final String value) { 167 return Collections.singletonMap(IdentifiedObject.NAME_KEY, value); 168 } 169 170 /** 171 * Tests the creation of the EPSG:4326 {@link GeographicCRS}. This method wraps the 172 * object factories in an {@link PseudoEpsgFactory} instance, then delegates to the 173 * {@link AuthorityFactoryTest#testWGS84()} method. 174 * 175 * @throws FactoryException if a factory fails to create a referencing object. 176 */ 177 @Test 178 public void testWGS84() throws FactoryException { 179 createAuthorityFactoryTest().testWGS84(); 180 } 181 182 /** 183 * Tests the creation of the WGS84 {@linkplain CoordinateReferenceSystem CRS} with ellipsoidal height, and 184 * verifies that the axes are in the given (<var>latitude</var>, <var>longitude</var>, <var>height</var>) order. 185 * 186 * @throws FactoryException if a factory fails to create a referencing object. 187 */ 188 @Test 189 public void testWGS84_3D() throws FactoryException { 190 CoordinateSystemAxis λ, φ, h; 191 EllipsoidalCS cs; 192 GeographicCRS crs; // The final product of this method. 193 GeodeticDatum datum; 194 195 final Unit<Length> metre = units.metre(); 196 final Unit<Angle> degree = units.degree(); 197 198 // Build a geodetic datum. 199 assumeNotNull(datumFactory); 200 validators.validate(datum = datumFactory.createGeodeticDatum(name("World Geodetic System 1984"), 201 datumFactory.createEllipsoid (name("WGS 84"), 6378137.0, 298.257223563, metre), 202 datumFactory.createPrimeMeridian(name("Greenwich"), 0.0, degree))); 203 204 // Build an ellipsoidal coordinate system. 205 assumeNotNull(csFactory); 206 validators.validate(λ = csFactory.createCoordinateSystemAxis(name("Geodetic longitude"), "λ", EAST, degree)); 207 validators.validate(φ = csFactory.createCoordinateSystemAxis(name("Geodetic latitude"), "φ", NORTH, degree)); 208 validators.validate(h = csFactory.createCoordinateSystemAxis(name("Ellipsoidal height"), "h", UP, metre)); 209 validators.validate(cs = csFactory.createEllipsoidalCS(name("WGS 84"), φ, λ, h)); 210 211 // Finally build the geographic coordinate reference system. 212 assumeNotNull(crsFactory); 213 validators.validate(crs = crsFactory.createGeographicCRS(name("WGS84(DD)"), datum, cs)); 214 215 datum = crs.getDatum(); 216 verifyIdentification(datum, "World Geodetic System 1984", null); 217 verifyPrimeMeridian(datum.getPrimeMeridian(), "Greenwich", 0.0, degree); 218 219 cs = crs.getCoordinateSystem(); 220 verifyCoordinateSystem(cs, EllipsoidalCS.class, 221 new AxisDirection[] { 222 AxisDirection.NORTH, 223 AxisDirection.EAST, 224 AxisDirection.UP 225 }, degree, degree, metre); 226 verifyIdentification(cs.getAxis(0), "Geodetic latitude", null); 227 verifyIdentification(cs.getAxis(1), "Geodetic longitude", null); 228 verifyIdentification(cs.getAxis(2), "Ellipsoidal height", null); 229 } 230 231 /** 232 * Tests the creation of a geocentric CRS. 233 * 234 * @throws FactoryException if a factory fails to create a referencing object. 235 */ 236 @Test 237 public void testGeocentric() throws FactoryException { 238 final CoordinateSystemAxis X, Y, Z; 239 final CartesianCS cs; 240 final GeocentricCRS crs; // The final product of this method. 241 final GeodeticDatum datum; 242 final PrimeMeridian greenwich; 243 final Ellipsoid ellipsoid; 244 245 final Unit<Length> metre = units.metre(); 246 final Unit<Angle> degree = units.degree(); 247 248 assumeNotNull(datumFactory); 249 validators.validate(greenwich = datumFactory.createPrimeMeridian (name("Greenwich Meridian"), 0, degree)); 250 validators.validate(ellipsoid = datumFactory.createFlattenedSphere(name("WGS84 Ellipsoid"), 6378137, 298.257223563, metre)); 251 validators.validate(datum = datumFactory.createGeodeticDatum (name("WGS84 Datum"), ellipsoid, greenwich)); 252 253 assumeNotNull(csFactory); 254 validators.validate(X = csFactory.createCoordinateSystemAxis(name("Geocentric X"), "X", GEOCENTRIC_X, metre)); 255 validators.validate(Y = csFactory.createCoordinateSystemAxis(name("Geocentric Y"), "Y", GEOCENTRIC_Y, metre)); 256 validators.validate(Z = csFactory.createCoordinateSystemAxis(name("Geocentric Z"), "Z", GEOCENTRIC_Z, metre)); 257 validators.validate(cs = csFactory.createCartesianCS(name("Geocentric CS"), X, Z, Y)); 258 259 assumeNotNull(crsFactory); 260 validators.validate(crs = crsFactory.createGeocentricCRS(name("Geocentric CRS"), datum, cs)); 261 assertAxisDirectionsEqual("GeocentricCRS", crs.getCoordinateSystem(), GEOCENTRIC_X, GEOCENTRIC_Z, GEOCENTRIC_Y); 262 } 263 264 /** 265 * Tests the creation of a projected CRS with vertical height. 266 * 267 * @throws FactoryException if a factory fails to create a referencing object. 268 * 269 * @deprecated Renamed {@link #testProjectedWithGeoidalHeight()} for making clearer that this is not 270 * a projected CRS associated to a 3D coordinate system. 271 */ 272 @Test 273 @Deprecated 274 public void testProjected3D() throws FactoryException { 275 testProjectedWithGeoidalHeight(); 276 } 277 278 /** 279 * Tests the creation of a compound CRS made of a projected CRS with a gravity-related height. 280 * 281 * @throws FactoryException if a factory fails to create a referencing object. 282 */ 283 @Test 284 public void testProjectedWithGeoidalHeight() throws FactoryException { 285 final CoordinateSystemAxis axisN, axisE, axisH, axisφ, axisλ; 286 287 final EllipsoidalCS baseCS; 288 final GeographicCRS baseCRS; 289 final GeodeticDatum baseDatum; 290 final PrimeMeridian greenwich; 291 final Ellipsoid ellipsoid; 292 293 final CartesianCS projectedCS; 294 final ProjectedCRS projectedCRS; 295 final OperationMethod projectionMethod; 296 final Conversion baseToUTM; 297 final int utmZone = 12; 298 299 final VerticalCS heightCS; 300 final VerticalCRS heightCRS; 301 final VerticalDatum heightDatum; 302 final CompoundCRS crs3D; // The final product of this method. 303 304 final Unit<Length> metre = units.metre(); 305 final Unit<Angle> degree = units.degree(); 306 307 assumeNotNull(datumFactory); 308 validators.validate(greenwich = datumFactory.createPrimeMeridian (name("Greenwich Meridian"), 0, degree)); 309 validators.validate(ellipsoid = datumFactory.createFlattenedSphere(name("WGS84 Ellipsoid"), 6378137, 298.257223563, metre)); 310 validators.validate(baseDatum = datumFactory.createGeodeticDatum (name("WGS84 Datum"), ellipsoid, greenwich)); 311 validators.validate(heightDatum = datumFactory.createVerticalDatum (name("WGS84 geoidal height"), VerticalDatumType.GEOIDAL)); 312 313 assumeNotNull(csFactory); 314 validators.validate(axisN = csFactory.createCoordinateSystemAxis(name("Northing"), "N", NORTH, metre)); 315 validators.validate(axisE = csFactory.createCoordinateSystemAxis(name("Easting"), "E", EAST, metre)); 316 validators.validate(axisH = csFactory.createCoordinateSystemAxis(name("Gravity-related Height"), "H", UP, metre)); 317 validators.validate(axisφ = csFactory.createCoordinateSystemAxis(name("Geodetic Latitude"), "φ", NORTH, degree)); 318 validators.validate(axisλ = csFactory.createCoordinateSystemAxis(name("Geodetic Longitude"), "λ", EAST, degree)); 319 validators.validate(baseCS = csFactory.createEllipsoidalCS (name("2D ellipsoidal"), axisλ, axisφ)); 320 validators.validate(projectedCS = csFactory.createCartesianCS (name("2D Cartesian CS"), axisN, axisE)); 321 validators.validate(heightCS = csFactory.createVerticalCS (name("Height CS"), axisH)); 322 323 assumeNotNull(crsFactory); 324 baseCRS = crsFactory.createGeographicCRS(name("2D geographic CRS"), baseDatum, baseCS); 325 heightCRS = crsFactory.createVerticalCRS (name("Height CRS"), heightDatum, heightCS); 326 327 assumeNotNull(copFactory); 328 validators.validate(projectionMethod = copFactory.getOperationMethod("Transverse_Mercator")); 329 final ParameterValueGroup paramUTM = projectionMethod.getParameters().createValue(); 330 paramUTM.parameter("central_meridian") .setValue(-180 + utmZone*6 - 3); 331 paramUTM.parameter("latitude_of_origin").setValue(0.0); 332 paramUTM.parameter("scale_factor") .setValue(0.9996); 333 paramUTM.parameter("false_easting") .setValue(500000.0); 334 paramUTM.parameter("false_northing") .setValue(0.0); 335 validators.validate(paramUTM); 336 337 validators.validate(baseToUTM = copFactory .createDefiningConversion(name("Transverse_Mercator"), projectionMethod, paramUTM)); 338 validators.validate(projectedCRS = crsFactory.createProjectedCRS(name("WGS 84 / UTM Zone 12 (2D)"), baseCRS, baseToUTM, projectedCS)); 339 validators.validate(crs3D = crsFactory.createCompoundCRS(name("3D Compound WGS 84 / UTM Zone 12"), projectedCRS, heightCRS)); 340 assertAxisDirectionsEqual("CompoundCRS", crs3D.getCoordinateSystem(), NORTH, EAST, UP); 341 } 342}