Internal¶
Please note that this page is optional and only for the curious. It covers some of the implementation classes.
A CoordinateReferenceSystem is a gt-opengis interface describing how a set of
ordinates is to be interpreted as a three dimensional point. This definition is standardized,
mathematical and generally not of interest unless something goes wrong.
CoordinateReferenceSystem¶
For most cases you are only interested in using a CoordinateReferenceSystem as a parameter to a
mathematical calculation (distance along the surface of the earth and “re-projection”
being the most common).
Creating a CoordinateReferenceSystem:
CoordinateReferenceSystem crs = CRS.decode("EPSG:26910", false);
You will need to ensure GeoTools is configured with an appropriate plugin for this example to work.
This plugin will provide an CRSAuthorityFactory registered for “EPSG” codes.
CRSAuthorityFactory¶
Internally the CRS class makes use of a CRSAuthorityFactory to provide the definition for
the indicated code. If you wish you can make use of the same facilities directly:
String code = "26910";
CRSAuthorityFactory crsAuthorityFactory =
ReferencingFactoryFinder.getCRSAuthorityFactory("EPSG", null);
CoordinateReferenceSystem crs = crsAuthorityFactory.createCoordinateReferenceSystem(code);
To create the actual CoordinateReferenceSystem object a CRSFactory is used, for example when parsing a “well known text” (WKT) definition:
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);
Where the code above corresponds to this definition:
GEOGCS[
"WGS 84",
DATUM[
"WGS_1984",
SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],
TOWGS84[0,0,0,0,0,0,0],
AUTHORITY["EPSG","6326"]],
PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],
UNIT["DMSH",0.0174532925199433,AUTHORITY["EPSG","9108"]],
AXIS["Lat",NORTH],
AXIS["Long",EAST],
AUTHORITY["EPSG","4326"]]
Creating a CoordinateReferenceSystem¶
You can use factories defined by the referencing system to create things by hand using java code.
This example shows the creation of a WGS84 / UTM 10N CoordinateReferenceSystem:
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);
The next example shows NAD 27 geographic CRS being defined, with a couple of interesting things to note:
The datum factory automatically adds alias names to the datum. (The
DatumAliasesTable.txtfile insidegt-referencinghas an entry for “North American Datum 1927”).The
toWGS84information being supplied for use in a datum transform is added to the Datum
Here is the example:
CRSFactory crsFactory = ReferencingFactoryFinder.getCRSFactory(null);
DatumFactory datumFactory = ReferencingFactoryFinder.getDatumFactory(null);
CSFactory csFactory = ReferencingFactoryFinder.getCSFactory(null);
Map<String, Object> map = new HashMap<>();
map.put("name", "Clarke 1866");
Ellipsoid clark1866ellipse =
datumFactory.createFlattenedSphere(map, 6378206.4, 294.978698213901, SI.METRE);
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);
Finally, here is no-holds-barred creation of a CoordinateReferenceSystem with all the usual helper classes
stripped away. It does not use any of the static objects available in GeoTools. The following example
creates a CoordinateReferenceSystem to represent WGS84.
CRSFactory crsFactory = ReferencingFactoryFinder.getCRSFactory(null);
DatumFactory datumFactory = ReferencingFactoryFinder.getDatumFactory(null);
CSFactory csFactory = ReferencingFactoryFinder.getCSFactory(null);
Map<String, Object> map = new HashMap<>();
//
// 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.METRE);
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.METRE);
map.clear();
map.put("name", "Cartesian Y axis");
CoordinateSystemAxis yAxis =
csFactory.createCoordinateSystemAxis(
map, "Y", AxisDirection.GEOCENTRIC_Y, SI.METRE);
map.clear();
map.put("name", "Cartesian Z axis");
CoordinateSystemAxis zAxis =
csFactory.createCoordinateSystemAxis(
map, "Z", AxisDirection.GEOCENTRIC_Z, SI.METRE);
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.METRE);
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.METRE);
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);
Referencing Factories¶
These are the “real” factories - interfaces that actually create stuff. All are gt-opengis interfaces, so you will need
to use ReferencingFactoryFinder to get started:
DatumFactory: Makes datums!CSFactoryMakesCoordinateSysteminstances, and many moreCRSFactoryMakesCoordinateReferenceSysteminstances, and many moreMathTransformFactoryMakesMathTransforminstances, and many more
You can quickly grab all four factories at once using ReferencingFactoryContainer:
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();
ReferencingFactoryFinderAs is custom we have included a
FactoryFinderso you can look up a good implementation on the CLASSPATH:DatumFactory datumFactory = ReferencingFactoryFinder.getDatumFactory(null);
The
ReferencingFactoryFinderreturns a couple of GeoTools implementations right now, in the future we hope to replace these defaults with an implementation fromJScience.ReferencingFactoryContainerYou may have noticed that to actually do anything you need several factories. We have gathered these together into a “container” for you. The container also adds a few more methods which use a couple of factories to gang up on a problem
You can set up
ReferencingFactoryContainerto use your own custom factory using hints as shown below:Map<Key, Object> map = new HashMap<>(); 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);
Please note that ReferencingFactoryContainer is not strictly needed, it just makes things easier. ReferencingFactoryFinder will be smart and recycle instances where possible:
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"); }
Referencing Authority Factories¶
Deep behind that CRS utility class is an amazing constellation of “factories” used to define what a
CoordinateReferenceSystem is, actually create the parts, and finally stitch them all together in a
unified whole.
These things are factories in name only; their real job is to supply the definitions (in pattern speak they would be called builders).
DatumAuthorityFactory: Defines a Datum using a code provided by a authority such as EPSGCSAuthorityFactory: Defines aCoordinateSystemusing a code provided by an authority such as EPSGCRSAuthorityFactory: Defines aCoordinateReferenceSystemfor a given authority (such as EPSG)CoordinateOperationAuthorityFactory: Defines coordinate operations from codes, backed by math transforms
To actually perform their function these authorities acquire a definition internally and then call a “real” factory class from ReferencingFactoryContainer.
Getting the EPSG
AuthorityFactoryYou can make direct use of the
CRSAuthorityFactoryconfigured to handle “EPSG” codes:CRSAuthorityFactory factory = ReferencingFactoryFinder.getCRSAuthorityFactory("EPSG", null); CoordinateReferenceSystem crs = factory.createCoordinateReferenceSystem("4326");
You will need to make sure that one of the epsg plugins is on your CLASSPATH (such as epsg-hsql).
Finding the available EPSG Codes:
CRSAuthorityFactory factory = ReferencingFactoryFinder.getCRSAuthorityFactory("EPSG", null); Set<String> authorityCodes = factory.getAuthorityCodes(CoordinateReferenceSystem.class);
Getting Other
AuthorityFactoryInstancesHere are several more examples that are understood by GeoTools:
Hints hints = null; // Put optional hints here. CRSAuthorityFactory crsAuthority = ReferencingFactoryFinder.getCRSAuthorityFactory("CRS", hints); CRSAuthorityFactory wms2Authority = ReferencingFactoryFinder.getCRSAuthorityFactory("AUTO", hints); CRSAuthorityFactory wms3Authority = ReferencingFactoryFinder.getCRSAuthorityFactory("AUTO2", hints);
IdentifiedObjectFinder for Controlled SearchingOne bit of functionality that is not available via the
CRSAuthorityinterfaces directly is the ability to carefully search through all the available definitions.:CRSAuthorityFactory factory = ReferencingFactoryFinder.getCRSAuthorityFactory("EPSG", null); AbstractAuthorityFactory custom = (AbstractAuthorityFactory) factory; IdentifiedObjectFinder finder = custom.getIdentifiedObjectFinder(CoordinateReferenceSystem.class); finder.setFullScanAllowed(true); // will search everything ever defined (may be slow) IdentifiedObject find = finder.find(crs); finder.setFullScanAllowed(false); // will limit search to what has been cached in memory IdentifiedObject find = finder.find(crs);
As shown above this is additional functionality made available through
AbstractAuthorityFactory- it is not part of the normalgt-opengisinterfaces.
You can construct finders to search through other categories of referencing Objects (like Datum and ReferencingSystem).