/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2003-2008, Open Source Geospatial Foundation (OSGeo) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ package org.geotools.referencing; import java.io.PrintStream; import java.io.PrintWriter; import java.io.StringWriter; import java.util.Collection; import java.util.Collections; import java.util.Map; import javax.measure.unit.NonSI; import javax.measure.unit.SI; import javax.measure.unit.Unit; import javax.measure.quantity.Angle; import javax.measure.quantity.Length; import org.opengis.parameter.ParameterValueGroup; import org.opengis.referencing.FactoryException; import org.opengis.referencing.crs.CRSFactory; import org.opengis.referencing.crs.GeographicCRS; import org.opengis.referencing.crs.ProjectedCRS; import org.opengis.referencing.cs.AxisDirection; import org.opengis.referencing.cs.CSFactory; import org.opengis.referencing.cs.CartesianCS; import org.opengis.referencing.cs.EllipsoidalCS; import org.opengis.referencing.datum.DatumFactory; import org.opengis.referencing.datum.Ellipsoid; import org.opengis.referencing.datum.GeodeticDatum; import org.opengis.referencing.datum.PrimeMeridian; import org.opengis.referencing.operation.Conversion; import org.opengis.referencing.operation.MathTransform; import org.opengis.referencing.operation.MathTransformFactory; import org.opengis.referencing.operation.OperationMethod; import org.opengis.referencing.operation.Projection; import org.opengis.util.GenericName; import org.opengis.util.ScopedName; import org.geotools.factory.Hints; import org.geotools.referencing.factory.DatumAliases; import org.geotools.referencing.factory.ReferencingObjectFactory; import org.geotools.referencing.factory.ReferencingFactoryContainer; import org.geotools.referencing.cs.DefaultCartesianCS; import org.geotools.referencing.datum.DefaultEllipsoid; import org.geotools.referencing.datum.DefaultPrimeMeridian; import org.geotools.referencing.crs.DefaultGeographicCRS; import org.geotools.referencing.operation.DefiningConversion; import org.geotools.referencing.operation.projection.MapProjection; import org.junit.*; import static org.junit.Assert.*; /** * Tests the creation of {@link CoordinateReferenceSystem} objects and dependencies through * factories (not authority factories). * * * @source $URL$ * @version $Id$ */ public final class FactoriesTest { /** * The output stream. Can be redirected to the standard output stream for debugging. */ private static PrintStream out = System.out; /** * Convenience method creating a map with only the "name" property. * This is the only mandatory property for object creation. */ private static Map<String,?> name(final String name) { return Collections.singletonMap("name", name); } /** * Tests the creation of new coordinate reference systems. * * @throws FactoryException if a coordinate reference system can't be created. */ @Test public void testCreation() throws FactoryException { out.println(); out.println("Testing CRS creations"); out.println("---------------------"); out.println(); out.println("create Coodinate Reference System....1: "); final DatumFactory datumFactory = ReferencingFactoryFinder.getDatumFactory (null); final CSFactory csFactory = ReferencingFactoryFinder.getCSFactory (null); final CRSFactory crsFactory = ReferencingFactoryFinder.getCRSFactory (null); final MathTransformFactory mtFactory = ReferencingFactoryFinder.getMathTransformFactory(null); final Ellipsoid airy1830; final Unit<Length> meters = SI.METER; airy1830 = datumFactory.createEllipsoid(name("Airy1830"), 6377563.396, 6356256.910, meters); out.println(); out.println("create Coodinate Reference System....2: "); out.println(airy1830.toWKT()); final PrimeMeridian greenwich; final Unit<Angle> degrees = NonSI.DEGREE_ANGLE; greenwich = datumFactory.createPrimeMeridian(name("Greenwich"), 0, degrees); out.println(); out.println("create Coodinate Reference System....3: "); out.println(greenwich.toWKT()); // NOTE: we could use the following pre-defined constant instead: // DefaultPrimeMeridian.GREENWICH; final GeodeticDatum datum; datum = datumFactory.createGeodeticDatum(name("Airy1830"), airy1830, greenwich); out.println(); out.println("create Coodinate Reference System....4: "); out.println(datum.toWKT()); // NOTE: we could use the following pre-defined constant instead: // DefaultEllipsoidalCS.GEODETIC_2D; final EllipsoidalCS ellCS; ellCS = csFactory.createEllipsoidalCS(name("Ellipsoidal"), csFactory.createCoordinateSystemAxis(name("Longitude"), "long", AxisDirection.EAST, degrees), csFactory.createCoordinateSystemAxis(name("Latitude"), "lat", AxisDirection.NORTH, degrees)); out.println(); out.println("create Coodinate Reference System....5: "); out.println(ellCS); // No WKT for coordinate systems final GeographicCRS geogCRS; geogCRS = crsFactory.createGeographicCRS(name("Airy1830"), datum, ellCS); out.println(); out.println("create Coodinate Reference System....6: "); out.println(geogCRS.toWKT()); final MathTransform p; final ParameterValueGroup param = mtFactory.getDefaultParameters("Transverse_Mercator"); param.parameter("semi_major") .setValue(airy1830.getSemiMajorAxis()); param.parameter("semi_minor") .setValue(airy1830.getSemiMinorAxis()); param.parameter("central_meridian") .setValue( 49); param.parameter("latitude_of_origin").setValue( -2); param.parameter("false_easting") .setValue( 400000); param.parameter("false_northing") .setValue(-100000); out.println(); out.println("create Coodinate System....7: "); out.println(param); // NOTE: we could use the following pre-defined constant instead: // DefaultCartesianCS.PROJECTED; final CartesianCS cartCS; cartCS = csFactory.createCartesianCS(name("Cartesian"), csFactory.createCoordinateSystemAxis(name("Easting"), "x", AxisDirection.EAST, meters), csFactory.createCoordinateSystemAxis(name("Northing"), "y", AxisDirection.NORTH, meters)); out.println(); out.println("create Coodinate Reference System....8: "); out.println(cartCS); // No WKT for coordinate systems final Hints hints = new Hints(); hints.put(Hints.DATUM_FACTORY, datumFactory); hints.put(Hints.CS_FACTORY, csFactory); hints.put(Hints.CRS_FACTORY, crsFactory); hints.put(Hints.MATH_TRANSFORM_FACTORY, mtFactory); final ReferencingFactoryContainer container = new ReferencingFactoryContainer(hints); assertSame(datumFactory, container.getDatumFactory()); assertSame(csFactory, container.getCSFactory()); assertSame(crsFactory, container.getCRSFactory()); assertSame(mtFactory, container.getMathTransformFactory()); final Conversion conversion = new DefiningConversion("GBN grid", param); final ProjectedCRS projCRS = crsFactory.createProjectedCRS( name("Great_Britian_National_Grid"), geogCRS, conversion, cartCS); out.println(); out.println("create Coodinate System....9: "); out.println(projCRS.toWKT()); } /** * Tests all map projection creation. * * @throws FactoryException If a CRS can not be created. */ @Test public void testMapProjections() throws FactoryException { out.println(); out.println("Testing classification names"); out.println("----------------------------"); final CRSFactory crsFactory = ReferencingFactoryFinder.getCRSFactory(null); final MathTransformFactory mtFactory = ReferencingFactoryFinder.getMathTransformFactory(null); final Collection<OperationMethod> methods = mtFactory.getAvailableMethods(Projection.class); final Map<String,?> dummyName = Collections.singletonMap("name", "Test"); for (final OperationMethod method : methods) { final String classification = method.getName().getCode(); final ParameterValueGroup param = mtFactory.getDefaultParameters(classification); try { param.parameter("semi_major").setValue(6377563.396); param.parameter("semi_minor").setValue(6356256.909237285); } catch (IllegalArgumentException e) { // Above parameters do not exists. Ignore. } final MathTransform mt; try { mt = mtFactory.createParameterizedTransform(param); } catch (FactoryException e) { // Probably not a map projection. This test is mostly about projection, so ignore. continue; } catch (UnsupportedOperationException e) { continue; } if (mt instanceof MapProjection) { /* * Tests map projection properties. Some tests are ommitted for south-oriented * map projections, since they are implemented as a concatenation of their North- * oriented variants with an affine transform. */ out.println(classification); final boolean skip = classification.equalsIgnoreCase("Transverse Mercator (South Orientated)") || classification.equalsIgnoreCase("Equidistant_Cylindrical"); if (!skip) { assertEquals(classification, ((MapProjection) mt).getParameterDescriptors().getName().getCode()); } final ProjectedCRS projCRS = crsFactory.createProjectedCRS(dummyName, DefaultGeographicCRS.WGS84, new DefiningConversion(dummyName, method, mt), DefaultCartesianCS.PROJECTED); final Conversion conversion = projCRS.getConversionFromBase(); assertSame(mt, conversion.getMathTransform()); final OperationMethod projMethod = conversion.getMethod(); assertEquals(classification, projMethod.getName().getCode()); } } } /** * Tests datum aliases. Note: ellipsoid and prime meridian are dummy values just * (not conform to the usage in real world) just for testing purpose. * * @throws FactoryException If a CRS can not be created. */ @Test public void testDatumAliases() throws FactoryException { final String name0 = "Nouvelle Triangulation Francaise (Paris)"; final String name1 = "Nouvelle_Triangulation_Francaise_Paris"; final String name2 = "D_NTF"; final String name3 = "NTF (Paris meridian)"; final Ellipsoid ellipsoid = DefaultEllipsoid.WGS84; final PrimeMeridian meridian = DefaultPrimeMeridian.GREENWICH; DatumFactory factory = new ReferencingObjectFactory(); final Map<String,?> properties = Collections.singletonMap("name", name1); GeodeticDatum datum = factory.createGeodeticDatum(properties, ellipsoid, meridian); assertTrue(datum.getAlias().isEmpty()); for (int i=0; i<3; i++) { switch (i) { case 0: factory = new DatumAliases(factory); break; case 1: factory = ReferencingFactoryFinder.getDatumFactory(null); break; case 2: ((DatumAliases) factory).freeUnused(); break; default: throw new AssertionError(); // Should not occurs. } final String pass = "Pass #"+i; datum = factory.createGeodeticDatum(properties, ellipsoid, meridian); final GenericName[] aliases = datum.getAlias().toArray(new GenericName[0]); assertEquals(pass, 4, aliases.length); assertEquals(pass, name0, aliases[0].tip().toString()); assertEquals(pass, name1, aliases[1].tip().toString()); assertEquals(pass, name2, aliases[2].tip().toString()); assertEquals(pass, name3, aliases[3].tip().toString()); assertTrue (pass, aliases[0] instanceof ScopedName); assertTrue (pass, aliases[1] instanceof ScopedName); assertTrue (pass, aliases[2] instanceof ScopedName); assertTrue (pass, aliases[3] instanceof ScopedName); } datum = factory.createGeodeticDatum(Collections.singletonMap("name", "Tokyo"), ellipsoid, meridian); Collection<GenericName> aliases = datum.getAlias(); assertEquals(4, aliases.size()); ((DatumAliases) factory).freeUnused(); datum = factory.createGeodeticDatum(Collections.singletonMap("name", "_toKyo _"), ellipsoid, meridian); assertEquals(4, datum.getAlias().size()); assertTrue(aliases.equals(datum.getAlias())); datum = factory.createGeodeticDatum(Collections.singletonMap("name", "D_Tokyo"), ellipsoid, meridian); assertEquals(4, datum.getAlias().size()); datum = factory.createGeodeticDatum(Collections.singletonMap("name", "Luxembourg 1930"), ellipsoid, meridian); assertEquals(3, datum.getAlias().size()); datum = factory.createGeodeticDatum(Collections.singletonMap("name", "Dummy"), ellipsoid, meridian); assertTrue("Non existing datum should have no alias.", datum.getAlias().isEmpty()); datum = factory.createGeodeticDatum(Collections.singletonMap("name", "WGS 84"), ellipsoid, meridian); assertTrue (AbstractIdentifiedObject.nameMatches(datum, "WGS 84")); assertTrue (AbstractIdentifiedObject.nameMatches(datum, "WGS_1984")); assertTrue (AbstractIdentifiedObject.nameMatches(datum, "World Geodetic System 1984")); assertFalse(AbstractIdentifiedObject.nameMatches(datum, "WGS 72")); } }