<a
<h1>Introduction</h1>
<b>PROJ</b> is a well-known library for performing conversions between cartographic projections.<br>
It's universally supported by almost all open source GIS-oriented applications and packages, so much so that most don't even realize that PROJ is being used in the background.<br>
So a short history would be appropriate to fully understand the current state of the art of this library:<br>
<h3>Past History</h3>

Very few users and developers realize how ancient  PROJ is, and how far it has progressed since its first steps:
<ul>
<li>in <b>1980</b> (about 40 years ago) Gerald Evenden started working on the very first PROJ version, which at the time it was a Ratfor (Rational Fortran) program.</li>
<li>in <b>1985</b> the code was completely rewritten in C to run on UNIX systems, and it was named
<li>in <b>1990</b> was released an updated version named <b>PROJ.3</li>
<li>in <b>1994</b> a more advanced version was released, and it was obviously named
<li>in <b>1995</b> Evenden stopped any further development activity and the project become inactive for several years.</li>
<li>in <b>2000</b> Frank Warmerdam became the new maintainer and released version
<li>After this rebirth of the project, it continued to be regularly maintained, but no further relevant improvements were introduced.<br>
PROJ.4 just continued without involving together with new found knowledge/experience of the last two decades .</li>
</ul><br>
<b><u>Short the fourth version of PROJ (aka <b>PROJ.4</b>) lasted for about two decades, a very uncommon situation.<br>
And consequently a full generation of developers and users became sincerely convinced that PROJ.4 was the real name of the library.
<h3>The revolution comes</h3>

