package org.geotools.referencing; import java.awt.RenderingHints.Key; import java.awt.geom.Point2D; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import javax.measure.unit.NonSI; import javax.measure.unit.SI; import org.geotools.factory.GeoTools; import org.geotools.factory.Hints; import org.geotools.geometry.GeneralDirectPosition; import org.geotools.geometry.jts.JTS; import org.geotools.metadata.iso.citation.Citations; import org.geotools.referencing.datum.BursaWolfParameters; import org.geotools.referencing.datum.DefaultGeodeticDatum; import org.geotools.referencing.factory.ReferencingFactoryContainer; import org.geotools.referencing.operation.DefiningConversion; import org.geotools.referencing.wkt.Formattable; import org.opengis.metadata.Identifier; import org.opengis.parameter.ParameterValueGroup; import org.opengis.referencing.FactoryException; import org.opengis.referencing.IdentifiedObject; import org.opengis.referencing.crs.CRSAuthorityFactory; import org.opengis.referencing.crs.CRSFactory; import org.opengis.referencing.crs.CoordinateReferenceSystem; 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.CoordinateSystemAxis; 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.MathTransformFactory; import org.opengis.util.GenericName; import com.vividsolutions.jts.geom.Coordinate; /** * The following examples are taken from CTSTutorial provided by Rueben Schulz. The examples were * constructed for a wiki page and have been repurposed for our sphinx documentation. * * @author Jody Garnett */ public class ReferencingExamples { private ProjectedCRS utm10NCRS; private GeographicCRS nad27CRS; ReferencingExamples() { try { premadeObjects(); creatCRSFromWKT(); createFromEPSGCode(); createFromEPSGCode2(); createCRSByHand1(); createCRSByHand2(); createCRSByHand3(); // createMathTransformBetweenCRSs(); // transformUsingCRSUtility(); // createAndUseMathTransform(); // hintExample(); // createTransformFromAuthorityCode(); toWKT(); toWKTFormat(); } catch (Exception e) { e.printStackTrace(); } } void factories() { // factories start Hints hints = null; // configure hints for the group of factories ReferencingFactoryContainer group = new ReferencingFactoryContainer(hints); CRSFactory crsFactory = group.getCRSFactory(); CSFactory csFactory = group.getCSFactory(); DatumFactory datumFactory = group.getDatumFactory(); // factories end } void referencingFactoryContainer() { Object datumFactory = null; Object csFactory = null; Object crsFactory = null; Object mtFactory = null; // referencingFactoryContainer start Map<Key, Object> map = new HashMap<Key, Object>(); map.put(Hints.DATUM_FACTORY, datumFactory); map.put(Hints.CS_FACTORY, csFactory); map.put(Hints.CRS_FACTORY, crsFactory); map.put(Hints.MATH_TRANSFORM_FACTORY, mtFactory); Hints hints = new Hints(map); ReferencingFactoryContainer container = new ReferencingFactoryContainer(hints); // referencingFactoryContainer end } void referencingFactoryContainer2() { // referencingFactoryContainer2 start Hints hints = GeoTools.getDefaultHints(); DatumFactory datumFactory = ReferencingFactoryFinder.getDatumFactory( hints ); ReferencingFactoryContainer container = new ReferencingFactoryContainer( hints ); if( datumFactory == container.getDatumFactory() ){ System.out.println( "Will be the same DatumFactory"); } // referencingFactoryContainer2 end } /** * A method with some examples of premade static objects. */ void premadeObjects() { // premadeObjects start GeographicCRS geoCRS = org.geotools.referencing.crs.DefaultGeographicCRS.WGS84; GeodeticDatum wgs84Datum = org.geotools.referencing.datum.DefaultGeodeticDatum.WGS84; PrimeMeridian greenwichMeridian = org.geotools.referencing.datum.DefaultPrimeMeridian.GREENWICH; CartesianCS cartCS = org.geotools.referencing.cs.DefaultCartesianCS.GENERIC_2D; CoordinateSystemAxis latAxis = org.geotools.referencing.cs.DefaultCoordinateSystemAxis.GEODETIC_LATITUDE; // premadeObjects end } /** * An example of creating a CRS from a WKT string. Additional examples of WKT strings can be found * in http://svn.geotools.org/geotools/trunk/gt/module/referencing/test/org/geotools/referencing * /test-data/ * * @throws Exception */ void creatCRSFromWKT() throws Exception { System.out.println("------------------------------------------"); System.out.println("Creating a CRS from a WKT string:"); // creatCRSFromWKT start CRSFactory crsFactory = ReferencingFactoryFinder.getCRSFactory(null); String wkt = "PROJCS[\"UTM_Zone_10N\", " + "GEOGCS[\"WGS84\", " + "DATUM[\"WGS84\", " + "SPHEROID[\"WGS84\", 6378137.0, 298.257223563]], " + "PRIMEM[\"Greenwich\", 0.0], " + "UNIT[\"degree\",0.017453292519943295], " + "AXIS[\"Longitude\",EAST], " + "AXIS[\"Latitude\",NORTH]], " + "PROJECTION[\"Transverse_Mercator\"], " + "PARAMETER[\"semi_major\", 6378137.0], " + "PARAMETER[\"semi_minor\", 6356752.314245179], " + "PARAMETER[\"central_meridian\", -123.0], " + "PARAMETER[\"latitude_of_origin\", 0.0], " + "PARAMETER[\"scale_factor\", 0.9996], " + "PARAMETER[\"false_easting\", 500000.0], " + "PARAMETER[\"false_northing\", 0.0], " + "UNIT[\"metre\",1.0], " + "AXIS[\"x\",EAST], " + "AXIS[\"y\",NORTH]]"; CoordinateReferenceSystem crs = crsFactory.createFromWKT(wkt); // creatCRSFromWKT end System.out.println(" CRS: " + crs.toWKT()); System.out.println("Identified CRS object:"); printIdentifierStuff(crs); System.out.println("Identified Datum object:"); printIdentifierStuff(((ProjectedCRS) crs).getDatum()); System.out.println("------------------------------------------"); } /** * Creates a CRS from an EPSG code. There are a few different EPSG authority factories in geotools * that do roughly the same thing: * * <ul> * <li>gt2-epsg-access.jar is backed by the official EPSG MS Access database (only works on MS * Windows, therefore I have not shown how to configure it here).</li> * <li>gt2-epsg-hsql.jar provides an embeded hsql database created from the EPSG SQL scripts. This * contains the same information as the MS Arcess database.</li> * <li>other factories allow the EPSG information to be in an external database (postgresql, mysql, * oracle)</li> * <li>gt2-epsg-wkt.jar is a simple properties file with WKT descriptions for EPSG defined CRS * codes. This file does not derive directly from the official EPSG database, so its should be used * with caution. It provides a very simple method of creating a new authority factory and named * objects.</li> * </ul> * * The specific authority factory returned by getCRSAuthorityFactory is dependent on the different * factories on your classpath (ie WKT or Access or HSQL) and the hints you provide. By default the * "better" authority factory should be used if more than one is available. * * TODO check on the use of hints TODO expand on how to use EPSG data in a postgres db (this may be * a 2.2 feature, but FactoryUsingANSISQL may work) * */ void createFromEPSGCode2() throws Exception { System.out.println("------------------------------------------"); System.out.println("Creating a CRS from an authority factory:"); // createFromEPSGCode2 start String code = "26910"; CRSAuthorityFactory crsAuthorityFactory = ReferencingFactoryFinder.getCRSAuthorityFactory( "EPSG", null); CoordinateReferenceSystem crs = crsAuthorityFactory.createCoordinateReferenceSystem(code); // createFromEPSGCode2 end System.out.println(" CRS: " + crs.toWKT()); System.out.println("Identified CRS object:"); printIdentifierStuff(crs); System.out.println("------------------------------------------"); } /** Creating using the CRS facade */ void createFromEPSGCode() throws Exception { System.out.println("------------------------------------------"); System.out.println("Creating a CRS from an authority factory:"); // createFromEPSGCode start CoordinateReferenceSystem crs = CRS.decode("EPSG:26910", false); // createFromEPSGCode end System.out.println(" CRS: " + crs.toWKT()); System.out.println("Identified CRS object:"); printIdentifierStuff(crs); System.out.println("------------------------------------------"); } /** * Creates a WGS 84/UTM Zone 10N CRS mostly (uses some premade objects) by hand. Uses the higher * level FactoryGroup instead of the lower level MathTransformFactory (commented out). * * @throws Exception */ void createCRSByHand1() throws Exception { System.out.println("------------------------------------------"); System.out.println("Creating a CRS by hand:"); // createCRSByHand1 start MathTransformFactory mtFactory = ReferencingFactoryFinder.getMathTransformFactory(null); CRSFactory crsFactory = ReferencingFactoryFinder.getCRSFactory(null); GeographicCRS geoCRS = org.geotools.referencing.crs.DefaultGeographicCRS.WGS84; CartesianCS cartCS = org.geotools.referencing.cs.DefaultCartesianCS.GENERIC_2D; ParameterValueGroup parameters = mtFactory.getDefaultParameters("Transverse_Mercator"); parameters.parameter("central_meridian").setValue(-111.0); parameters.parameter("latitude_of_origin").setValue(0.0); parameters.parameter("scale_factor").setValue(0.9996); parameters.parameter("false_easting").setValue(500000.0); parameters.parameter("false_northing").setValue(0.0); Conversion conversion = new DefiningConversion("Transverse_Mercator", parameters); Map<String, ?> properties = Collections.singletonMap("name", "WGS 84 / UTM Zone 12N"); ProjectedCRS projCRS = crsFactory.createProjectedCRS(properties, geoCRS, conversion, cartCS); // createCRSByHand1 end // parameters.parameter("semi_major").setValue(((GeodeticDatum)geoCRS.getDatum()).getEllipsoid().getSemiMajorAxis()); // parameters.parameter("semi_minor").setValue(((GeodeticDatum)geoCRS.getDatum()).getEllipsoid().getSemiMinorAxis()); // MathTransform trans = mtFactory.createParameterizedTransform(parameters); // ProjectedCRS projCRS = crsFactory.createProjectedCRS( // Collections.singletonMap("name", "WGS 84 / UTM Zone 12N"), // new org.geotools.referencing.operation.OperationMethod(trans), // geoCRS, trans, cartCS); System.out.println(" Projected CRS: " + projCRS.toWKT()); System.out.println("------------------------------------------"); // save for later use in createMathTransformBetweenCRSs() this.utm10NCRS = projCRS; } /** * Creates a NAD 27 geographic CRS. Notice that the datum factory automatically adds aliase names to * the datum (because "North American Datum 1927" has an entry in http://svn.geotools.org * /geotools/trunk/gt/module/referencing/src/org/geotools/referencing/factory /DatumAliasesTable.txt * ). Also notice that toWGS84 information (used in a datum transform) was also added to the datum. */ void createCRSByHand2() throws Exception { System.out.println("------------------------------------------"); System.out.println("Creating a CRS by hand:"); // createCRSByHand2 start CRSFactory crsFactory = ReferencingFactoryFinder.getCRSFactory(null); DatumFactory datumFactory = ReferencingFactoryFinder.getDatumFactory(null); CSFactory csFactory = ReferencingFactoryFinder.getCSFactory(null); Map<String, Object> map = new HashMap<String, Object>(); map.put("name", "Clarke 1866"); Ellipsoid clark1866ellipse = datumFactory.createFlattenedSphere(map, 6378206.4, 294.978698213901, SI.METER); PrimeMeridian greenwichMeridian = org.geotools.referencing.datum.DefaultPrimeMeridian.GREENWICH; final BursaWolfParameters toWGS84 = new BursaWolfParameters(DefaultGeodeticDatum.WGS84); toWGS84.dx = -3.0; toWGS84.dy = 142; toWGS84.dz = 183; map.clear(); map.put("name", "North American Datum 1927"); map.put(DefaultGeodeticDatum.BURSA_WOLF_KEY, toWGS84); GeodeticDatum clark1866datum = datumFactory.createGeodeticDatum(map, clark1866ellipse, greenwichMeridian); System.out.println(clark1866datum.toWKT()); // notice all of the lovely datum aliases (used to determine if two // datums are the same) System.out.println("Identified Datum object:"); printIdentifierStuff(clark1866datum); map.clear(); map.put("name", "<lat>, <long>"); CoordinateSystemAxis latAxis = org.geotools.referencing.cs.DefaultCoordinateSystemAxis.GEODETIC_LATITUDE; CoordinateSystemAxis longAxis = org.geotools.referencing.cs.DefaultCoordinateSystemAxis.GEODETIC_LONGITUDE; EllipsoidalCS ellipsCS = csFactory.createEllipsoidalCS(map, latAxis, longAxis); map.clear(); map.put("name", "NAD 27"); map.put("authority", "9999"); // TODO add an authority code here (should be an identifier) GeographicCRS nad27CRS = crsFactory.createGeographicCRS(map, clark1866datum, ellipsCS); // createCRSByHand2 end System.out.println(nad27CRS.toWKT()); System.out.println("Identified CRS object:"); printIdentifierStuff(nad27CRS); System.out.println("------------------------------------------"); // save for latter use in createMathTransformBetweenCRSs() this.nad27CRS = nad27CRS; } /** * Creates two coordinate reference system by hand without using any of the GT2 APIs (except * FactoryFinder to get things started). It does not use any of the static objects available in * geotools implementations. The following example creates a CRS to represent the Airy 1830 * ellipsoid with the incoming data in the order of (long,lat,height) and a geocentric CRS with * (x,y,z) axises. * * TODO the Airy CRS described below is actually wgs84, FIX this. * * @throws FactoryException */ void createCRSByHand3() throws FactoryException { System.out.println("------------------------------------------"); System.out.println("Creating two CRSs by hand:"); // createCRSByHand3 start CRSFactory crsFactory = ReferencingFactoryFinder.getCRSFactory(null); DatumFactory datumFactory = ReferencingFactoryFinder.getDatumFactory(null); CSFactory csFactory = ReferencingFactoryFinder.getCSFactory(null); Map<String, Object> map = new HashMap<String, Object>(); // // Create a datum used for each CRS // map.clear(); map.put("name", "Greenwich Meridian"); PrimeMeridian greenwichMeridian = datumFactory.createPrimeMeridian(map, 0, NonSI.DEGREE_ANGLE); map.clear(); map.put("name", "WGS 84 Ellipsoid Datum"); Ellipsoid wgs84Ellipsoid = datumFactory.createFlattenedSphere(map, 6378137, 298.257223563, SI.METER); map.clear(); map.put("name", "WGS84 Height Datum"); GeodeticDatum wgs84Datum = datumFactory.createGeodeticDatum(map, wgs84Ellipsoid, greenwichMeridian); // // Create a geocentric CRS // // Create a collection of axes for the coordinate system. map.clear(); map.put("name", "Cartesian X axis"); CoordinateSystemAxis xAxis = csFactory.createCoordinateSystemAxis(map, "X", AxisDirection.GEOCENTRIC_X, SI.METER); map.clear(); map.put("name", "Cartesian Y axis"); CoordinateSystemAxis yAxis = csFactory.createCoordinateSystemAxis(map, "Y", AxisDirection.GEOCENTRIC_Y, SI.METER); map.clear(); map.put("name", "Cartesian Z axis"); CoordinateSystemAxis zAxis = csFactory.createCoordinateSystemAxis(map, "Z", AxisDirection.GEOCENTRIC_Z, SI.METER); map.clear(); map.put("name", "Rendered Cartesian CS"); CartesianCS worldCS = csFactory.createCartesianCS(map, xAxis, yAxis, zAxis); // Now, the geocentric coordinate reference system that we'd use for output - eg to a 3D // renderer map.clear(); map.put("name", "Output Cartesian CS"); CoordinateReferenceSystem geocentricCRS = crsFactory.createGeocentricCRS(map, wgs84Datum, worldCS); System.out.println("Geocentric CRS: " + geocentricCRS.toWKT()); // // Create a geograyhic CRS for the Airy 1830 ellipsoid // map.clear(); // map.put("name", "Airy 1830"); // Ellipsoid airyEllipse = // datumFactory.createFlattenedSphere(map, 6377563.396, 299.3249646, SI.METER); map.clear(); map.put("name", "Geodetic North axis"); CoordinateSystemAxis northAxis = csFactory.createCoordinateSystemAxis(map, "N", AxisDirection.NORTH, NonSI.DEGREE_ANGLE); map.clear(); map.put("name", "Geodetic East axis"); CoordinateSystemAxis eastAxis = csFactory.createCoordinateSystemAxis(map, "E", AxisDirection.EAST, NonSI.DEGREE_ANGLE); map.clear(); map.put("name", "Geodetic Height axis"); CoordinateSystemAxis heightAxis = csFactory.createCoordinateSystemAxis(map, "Up", AxisDirection.UP, SI.METER); map.clear(); map.put("name", "<long>,<lat> Airy 1830 geodetic"); EllipsoidalCS airyCS = csFactory.createEllipsoidalCS(map, eastAxis, northAxis, heightAxis); // finally create the source geographic CRS CoordinateReferenceSystem airyCRS = crsFactory.createGeographicCRS(map, wgs84Datum, airyCS); // createCRSByHand3 end // TODO crs.toWKT() throws exceptions here (.toString() works) System.out.println("Geographic CRS: " + airyCRS.toString()); System.out.println("Identified CRS object:"); printIdentifierStuff(airyCRS); System.out.println("Identified Datum object:"); printIdentifierStuff(((GeographicCRS) airyCRS).getDatum()); // you could now use these two CRS's to create a transform between them // as done below in createMathTransformBetweenCRSs(). The transform can // be used to convert points from lat,long to geocentric x,y,z. System.out.println("------------------------------------------"); } /** * Print out information about an identified object */ // START SNIPPET: identifiedObject void printIdentifierStuff(IdentifiedObject identObj) { System.out.println(" getName().getCode() - " + identObj.getName().getCode()); System.out.println(" getName().getAuthority() - " + identObj.getName().getAuthority()); System.out.println(" getRemarks() - " + identObj.getRemarks()); System.out.println(" getAliases():"); Iterator<GenericName> aliases = identObj.getAlias().iterator(); if (!aliases.hasNext()) { System.out.println(" no aliases"); } else { for (int i = 0; aliases.hasNext(); i++) { System.out.println(" alias(" + i + "): " + (GenericName) aliases.next()); } } System.out.println(" getIdentifiers():"); // Identifier[] Iterator<? extends Identifier> idents = identObj.getIdentifiers().iterator(); if (!idents.hasNext()) { System.out.println(" no extra identifiers"); } else { for (int i = 0; idents.hasNext(); i++) { Identifier ident = idents.next(); System.out.println(" identifier(" + i + ").getCode() - " + ident.getCode()); System.out .println(" identifier(" + i + ").getAuthority() - " + ident.getAuthority()); } } } //END SNIPPET: identifiedObject public void distance() throws Exception { Coordinate start = null; Coordinate end = null; CoordinateReferenceSystem crs = null; // distance start // the following code is based on JTS.orthodromicDistance( start, end, crs ) GeodeticCalculator gc = new GeodeticCalculator(crs); gc.setStartingPosition( JTS.toDirectPosition( start, crs ) ); gc.setDestinationPosition( JTS.toDirectPosition( end, crs ) ); double distance = gc.getOrthodromicDistance(); int totalmeters = (int) distance; int km = totalmeters / 1000; int meters = totalmeters - (km * 1000); float remaining_cm = (float) (distance - totalmeters) * 10000; remaining_cm = Math.round(remaining_cm); float cm = remaining_cm / 100; System.out.println("Distance = " + km + "km " + meters + "m " + cm + "cm"); // distance end // angle start double angle = gc.getAzimuth(); System.out.println("Angle = " + angle ); // angle end } public void movePoint() { // movePoint start GeodeticCalculator calc = new GeodeticCalculator(); // mind, this is lon/lat calc.setStartingGeographicPoint(45.4644, 9.1908); calc.setDirection(90 /* azimuth */, 200/* distance */); Point2D dest = calc.getDestinationGeographicPoint(); System.out.println("Longitude: " + dest.getX() + " Latitude: " + dest.getY()); // movePoint end } public void toWKT() throws Exception { // toWKT start CoordinateReferenceSystem crs = CRS.decode("EPSG:32735"); String wkt = crs.toWKT(); System.out.println("wkt for EPSG:32735"); System.out.println( wkt ); // toWKT end } public void toWKTFormat() throws Exception { // toWKTFormat start CoordinateReferenceSystem crs = CRS.decode("EPSG:32735"); Formattable f = (Formattable) CRS.decode("EPSG:32735", true); String wkt = f.toWKT(Citations.ESRI, 2); // use 0 indent for single line System.out.println("wkt for EPSG:32735 (ESRI)"); System.out.println( wkt ); // toWKTFormat end } public static void main(String[] args) { new ReferencingExamples(); } }