1Spatial References
2==================
3
4We specify locations on the Earth using *coordinates*, tuples of numbers that
5pinpoint a particular place on the map at some level of precision. But just
6knowing the coordinates is not enough; you need to know how to interpret them.
7
8  A **Spatial Reference** (SRS) maps a set of coordinates
9  to a corresponding real location on the earth.
10
11For example, given the coordinates of a location on the earth::
12
13  (-121.5, 36.8, 2000.0)
14
15Those numbers are meaningless unless you know how to use them.
16So combine that with some reference information::
17
18  Coordinate System Type: Geographic
19  Units:                  Degrees
20  Horizontal datum:       WGS84
21  Vertical datum:         EGM96
22
23Now you can figure out exactly where the point is on earth, where it is relative to
24other points, and how to convert it to other representations.
25
26Components of an SRS
27--------------------
28
29A *spatial reference*, or *SRS*, contains:
30
31* `Coordinate System Type`_
32* `Horizontal Datum`_
33* `Vertical Datum`_
34* `Projection`_
35
36Coordinate System Type
37~~~~~~~~~~~~~~~~~~~~~~
38
39osgEarth supports three basic coordinate system types:
40
41* **Geographic** - A whole-earth, ellipsoidal model. Coordinates are spherical angles
42  in *degrees* (longitude and latitude). Examples include WGS84 and NAD83.
43  (`Learn more <http://en.wikipedia.org/wiki/Geographic_coordinate_system>`_)
44
45* **Projected** - A local coordinate system takes a limited region of the earth and
46  "projects" it into a 2D cartesion (X,Y) plane. Examples include UTM, US State Plane,
47  and Mercator.
48  (`Learn more <http://en.wikipedia.org/wiki/Map_projection>`_.)
49
50* **ECEF** - A whole earth, cartesian system. ECEF = Earth Centered Earth Fixed; it is
51  a 3D cartesion system (X,Y,Z) with the origin (0,0,0) at the earth's center; the X-axis
52  intersecting lat/long (0,0), the Y-axis intersecting lat/long (0,-90), and the Z-axis
53  intersecting the north pole. ECEF is the native system in which osgEarth renders its
54  graphics. (`Learn more <http://en.wikipedia.org/wiki/ECEF>`_)
55
56Horizontal Datum
57~~~~~~~~~~~~~~~~
58
59A *datum* is a reference point (or set of points) against which geospatial
60measurements are made. The same location on earth can have different coordinates
61depending on which datum is in use. There are two classes of datum:
62
63  A **horizontal datum** measures positions on the earth. Since the earth is not
64  a perfect sphere or even a perfect ellipsoid, particular datums are usually
65  designed to approximate the shape of the earth in a particular region.
66  Common datums include **WGS84** and **NAD83** in North America, and **ETR89**
67  in Europe.
68
69Vertical Datum
70~~~~~~~~~~~~~~
71
72A **vertical datum** measures elevation. There are several classes of vertical
73datum; osgEarth supports *geodetic* (based on an ellipsoid) and *geoid* (based
74on a sample set of elevation points around the planet).
75
76osgEarth has the following vertical datums built in:
77
78* Geodetic - the default; osgEarth uses the Horizontal datum ellipsoid as a reference
79* EGM84 geoid
80* EGM96 geoid - commonly called *MSL*; used in DTED and KML
81* EGM2008 geoid
82
83By default, SRS's in osgEarth use a *geodetic* vertical datum; i.e., altitude is
84measured as "height above ellipsoid (HAE)".
85
86Projection
87~~~~~~~~~~
88
89A *projected* SRS will also have a *Projection*. This is a mathematical formula
90for transforming a point on the ellipsoid into a 2D plane (and back).
91
92osgEarth supports thousands of known projections (by way of the GDAL/OGR toolkit).
93Notable ones include:
94
95* UTM (Universal Transverse Mercator)
96* Sterographic
97* LCC (Lambert Conformal Conic)
98
99Each has particular characteristics that makes it desirable for certain types of
100applications. Please see `Map Projections`_ on Wikipedia to learn more.
101
102.. _Map Projections:       http://en.wikipedia.org/wiki/Map_projection
103
104
105SRS Representations
106-------------------
107
108There are many ways to define an SRS. osgEarth supports the following.
109
110WKT (Well Known Text)
111~~~~~~~~~~~~~~~~~~~~~
112
113WKT is an OGC standard for describing a coordinate system. It is commonly
114found in a ".prj" file alongside a piece of geospatial data, like a shapefile
115or an image.
116
117Here is the WKT representation for the *UTM Zone 15N* projection::
118
119    PROJCS["NAD_1983_UTM_Zone_15N",
120        GEOGCS["GCS_North_American_1983",
121            DATUM["D_North_American_1983",
122                SPHEROID["GRS_1980",6378137.0,298.257222101]],
123            PRIMEM["Greenwich",0.0],
124            UNIT["Degree",0.0174532925199433]],
125        PROJECTION["Transverse_Mercator"],
126        PARAMETER["False_Easting",500000.0],
127        PARAMETER["False_Northing",0.0],
128        PARAMETER["Central_Meridian",-93.0],
129        PARAMETER["Scale_Factor",0.9996],
130        PARAMETER["Latitude_Of_Origin",0.0],
131        UNIT["Meter",1.0]]
132
133PROJ4
134~~~~~
135
136*PROJ4* is a map projections toolkit used by osgEarth and hundreds of other
137geospatial applications and toolkits. It has a shorthand represtation for
138describing an SRS. Here is the same SRS above, this time in PROJ4 format::
139
140    +proj=utm +zone=15 +ellps=GRS80 +units=m +no_defs
141
142PROJ4 has data tables for all the common components (like UTM zones and datums)
143so you don't have to explicitly define everything like you do with WKT.
144
145EPSG Codes
146~~~~~~~~~~
147
148The EPSG (the now-defunct European Petroleum Survey Group) established a table
149of numerical codes for referencing well-known projections. You can browse a list
150of there `here <http://spatialreference.org/ref/epsg>`_. osgEarth will accept
151EPSG codes; again for the example above::
152
153    epsg:26915
154
155If you know the EPSG code it's a nice shorthand way to express it. OGR/PROJ4,
156which osgEarth requires, includes a large table of EPSG codes.
157
158Aliases
159~~~~~~~
160
161The last category is the *named SRS*. There are some SRS's that are so common
162that we include shorthand notation for them. These include:
163
164    :wgs84:              World Geographic Survey 1984 geographic system
165    :spherical-mercator: Spherical mercator (commonly used in web mapping systems)
166    :plate-carre:        WGS84 projected flat (X=longitude, Y=latitude)
167
168
169
170
171Using Spatial References in osgEarth
172------------------------------------
173
174There are several ways to work with an SRS in osgEarth, but the easiest way it
175to use the ``GeoPoint`` class. However let's look at creating an SRS first and
176then move on to the class.
177
178SpatialReference API
179~~~~~~~~~~~~~~~~~~~~
180
181The ``SpatialReference`` class represents an SRS. Lots of classes and functions in
182osgEarth require an SRS. Here's how you create on in code::
183
184    const SpatialReference* srs = SpatialReference::get("epsg:4326");
185
186That will give you an SRS. The ``get()`` function will accept any of the SRS
187representations we discussed above: WKT, PROJ4, EPSG, or Aliases.
188
189If you need an SRS with a vertical datum, express that as a second parameter.
190osgEarth support ``egm84``, ``egm96``, and ``egm2008``. Use it like this::
191
192    srs = SpatialReference::get("epsg:4326", "egm96");
193
194It's sometimes useful to be able to access an SRS's component types as well. For
195example, every *projected* SRS has a base *geographic* SRS that it's based upon.
196You can get this by calling::
197
198    geoSRS = srs->getGeographicSRS();
199
200If you're transforming a projected point to latitude/longitude, that's the output
201SRS you will want.
202
203You can also grab a geocentric (ECEF) SRS corresponding to any SRS, like so::
204
205    geocentricSRS = srs->getGeocentricSRS();
206
207``SpatialReference`` has lots of functions for doing transformations, etc. Consult
208the header file for information on those. But in practice it is usually best to use
209classes like ``GeoPoint`` instead of using ``SpatialReference`` directly.
210
211
212GeoPoint API
213~~~~~~~~~~~~
214
215A ``GeoPoint`` is a georeferenced 2D or 3D point. ("Georeferenced" means that the
216coordinate values are paired with an SRS - this means all the information necessary
217to plot that point on the map is self-contained.) There are other "Geo" classes
218including ``GeoExtent`` (a bounding box) and ``GeoCircle`` (a bounding circle).
219
220Here is how you create a 2D ``GeoPoint``::
221
222    GeoPoint point(srs, x, y);
223
224You can also create a 3D ``GeoPoint`` with an altitude::
225
226    GeoPoint point(srs, x, y, z, ALTMODE_ABSOLUTE);
227
228The ``ALTMODE_ABSOLUTE`` is the *altitude mode*, and it required when you specify
229a 3D coordinate:
230
231    :``ALTMODE_ABSOLUTE``:  Z is relative to the SRS' vertical datum, i.e.,
232                            height above ellipsoid or height above the geoid.
233    :``ALTMODE_RELATIVE``:  Z is relative to the height of the terrain under
234                            the point.
235
236Now that you have your ``GeoPoint`` you can do transformations on it. Say you
237want to transform it to another SRS::
238
239    GeoPoint point(srs, x, y);
240    GeoPoint newPoint = point.transform(newSRS);
241
242Here's a more concrete example. Say you have a point in latitude/longitude (WGS84)
243and you need to express it in UTM Zone 15N::
244
245    const SpatialReference* wgs84 = SpatialReference::get("wgs84");
246    const SpatialReference* utm15 = SpatialReference::get("+proj=utm +zone=15 +ellps=GRS80 +units=m");
247    ...
248    GeoPoint wgsPoint( wgs84, -93.0, 34.0 );
249    GeoPoint utmPoint = wgsPoint.transform( utm15 );
250
251    if ( utmPoint.isValid() )
252       // do something
253
254Always check ``isValid()`` because not every point in one SRS can be transformed
255into another SRS. UTM Zone 15, for example, is only defined for a 6-degree span
256of longitude -- values too far outside this range might fail!
257
258