MySQL 8.0.11 comes with a catalog of 5108 spatial reference system (SRS) definitions. In a previous post, we covered the definitions of geographic SRSs. In this post we’ll go into the details of projected SRSs. (If you haven’t done so already, I suggest you read the previous post first.)
Projected SRSs are flat, Cartesian coordinate systems created by projecting points on (an oblate spheroidal model of) Earth onto a flat surface. They are flat maps. Unlike geographic systems, which deal with latitude and longitude, projected SRSs have X and Y axes in meters, survey feet or some other measure of length. Since Earth is round(ish) and maps are flat, some distortion is expected.
To get a feel for how projection may distort data, try peeling an orange (one big piece of orange peel) and flatten the orange peel on the table. Apart from the color, does it resemble an orange? I’d be amazed if it did.
But if we zoom in, some part of the orange peel has a close resemblance to some part of the orange. In the same way, a map projection may be accurate in a limited area. That’s why we have so many of them — 4628 different projected SRSs in MySQL 8.0.11. Some cover the globe (very inaccurate in some places), but most are meant to be used in a much smaller area, in which they are pretty accurate.
But if MySQL 8.0 has geography support, why do we need flat maps? There are several reasons:
- We want to display the result on a flat screen, in a map. Therefore, we also need a map definition.
- Computing in a Cartesian SRS is much faster than on an ellipsoid. If we’re operating in a small area, the accuracy may be good enough.
- Maps are easy for humans to use. Most of us understand coordinates on a flat, Cartesian plane much better than we understand the surface of an ellipsoid, which requires 3d thinking.
Projected SRS Definitions
One projected SRS we see almost daily is SRID 3857, named “WGS 84 / Pseudo-Mercator”. What is that? It’s the map we see on our screens if we look at Google Maps, Bing Maps, OpenStreetMap, or almost any web world map out there. Let’s look at the definition:
1 2 3 4 5 6 7 8 9 |
mysql> SELECT * FROM INFORMATION_SCHEMA.ST_SPATIAL_REFERENCE_SYSTEMS WHERE SRS_ID=3857\G *************************** 1. row *************************** SRS_NAME: WGS 84 / Pseudo-Mercator SRS_ID: 3857 ORGANIZATION: EPSG ORGANIZATION_COORDSYS_ID: 3857 DEFINITION: PROJCS["WGS 84 / Pseudo-Mercator",GEOGCS["WGS 84",DATUM["World Geodetic System 1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.017453292519943278,AUTHORITY["EPSG","9122"]],AXIS["Lat",NORTH],AXIS["Lon",EAST],AUTHORITY["EPSG","4326"]],PROJECTION["Popular Visualisation Pseudo Mercator",AUTHORITY["EPSG","1024"]],PARAMETER["Latitude of natural origin",0,AUTHORITY["EPSG","8801"]],PARAMETER["Longitude of natural origin",0,AUTHORITY["EPSG","8802"]],PARAMETER["False easting",0,AUTHORITY["EPSG","8806"]],PARAMETER["False northing",0,AUTHORITY["EPSG","8807"]],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AXIS["X",EAST],AXIS["Y",NORTH],AUTHORITY["EPSG","3857"]] DESCRIPTION: NULL 1 row in set (0,00 sec) |
Like all WKT strings, the definition looks better in pretty-print:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
PROJCS[ "WGS 84 / Pseudo-Mercator", GEOGCS[ "WGS 84", DATUM[ "World Geodetic System 1984", SPHEROID[ "WGS 84", 6378137, 298.257223563, AUTHORITY["EPSG","7030"] ], AUTHORITY["EPSG","6326"] ], PRIMEM[ "Greenwich", 0, AUTHORITY["EPSG","8901"] ], UNIT[ "degree", 0.017453292519943278, AUTHORITY["EPSG","9122"] ], AXIS[ "Lat", NORTH ], AXIS[ "Lon", EAST ], AUTHORITY["EPSG","4326"] ], PROJECTION[ "Popular Visualisation Pseudo Mercator", AUTHORITY["EPSG","1024"] ], PARAMETER[ "Latitude of natural origin", 0, AUTHORITY["EPSG","8801"] ], PARAMETER[ "Longitude of natural origin", 0, AUTHORITY["EPSG","8802"] ], PARAMETER[ "False easting", 0, AUTHORITY["EPSG","8806"] ], PARAMETER[ "False northing", 0, AUTHORITY["EPSG","8807"] ], UNIT[ "metre", 1, AUTHORITY["EPSG","9001"] ], AXIS[ "X", EAST ], AXIS[ "Y", NORTH ], AUTHORITY["EPSG","3857"] ] |
Projected SRS definitions start with the string “PROJCS” (line 1) and a name (line 2), but MySQL doesn’t care about the names, only about the numbers. Then follows a geographic SRS definition (lines 3-34) for the SRS that this SRS is a projection of. To rephrase: The geographic SRS we define here is the SRS we’re projecting from when we create our projected SRS. The geographic SRS definition was covered in a previous post, so we won’t go into details here. Just note that the authority clause (line 33) of the geographic SRS is EPSG 4326, the World Geodetic System 1984. This means that our projected SRS (SRID 3857) is a projection of WGS 84 data onto a flat surface.
After the geographic SRS comes the declaration of which projection method is used to produce the map (lines 35-38). The name of the projection (line 36) is for humans. MySQL cares only about the authority code (line 37). This code is what makes MySQL recognize this as a popular visualization pseudo Mercator projection (see the table of supported projection methods below). The matching of the authority name (“EPSG”) is case-insensitive. If there is no authority clause, or the authority name or code is unknown, MySQL regards this as an unknown projection. Even if the details about the SRS aren’t known, MySQL knows that it’s a Cartesian system and some other parameters. MySQL can still do computations within the SRS, but data can’t be converted to or from the SRS.
Having an AUTHORITY
subclause to the PROJECTION
clause is a MySQL extension of the WKT format. The standard doesn’t allow it. But the standard also fails to specify canonical names for all the projections, so string matching is not a viable option either. The PROJECTION
clause is also the only clause (where it matters) that doesn’t have an AUTHORITY
clause in the standard, so it looks like an oversight by the standards committee. PostGIS has solved this by recording the actual projection type outside the definition (in their proj4 parameter string). We decided that adding an AUTHORITY
clause was a better solution for us. It’s not according to the standard, but it is in the spirit of the standard.
After the projection method comes the projection parameters (lines 39-58). All parameters have a mandatory name, a mandatory value, and an optional authority clause. The authority clause refers to the parameter name/type, not the value. E.g., the latitude of natural origin (lines 39-43) would be EPSG 8801 also if the value was something else.
MySQL will verify that an SRS definition has all the required parameters for that specific projection method, and these, too, are recognized based on the authority code. However, if there is no authority code, or the authority is not “EPSG” (case insensitive matching), MySQL will try to match the parameter name with a list of known parameter names (case insensitive matching). There are different parameters for different projection methods, and it would take too long to go through all of them here. See below for summary tables of supported projection methods and mandatory parameters.
The map units are length units, not latitude and longitude. The unit specification (lines 59-63) specify exactly which unit, and the conversion factor to meters (line 61). In this case it’s 1, since 1 meter is 1 meter. But there are other SRSs that use other units, e.g., US survey foot, with a conversion factor of 0.30480060960121924.
The first axis (lines 64-67) has a name (line 65) and a direction (line 66). In this case the name is “X”, but even if it were “Y”, this would still be what MySQL understands as the X axis. Remember: Names have no meaning. Numbers do. MySQL considers the X axis to be the first axis, which is the axis that appears first in the SRS definition. Since the axis direction is east, the positive numbers on the axis are east of the origin.
The second axis (lines 68-71) has the name “Y” (line 69), and it is also what MySQL considers the Y axis. The direction (line 70) indicates that positive numbers are north of the origin.
Finally, there is the authority code of the SRS (line 72). MySQL uses the same SRIDs as the EPSG Dataset, so EPSG SRS number 3857 is MySQL SRID 3857.
Supported Projections
MySQL supports a number of projection methods. SRSs using unknown projection methods are allowed, but MySQL will not be able to check for mandatory parameters (it doesn’t know what they are), and will not be able to convert data to or from an unknown projection.
EPSG Guidance Note 7-2 has detailed explanations of how each projection works, including formulas.
EPSG code | Name | Mandatory parameters (EPSG codes) |
---|---|---|
1024 | Popular Visualisation Pseudo Mercator | 8801, 8802, 8806, 8807 |
1027 | Lambert Azimuthal Equal Area (Spherical) | 8801, 8802, 8806, 8807 |
1028 | Equidistant Cylindrical | 8823, 8802, 8806, 8807 |
1029 | Equidistant Cylindrical (Spherical) | 8823, 8802, 8806, 8807 |
1041 | Krovak (North Orientated) | 8811, 8833, 1036, 8818, 8819, 8806, 8807 |
1042 | Krovak Modified | 8811, 8833, 1036, 8818, 8819, 8806, 8807, 8617, 8618, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035 |
1043 | Krovak Modified (North Orientated) | 8811, 8833, 1036, 8818, 8819, 8806, 8807, 8617, 8618, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035 |
1051 | Lambert Conic Conformal (2SP Michigan) | 8821, 8822, 8823, 8824, 8826, 8827, 1038 |
1052 | Colombia Urban | 8801, 8802, 8806, 8807, 1039 |
9801 | Lambert Conic Conformal (1SP) | 8801, 8802, 8805, 8806, 8807 |
9802 | Lambert Conic Conformal (2SP) | 8821, 8822, 8823, 8824, 8826, 8827 |
9803 | Lambert Conic Conformal (2SP Belgium) | 8821, 8822, 8823, 8824, 8826, 8827 |
9804 | Mercator (variant A) | 8801, 8802, 8805, 8806, 8807 |
9805 | Mercator (variant B) | 8823, 8802, 8806, 8807 |
9806 | Cassini-Soldner | 8801, 8802, 8806, 8807 |
9807 | Transverse Mercator | 8801, 8802, 8805, 8806, 8807 |
9808 | Transverse Mercator (South Orientated) | 8801, 8802, 8805, 8806, 8807 |
9809 | Oblique Stereographic | 8801, 8802, 8805, 8806, 8807 |
9810 | Polar Stereographic (variant A) | 8801, 8802, 8805, 8806, 8807 |
9811 | New Zealand Map Grid | 8801, 8802, 8806, 8807 |
9812 | Hotine Oblique Mercator (variant A) | 8811, 8812, 8813, 8814, 8815, 8806, 8807 |
9813 | Laborde Oblique Mercator | 8811, 8812, 8813, 8815, 8806, 8807 |
9815 | Hotine Oblique Mercator (variant B) | 8811, 8812, 8813, 8814, 8815, 8816, 8817 |
9816 | Tunisia Mining Grid | 8821, 8822, 8826, 8827 |
9817 | Lambert Conic Near-Conformal | 8801, 8802, 8805, 8806, 8807 |
9818 | American Polyconic | 8801, 8802, 8806, 8807 |
9819 | Krovak | 8811, 8833, 1036, 8818, 8819, 8806, 8807 |
9820 | Lambert Azimuthal Equal Area | 8801, 8802, 8806, 8807 |
9822 | Albers Equal Area | 8821, 8822, 8823, 8824, 8826, 8827 |
9824 | Transverse Mercator Zoned Grid System | 8801, 8830, 8831, 8805, 8806, 8807 |
9826 | Lambert Conic Conformal (West Orientated) | 8801, 8802, 8805, 8806, 8807 |
9828 | Bonne (South Orientated) | 8801, 8802, 8806, 8807 |
9829 | Polar Stereographic (variant B) | 8832, 8833, 8806, 8807 |
9830 | Polar Stereographic (variant C) | 8832, 8833, 8826, 8827 |
9831 | Guam Projection | 8801, 8802, 8806, 8807 |
9832 | Modified Azimuthal Equidistant | 8801, 8802, 8806, 8807 |
9833 | Hyperbolic Cassini-Soldner | 8801, 8802, 8806, 8807 |
9834 | Lambert Cylindrical Equal Area (Spherical) | 8823, 8802, 8806, 8807 |
9835 | Lambert Cylindrical Equal Area | 8823, 8802, 8806, 8807 |
Projection Parameters
MySQL recognizes projection parameters primarily by authority code. However, if there is no authority code, MySQL reverts to case-insensitive string matching on the parameter name.
For details about each parameter, look it up by code in the EPSG Online Registry.
EPSG Code | Fallback Name (recognized by MySQL) | EPSG Name |
---|---|---|
1026 | c1 | C1 |
1027 | c2 | C2 |
1028 | c3 | C3 |
1029 | c4 | C4 |
1030 | c5 | C5 |
1031 | c6 | C6 |
1032 | c7 | C7 |
1033 | c8 | C8 |
1034 | c9 | C9 |
1035 | c10 | C10 |
1036 | azimuth | Co-latitude of cone axis |
1038 | ellipsoid_scale_factor | Ellipsoid scaling factor |
1039 | projection_plane_height_at_origin | Projection plane origin height |
8617 | evaluation_point_ordinate_1 | Ordinate 1 of evaluation point |
8618 | evaluation_point_ordinate_2 | Ordinate 2 of evaluation point |
8801 | latitude_of_origin | Latitude of natural origin |
8802 | central_meridian | Longitude of natural origin |
8805 | scale_factor | Scale factor at natural origin |
8806 | false_easting | False easting |
8807 | false_northing | False northing |
8811 | latitude_of_center | Latitude of projection centre |
8812 | longitude_of_center | Longitude of projection centre |
8813 | azimuth | Azimuth of initial line |
8814 | rectified_grid_angle | Angle from Rectified to Skew Grid |
8815 | scale_factor | Scale factor on initial line |
8816 | false_easting | Easting at projection centre |
8817 | false_northing | Northing at projection centre |
8818 | pseudo_standard_parallel_1 | Latitude of pseudo standard parallel |
8819 | scale_factor | Scale factor on pseudo standard parallel |
8821 | latitude_of_origin | Latitude of false origin |
8822 | central_meridian | Longitude of false origin |
8823 | standard_parallel_1, standard_parallel1 | Latitude of 1st standard parallel |
8824 | standard_parallel_2, standard_parallel2 | Latitude of 2nd standard parallel |
8826 | false_easting | Easting at false origin |
8827 | false_northing | Northing at false origin |
8830 | initial_longitude | Initial longitude |
8831 | zone_width | Zone width |
8832 | standard_parallel | Latitude of standard parallel |
8833 | longitude_of_center | Longitude of origin |
Thank you for using MySQL !