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.txt
file insidegt-referencing
has an entry for “North American Datum 1927”).The
toWGS84
information 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!CSFactory
MakesCoordinateSystem
instances, and many moreCRSFactory
MakesCoordinateReferenceSystem
instances, and many moreMathTransformFactory
MakesMathTransform
instances, 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();
ReferencingFactoryFinder
As is custom we have included a
FactoryFinder
so you can look up a good implementation on the CLASSPATH:DatumFactory datumFactory = ReferencingFactoryFinder.getDatumFactory(null);
The
ReferencingFactoryFinder
returns a couple of GeoTools implementations right now, in the future we hope to replace these defaults with an implementation fromJScience
.ReferencingFactoryContainer
You 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
ReferencingFactoryContainer
to 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 aCoordinateSystem
using a code provided by an authority such as EPSGCRSAuthorityFactory
: Defines aCoordinateReferenceSystem
for 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
AuthorityFactory
You can make direct use of the
CRSAuthorityFactory
configured 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
AuthorityFactory
InstancesHere 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);
IdentifiedObject
Finder for Controlled SearchingOne bit of functionality that is not available via the
CRSAuthority
interfaces 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-opengis
interfaces.
You can construct finders to search through other categories of referencing Objects (like Datum
and ReferencingSystem
).