<ul>
<li>in <b>2018</b> Kristian Evers, Even Rouault, and others started developing
a revolutionized PROJ supporting many relevant innovations.<br>
<b>PROJ.5</b> was intended to be the first preliminary step of a more complex evolution schema.</li>
<li>on <b>March 2019</b> a more mature version was released, and it's
<li>Next year (2020) <b>PROJ.7</b> is expected to be released, and thus complete the transition between the old and new architectures.</li>
</ul>
<br>
the whole transition requires many relevant changes, so that a deeply revised API will be required.
In other words, the old <b>PROJ.4</b> and the new <b>PROJ.7</b> will support two different APIs, thus abruptly breaking cross-version compatibility.<br>
This is unpleasant news, because it practically means that all software modules depending on PROJ (including SpatiaLite) will require a not at all trivial rewrite in order to fulfill the new API requirements.<br>
But considering that this is the first major API break in 40 years and with so many useful innovations, such a breakage is fully justified and reasonable.<br><br>
<b><u>More details about the API
<ul>
<li><b>PROJ.5</b> introduced the new API, but still supported the traditional API.</li>
<li>in <b>PROJ.6</b> the old traditional API was deprecated.<br>
The traditional API could only be used when compiled by explicitly defining a <b>-DACCEPT_USE_OF_DEPRECATED_PROJ_API_H=1</b> directive to enable its use.</li>
<li>and finally in the next-to-come <b>PROJ.7</b> the traditional API will be completely removed.</li>
</ul>
<br>
<hr>
<h1>What's new in PROJ.6</h1>
<h3>Fully supporting ISO 19162:2018 WKT</h3>
Old versions of PROJ (including <b>PROJ.4</b>) required to define each <b>CRS</b> (<i>Coordinate Reference System</i>) by a corresponding <b>proj-string</b>.
The following table exemplifies the case of few CRSes:<br><br>
<table cellspacing="8" cellpadding="8" bgcolor="#e8ffe8" border="1">
<tr><th bgcolor="#ffb03e">SRID</th><th bgcolor="#ffb03e">CRS Name</th><th bgcolor="#ffb03e">proj-string (PROJ.4 style)</th><th bgcolor="#ffb03e">proj-string (PROJ.6
<tr><td align="right">3003</td><td>Monte Mario / Italy zone 1</td>
<td>+proj=tmerc +lat_0=0 +lon_0=9 +k=0.9996 +x_0=1500000 +y_0=0 \<br>
+ellps=intl +towgs84=-104.1,-49.1,-9.9,0.971,-2.917,0.714,-11.68 +units=m +no_defs</td><td>+proj=tmerc +lat_0=0 +lon_0=9 +k=0.9996 +x_0=1500000 +y_0=0 \<br>
+ellps=intl +units=m +no_defs
<tr><td align="right">4326</td><td>WGS 84</td>
<td>+proj=longlat +datum=WGS84 +no_defs</td><td>+proj=longlat +datum=WGS84 +no_defs
<tr><td align="right">32632</td><td>WGS 84 / UTM zone 32N</td>
<td>+proj=utm +zone=32 +datum=WGS84 +units=m +no_defs</td><td>+proj=utm +zone=32 +datum=WGS84 +units=m +no_defs +type=crs</td>
</table>
<br>
PROJ.6 still continues to support the old proj-strings, but it now adopts a slightly changed notation:
<ul>
<li>there is a new <b>+type=crs</b> member explicitly stating that the string is intended to be a CRS definition.</li>
<li>as a general rule the <b>+towgs84=</b> member is no longer supported.<br>
<b>Note</b>: this is a very critical change, that can easily lead to unexpected results.<br>
As an example, in the case of <b>EPSG:3003 <i>(Italy , suppressing the +towgs84 member causes a shift of about 100m in coordinate transformations. So be warned.<br>
Another example, such as all <b>DHDN</b> projections which uses the grid file suppressing the <b>+towgs84</b> member will also lead to incorrect results.<br>
The use of supported grid files, where they exist, is now madatory.
</li>
</ul>
<br>
Although the newer versions of PROJ (starting with <b>PROJ.6</b>) will still continue to support the old <b>proj-strings</b>, this is no longer the preferred notation for defining a CRS.<br>
The newer, preferred, notation is fully conforms to the <b>ISO 19162:2018</b> international standard
(<i>OGC Abstract Specification Topic 2: “Referencing By Coordinates”</i>).<br>
The following table exemplifies the same CRSes as above in the more recent ISO WKT notation:
<br><br>
<table cellspacing="8" cellpadding="8" bgcolor="#e8ffe8" border="1">
<tr><th
<tr><th bgcolor="#ffb03e">CRS Name</th><td>Monte Mario / Italy zone 84</td><td>WGS 84 / UTM zone
<tr><th bgcolor="#ffb03e">ISO-2018 WKT</th>
<td valign="top">
<verbatim>
PROJCRS["Monte Mario / Italy zone 1",
    BASEGEODCRS["Monte Mario",
        DATUM["Monte Mario",
            ELLIPSOID["International 1924",6378388,297,
                LENGTHUNIT["metre",1]]],
        PRIMEM["Greenwich",0,
            ANGLEUNIT["degree",0.0174532925199433]]],
    CONVERSION["Italy zone 1",
        METHOD["Transverse Mercator",
            ID["EPSG",9807]],
        PARAMETER["Latitude of natural origin",0,
            ANGLEUNIT["degree",0.0174532925199433],
            ID["EPSG",8801]],
        PARAMETER["Longitude of natural origin",9,
            ANGLEUNIT["degree",0.0174532925199433],
            ID["EPSG",8802]],
        PARAMETER["Scale factor at natural origin",0.9996,
            SCALEUNIT["unity",1],
            ID["EPSG",8805]],
        PARAMETER["False easting",1500000,
            LENGTHUNIT["metre",1],
            ID["EPSG",8806]],
        PARAMETER["False northing",0,
            LENGTHUNIT["metre",1],
            ID["EPSG",8807]]],
    CS[Cartesian,2],
        AXIS["easting (X)",east,
            ORDER[1],
            LENGTHUNIT["metre",1]],
        AXIS["northing (Y)",north,
            ORDER[2],<br>
            LENGTHUNIT["metre",1]],
    AREA["Italy - west of 12°E"],
    BBOX[36.53,5.94,47.04,12],
    ID["EPSG",3003]]

<td valign="top"><verbatim>
GEODCRS["WGS 84",
    DATUM["World Geodetic System 1984",
        ELLIPSOID["WGS 84",6378137,298.257223563,
            LENGTHUNIT["metre",1]]],
    PRIMEM["Greenwich",0,
        ANGLEUNIT["degree",0.0174532925199433]],
    CS[ellipsoidal,2],
        AXIS["geodetic latitude (Lat)",north,
            ORDER[1],
            ANGLEUNIT["degree",0.0174532925199433]],
        AXIS["geodetic longitude (Lon)",east,
            ORDER[2],
            ANGLEUNIT["degree",0.0174532925199433]],
    AREA["World"],
    BBOX[-90,-180,90,180],
    ID["EPSG",4326]]

<td valign="top"><verbatim>
PROJCRS["WGS 84 / UTM zone 32N",
    BASEGEODCRS["WGS 84",
        DATUM["World Geodetic System 1984",
            ELLIPSOID["WGS 84",6378137,298.257223563,
                LENGTHUNIT["metre",1]]],
        PRIMEM["Greenwich",0,
            ANGLEUNIT["degree",0.0174532925199433]]],
    CONVERSION["UTM zone 32N",
        METHOD["Transverse Mercator",
            ID["EPSG",9807]],
        PARAMETER["Latitude of natural origin",0,
            ANGLEUNIT["degree",0.0174532925199433],
            ID["EPSG",8801]],
        PARAMETER["Longitude of natural origin",9,
            ANGLEUNIT["degree",0.0174532925199433],
            ID["EPSG",8802]],
        PARAMETER["Scale factor at natural origin",0.9996,
            SCALEUNIT["unity",1],
            ID["EPSG",8805]],
        PARAMETER["False easting",500000,
            LENGTHUNIT["metre",1],
            ID["EPSG",8806]],
        PARAMETER["False northing",0,
            LENGTHUNIT["metre",1],
            ID["EPSG",8807]]],
    CS[Cartesian,2],
        AXIS["(E)",east,
            ORDER[1],
            LENGTHUNIT["metre",1]],
        AXIS["(N)",north,
            ORDER[2],
            LENGTHUNIT["metre",1]],
    AREA["World - N hemisphere - 6°E to 12°E - by country"],
    BBOX[0,6,84,12],
    ID["EPSG",32632]]

</tr>
</table>
<br>
As you can see, the two notations are profoundly different.
The old <b>proj-string</b> notation is extremely concise and rough, whilst the new <b>ISO-WKT</b> is verbose but exhaustive, detailed and precise.<br>
They are radically different: ISO-WKT is clearly superior and more sophisticated in every way.<br>
Not surprisingly, the coordinate transformations based on ISO-WKT definitions (instead of proj-strings) are usually expected to be more accurate, complete and extendable.<br><br>
And that's not all; the old <b>proj-strings</b> weren't formally defined by any standard, and only PROJ, GDAL and few other FLOSS / GFOSS implementations could be expected to understand them.<br>
The new <b>ISO-WKT</b>, on the other hand, is a formally defined international standard, and almost all free and proprietary implementations are expected to support it.<br>
This is a very relevant change that ensures a robust compatibility between different applications.<br><br>
<table cellspacing="8" cellpadding="16" bgcolor="#ffffe9">
<tr><td>
<b><u>Important there are several dialects in the WKT notation describing CRSes.<br>
All them share the same common core and mainly differ in few minor details.<br>
PROJ.6 can understand the following dialects:
<ol>
<li><b>ESRI WKT</b>: a dialect widely adopted by ESRI proprietary software.</li>
<li><b>GDAL WKT1</b>: a dialect historically supported by the open source GDAL library.</li>
<li><b>WKT2:2015</b>: as defined by <b>ISO 19162:2015</b> standard specification (now superseded).</li>
<li><b>WKT2:2018</b>: as defined by the more recent <b>ISO 19162:2018</b> standard specification .</li>
</ol>

</table><br>
<h3>The private SQLite database supporting PROJ.6</h3>
Since <b>PROJ.6</b> the PROJ library is supported by a private SQLite database containing all definitions about supported CRSes, Ellipsoids, Prime Meridians, Units of Measure, Conversions, Transformations and alike.<br>
many of the new advanced PROJ.6 features will fail if this database is not available at run time.
<h3>Direct transformations from CRS to CRS</h3>
As apposed to all previous versions, PROJ.6 can now apply any transformation from a CRS to another without specifying the CRS definitions or
This is because PROJ.6 is now capable to retrieve any CRS definition directly
from its own private SQLite database, and consequently each CRS can be fully identified by simply specifying its symbolic name, as in:
<ul>

</ul>
or alternatively
<ul>

</ul>
<br>
<table cellspacing="8" cellpadding="16" bgcolor="#ffffe9">
<tr><td>
<b><u>Another major which results in more precise transformations:
<ul>
<li><b>PROJ.4</b>: always transformed first to <b>WSG84</b> and from there to the target projection.</li>
<li><b>PROJ.6</b>: will transform to the target projection
</ul>
This will also avoid <a point accuracy problems</a> which may occur through the extra <b>WSG84</b> transformation

</table>
<h3>Supporting specific areas of use</h3>
<table cellspacing="8" cellpadding="8" bgcolor="#e8ffe8" border="1">
<tr><td>
PROJ.6 is now able to make a distinction between different <b>areas of use</b> within a CRS, and can eventually apply the most appropriate transformation when the intended area-of-use is explicitly specified, thus leading to more precise results.<br><br>
The side figure shows the situation for the Italian peninsula.<br>
As you can see there are two main areas and of longitude <b>12E</b>), but there are several smaller areas covering specific regions.
<ul>
<li>The two main areas correspond to <b>EPSG:3003 <i>Monte Mario / Italy zone and <b>EPSG:3004 <i>Monte Mario / Italy zone
<li>The smaller areas correspond to the more specific <b><i>areas of now supported by PROJ.6</li>
</ul><br>
If your specific area of interest is contained within one of these sub-regions you can inform PROJ.6 which sub-region you want by giving either the area BBOX or name, and then PROJ.6 will attempt to use the most specific transformation parameters available.<br><br>
We'll examine this topic in more depth in the following sections.
</td>
<td>
<img alt="italy areas of use">

</table>
<br><br>
<table cellspacing="8" cellpadding="16" bgcolor="#ffffe9">
<tr><td>
<h3>Concepts to keep well in mind</h3>
<ul>
<li>forget the old proj-strings; they are no longer the best way for taking full profit from PROJ.6</li>
<li>the best way to utilize PROJ.6 capabilities is by allowing the library to freely choose the best possible transformation paths between the origin and the destination CRSes.<br>
This, however, strictly requires that the libraries private database (<b>proj.db</b>) can be found.</li>
</ul>
<h3>Additional concept</h3>
The traditional <b>spatial_ref_sys</b> table contained within any SpatiaLite DB noticeably changes its intended purpose when using PROJ.6:
<ul>
<li><b>srid</b>, <b>auth_name</b>, <b>auth_srid</b> and <b>ref_sys_name</b> columns are still required in order to define all supported CRSes and to support
relations based on Primary and Foreign Keys.</li>
<li>but columns <b>proj4text</b> and <b>srtext</b> are now practically useless, because PROJ.6 is now capable of retrieving the needed CRS definitions from its own private database.</li>
<li><i><u>Future both <b>proj4text</b> and <b>srtext</b> will  probably be removed in some future version of SpatiaLite.<br>
For now they will continue to be needed for versions of SpatiaLite that uses, the now superseded, PROJ.4</li>
</ul>

</table>
<h3>Transformation pipelines</h3>
There is a last astonishing innovation introduced in PROJ.6: <b><i>transformation
When using a you can freely define any complex geodetic transformation by combining many elementary steps such as conversion, transformation, projection, axis swap and so on.<br>
A pipeline is conceptually similar to a UNIX shell script, with a dataflow processing each step until the final result is produced.<br>
The following is a practical example of a pipeline corresponding to a transformation from <b>EPSG:4326</b> <i>WGS 84</i> to <b>EPSG:32632</b> <i>WGS 84 / UTM zone 32N</i>:
<verbatim>
+proj=pipeline
+step +proj=axisswap +order=2,1
+step +proj=unitconvert +xy_in=deg +xy_out=rad
+step +proj=utm +zone=32 +ellps=WGS84
</verbatim>
<ul>
<li>Step 0: start a
<li>Step 1: switch the <b>y,x</b> based order to
<li>Step 2: convert previous result from <b>degrees</b> to
<li>Step 3: convert previous result from <b>WSG84</b> to <b>UTM
</ul>
<br><br>
<table cellspacing="8" cellpadding="16" bgcolor="#ffffd0">
<tr><td>
<b><u>Useful PROJ.6 supports a new CLI tool (<b>projinfo</b>) for inspecting, in full detail, the internal definitions of CRSes, Transformations etc.<br>
The above pipeline is simply the output of the following command:
<verbatim>
projinfo -s EPSG:4326 -t EPSG:32632 -o proj
</verbatim>
<b>projinfo</b> is a very usefull resource; don't hesitate to use it frequently in order to discover what's really being done in the background.<br>
It's the best and easiest way to fully understand what PROJ.6 really does.<br><br>
<b>projinfo</b> also gives good hints when problems exist.
In this case <b>PROJ_LIB</b> was incorrectly set and the needed grid files could not be found:
<verbatim>
Grid BETA2007.gsb needed but not found on the system.
Can be obtained from the proj-datumgrid package at
</verbatim>
It not only tells you which grid-file is needed, but also where to get it.

</table><br><br>
<table cellspacing="8" cellpadding="8" bgcolor="#ffffe9">
<tr><th>
In order to learn more about the many interesting and cool new features supported by PROJ.6 please consult the <a PROJ documentation</a>

</table><br>
<hr>
<h1>PROJ.6 support on SpatiaLite-5.0.0</h1>
<h3>Creating and populating the spatial_ref_sys metatable</h3>
There is no relevant change. As in all previous versions <b>spatial_ref_sys</b> will be automatically created and properly populate by calling the appropriate SQL function.
<verbatim>
SELECT InitSpatialMetaData(1);
      or
SELECT InitSpatialMetaDataFull(1);
</verbatim>
<table cellspacing="8" cellpadding="8" bgcolor="#ffffe9">
<tr><td>
Please remember that now in SpatiaLite-5.0.0 <b>InitSpatialMetaDataFull</b> represents the preferred method for creating all metadata tables required by this version.<br>
<b>InitSpatialMetaData</b> is still maintained so to not break historical compatibility, but should no longer be used.

</table><br>
The most relevant change is that different versions of SpatiaLite/PROJ will now behave in radically different ways, as summarized in the following cross-version compatibility table.<br><br>
<table cellspacing="8" cellpadding="16" bgcolor="#e8ffe8" border="1">
<tr><th bgcolor="#ffb03e">SpatiaLite / PROJ version</th><th bgcolor="#ffb03e">Connected DB</th><th
<tr>
<td rowspan="2">SpatiaLite-5 built on
<td>DB created by SpatiaLite-5 / PROJ.6</td>
<td rowspan="2">
<b>libspatialite-5</b> when built on <b>PROJ.6</b> will always ignore both the proj-strings stored in column <b>proj4text</b> and the WKT definitions stored in column <b>srtext</b>.<br>
It will instead allow PROJ.6 to retrieve the needed CRS definitions contained in its own private database.<br><br>
Note that this applies indifferently to both <b><i>legacy created by any previous version and <b><i>most modern created by the latest version.

<tr>
<td>DB created by SpatiaLite-5 / PROJ.4<br>
or<br>
by any previous version of SpatiaLite (< 5.0.0)</td>
</tr>
<tr>
<td rowspan="2">SpatiaLite-5 built on <b>PROJ.4</b><br>
or<br>
any previous version of SpatiaLite (< 5.0.0)</td>
<td>DB created by SpatiaLite-5 / PROJ.6</td>
<td rowspan="2">
When <b>libspatialite</b> (any version, including 5.0.0) that was not compiled against PROJ.6, then the traditional approach will be always applied, and each CRS will be consequently identified by its corresponding proj-string stored in column <b>proj4text</b><br><br>
Note that even when PROJ.6 is not supported any version of SpatiaLite (including 5.0.0) can safely connect to any DB-file created by the most recent version created with full PROJ.6 support.
</td>
</tr>
<tr>
<td>DB created by SpatiaLite-5 / PROJ.4<br>
or<br>
by any previous version of SpatiaLite (< 5.0.0)</td>
</tr>
</table><br><br>
<h3>Existing SQL functions affected by PROJ.6</h3>
<table cellspacing="8" cellpadding="8" bgcolor="#e8ffe8" border="1">
<tr><th bgcolor="#ffb03e">SQL Function</th><th bgcolor="#ffb03e">Extended signature</th><th bgcolor="#ffb03e">Behavior under

<td>
<b>ST_Transform</b> ( geom <i>Geometry</i> , newSrid <i>Integer</i> , area <i>Geometry</i> ) : <i>Geometry</i><hr>
<b>ST_Transform</b> ( geom <i>Geometry</i> , newSrid <i>Integer</i> , area <i>Geometry</i> , proj_string_from <i>Text</i> ) : <i>Geometry</i><hr>
<b>ST_Transform</b> ( geom <i>Geometry</i> , newSrid <i>Integer</i> , area <i>Geometry</i> , proj_string_from <i>Text</i> , proj_string_to <i>Text</i> ) : <i>Geometry</i>
</td>
<td>
<table cellspacing="4" cellpadding="4" bgcolor="#ffffd0">
<tr><td>
all these <b><i>extended are supported only when <b>libspatialite-5.0</b> has been built on the top of <b>PROJ.6</b><br>
If the library has been built instead on earlier versions of PROJ any attempt to call these extended signatures will just return a <b><i>wrong number of arguments to function error.
</td><tr>
</table><br>
<table cellspacing="4" cellpadding="4" bgcolor="#ffdfd0">
<tr><td>
Any invalid argument passed to <b>ST_Transform()</b> (<b><i>extended will raise an <b>SQL Exception</b>.
</td><tr>
</table><br>
<ul>
<li>the optional argument <b>area</b> may be <b>NULL</b> (<i>default setting</i>).<br>
Otherwise it's expected to contain a valid Geometry in <b>SRID=4326
When an <b><i>area of is explicitly supplied, then <b>PROJ.6</b> may eventually use the corresponding <b>BBOX</b> for a fine tuned and more accurate transformation.</li>
<li>both the optional arguments <b>proj_string_from</b> and <b>proj_string_to</b> may be <b>NULL</b> (<i>default setting</i>).<br>
Otherwise they are expected to contain a valid string to be used for identifying the corresponding CRS.<br>
PROJ.6 accepts the following CRS strings:
<ul>
<li>traditional used by all previous versions of PROJ, as e.g.
<ul>
<li><b>+proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +wktext
<li><b>+proj=utm +zone=32 +south +ellps=WGS72 +towgs84=0,0,4.5,0,0,0.554,0.2263 +units=m
<li><b>+proj=utm +zone=32 +ellps=intl +towgs84=-87,-98,-121,0,0,0,0 +units=m
</ul>
<li>any <b><i>WKT defining a CRS.</li>
<li>a <b><i>CRS as e.g.
<ul>
<li><b>WGS
<li><b>WGS 84 / UTM zone
<li><b>IGM95 / UTM zone

<li>any <b><i>canonical CRS as e.g.
<ul>


</ul>
<br>
<ul>
<li><b><u><i>Special if <b>proj_string_to</b> is NULL and <b>proj_string_from</b> is explicitly set, then it will be interpreted as an user defined <b>transformation string</b> (possibly, as a <b>transformation pipeline</b>) as e.g.
<ul>
<li><b>+proj=pipeline<br>
+step +proj=axisswap +order=2,1<br>
+step +proj=unitconvert +xy_in=deg +xy_out=rad<br>
+step +proj=push +v_3<br>
+step +proj=cart +ellps=WGS84<br>
+step +inv +proj=helmert +x=-104.1 +y=-49.1 +z=-9.9 +rx=0.971 +ry=-2.917 +rz=0.714 +s=-11.68 +convention=position_vector<br>
+step +inv +proj=cart +ellps=intl<br>
+step +proj=pop +v_3<br>
+step +proj=tmerc +lat_0=0 +lon_0=9 +k=0.9996 +x_0=1500000 +y_0=0
</ul>
</ul>

<tr><td colspan="3">
<h3>Notes</h3>
<ul>
<li>SpatiaLite does not constrain you in any way by making any <i>magical assumptions</i> and allows the users the freedom to contruct any combination supported by PROJ.
<ul>
<li>The new <b><i>extended supported by <b>ST_Transform</b> closely mimic the most recent PROJ.6 API, so you are free to define your coordinates transformations in several different ways.</li>
<li>The default behavior of SpatiaLite when using PROJ.6 is to completely ignore the CRS definitions stored within the internal table <b>spatial_ref_sys</b><br>
Any required CRS definition will be always retrieved from PROJ.6 itself that will simply receive a request in the form <b><i>from EPSG:32632 to
<li>If, for whatever reason,  you are free to use any kind of proj-strings, WKT definitions or CRS names supported by PROJ.6</b>.<br>
But do not be suprised if the result of your construction results in an exception that contains the text: <b>'PROJ reports'</b> !!!<br>
Care must be taken to analyse the reported PROJ error in such a way as to resolve the PROJ error.</li>

<li>SpatiaLite encourages and promotes the most creative use of PROJ.6, this including the use of your own customized <b>transformation pipelines.</b>.<br>
Correctly using custom transformations isn't necessarily simple and easy,  but offers great opportunities for all skilled and talented power users.</li>
</ul><br><br>

</table><br>
A few practical SQL examples:
<verbatim>
-- from EPSG:4326 to EPSG:3003 - default settings; ignoring spatialite_ref_sys and relying on PROJ.6 own private database
SELECT AsEWKT ( ST_Transform( MakePoint( 11.878056 , 43.463056 , 4326 ) , 3003 ));
-------------------------------------
SRID=3003;POINT(1732852.942716769 4816277.617690674)


-- from EPSG:4326 to EPSG:3003 - exactly the same as above, but this time in an explicit form
SELECT AsEWKT ( ST_Transform( MakePoint( 11.878056 , 43.463056, 4326 ) , 3003, NULL, 'EPSG:4326', 'EPSG:3003'));
-------------------------------------
SRID=3003;POINT(1732852.942716769 4816277.617690674)


-- from EPSG:4326 to EPSG:3003 - same as above, using the alternative notation
SELECT AsEWKT ( ST_Transform( MakePoint( 11.878056 , 43.463056, 4326 ) , 3003, NULL, 'urn:ogc:def:crs:EPSG::4326', 'urn:ogc:def:crs:EPSG::3003'));
-------------------------------------
SRID=3003;POINT(1732852.942716769 4816277.617690674)


-- from EPSG:4326 to EPSG:3003 - explicitly passing CRS names
SELECT AsEWKT ( ST_Transform( MakePoint( 11.878056 , 43.463056, 4326 ) , 3003, NULL, 'WGS 84', 'Monte Mario / Italy zone 1'));
-------------------------------------
SRID=3003;POINT(1732852.942716769 4816277.617690674)


-- from EPSG:4326 to EPSG:3003 - simulating the classic PROJ.4 approach based on proj-strings stored into spatial_ref_sys
SELECT AsEWKT ( ST_Transform( MakePoint( 11.878056 , 43.463056, 4326 ) , 3003 , NULL ,
  (SELECT proj4text FROM spatial_ref_sys WHERE srid = 4326),
  (SELECT proj4text FROM spatial_ref_sys WHERE srid = 3003)));
-------------------------------------
SRID=3003;POINT(1732852.942716769 4816277.617690674)


-- from EPSG:4326 to EPSG:3003 - fancy mode based on WKT expressions stored into spatial_ref_sys
SELECT AsEWKT ( ST_Transform( MakePoint( 11.878056 , 43.463056, 4326 ) , 3003, NULL,
  (SELECT srtext FROM spatial_ref_sys WHERE srid = 4326),
  (SELECT srtext FROM spatial_ref_sys WHERE srid = 3003)));
-------------------------------------
SRID=3003;POINT(1732852.942716769 4816277.617690674)
</verbatim>
This first test is based on a new SpatiaLite database created with full PROJ.6 support. Nothing special here other that all methods return the same results.<br><br>
<verbatim>
-- from EPSG:4326 to EPSG:3003 - using a transformation pipeline
SELECT AsEWKT ( ST_Transform( SwapCoords ( MakePoint( 11.878056 , 43.463056, 4326 ) ) , 3003 , NULL ,
'+proj=pipeline
+step +proj=axisswap +order=2,1
+step +proj=unitconvert +xy_in=deg +xy_out=rad
+step +proj=push +v_3
+step +proj=cart +ellps=WGS84
+step +inv +proj=helmert +x=-104.1 +y=-49.1 +z=-9.9 +rx=0.971 +ry=-2.917 +rz=0.714 +s=-11.68 +convention=position_vector
+step +inv +proj=cart +ellps=intl
+step +proj=pop +v_3
+step +proj=tmerc +lat_0=0 +lon_0=9 +k=0.9996 +x_0=1500000 +y_0=0 +ellps=intl' ));
-------------------------------------
SRID=3003;POINT(1732852.942716769 4816277.617690674)


-- from EPSG:4326 to EPSG:3003 - using a customized transformation pipeline
SELECT AsEWKT ( ST_Transform( MakePoint( 11.878056 , 43.463056, 4326 ) , 3003 , NULL ,
'+proj=pipeline
+step +proj=unitconvert +xy_in=deg +xy_out=rad
+step +proj=push +v_3
+step +proj=cart +ellps=WGS84
+step +inv +proj=helmert +x=-104.1 +y=-49.1 +z=-9.9 +rx=0.971 +ry=-2.917 +rz=0.714 +s=-11.68 +convention=position_vector
+step +inv +proj=cart +ellps=intl
+step +proj=pop +v_3
+step +proj=tmerc +lat_0=0 +lon_0=9 +k=0.9996 +x_0=1500000 +y_0=0 +ellps=intl' ));
-------------------------------------
SRID=3003;POINT(1732852.942716769 4816277.617690674)
</verbatim>
This second test is based on using <b><i>transformation
<ul>
<li>the first query directly uses a canonical string representing the pipeline as returning by this command executed from the shell:
<verbatim>
projinfo  -s EPSG:4326 -t EPSG:3003 --area  "Italy - mainland" -o proj
</verbatim>
(we'll see this topic in more depth on the next section).</li>
<li>the second query is just a small adaptation of the first one:
<ul>
<li>As you can notice the first query requires calling <b>SwapCoodinates()</b> because the first step of the pipeline has an <b>axisswap</b> directive.</li>
<li>The second query just avoids to call <b>SwapCoords()</b> and consequently this first step has been removed from the pipeline so to get the same identical overall effect.</li>

SpatiaLite and PROJ.6 will always attempt to determine if swapping the coordinates is required or not.<br>
But in the specific case of transformation pipelines the user is expected to explicitly call <b>SwapCoords()</b> whenever required.</li>
</ul><br>
<table cellspacing="8" cellpadding="16" bgcolor="#c9fff0">
<tr><td>
<h2>Tech Note: using projinfo for discovering pipelines and areas of use</h2>
<verbatim>
projinfo -s EPSG:4326 -t EPSG:3003 -o proj --spatial-test intersect
Candidate operations found: 3
-------------------------------------
Operation n°1:

unknown id, Inverse of Monte Mario to WGS 84 (4) + Italy zone 1, 4 m, Italy - mainland

PROJ string:
+proj=pipeline
+step +proj=axisswap +order=2,1
+step +proj=unitconvert +xy_in=deg +xy_out=rad
+step +proj=push +v_3
+step +proj=cart +ellps=WGS84
+step +inv +proj=helmert +x=-104.1 +y=-49.1 +z=-9.9 +rx=0.971 +ry=-2.917 +rz=0.714 +s=-11.68 +convention=position_vector
+step +inv +proj=cart +ellps=intl
+step +proj=pop +v_3
+step +proj=tmerc +lat_0=0 +lon_0=9 +k=0.9996 +x_0=1500000 +y_0=0 +ellps=intl

-------------------------------------
Operation n°2:

unknown id, Inverse of Monte Mario to WGS 84 (2) + Italy zone 1, 4 m, Italy - Sardinia onshore

PROJ string:
+proj=pipeline
+step +proj=axisswap +order=2,1
+step +proj=unitconvert +xy_in=deg +xy_out=rad
+step +proj=push +v_3
+step +proj=cart +ellps=WGS84
+step +inv +proj=helmert +x=-168.6 +y=-34 +z=38.6 +rx=-0.374 +ry=-0.679 +rz=-1.379 +s=-9.48 +convention=position_vector
+step +inv +proj=cart +ellps=intl
+step +proj=pop +v_3
+step +proj=tmerc +lat_0=0 +lon_0=9 +k=0.9996 +x_0=1500000 +y_0=0 +ellps=intl

-------------------------------------
Operation n°3:

unknown id, Inverse of Monte Mario to WGS 84 (11) + Italy zone 1, 10 m, Italy - Sicily Strait west of 13°E

PROJ string:
+proj=pipeline
+step +proj=axisswap +order=2,1
+step +proj=unitconvert +xy_in=deg +xy_out=rad
+step +proj=push +v_3
+step +proj=cart +ellps=WGS84
+step +proj=helmert +x=230.47 +y=56.08 +z=-22.43
+step +inv +proj=cart +ellps=intl
+step +proj=pop +v_3
+step +proj=tmerc +lat_0=0 +lon_0=9 +k=0.9996 +x_0=1500000 +y_0=0 +ellps=intl
</verbatim>

</table><br><br>
<verbatim>
-- from EPSG:426 to EPSG:3003 - default settings, NULL area of use
SELECT AsEWKT ( ST_Transform( MakePoint( 9.169464, 39.478275, 4326 ), 3003 ));
-------------------------------------
SRID=3003;POINT(1514600.134321862 4369874.489269957)


-- from EPSG:426 to EPSG:3003 - default settings, but this time explicitly defining the MBR aka BBOX of a specific area of use
SELECT AsEWKT ( ST_Transform( MakePoint( 9.169464, 39.478275, 4326 ), 3003 , BuildMBR(9.1 , 39.4 , 9.2 , 39.5 , 4326 )));
-------------------------------------
SRID=3003;POINT(1514605.982762248 4369873.004226943)
</verbatim>
Third and final example. In some cases explicitly defining a specific <b><i>area of may enable PROJ.6 to select an optimized transformation leading to more precise results.<br>
In this example we've used a Point located in Sardinia, and PROJ.6 supports several flavors of <b>EPSG:3003</b> depending on the specific area of use and
<b>Italy - Sardinia onshore</b> is one between them.
<ul>
<li>the first query does not define any specific area of use, and consequently PROJ.6 calculated the transformation by applying the generic parameters supporting <b>Italy -
<li>the second query instead defines a specific are of use, and this time PROJ.6 calculated the transformation by applying the most precise parameters supporting <b>Italy - Sardinia
</ul><br><br>
<table cellspacing="8" cellpadding="16" bgcolor="#ffffd0">
<tr><td>
<b><u>Lesson
<ul>
<li>The best mode for taking full profit from PROJ.6 is by ignoring all CRS definitions contained into <b>spatial_ref_sys</b>, thus leaving PROJ free to choose the best possible approach. (which is the <b><i>default
This way you'll be absolutely sure that the most recent and fully detailed definitions will always be retrieved from the PROJ.6 own private database.<br>
This will happen even when processing processing some <b><i>legacy that was created by a earlier version and thus potentially contains an outdated table.</li>
<li>SpatiaLite fully respects users freedom, avoiding any imposed constraint.<br>
If you think that using another CRS definitions is a good idea, you are free to use traditional proj-strings, WKT definitions, CRS names and whatever else that may be deemed appropriate.</li>
<li>SpatiaLite encourages and promotes the most creative use of PROJ.6: using your own custom <b><i>transformation isn't necessarily simple and easy, but offers a flexible capability to resolve complex problems or non-standard solutions.</li>
</ul>

</table><br>
<h3>New auxiliary SQL functions specifically supporting PROJ.6</h3>
<table cellspacing="8" cellpadding="8" bgcolor="#e8ffe8" border="1">
<tr><th bgcolor="#ffb03e">SQL Function</th><th bgcolor="#ffb03e">Supported arguments</th><th
<tr><td><b>HasProj6</b>( <i>void</i> ) :
<td>None</td>
<td>Will return <b>1</b> (<b>TRUE</b>) if the library has been built on <b>PROJ.6</b> (or any later version), otherwise <b>0</b>
<tr><td><b>PROJ_GetLastErrorMsg</b>( <i>void</i> ) :
<td>None</td>
<td>Will return the most recent error message returned by PROJ (if any).<br>
<b>NULL</b> will be returned if there is no currently pending PROJ
<tr><td><b>PROJ_GetDatabasePath</b>( <i>void</i> :
<td>None</td>
<td>Will return the currently set pathname leading to the private PROJ's SQLite database.<br>
<b>NULL</b> will be returned if there is no private PROJ's SQLite database currently
<tr><td><b>PROJ_SetDatabasePath</b> ( new_path <i>String</i> ) :
<td>
<ul>
<li><b>new_path</b>: a relative or absolute pathname leading to a valid PROJ's SQLite database.</li>

<td>Will change the currently set pathname leading to the private PROJ's SQLite database.<br>
<b>NULL</b> will be returned if the passed path is invalid, otherwise the path of the currently set private PROJ's SQLite database will be
<tr><td><b>PROJ_AsProjString</b> ( auth_name <i>String</i> , auth_srid <i>Integer</i> ) :
<td><ul>
<li><b>auth_name</b> and <b>auth_srid</b> identify the intended CRS.<br>
<b>auth_name</b> can be <b>NULL</b>, and in this case <b>EPSG</b> will be assumed.</li>

<td>Will return the WKT expression corresponding to a given CRS; the definitions will be taken directly from the private PROJ's own database.<br>
<b>NULL</b> will be returned on failure or on invalid
<tr><td><b>PROJ_AsWKT</b> ( auth_name <i>String</i> , auth_srid <i>Integer</i> ) : <i>String</i><hr>
<b>PROJ_AsWKT</b> ( auth_name <i>String</i> , auth_srid <i>Integer</i> , wkt_style <i>String</i> ) : <i>String</i><hr>
<b>PROJ_AsWKT</b> ( auth_name <i>String</i> , auth_srid <i>Integer</i> , wkt_style <i>String</i> , indented <i>Boolean</i> ) : <i>String</i><hr>
<b>PROJ_AsWKT</b> ( auth_name <i>String</i> , auth_srid <i>Integer</i> , wkt_style <i>String</i> , indented <i>Boolean</i> , indentation <i>Integer</i> ) :
<td><ul>
<li><b>auth_name</b> and <b>auth_srid</b> identify the intended CRS.<br>
<b>auth_name</b> can be <b>NULL</b>, and in this case <b>EPSG</b> will be assumed.</li>
<li>the optional argument <b>style</b> determines which specific WKT format should be adopted, and must be one between <b>GDAL</b>, <b>ESRI</b>, <b>ISO-2015</b> or <b>ISO-2018</b> (this latter being the default setting).</li>
<li>the optional argument <b>indented</b> if set to <b>TRUE</b> will nicely format a multiline WKT expression, otherwise a single monolithic line lacking any white-space or new-line will be printed (the default is
<li>the optional argument <b>indentation</b> determines how many white-spaces are to be used for indenting (only meaningful if the default values is

<td>Will return the WKT expression corresponding to a given CRS; the definitions will be taken directly from the private PROJ's own database.<br>
<b>NULL</b> will be returned on failure or on invalid
<tr><td><b>PROJ_GuessSridFromWKT</b> ( wkt_expr <i>String</i> ) :
<td><ul>
<li><b>wkt_expr</b>: the WKT expression to be evaluated.</li>

<td>
Will possibly return the <b>SRID value</b> corresponding to a given WKT expression defining a CRS.<br>
<b>-1</b> will be returned if no CRS supported by PROJ.6 matches the WKT expression.<br>
<b>NULL</b> will be returned on invalid argument.

<tr><td><b>PROJ_GuessSridFromSHP</b> ( filename <i>String</i> ) :
<td><ul>
<li><b>filename</b>: the absolute or relative path leading to some Shapefile.<br>
Note: exactly as required by must omit any <b>.shp</b>, <b>.shx</b>, <b>.dbf</b> or <b>.prj</b> suffix.</li>

<td>
Will possibly return the <b>SRID value</b> corresponding to the CRS defined by the .PRJ member of the Shapefile.<br>
<b>-1</b> will be returned if no CRS supported by PROJ.6 matches PRJ member of the Shapefile.<br>
<b>NULL</b> will be returned on invalid argument.<hr>
<u>Please note well</u>: this SQL function opens the door to many potential security issues, and thus is always <i>disabled by default</i>.<br>
Explicitly setting the environment variable <b>SPATIALITE_SECURITY=relaxed</b> is absolutely required in order to enable this function.

</table><br>
<table cellspacing="8" cellpadding="16" bgcolor="#ffffe9">
<tr><td>
all the above SQL Functions will be available only when Spatialite-5.0.0 has been built against <b>PROJ.6</b> (or any subsequent version).<br>
If SpatiaLite-5.0.0 has been built instead against any previous version (as e.g. <b>PROJ.4</b>) any attempt to call one of these SQL Functions will simply return a <b><i><u>no such SQL error.

</table><br>
<b>Practical examples:</b>
<verbatim>
SELECT PROJ_GetDatabasePath();  -- retrieving the currently set PROJ's own database
------------------------------


SELECT -- non existing database
------------------------------
NULL


SELECT PROJ_GetLastErrorMsg(); -- retrieving the failure cause
------------------------------
proj_context_set_database_path: Open of failed


SELECT -- valid database
------------------------------


SELECT PROJ_AsProjString('EPSG', 32632);
------------------------------
+proj=utm +zone=32 +datum=WGS84 +units=m +no_defs +type=crs


SELECT PROJ_AsWKT('EPSG', 4326); -- default settings: ISO-2018 style, indented with indentation 4
------------------------------
GEODCRS["WGS 84",
    DATUM["World Geodetic System 1984",
        ELLIPSOID["WGS 84",6378137,298.257223563,
            LENGTHUNIT["metre",1]]],
    PRIMEM["Greenwich",0,
        ANGLEUNIT["degree",0.0174532925199433]],
    CS[ellipsoidal,2],
        AXIS["geodetic latitude (Lat)",north,
            ORDER[1],
            ANGLEUNIT["degree",0.0174532925199433]],
        AXIS["geodetic longitude (Lon)",east,
            ORDER[2],
            ANGLEUNIT["degree",0.0174532925199433]],
    AREA["World"],
    BBOX[-90,-180,90,180],
    ID["EPSG",4326]]


SELECT PROJ_AsWKT('EPSG', 4326, 'ESRI', 0, 0); -- ESRI style, monolithic line
------------------------------
GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137.0,298.257223563]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]]


SELECT PROJ_GuessSridFromWKT('GEOGCS["GCS_Monte_Mario_Rome",DATUM["D_Monte_Mario",SPHEROID["International_1924",6378388.0,297.0]],PRIMEM["Rome",12.4523333333333],UNIT["Degree",0.0174532925199433]]');
------------------------------
4806


SELECT -- remember: requires to explicitly set SPATIALITE_SECURITY=relaxed
------------------------------
3003
</verbatim>
<br>
<hr><br>
<table cellspacing="8" cellpadding="8" bgcolor="#ffe0e9" width="100%">
<tr><th>
<h1>Important notice for Windows users</h1>

<tr><td>
<b>PROJ.6</b> critically depends on its own private SQLite database (<b>proj.db</b>) containing all relevant definitions about Ellipsoids, Prime Meridians, CRSes, Transformations and alike.<br>
If PROJ.6 is unable to correctly establish a connection to this database it will be severely limited and will not be able to correctly behave as expected.<br><br>
<ul>
<li><b><u><i>Short installing the software alone is not enough.<br>
The PROJ.6 private database <b>proj.db</b> must be properly installed as well, in order to ensure that anything runs smoothly.</li>
</ul><br>
This isn't usually a big issue on Linux and Unix-like platforms, where a rational and very clear filesystem layout exists.<br>
On these operating systems the package manager (or <b>make install</b>) will automatically take care to install <b>proj.db</b> on the most appropriate directory (usually as or as and that's all.<br><br>
Things are unhappily a little bit more difficult on Windows platforms.
The user itself is responsible for properly installing <b>proj.db</b>
So it becomes critical understanding the basic rules adopted by <b>libspatialite</b> in order to properly locate <b>proj.db</b> on Windows.

<tr><th>
<h2>Where proj.db is expected to be found on Windows</h2>

<tr><td>
<ol>
<li>the first place where <b>proj.db</b> will be searched is the same folder form where the <b>EXE</b> binary was initially loaded.<br>
assuming that you are currently executing
<ul>
<li>then an attempt will be made to connect

<li>a second attempt will be made on behalf of the <b>Public</b> folder.<br>
an attempt will be made to connect
<li>a third (and last) attempt will be made on behalf of the <b>User</b> folder.<br>
an attempt will be made to connect
</ol>
<h3>An useful diagnostic check</h3>
<verbatim>
SELECT PROJ_GetDatabasePath();
</verbatim>
<ul>
<li>if <b>NULL</b> is returned, then PROJ.6 is definitely unable to connect to its own private SQLite database <b>proj.db</b><br>
You have to carefully verify that it's really installed on one of the expected standard locations.</li>
<li>otherwise the path leading to the currently connected <b>proj.db</b> will be returned.</li>
</ul><br>

</table><br><br>
<table cellspacing="8" cellpadding="8" bgcolor="#c9fff0">
<tr><th>
<h2>Using the environment variable PROJ_LIB</h2>

<tr><td>
<b>PROJ_LIB</b> is a standard environment variable supported by PROJ itself.<br>
When <b>PROJ_LIB</b> is set, then PROJ.6 will directly search its own private database into the directory referenced by the variable.<br>
Such a capability is supported on both Windows and Linux (and on any other platform).<br><br>
<i><u>Linux
<ul>
<li><b>export
echo $PROJ_LIB<br>
spatialite<b></li>
</ul><br><br>
<i><u>Windows
<ul>
<li><b>SET
echo %PROJ_LIB%<br>
spatialite_gui<b></li>
</ul><br><br>

</table><br>
<hr>
<h1>PROJ.6 support on spatialite_gui</h1>
<table cellspacing="8" cellpadding="8" bgcolor="#e8ffe8" border="1">
<tr><td>
The GUI tool just introduces a single new feature intended to make as easy as possible using PROJ.6<br><br>
The main menu now contains an <b><i>External variable item.<br>
After activating the corresponding option a standard <b><i>File Selection Dialog will show on the screen, thus enabling the user to locate on the file-system the private <b>proj.db</b> database of PROJ.6.<br><br>
Once that <b>proj.db</b> will be correctly located then <b>spatialite_gui</b> will automatically set the <b>PROJ_LIB</b> variable.<br><br>
And that's not all; <b>spatialite_gui</b> will persistently store the current value of <b>PROJ_LIB</b>, so as to able to set it automatically for each subsequent invocation.
</td>
<td>
<img alt="gui proj6">

There is a further enhancement available when <b>spatialite_gui</b> is backed up by PROJ.6<br>
It's a very little evident innovation, but it will probably be highly appreciated by many users.<br><br>
When loading some Shapefile now the appropriate <b>SRID value</b> will be automatically determined by examining the content of the companion <b>.prj</b> memebr (if supplied).
</td>
<td>
<img alt="gui proj6">

</table><br>
<hr><br>
<a