Comparing CoordinateReferenceSystem

The objects defined in the referencing module can be compared in a number of different ways.

Related:

Compare Identifier

You can use the identifier name to compare two CoordinateReferenceSystem objects.

A ReferenceIdentifier is often composed of two parts:

  • Authority: assigned by by an authority body such as the European Petroleum Standards Group

  • Code: uniquely identifiers the referencing object according to the authority body mentioned above

Here is what that looks like:

CoordinateReferenceSystem crs1 = shapefile.getSchema().getDefaultGeometry().getCoordinateReferenceSystem();
CoordinateReferenceSystem crs2 = CRS.decode("EPSG:4326");

if( crs1.getName().equals( crs2.getName() ){
   // The CoordinateReferenceSystem objects have the same formal definition,
   // the objects may not be exactly the same .. but they are supposed to be
   //
   // we are going to use crs2; as we trust our internal database more than
   // a projection file provided by the user
   ...
}

In this case you are only comparing the name (i.e. metadata) of the two objects. You are trusting that the two objects are the same, if they are called the same name.

Compare Equals

Equals comparison is used to check when a CoordinateReferenceSystem, and all its component parts such as Datum, are exactly equal.:

CoordinateReferenceSystem crs1 = shapefile.getSchema().getDefaultGeometry().getCoordinateReferenceSystem();
CoordinateReferenceSystem crs2 = CRS.decode("EPSG:4326");

if( crs1.equals( crs2 ){
   // The CoordinateReferenceSystem objects are exactly the same data structure
   ...
}

While the above makes sense, if it not often exactly what you want.

Often it does not matter what name (i.e. metadata) the data structure goes by, so far it numerically represents the same idea.

You can check if two objects are equal, while ignoring metadata (such as the exact name used for the CoordinateReferenceSystem). This technique compares significant values only, i.e. mostly (with a few exception) the ones that would changes the numerical results when transforming a position from one CRS to the other.:

if( CRS.equalsIgnoreMetadata(crs1, crs2)){

}

The name is usually ignored, with only 2 exceptions:

  • Datum - The reason that we cannot ignore the name for a Datum is that it is the only way to differentiate between datum. We can have many datum using the same Ellipsoid and PrimeMeridian, and still be different datum (because AbstractDatum do not stores all the geodesy work behind the datum definition - it would be complex and out of ISO 19111 scope anyway).

    In order to still allow a relaxed check we make use of a DatumAlias class, which help the referencing engine to recognize for example that “WGS84” and “D_WGS84” are synonymous.

  • CoordinateSystemAxis - CoordinateSystemAxis is clearly defined by ISO19111, but some variation is still seen in the wild. The DefaultCoordinateSystemAxis implementation handles a couple of alias as well (much less than Datum however).

    We have be unable to define an alias for “x” and “y” up to date, because “x” (for example) can means too many different things: “Easting” in a map projection, “Geocentric X” in a GeocentricCRS, “Column” in an ImageCRS, etc…

Compare Equivalent

You can check if two CRSs are equivalent, while ignoring the metadata as above, and eventually checking if a Transformation is required between the two.:

if( CRS.isEquivalent(crs1, crs2)){

}

This method will first determine if the two objects are equal by ignoring metadata, using the previously mentioned equalsIgnoreMetadata method as the initial step. If the objects are not equal, it will then check for the existence of a transformation between them. If no transformation is required, meaning the transformation is the identity and does not alter any points, the objects can be considered equivalent.