Skip to content
Huidae Cho edited this page May 31, 2021 · 2 revisions

PROJ documentation and standards

PROJ implements the standard ISO19111 per OSGEO

Full tech paper for PROJ.8.0.1 as of May 8th, 2021

Spatialite documentation of key updates from PROJ.4 to PROJ.6, i.e. change from proj-strings to WKT (ISO19162).

ISO 19162 - WKT

WKT Characteristics

Within the WKT string, each object is comprised of a key word followed by a set of attributes. Delimiters which enclose each object are normally [...]. The PROJ library uses the same.

Key words are case insensitive but will be in upper case when human readability is important.

The PROJJSON format introduced in PROJ.6 follows the WKT format as close as possible.

Usage attribute

optional attribute* which includes both scope and extent. Extent may consist of one or more of area textual description, area bounding box, vertical extent and/or temporal extent.

WKT Examples:

  • EPSG:9674
USAGE[
    SCOPE["Forestry."],
    AREA["United States (USA) - Oregon and Washington."],
    BBOX[41.98,-124.79,49.05,-116.47]],
  • EPSG:4326
USAGE[
    SCOPE["Horizontal component of 3D system."],
    AREA["World."],
    BBOX[-90,-180,90,180]],

PROJJSON Examples:

  • EPSG:9674
  "scope": "Forestry.",
  "area": "United States (USA) - Oregon and Washington.",
  "bbox": {
    "south_latitude": 41.98,
    "west_longitude": -124.79,
    "north_latitude": 49.05,
    "east_longitude": -116.47
  • EPSG:4326
  "scope": "Horizontal component of 3D system.",
  "area": "World.",
  "bbox": {
    "south_latitude": -90,
    "west_longitude": -180,
    "north_latitude": 90,
    "east_longitude": 180

Scope

Scope describes purpose and uses for which a CRS, datum, etc is applied. Within the WKT scope will be seen by SCOPE["Map usage"].

Extent

Extent describes spatial applicability of a crs, datum, etc.

Horizontal extent can be described by description and/or geographic bounding box, but not by polygon due to string length considerations.

Area

AREA is an optional attribute which describes a geographic are over which a crs or coordinate operation is applicable. I.e for EPSG:2000

Geographic bounding box

Describes "north up" area. It is an approximate description of location. Precision of two decimal places.

CRS Tables

proj.db has 5 tables corresponding to various coordinate reference systems.

sqlite3 /usr/share/proj/proj.db ".tables" | grep crs
  • compound_crs
  • crs_view
  • geodetic_crs
  • projected_crs
  • vertical_crs

In order of importance:

  1. Projected coordinate systems (projected_crs)
  2. Geodetic coordinate systems (geodetic_crs)
  3. Vertical coordinate systems (vertical_crs)
  4. Compound coordinate systems (compound_crs)

projected_crs

"Derived from a CRS with a geodetic reference frame by applying the coordinate conversion known as a map projection." - ISO191111

This table will contain all projections designed to represent a localized region.

Count of all EPSG codes in projected_crs

sqlite3 /usr/share/proj/proj.db "SELECT code FROM projected_crs WHERE auth_name = 'EPSG';" | wc
   5120    5120   27068

geodetic_crs

Contains global coordinate systems

sqlite3 /usr/share/proj/proj.db "SELECT code FROM geodetic_crs WHERE auth_name = 'EPSG';" | wc
   1063    1063    5315

e.g. EPSG:4326

sqlite3 /usr/share/proj/proj.db "SELECT code FROM geodetic_crs WHERE auth_name = 'EPSG';" | grep 4326
4326

PROJ db

The sqlite database provided follows the same format as described in ISO 19162 - Geographic information — Well known text representation of coordinate reference systems with each table representative of a main attribute that would be found in a WKT string.

Both the scope (purpose and uses) and usage (area and bbox) attributes have their own tables which can be queried by both authorities and codes.

sqlite> .headers on
sqlite> select * from extent limit 5;
auth_name|code|name|description|south_lat|north_lat|west_lon|east_lon|deprecated
EPSG|1024|Afghanistan|Afghanistan.|29.4|38.48|60.5|74.92|0
EPSG|1025|Albania|Albania - onshore and offshore.|39.63|42.67|18.46|21.06|0
EPSG|1026|Algeria|Algeria - onshore and offshore.|18.97|38.8|-8.67|11.99|0
EPSG|1027|American Samoa|American Samoa - onshore and offshore.|-17.56|-10.02|-173.75|-165.2|0
EPSG|1028|Andorra|Andorra.|42.43|42.66|1.42|1.79|0
sqlite> select * from scope limit 5;
auth_name|code|scope|deprecated
EPSG|1024|Not known.|0
EPSG|1025|?|1
EPSG|1026|Spatial referencing.|0
EPSG|1027|Geodesy.|0
EPSG|1028|Cadastre.|0

Querying extent and scope

The usage table creates a relation which is similar to the structure of the USAGE WKT attribute within which the extent and scope attributes are.
The usage table has the following columns

auth_name|code|object_table_name|object_auth_name|object_code|extent_auth_name|extent_code|scope_auth_name|scope_code

To query extent and scope their respective codes must be obtained from the usage table. The EPSG code which is used to identify the CRS will be queried against the object_code, NOT the code column.

I.e. if we incorrectly query the EPSG code 9674 against the code column, we get

sqlite3 /usr/share/proj/proj.db "select * from usage where auth_name = 'EPSG' and code = 9674"
EPSG|9674|conversion|EPSG|6236|EPSG|4156|EPSG|1055

where the scope_code will be 1055 and the extent_code will be 4156. Using these we can query both tables

sqlite3 /usr/share/proj/proj.db "select * from scope where auth_name = 'EPSG' and code = 1055"
EPSG|1055|Cadastre, engineering survey, topographic mapping (large scale).|0

sqlite3 /usr/share/proj/proj.db "select * from extent where auth_name = 'EPSG' and code = 4156"
EPSG|4156|Colombia - San Andres city|Colombia - San Andres city.|12.43|12.65|-81.82|-81.6|0

These results are wrong!!

Instead we must query the EPSG code 9674 against the object_code column which returns

sqlite3 /usr/share/proj/proj.db "select * from usage where auth_name = 'EPSG' and object_code = 9674"
EPSG|14787|projected_crs|EPSG|9674|EPSG|2381|EPSG|1165

where 1165 is the scope_code and 2381 is the extent_code. When queried respectively we get

sqlite3 /usr/share/proj/proj.db "select * from scope where auth_name = 'EPSG' and code = 1165"
EPSG|1165|Forestry.|0

sqlite3 /usr/share/proj/proj.db "select * from extent where auth_name = 'EPSG' and code = 2381"
EPSG|2381|USA - Oregon and Washington|United States (USA) - Oregon and Washington.|41.98|49.05|-124.79|-116.47|0

These are correct and we can verify these results directly with both the PROJ WKT and PROJJSON outputs for the same EPSG code

USAGE[
    SCOPE["Forestry."],
    AREA["United States (USA) - Oregon and Washington."],
    BBOX[41.98,-124.79,49.05,-116.47]],
ID["EPSG",9674]]
  "scope": "Forestry.",
  "area": "United States (USA) - Oregon and Washington.",
  "bbox": {
    "south_latitude": 41.98,
    "west_longitude": -124.79,
    "north_latitude": 49.05,
    "east_longitude": -116.47
  },
  "id": {
    "authority": "EPSG",
    "code": 9674

BBOX

Is bounding box always "defined in rectangular bboxes in lat/long, not in a projected CS"?

PROJ uses ISO 19115-1 Geographic information — Metadata to dictate metadata standardizations. ISO 19115-1 also dictates essentially every other standard pertaining to Geospatial Data Management. I am not able to get ISO 19115-1 in full without buying it, however using other standards and resources I am able to gather that it dictates that Geographic Bounding boxes are to be in Decimal Degrees lat/lon.

The geographic bounding box is found in class EX_GeographicBoundingBox in all documents and GeographicBoundingBox in all source code. Details about the specification can be seen in

In addition, per the PROJ source code, the PROJ GeographicBoundingBox Class implements the GeographicBoundingBox from GeoAPI which uses coordinate values expressed in decimal degrees.