aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/source/development/reference/functions.rst63
-rw-r--r--include/proj/internal/io_internal.hpp22
-rw-r--r--include/proj/io.hpp12
-rw-r--r--src/4D_api.cpp197
-rw-r--r--src/apps/cs2cs.cpp16
-rw-r--r--src/init.cpp10
-rw-r--r--src/internal.cpp2
-rw-r--r--src/iso19111/c_api.cpp97
-rw-r--r--src/iso19111/crs.cpp9
-rw-r--r--src/iso19111/factory.cpp6
-rw-r--r--src/iso19111/io.cpp482
-rw-r--r--src/pipeline.cpp2
-rw-r--r--src/proj.h16
-rw-r--r--src/proj_internal.h5
-rw-r--r--src/proj_symbol_rename.h4
-rw-r--r--test/cli/testprojinfo_out.dist10
-rw-r--r--test/unit/pj_transform_test.cpp1
-rw-r--r--test/unit/test_c_api.cpp93
-rw-r--r--test/unit/test_crs.cpp135
-rw-r--r--test/unit/test_factory.cpp24
-rw-r--r--test/unit/test_io.cpp603
-rw-r--r--test/unit/test_operation.cpp87
22 files changed, 1049 insertions, 847 deletions
diff --git a/docs/source/development/reference/functions.rst b/docs/source/development/reference/functions.rst
index 351d2ed3..aa548664 100644
--- a/docs/source/development/reference/functions.rst
+++ b/docs/source/development/reference/functions.rst
@@ -29,7 +29,9 @@ paragraph for more details.
.. c:function:: PJ* proj_create(PJ_CONTEXT *ctx, const char *definition)
- Create a transformation object from a proj-string.
+ Create a transformation object, or a CRS object, from a proj-string,
+ a WKT string, or object code (like "EPSG:4326", "urn:ogc:def:crs:EPSG::4326",
+ "urn:ogc:def:coordinateOperation:EPSG::1671").
Example call:
@@ -37,6 +39,16 @@ paragraph for more details.
PJ *P = proj_create(0, "+proj=etmerc +lat_0=38 +lon_0=125 +ellps=bessel");
+ If a proj-string contains a +type=crs option, then it is interpreted as
+ a CRS definition. In particular geographic CRS are assumed to have axis
+ in the longitude, latitude order and with degree angular unit. The use
+ of proj-string to describe a CRS is discouraged. It is a legacy means of
+ conveying CRS descriptions: use of object codes (EPSG:XXXX typically) or
+ WKT description is recommended for better expressivity.
+
+ If a proj-string does not contain +type=crs, then it is interpreted as a
+ coordination operation / transformation.
+
If creation of the transformation object fails, the function returns `0` and
the PROJ error number is updated. The error number can be read with
:c:func:`proj_errno` or :c:func:`proj_context_errno`.
@@ -50,7 +62,7 @@ paragraph for more details.
.. c:function:: PJ* proj_create_argv(PJ_CONTEXT *ctx, int argc, char **argv)
- Create transformation object with argc/argv-style initialization. For this
+ Create a transformation object, or a CRS object, with argc/argv-style initialization. For this
application each parameter in the defining proj-string is an entry in :c:data:`argv`.
Example call:
@@ -60,6 +72,13 @@ paragraph for more details.
char *args[3] = {"proj=utm", "zone=32", "ellps=GRS80"};
PJ* P = proj_create_argv(0, 3, args);
+ If there is a type=crs argument, then the arguments are interpreted as
+ a CRS definition. In particular geographic CRS are assumed to have axis
+ in the longitude, latitude order and with degree angular unit.
+
+ If there is no type=crs argument, then it is interpreted as a
+ coordination operation / transformation.
+
If creation of the transformation object fails, the function returns `0` and
the PROJ error number is updated. The error number can be read with
:c:func:`proj_errno` or :c:func:`proj_context_errno`.
@@ -71,28 +90,34 @@ paragraph for more details.
:param char** argv: Vector of strings with proj-string parameters, e.g. ``+proj=merc``
:returns: :c:type:`PJ*`
-.. c:function:: PJ* proj_create_crs_to_crs(PJ_CONTEXT *ctx, const char *srid_from, const char *srid_to, PJ_AREA *area)
+.. c:function:: PJ* proj_create_crs_to_crs(PJ_CONTEXT *ctx, const char *source_crs, const char *target_crs, PJ_AREA *area)
Create a transformation object that is a pipeline between two known
coordinate reference systems.
- :c:data:`srid_from` and :c:data:`srid_to` should be the value part of a ``+init=...`` parameter
- set, i.e. "epsg:25833" or "IGNF:AMST63". Any projection definition that
- can be found in a init-file in :envvar:`PROJ_LIB` is a valid input to this function.
+ source_crs and target_crs can be :
+
+ - a "AUTHORITY:CODE", like EPSG:25832. When using that syntax for a source
+ CRS, the created pipeline will expect that the values passed to :c:func:`proj_trans`
+ respect the axis order and axis unit of the official definition (
+ so for example, for EPSG:4326, with latitude first and longitude next,
+ in degrees). Similarly, when using that syntax for a target CRS, output
+ values will be emitted according to the official definition of this CRS.
+
+ - a PROJ string, like "+proj=longlat +datum=WGS84".
+ When using that syntax, the axis order and unit for geographic CRS will
+ be longitude, latitude, and the unit degrees.
+
+ - more generally any string accepted by :c:func:`proj_create`
- For now the function mimics the cs2cs app: An input and an output CRS is
- given and coordinates are transformed via a hub datum (WGS84). This
- transformation strategy is referred to as "early-binding" by the EPSG. The
- function can be extended to support "late-binding" transformations in the
- future without affecting users of the function. When the function is extended
- to the late-binding approach the :c:data:`area` argument will be used. For
- now it is just a place-holder for a future improved implementation.
+ An "area of use" can be specified in area. When it is supplied, the more
+ accurate transformation between two given systems can be chosen.
Example call:
.. code-block:: C
- PJ *P = proj_create_crs_to_crs(0, "epsg:25832", "epsg:25833", 0);
+ PJ *P = proj_create_crs_to_crs(0, "EPSG:25832", "EPSG:25833", 0);
If creation of the transformation object fails, the function returns `0` and
the PROJ error number is updated. The error number can be read with
@@ -579,17 +604,17 @@ Various
C API for ISO-19111 functionality
+++++++++++++++++++++++++++++++++
-The PJ* objects returned by :c:func:`proj_create_from_user_input`,
-:c:func:`proj_create_from_wkt`, :c:func:`proj_create_from_proj_string`,
-:c:func:`proj_create_from_database` and other functions
+The PJ* objects returned by :c:func:`proj_create_from_wkt`,
+:c:func:`proj_create_from_database` and other functions in that section
will have generally minimal interaction with the functions declared in the
previous sections (calling those functions on those objects
will either return an error or default/non-sensical values). The exception is
for ISO19111 objects of type CoordinateOperation that can be exported as a
valid PROJ pipeline. In this case, objects will work for example with
:c:func:`proj_trans_generic`.
-Conversely, objects returned by :c:func:`proj_create` and :c:func:`proj_create_argv` will
-return an error when used with functions of this section.
+Conversely, objects returned by :c:func:`proj_create` and :c:func:`proj_create_argv`,
+which are not of type CRS (can be tested with :c:func:`proj_is_crs`),
+will return an error when used with functions of this section.
.. doxygengroup:: iso19111_functions
:project: cpp_stuff
diff --git a/include/proj/internal/io_internal.hpp b/include/proj/internal/io_internal.hpp
index 62196fef..be6a11bd 100644
--- a/include/proj/internal/io_internal.hpp
+++ b/include/proj/internal/io_internal.hpp
@@ -36,6 +36,7 @@
#include <string>
#include <vector>
+#include "proj/io.hpp"
#include "proj/util.hpp"
//! @cond Doxygen_Suppress
@@ -159,6 +160,27 @@ class WKTConstants {
NS_PROJ_END
+// ---------------------------------------------------------------------------
+
+/** Auxiliary structure to PJ_CONTEXT storing C++ context stuff. */
+struct projCppContext {
+ NS_PROJ::io::DatabaseContextNNPtr databaseContext;
+ std::string lastUOMName_{};
+
+ explicit projCppContext(PJ_CONTEXT *ctx, const char *dbPath = nullptr,
+ const char *const *auxDbPaths = nullptr)
+ : databaseContext(NS_PROJ::io::DatabaseContext::create(
+ dbPath ? dbPath : std::string(), toVector(auxDbPaths), ctx)) {}
+
+ static std::vector<std::string> toVector(const char *const *auxDbPaths) {
+ std::vector<std::string> res;
+ for (auto iter = auxDbPaths; iter && *iter; ++iter) {
+ res.emplace_back(std::string(*iter));
+ }
+ return res;
+ }
+};
+
//! @endcond
#endif // IO_INTERNAL_HH_INCLUDED
diff --git a/include/proj/io.hpp b/include/proj/io.hpp
index ac951233..825e8e44 100644
--- a/include/proj/io.hpp
+++ b/include/proj/io.hpp
@@ -526,7 +526,9 @@ class PROJ_GCC_DLL IPROJStringExportable {
*
* <li>For PROJStringFormatter::Convention::PROJ_4, format a string
* compatible with the OGRSpatialReference::exportToProj4() of GDAL
- * &lt;=2.3.
+ * &lt;=2.3. It is only compatible of a few CRS objects. The PROJ string
+ * will also contain a +type=crs parameter to disambiguish the nature of
+ * the string from a CoordinateOperation.
* <ul>
* <li>For a crs::GeographicCRS, returns a proj=longlat string, with
* ellipsoid / datum / prime meridian information, ignoring axis order
@@ -600,6 +602,9 @@ createFromUserInput(const std::string &text,
const DatabaseContextPtr &dbContext,
bool usePROJ4InitRules = false);
+PROJ_DLL util::BaseObjectNNPtr createFromUserInput(const std::string &text,
+ PJ_CONTEXT *ctx);
+
// ---------------------------------------------------------------------------
/** \brief Parse a WKT string into the appropriate suclass of util::BaseObject.
@@ -662,6 +667,11 @@ class PROJ_GCC_DLL PROJStringParser {
PROJ_DLL util::BaseObjectNNPtr createFromPROJString(
const std::string &projString); // throw(ParsingException)
+ PROJ_PRIVATE :
+ //! @cond Doxygen_Suppress
+ PROJStringParser &
+ attachContext(PJ_CONTEXT *ctx);
+ //! @endcond
private:
PROJ_OPAQUE_PRIVATE_DATA
};
diff --git a/src/4D_api.cpp b/src/4D_api.cpp
index ba292262..5502c96f 100644
--- a/src/4D_api.cpp
+++ b/src/4D_api.cpp
@@ -27,6 +27,8 @@
* DEALINGS IN THE SOFTWARE.
*****************************************************************************/
+#define FROM_PROJ_CPP
+
#include <errno.h>
#include <stddef.h>
#include <stdio.h>
@@ -44,7 +46,9 @@
#include "proj/common.hpp"
#include "proj/coordinateoperation.hpp"
+#include "proj/internal/internal.hpp"
+using namespace NS_PROJ::internal;
/* Initialize PJ_COORD struct */
PJ_COORD proj_coord (double x, double y, double z, double t) {
@@ -458,7 +462,7 @@ Returns 1 on success, 0 on failure
if (nullptr==def)
return 0;
sprintf (def, "break_cs2cs_recursion proj=axisswap axis=%s", P->axis);
- Q = proj_create (P->ctx, def);
+ Q = pj_create_internal (P->ctx, def);
free (def);
if (nullptr==Q)
return 0;
@@ -473,7 +477,7 @@ Returns 1 on success, 0 on failure
if (nullptr==def)
return 0;
sprintf (def, "break_cs2cs_recursion proj=vgridshift grids=%s", gridnames);
- Q = proj_create (P->ctx, def);
+ Q = pj_create_internal (P->ctx, def);
free (def);
if (nullptr==Q)
return 0;
@@ -488,7 +492,7 @@ Returns 1 on success, 0 on failure
if (nullptr==def)
return 0;
sprintf (def, "break_cs2cs_recursion proj=hgridshift grids=%s", gridnames);
- Q = proj_create (P->ctx, def);
+ Q = pj_create_internal (P->ctx, def);
free (def);
if (nullptr==Q)
return 0;
@@ -520,7 +524,7 @@ Returns 1 on success, 0 on failure
if (nullptr==def)
return 0;
sprintf (def, "break_cs2cs_recursion proj=helmert exact %s convention=position_vector", s);
- Q = proj_create (P->ctx, def);
+ Q = pj_create_internal (P->ctx, def);
free(def);
if (nullptr==Q)
return 0;
@@ -546,14 +550,14 @@ Returns 1 on success, 0 on failure
*next_pos = '.';
}
}
- Q = proj_create (P->ctx, def);
+ Q = pj_create_internal (P->ctx, def);
if (nullptr==Q)
return 0;
P->cart = skip_prep_fin (Q);
if (!P->is_geocent) {
sprintf (def, "break_cs2cs_recursion proj=cart ellps=WGS84");
- Q = proj_create (P->ctx, def);
+ Q = pj_create_internal (P->ctx, def);
if (nullptr==Q)
return 0;
P->cart_wgs84 = skip_prep_fin (Q);
@@ -564,9 +568,10 @@ Returns 1 on success, 0 on failure
}
-
/*************************************************************************************/
-PJ *proj_create (PJ_CONTEXT *ctx, const char *definition) {
+PJ *pj_create_internal (PJ_CONTEXT *ctx, const char *definition) {
+/*************************************************************************************/
+
/**************************************************************************************
Create a new PJ object in the context ctx, using the given definition. If ctx==0,
the default context is used, if definition==0, or invalid, a null-pointer is
@@ -619,8 +624,6 @@ PJ *proj_create (PJ_CONTEXT *ctx, const char *definition) {
return P;
}
-
-
/*************************************************************************************/
PJ *proj_create_argv (PJ_CONTEXT *ctx, int argc, char **argv) {
/**************************************************************************************
@@ -653,6 +656,34 @@ indicator, as in {"+proj=utm", "+zone=32"}, or leave it out, as in {"proj=utm",
return P;
}
+/*************************************************************************************/
+PJ *pj_create_argv_internal (PJ_CONTEXT *ctx, int argc, char **argv) {
+/**************************************************************************************
+Same as proj_create_argv() but calls pj_create_internal() instead of proj_create() internally
+**************************************************************************************/
+ PJ *P;
+ const char *c;
+
+ if (nullptr==ctx)
+ ctx = pj_get_default_ctx ();
+ if (nullptr==argv) {
+ proj_context_errno_set(ctx, PJD_ERR_NO_ARGS);
+ return nullptr;
+ }
+
+ /* We assume that free format is used, and build a full proj_create compatible string */
+ c = pj_make_args (argc, argv);
+ if (nullptr==c) {
+ proj_context_errno_set(ctx, ENOMEM);
+ return nullptr;
+ }
+
+ P = pj_create_internal (ctx, c);
+
+ pj_dealloc ((char *) c);
+ return P;
+}
+
/** Create an area of use */
PJ_AREA * proj_area_create(void) {
return static_cast<PJ_AREA*>(pj_calloc(1, sizeof(PJ_AREA)));
@@ -726,6 +757,20 @@ int proj_context_get_use_proj4_init_rules(PJ_CONTEXT *ctx, int from_legacy_code_
return from_legacy_code_path;
}
+/** Adds a " +type=crs" suffix to a PROJ string (if it is a PROJ string) */
+std::string pj_add_type_crs_if_needed(const std::string& str)
+{
+ std::string ret(str);
+ if( (starts_with(str, "proj=") ||
+ starts_with(str, "+proj=") ||
+ starts_with(str, "+init=") ||
+ starts_with(str, "+title=")) &&
+ str.find("type=crs") == std::string::npos )
+ {
+ ret += " +type=crs";
+ }
+ return ret;
+}
/*****************************************************************************/
PJ *proj_create_crs_to_crs (PJ_CONTEXT *ctx, const char *source_crs, const char *target_crs, PJ_AREA *area) {
@@ -743,7 +788,7 @@ PJ *proj_create_crs_to_crs (PJ_CONTEXT *ctx, const char *source_crs, const char
- a PROJ string, like "+proj=longlat +datum=WGS84".
When using that syntax, the axis order and unit for geographic CRS will
be longitude, latitude, and the unit degrees.
- - more generally any string accepted by proj_create_from_user_input()
+ - more generally any string accepted by proj_create()
An "area of use" can be specified in area. When it is supplied, the more
accurate transformation between two given systems can be chosen.
@@ -754,88 +799,94 @@ PJ *proj_create_crs_to_crs (PJ_CONTEXT *ctx, const char *source_crs, const char
******************************************************************************/
const char* proj_string;
- const char* const optionsProj4Mode[] = { "USE_PROJ4_INIT_RULES=YES", nullptr };
if( !ctx ) {
ctx = pj_get_default_ctx();
}
- const char* const* optionsImportCRS =
- proj_context_get_use_proj4_init_rules(ctx, FALSE) ? optionsProj4Mode : nullptr;
+ try
+ {
+ std::string source_crs_modified(pj_add_type_crs_if_needed(source_crs));
+ std::string target_crs_modified(pj_add_type_crs_if_needed(target_crs));
- auto src = proj_create_from_user_input(ctx, source_crs, optionsImportCRS);
- if( !src ) {
- proj_context_log_debug(ctx, "Cannot instantiate source_crs");
- return nullptr;
- }
+ auto src = proj_create(ctx, source_crs_modified.c_str());
+ if( !src ) {
+ proj_context_log_debug(ctx, "Cannot instantiate source_crs");
+ return nullptr;
+ }
- auto dst = proj_create_from_user_input(ctx, target_crs, optionsImportCRS);
- if( !dst ) {
- proj_context_log_debug(ctx, "Cannot instantiate target_crs");
- proj_destroy(src);
- return nullptr;
- }
+ auto dst = proj_create(ctx, target_crs_modified.c_str());
+ if( !dst ) {
+ proj_context_log_debug(ctx, "Cannot instantiate target_crs");
+ proj_destroy(src);
+ return nullptr;
+ }
- auto operation_ctx = proj_create_operation_factory_context(ctx, nullptr);
- if( !operation_ctx ) {
- proj_destroy(src);
- proj_destroy(dst);
- return nullptr;
- }
+ auto operation_ctx = proj_create_operation_factory_context(ctx, nullptr);
+ if( !operation_ctx ) {
+ proj_destroy(src);
+ proj_destroy(dst);
+ return nullptr;
+ }
- if( area && area->bbox_set ) {
- proj_operation_factory_context_set_area_of_interest(
- ctx,
- operation_ctx,
- area->west_lon_degree,
- area->south_lat_degree,
- area->east_lon_degree,
- area->north_lat_degree);
- }
+ if( area && area->bbox_set ) {
+ proj_operation_factory_context_set_area_of_interest(
+ ctx,
+ operation_ctx,
+ area->west_lon_degree,
+ area->south_lat_degree,
+ area->east_lon_degree,
+ area->north_lat_degree);
+ }
- proj_operation_factory_context_set_grid_availability_use(
- ctx, operation_ctx, PROJ_GRID_AVAILABILITY_DISCARD_OPERATION_IF_MISSING_GRID);
+ proj_operation_factory_context_set_grid_availability_use(
+ ctx, operation_ctx, PROJ_GRID_AVAILABILITY_DISCARD_OPERATION_IF_MISSING_GRID);
- auto op_list = proj_create_operations(ctx, src, dst, operation_ctx);
+ auto op_list = proj_create_operations(ctx, src, dst, operation_ctx);
- proj_operation_factory_context_destroy(operation_ctx);
- proj_destroy(src);
- proj_destroy(dst);
+ proj_operation_factory_context_destroy(operation_ctx);
+ proj_destroy(src);
+ proj_destroy(dst);
- if( !op_list ) {
- return nullptr;
- }
+ if( !op_list ) {
+ return nullptr;
+ }
+
+ if( proj_list_get_count(op_list) == 0 ) {
+ proj_list_destroy(op_list);
+ proj_context_log_debug(ctx, "No operation found matching criteria");
+ return nullptr;
+ }
- if( proj_list_get_count(op_list) == 0 ) {
+ auto op = proj_list_get(ctx, op_list, 0);
proj_list_destroy(op_list);
- proj_context_log_debug(ctx, "No operation found matching criteria");
- return nullptr;
- }
+ if( !op ) {
+ return nullptr;
+ }
- auto op = proj_list_get(ctx, op_list, 0);
- proj_list_destroy(op_list);
- if( !op ) {
- return nullptr;
- }
+ proj_string = proj_as_proj_string(ctx, op, PJ_PROJ_5, nullptr);
+ if( !proj_string) {
+ proj_destroy(op);
+ proj_context_log_debug(ctx, "Cannot export operation as a PROJ string");
+ return nullptr;
+ }
+
+ PJ* P;
+ if( proj_string[0] == '\0' ) {
+ /* Null transform ? */
+ P = proj_create(ctx, "proj=affine");
+ } else {
+ P = proj_create(ctx, proj_string);
+ }
- proj_string = proj_as_proj_string(ctx, op, PJ_PROJ_5, nullptr);
- if( !proj_string) {
proj_destroy(op);
- proj_context_log_debug(ctx, "Cannot export operation as a PROJ string");
- return nullptr;
- }
- PJ* P;
- if( proj_string[0] == '\0' ) {
- /* Null transform ? */
- P = proj_create(ctx, "proj=affine");
- } else {
- P = proj_create(ctx, proj_string);
+ return P;
+ }
+ catch( const std::exception& )
+ {
+ return nullptr;
}
-
- proj_destroy(op);
-
- return P;
}
PJ *proj_destroy (PJ *P) {
diff --git a/src/apps/cs2cs.cpp b/src/apps/cs2cs.cpp
index af53a051..1c49965a 100644
--- a/src/apps/cs2cs.cpp
+++ b/src/apps/cs2cs.cpp
@@ -210,11 +210,10 @@ static void process(FILE *fid)
/************************************************************************/
static PJ *instanciate_crs(const std::string &definition,
- const char *const *optionsImportCRS,
bool &isGeog, double &toRadians,
bool &isLatFirst) {
- PJ *crs = proj_create_from_user_input(nullptr, definition.c_str(),
- optionsImportCRS);
+ PJ *crs = proj_create(nullptr,
+ pj_add_type_crs_if_needed(definition).c_str());
if (!crs) {
return nullptr;
}
@@ -535,16 +534,13 @@ int main(int argc, char **argv) {
emess(3, "missing source and target coordinate systems");
}
- const char *const optionsProj4Mode[] = {"USE_PROJ4_INIT_RULES=YES",
- nullptr};
- const char *const *optionsImportCRS =
- proj_context_get_use_proj4_init_rules(nullptr, TRUE) ? optionsProj4Mode
- : nullptr;
+ proj_context_use_proj4_init_rules(nullptr,
+ proj_context_get_use_proj4_init_rules(nullptr, TRUE));
PJ *src = nullptr;
if (!fromStr.empty()) {
bool ignored;
- src = instanciate_crs(fromStr, optionsImportCRS, srcIsGeog,
+ src = instanciate_crs(fromStr, srcIsGeog,
srcToRadians, ignored);
if (!src) {
emess(3, "cannot instantiate source coordinate system");
@@ -553,7 +549,7 @@ int main(int argc, char **argv) {
PJ *dst = nullptr;
if (!toStr.empty()) {
- dst = instanciate_crs(toStr, optionsImportCRS, destIsGeog,
+ dst = instanciate_crs(toStr, destIsGeog,
destToRadians, destIsLatLong);
if (!dst) {
emess(3, "cannot instantiate target coordinate system");
diff --git a/src/init.cpp b/src/init.cpp
index 2ed34a09..8af3d26c 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -238,6 +238,10 @@ Expand key from buffer or (if not in buffer) from init file
char *definition = nullptr;
paralist *init_items = nullptr;
+ if( !ctx ) {
+ ctx = pj_get_default_ctx();
+ }
+
/* support "init=file:section", "+init=file:section", and "file:section" format */
xkey = strstr (key, "init=");
if (nullptr==xkey)
@@ -270,7 +274,6 @@ Expand key from buffer or (if not in buffer) from init file
}
if( !exists ) {
- const char* const optionsProj4Mode[] = { "USE_PROJ4_INIT_RULES=YES", nullptr };
char szInitStr[7 + 64];
PJ* src;
const char* proj_string;
@@ -287,7 +290,10 @@ Expand key from buffer or (if not in buffer) from init file
strcpy(szInitStr, "+init=");
strcat(szInitStr, xkey);
- src = proj_create_from_user_input(ctx, szInitStr, optionsProj4Mode);
+ auto old_proj4_init_rules = ctx->use_proj4_init_rules;
+ ctx->use_proj4_init_rules = true;
+ src = proj_create(ctx, szInitStr);
+ ctx->use_proj4_init_rules = old_proj4_init_rules;
if( !src ) {
return nullptr;
}
diff --git a/src/internal.cpp b/src/internal.cpp
index fbc7c9a1..84db5d82 100644
--- a/src/internal.cpp
+++ b/src/internal.cpp
@@ -207,6 +207,8 @@ consuming their surrounding whitespace.
pj_chomp (c);
n = strlen (c);
+ if (n==0)
+ return c;
/* First collapse repeated whitespace (including +/;) */
i = 0;
diff --git a/src/iso19111/c_api.cpp b/src/iso19111/c_api.cpp
index d13c33c7..06a3c02e 100644
--- a/src/iso19111/c_api.cpp
+++ b/src/iso19111/c_api.cpp
@@ -47,6 +47,7 @@
#include "proj/util.hpp"
#include "proj/internal/internal.hpp"
+#include "proj/internal/io_internal.hpp"
// PROJ include order is sensitive
// clang-format off
@@ -91,25 +92,6 @@ static void PROJ_NO_INLINE proj_log_debug(PJ_CONTEXT *ctx, const char *function,
//! @cond Doxygen_Suppress
-/** Auxiliary structure to PJ_CONTEXT storing C++ context stuff. */
-struct projCppContext {
- DatabaseContextNNPtr databaseContext;
- std::string lastUOMName_{};
-
- explicit projCppContext(PJ_CONTEXT *ctx, const char *dbPath = nullptr,
- const char *const *auxDbPaths = nullptr)
- : databaseContext(DatabaseContext::create(
- dbPath ? dbPath : std::string(), toVector(auxDbPaths), ctx)) {}
-
- static std::vector<std::string> toVector(const char *const *auxDbPaths) {
- std::vector<std::string> res;
- for (auto iter = auxDbPaths; iter && *iter; ++iter) {
- res.emplace_back(std::string(*iter));
- }
- return res;
- }
-};
-
// ---------------------------------------------------------------------------
void proj_context_delete_cpp_context(struct projCppContext *cppContext) {
@@ -150,8 +132,9 @@ static PJ *pj_obj_create(PJ_CONTEXT *ctx, const IdentifiedObjectNNPtr &objIn) {
try {
auto formatter = PROJStringFormatter::create(
PROJStringFormatter::Convention::PROJ_5, dbContext);
- auto pj = proj_create(
- ctx, coordop->exportToPROJString(formatter.get()).c_str());
+ auto projString = coordop->exportToPROJString(formatter.get());
+ auto pj = pj_create_internal(
+ ctx, projString.empty() ? "+proj=affine" : projString.c_str());
if (pj) {
pj->iso_obj = objIn;
return pj;
@@ -346,41 +329,20 @@ PJ *proj_clone(PJ_CONTEXT *ctx, const PJ *obj) {
*
* @param ctx PROJ context, or NULL for default context
* @param text String (must not be NULL)
- * @param options null-terminated list of options, or NULL. Currently
- * supported options are:
- * <ul>
- * <li>USE_PROJ4_INIT_RULES=YES/NO. Defaults to NO. When set to YES,
- * init=epsg:XXXX syntax will be allowed and will be interpreted according to
- * PROJ.4 and PROJ.5 rules, that is geodeticCRS will have longitude, latitude
- * order and will expect/output coordinates in radians. ProjectedCRS will have
- * easting, northing axis order (except the ones with Transverse Mercator South
- * Orientated projection). In that mode, the epsg:XXXX syntax will be also
- * interprated the same way.</li>
- * </ul>
* @return Object that must be unreferenced with proj_destroy(), or NULL in
* case of error.
*/
-PJ *proj_create_from_user_input(PJ_CONTEXT *ctx, const char *text,
- const char *const *options) {
+PJ *proj_create(PJ_CONTEXT *ctx, const char *text) {
SANITIZE_CTX(ctx);
assert(text);
- (void)options;
- auto dbContext = getDBcontextNoException(ctx, __FUNCTION__);
+
+ // Only connect to proj.db if needed
+ if( strstr(text, "proj=") == nullptr || strstr(text, "init=") != nullptr ) {
+ getDBcontextNoException(ctx, __FUNCTION__);
+ }
try {
- bool usePROJ4InitRules = false;
- for (auto iter = options; iter && iter[0]; ++iter) {
- const char *value;
- if ((value = getOptionValue(*iter, "USE_PROJ4_INIT_RULES="))) {
- usePROJ4InitRules = ci_equal(value, "YES");
- } else {
- std::string msg("Unknown option :");
- msg += *iter;
- proj_log_error(ctx, __FUNCTION__, msg.c_str());
- return nullptr;
- }
- }
auto identifiedObject = nn_dynamic_pointer_cast<IdentifiedObject>(
- createFromUserInput(text, dbContext, usePROJ4InitRules));
+ createFromUserInput(text, ctx));
if (identifiedObject) {
return pj_obj_create(ctx, NN_NO_CHECK(identifiedObject));
}
@@ -520,43 +482,6 @@ PJ *proj_create_from_wkt(PJ_CONTEXT *ctx, const char *wkt,
// ---------------------------------------------------------------------------
-/** \brief Instantiate an object from a PROJ string.
- *
- * This function calls osgeo::proj::io::PROJStringParser::createFromPROJString()
- *
- * The returned object must be unreferenced with proj_destroy() after use.
- * It should be used by at most one thread at a time.
- *
- * @param ctx PROJ context, or NULL for default context
- * @param proj_string PROJ string (must not be NULL)
- * @param options should be set to NULL for now
- * @return Object that must be unreferenced with proj_destroy(), or NULL in
- * case of error.
- */
-PJ *proj_create_from_proj_string(PJ_CONTEXT *ctx, const char *proj_string,
- const char *const *options) {
- SANITIZE_CTX(ctx);
- (void)options;
- assert(proj_string);
- try {
- PROJStringParser parser;
- auto dbContext = getDBcontextNoException(ctx, __FUNCTION__);
- if (dbContext) {
- parser.attachDatabaseContext(NN_NO_CHECK(dbContext));
- }
- auto identifiedObject = nn_dynamic_pointer_cast<IdentifiedObject>(
- parser.createFromPROJString(proj_string));
- if (identifiedObject) {
- return pj_obj_create(ctx, NN_NO_CHECK(identifiedObject));
- }
- } catch (const std::exception &e) {
- proj_log_error(ctx, __FUNCTION__, e.what());
- }
- return nullptr;
-}
-
-// ---------------------------------------------------------------------------
-
/** \brief Instantiate an object from a database lookup.
*
* The returned object must be unreferenced with proj_destroy() after use.
diff --git a/src/iso19111/crs.cpp b/src/iso19111/crs.cpp
index 7bf40e0c..74b94a1f 100644
--- a/src/iso19111/crs.cpp
+++ b/src/iso19111/crs.cpp
@@ -1176,7 +1176,8 @@ void GeodeticCRS::_exportToPROJString(
{
const auto &extensionProj4 = CRS::getPrivate()->extensionProj4_;
if (!extensionProj4.empty()) {
- formatter->ingestPROJString(extensionProj4);
+ formatter->ingestPROJString(
+ replaceAll(extensionProj4, " +type=crs", ""));
formatter->addNoDefs(false);
return;
}
@@ -1907,7 +1908,8 @@ void GeographicCRS::_exportToPROJString(
{
const auto &extensionProj4 = CRS::getPrivate()->extensionProj4_;
if (!extensionProj4.empty()) {
- formatter->ingestPROJString(extensionProj4);
+ formatter->ingestPROJString(
+ replaceAll(extensionProj4, " +type=crs", ""));
formatter->addNoDefs(false);
return;
}
@@ -2719,7 +2721,8 @@ void ProjectedCRS::_exportToPROJString(
{
const auto &extensionProj4 = CRS::getPrivate()->extensionProj4_;
if (!extensionProj4.empty()) {
- formatter->ingestPROJString(extensionProj4);
+ formatter->ingestPROJString(
+ replaceAll(extensionProj4, " +type=crs", ""));
formatter->addNoDefs(false);
return;
}
diff --git a/src/iso19111/factory.cpp b/src/iso19111/factory.cpp
index fb75b7b6..54fc3fd3 100644
--- a/src/iso19111/factory.cpp
+++ b/src/iso19111/factory.cpp
@@ -2086,7 +2086,8 @@ AuthorityFactory::createGeodeticCRS(const std::string &code,
if (!text_definition.empty()) {
DatabaseContext::Private::RecursionDetector detector(d->context());
- auto obj = createFromUserInput(text_definition, d->context());
+ auto obj = createFromUserInput(
+ pj_add_type_crs_if_needed(text_definition), d->context());
auto geodCRS = util::nn_dynamic_pointer_cast<crs::GeodeticCRS>(obj);
if (geodCRS) {
return cloneWithProps(NN_NO_CHECK(geodCRS), props);
@@ -2333,7 +2334,8 @@ AuthorityFactory::createProjectedCRS(const std::string &code) const {
if (!text_definition.empty()) {
DatabaseContext::Private::RecursionDetector detector(d->context());
- auto obj = createFromUserInput(text_definition, d->context());
+ auto obj = createFromUserInput(
+ pj_add_type_crs_if_needed(text_definition), d->context());
auto projCRS = dynamic_cast<const crs::ProjectedCRS *>(obj.get());
if (projCRS) {
const auto &conv = projCRS->derivingConversionRef();
diff --git a/src/iso19111/io.cpp b/src/iso19111/io.cpp
index 52c484b9..bac42d5b 100644
--- a/src/iso19111/io.cpp
+++ b/src/iso19111/io.cpp
@@ -3344,6 +3344,9 @@ ConversionNNPtr WKTParser::Private::buildProjectionStandard(
ci_equal(stripQuotes(extensionChildren[0]), "PROJ4")) {
std::string projString = stripQuotes(extensionChildren[1]);
if (starts_with(projString, "+proj=")) {
+ if (projString.find(" +type=crs") == std::string::npos) {
+ projString += " +type=crs";
+ }
try {
auto projObj =
PROJStringParser().createFromPROJString(projString);
@@ -4281,58 +4284,44 @@ BaseObjectNNPtr WKTParser::Private::build(const WKTNodeNNPtr &node) {
throw ParsingException(concat("unhandled keyword: ", name));
}
-//! @endcond
// ---------------------------------------------------------------------------
-/** \brief Instantiate a sub-class of BaseObject from a user specified text.
- *
- * The text can be a:
- * <ul>
- * <li>WKT string</li>
- * <li>PROJ string</li>
- * <li>database code, prefixed by its authoriy. e.g. "EPSG:4326"</li>
- * <li>URN. e.g. "urn:ogc:def:crs:EPSG::4326",
- * "urn:ogc:def:coordinateOperation:EPSG::1671"</li>
- * <li>an objet name. e.g "WGS 84", "WGS 84 / UTM zone 31N". In that case as
- * uniqueness is not guaranteed, the function may apply heuristics to
- * determine the appropriate best match.</li>
- * </ul>
- *
- * @param text One of the above mentioned text format
- * @param dbContext Database context, or nullptr (in which case database
- * lookups will not work)
- * @param usePROJ4InitRules When set to true,
- * init=epsg:XXXX syntax will be allowed and will be interpreted according to
- * PROJ.4 and PROJ.5 rules, that is geodeticCRS will have longitude, latitude
- * order and will expect/output coordinates in radians. ProjectedCRS will have
- * easting, northing axis order (except the ones with Transverse Mercator South
- * Orientated projection). In that mode, the epsg:XXXX syntax will be also
- * interprated the same way.
- * @throw ParsingException
- */
-BaseObjectNNPtr createFromUserInput(const std::string &text,
- const DatabaseContextPtr &dbContext,
- bool usePROJ4InitRules) {
+static BaseObjectNNPtr createFromUserInput(const std::string &text,
+ const DatabaseContextPtr &dbContext,
+ bool usePROJ4InitRules,
+ PJ_CONTEXT *ctx) {
- for (const auto &wktConstants : WKTConstants::constants()) {
- if (ci_starts_with(text, wktConstants)) {
- return WKTParser()
- .attachDatabaseContext(dbContext)
- .setStrict(false)
- .createFromWKT(text);
+ if (!ci_starts_with(text, "step proj=") &&
+ !ci_starts_with(text, "step +proj=")) {
+ for (const auto &wktConstants : WKTConstants::constants()) {
+ if (ci_starts_with(text, wktConstants)) {
+ return WKTParser()
+ .attachDatabaseContext(dbContext)
+ .setStrict(false)
+ .createFromWKT(text);
+ }
}
}
+
const char *textWithoutPlusPrefix = text.c_str();
if (textWithoutPlusPrefix[0] == '+')
textWithoutPlusPrefix++;
if (strncmp(textWithoutPlusPrefix, "proj=", strlen("proj=")) == 0 ||
+ text.find(" +proj=") != std::string::npos ||
+ text.find(" proj=") != std::string::npos ||
strncmp(textWithoutPlusPrefix, "init=", strlen("init=")) == 0 ||
+ text.find(" +init=") != std::string::npos ||
+ text.find(" init=") != std::string::npos ||
strncmp(textWithoutPlusPrefix, "title=", strlen("title=")) == 0) {
return PROJStringParser()
.attachDatabaseContext(dbContext)
- .setUsePROJ4InitRules(usePROJ4InitRules)
+ .attachContext(ctx)
+ .setUsePROJ4InitRules(ctx != nullptr
+ ? (proj_context_get_use_proj4_init_rules(
+ ctx, false) == TRUE)
+ : usePROJ4InitRules)
.createFromPROJString(text);
}
@@ -4449,6 +4438,69 @@ BaseObjectNNPtr createFromUserInput(const std::string &text,
throw ParsingException("unrecognized format / unknown name");
}
+//! @endcond
+
+// ---------------------------------------------------------------------------
+
+/** \brief Instantiate a sub-class of BaseObject from a user specified text.
+ *
+ * The text can be a:
+ * <ul>
+ * <li>WKT string</li>
+ * <li>PROJ string</li>
+ * <li>database code, prefixed by its authoriy. e.g. "EPSG:4326"</li>
+ * <li>URN. e.g. "urn:ogc:def:crs:EPSG::4326",
+ * "urn:ogc:def:coordinateOperation:EPSG::1671"</li>
+ * <li>an objet name. e.g "WGS 84", "WGS 84 / UTM zone 31N". In that case as
+ * uniqueness is not guaranteed, the function may apply heuristics to
+ * determine the appropriate best match.</li>
+ * </ul>
+ *
+ * @param text One of the above mentioned text format
+ * @param dbContext Database context, or nullptr (in which case database
+ * lookups will not work)
+ * @param usePROJ4InitRules When set to true,
+ * init=epsg:XXXX syntax will be allowed and will be interpreted according to
+ * PROJ.4 and PROJ.5 rules, that is geodeticCRS will have longitude, latitude
+ * order and will expect/output coordinates in radians. ProjectedCRS will have
+ * easting, northing axis order (except the ones with Transverse Mercator South
+ * Orientated projection). In that mode, the epsg:XXXX syntax will be also
+ * interprated the same way.
+ * @throw ParsingException
+ */
+BaseObjectNNPtr createFromUserInput(const std::string &text,
+ const DatabaseContextPtr &dbContext,
+ bool usePROJ4InitRules) {
+ return createFromUserInput(text, dbContext, usePROJ4InitRules, nullptr);
+}
+
+// ---------------------------------------------------------------------------
+
+/** \brief Instantiate a sub-class of BaseObject from a user specified text.
+ *
+ * The text can be a:
+ * <ul>
+ * <li>WKT string</li>
+ * <li>PROJ string</li>
+ * <li>database code, prefixed by its authoriy. e.g. "EPSG:4326"</li>
+ * <li>URN. e.g. "urn:ogc:def:crs:EPSG::4326",
+ * "urn:ogc:def:coordinateOperation:EPSG::1671"</li>
+ * <li>an objet name. e.g "WGS 84", "WGS 84 / UTM zone 31N". In that case as
+ * uniqueness is not guaranteed, the function may apply heuristics to
+ * determine the appropriate best match.</li>
+ * </ul>
+ *
+ * @param text One of the above mentioned text format
+ * @param ctx PROJ context
+ * @throw ParsingException
+ */
+BaseObjectNNPtr createFromUserInput(const std::string &text, PJ_CONTEXT *ctx) {
+ return createFromUserInput(
+ text, ctx != nullptr && ctx->cpp_context
+ ? ctx->cpp_context->databaseContext.as_nullable()
+ : nullptr,
+ false, ctx);
+}
// ---------------------------------------------------------------------------
@@ -4619,6 +4671,9 @@ std::string IPROJStringExportable::exportToPROJString(
}
}
if (bIsCRS) {
+ if (!formatter->hasParam("type")) {
+ formatter->addParam("type", "crs");
+ }
formatter->setCRSExport(false);
}
return formatter->toString();
@@ -5217,17 +5272,68 @@ void PROJStringFormatter::Private::appendToResult(const char *str) {
static void
PROJStringSyntaxParser(const std::string &projString, std::vector<Step> &steps,
std::vector<Step::KeyValue> &globalParamValues,
- std::string &title, std::string &vunits,
- std::string &vto_meter) {
+ std::string &title) {
std::string word;
std::istringstream iss(projString, std::istringstream::in);
- bool inverted = false;
- bool prevWasStep = false;
- bool inProj = false;
- bool inPipeline = false;
bool prevWasTitle = false;
- bool prevWasInit = false;
+ if (projString.find("proj=pipeline") == std::string::npos) {
+ const bool hasProj = projString.find("proj=") == 0 ||
+ projString.find("+proj=") == 0 ||
+ projString.find(" proj=") != std::string::npos ||
+ projString.find(" +proj=") != std::string::npos;
+ const bool hasInit = projString.find("init=") == 0 ||
+ projString.find("+init=") == 0 ||
+ projString.find(" init=") != std::string::npos ||
+ projString.find(" +init=") != std::string::npos;
+ if (hasProj || hasInit) {
+ steps.push_back(Step());
+ }
+
+ while (iss >> word) {
+ if (word[0] == '+') {
+ word = word.substr(1);
+ } else if (prevWasTitle && word.find('=') == std::string::npos) {
+ title += " ";
+ title += word;
+ continue;
+ }
+
+ prevWasTitle = false;
+ if (starts_with(word, "proj=") && !hasInit) {
+ assert(hasProj);
+ auto stepName = word.substr(strlen("proj="));
+ steps.back().name = stepName;
+ } else if (starts_with(word, "init=")) {
+ assert(hasInit);
+ auto initName = word.substr(strlen("init="));
+ steps.back().name = initName;
+ steps.back().isInit = true;
+ } else if (word == "inv") {
+ if (!steps.empty()) {
+ steps.back().inverted = true;
+ }
+ } else if (starts_with(word, "title=")) {
+ title = word.substr(strlen("title="));
+ prevWasTitle = true;
+ } else if (word != "step") {
+ const auto pos = word.find('=');
+ auto key = word.substr(0, pos);
+ auto pair = (pos != std::string::npos)
+ ? Step::KeyValue(key, word.substr(pos + 1))
+ : Step::KeyValue(key);
+ if (steps.empty()) {
+ globalParamValues.push_back(pair);
+ } else {
+ steps.back().paramValues.push_back(pair);
+ }
+ }
+ }
+ return;
+ }
+
+ bool inPipeline = false;
+ bool invGlobal = false;
while (iss >> word) {
if (word[0] == '+') {
word = word.substr(1);
@@ -5242,52 +5348,31 @@ PROJStringSyntaxParser(const std::string &projString, std::vector<Step> &steps,
if (inPipeline) {
throw ParsingException("nested pipeline not supported");
}
- inverted = false;
- prevWasStep = false;
- inProj = true;
inPipeline = true;
} else if (word == "step") {
if (!inPipeline) {
throw ParsingException("+step found outside pipeline");
}
- inverted = false;
- prevWasStep = true;
- prevWasInit = false;
+ steps.push_back(Step());
} else if (word == "inv") {
- if (prevWasStep) {
- inverted = true;
+ if (steps.empty()) {
+ invGlobal = true;
} else {
- if (steps.empty()) {
- throw ParsingException("+inv found at unexpected place");
- }
steps.back().inverted = true;
}
- prevWasStep = false;
- } else if (starts_with(word, "proj=")) {
+ } else if (inPipeline && !steps.empty() && starts_with(word, "proj=") &&
+ steps.back().name.empty()) {
auto stepName = word.substr(strlen("proj="));
- if (prevWasInit) {
- steps.back() = Step();
- prevWasInit = false;
- } else {
- steps.push_back(Step());
- }
steps.back().name = stepName;
- steps.back().inverted = inverted;
- prevWasStep = false;
- inProj = true;
- } else if (starts_with(word, "init=")) {
- if (prevWasInit) {
- throw ParsingException("+init= found at unexpected place");
- }
+ } else if (inPipeline && !steps.empty() && starts_with(word, "init=") &&
+ steps.back().name.empty()) {
auto initName = word.substr(strlen("init="));
- steps.push_back(Step());
steps.back().name = initName;
steps.back().isInit = true;
- steps.back().inverted = inverted;
- prevWasStep = false;
- prevWasInit = true;
- inProj = true;
- } else if (inProj) {
+ } else if (!inPipeline && starts_with(word, "title=")) {
+ title = word.substr(strlen("title="));
+ prevWasTitle = true;
+ } else {
const auto pos = word.find('=');
auto key = word.substr(0, pos);
auto pair = (pos != std::string::npos)
@@ -5298,18 +5383,14 @@ PROJStringSyntaxParser(const std::string &projString, std::vector<Step> &steps,
} else {
steps.back().paramValues.push_back(pair);
}
- prevWasStep = false;
- } else if (starts_with(word, "vunits=")) {
- vunits = word.substr(strlen("vunits="));
- } else if (starts_with(word, "vto_meter=")) {
- vto_meter = word.substr(strlen("vto_meter="));
- } else if (starts_with(word, "title=")) {
- title = word.substr(strlen("title="));
- prevWasTitle = true;
- } else {
- throw ParsingException("Unexpected token: " + word);
}
}
+ if (invGlobal) {
+ for (auto &step : steps) {
+ step.inverted = !step.inverted;
+ }
+ std::reverse(steps.begin(), steps.end());
+ }
}
// ---------------------------------------------------------------------------
@@ -5319,10 +5400,7 @@ void PROJStringFormatter::ingestPROJString(
{
std::vector<Step> steps;
std::string title;
- std::string vunits;
- std::string vto_meter;
- PROJStringSyntaxParser(str, steps, d->globalParamValues_, title, vunits,
- vto_meter);
+ PROJStringSyntaxParser(str, steps, d->globalParamValues_, title);
d->steps_.insert(d->steps_.end(), steps.begin(), steps.end());
}
@@ -5596,6 +5674,7 @@ const DatabaseContextPtr &PROJStringFormatter::databaseContext() const {
struct PROJStringParser::Private {
DatabaseContextPtr dbContext_{};
+ PJ_CONTEXT *ctx_{};
bool usePROJ4InitRules_ = false;
std::vector<std::string> warningList_{};
@@ -5623,6 +5702,17 @@ struct PROJStringParser::Private {
template <class T>
// cppcheck-suppress functionStatic
+ const std::string &getGlobalParamValue(const T key) {
+ for (const auto &pair : globalParamValues_) {
+ if (ci_equal(pair.key, key)) {
+ return pair.value;
+ }
+ }
+ return emptyString;
+ }
+
+ template <class T>
+ // cppcheck-suppress functionStatic
const std::string &getParamValue(const Step &step, const T key) {
for (const auto &pair : globalParamValues_) {
if (ci_equal(pair.key, key)) {
@@ -5704,6 +5794,15 @@ PROJStringParser::attachDatabaseContext(const DatabaseContextPtr &dbContext) {
// ---------------------------------------------------------------------------
+//! @cond Doxygen_Suppress
+PROJStringParser &PROJStringParser::attachContext(PJ_CONTEXT *ctx) {
+ d->ctx_ = ctx;
+ return *this;
+}
+//! @endcond
+
+// ---------------------------------------------------------------------------
+
/** \brief Set how init=epsg:XXXX syntax should be interpreted.
*
* @param enable When set to true,
@@ -6902,7 +7001,7 @@ CRSNNPtr PROJStringParser::Private::buildProjectedCRS(
param.key == "towgs84" || param.key == "nadgrids" ||
param.key == "geoidgrids" || param.key == "units" ||
param.key == "to_meter" || param.key == "vunits" ||
- param.key == "vto_meter") {
+ param.key == "vto_meter" || param.key == "type") {
continue;
}
if (param.value.empty()) {
@@ -7252,22 +7351,24 @@ static const metadata::ExtentPtr &getExtent(const crs::CRS *crs) {
// ---------------------------------------------------------------------------
/** \brief Instantiate a sub-class of BaseObject from a PROJ string.
+ *
+ * The projString must contain +type=crs for the object to be detected as a
+ * CRS instead of a CoordinateOperation.
+ *
* @throw ParsingException
*/
BaseObjectNNPtr
PROJStringParser::createFromPROJString(const std::string &projString) {
- std::string vunits;
- std::string vto_meter;
-
d->steps_.clear();
d->title_.clear();
d->globalParamValues_.clear();
d->projString_ = projString;
PROJStringSyntaxParser(projString, d->steps_, d->globalParamValues_,
- d->title_, vunits, vto_meter);
+ d->title_);
if (d->steps_.empty()) {
-
+ const auto &vunits = d->getGlobalParamValue("vunits");
+ const auto &vto_meter = d->getGlobalParamValue("vto_meter");
if (!vunits.empty() || !vto_meter.empty()) {
Step fakeStep;
if (!vunits.empty()) {
@@ -7288,9 +7389,10 @@ PROJStringParser::createFromPROJString(const std::string &projString) {
}
}
- if ((d->steps_.size() == 1 ||
+ if (((d->steps_.size() == 1 &&
+ d->getParamValue(d->steps_[0], "type") == "crs") ||
(d->steps_.size() == 2 && d->steps_[1].name == "unitconvert")) &&
- isGeocentricStep(d->steps_[0].name)) {
+ !d->steps_[0].inverted && isGeocentricStep(d->steps_[0].name)) {
return d->buildBoundOrCompoundCRSIfNeeded(
0, d->buildGeocentricCRS(0, (d->steps_.size() == 2 &&
d->steps_[1].name == "unitconvert")
@@ -7300,7 +7402,7 @@ PROJStringParser::createFromPROJString(const std::string &projString) {
// +init=xxxx:yyyy syntax
if (d->steps_.size() == 1 && d->steps_[0].isInit &&
- d->steps_[0].paramValues.size() == 0) {
+ !d->steps_[0].inverted) {
// Those used to come from a text init file
// We only support them in compatibility mode
@@ -7331,9 +7433,14 @@ PROJStringParser::createFromPROJString(const std::string &projString) {
if (!file_found) {
auto obj = createFromUserInput(stepName, d->dbContext_, true);
auto crs = dynamic_cast<CRS *>(obj.get());
- if (crs) {
+ if (crs &&
+ (d->steps_[0].paramValues.empty() ||
+ (d->steps_[0].paramValues.size() == 1 &&
+ d->getParamValue(d->steps_[0], "type") == "crs"))) {
PropertyMap properties;
- properties.set(IdentifiedObject::NAME_KEY, crs->nameStr());
+ properties.set(IdentifiedObject::NAME_KEY,
+ d->title_.empty() ? crs->nameStr()
+ : d->title_);
const auto &extent = getExtent(crs);
if (extent) {
properties.set(
@@ -7342,12 +7449,12 @@ PROJStringParser::createFromPROJString(const std::string &projString) {
}
auto geogCRS = dynamic_cast<GeographicCRS *>(crs);
if (geogCRS) {
- // Override with longitude latitude in radian
+ // Override with longitude latitude in degrees
return GeographicCRS::create(
properties, geogCRS->datum(),
geogCRS->datumEnsemble(),
EllipsoidalCS::createLongitudeLatitude(
- UnitOfMeasure::RADIAN));
+ UnitOfMeasure::DEGREE));
}
auto projCRS = dynamic_cast<ProjectedCRS *>(crs);
if (projCRS) {
@@ -7363,8 +7470,31 @@ PROJStringParser::createFromPROJString(const std::string &projString) {
->unit()));
}
}
+ return obj;
+ }
+ auto projStringExportable =
+ dynamic_cast<IPROJStringExportable *>(crs);
+ if (projStringExportable) {
+ std::string expanded;
+ if (!d->title_.empty()) {
+ expanded = "title=";
+ expanded += d->title_;
+ }
+ for (const auto &pair : d->steps_[0].paramValues) {
+ if (!expanded.empty())
+ expanded += ' ';
+ expanded += '+';
+ expanded += pair.key;
+ if (!pair.value.empty()) {
+ expanded += '=';
+ expanded += pair.value;
+ }
+ }
+ expanded += ' ';
+ expanded += projStringExportable->exportToPROJString(
+ PROJStringFormatter::create().get());
+ return createFromPROJString(expanded);
}
- return obj;
}
}
@@ -7372,18 +7502,23 @@ PROJStringParser::createFromPROJString(const std::string &projString) {
if (!init) {
throw ParsingException("out of memory");
}
- PJ_CONTEXT *ctx = proj_context_create();
+ PJ_CONTEXT *ctx = d->ctx_ ? d->ctx_ : proj_context_create();
if (!ctx) {
pj_dealloc(init);
throw ParsingException("out of memory");
}
paralist *list = pj_expand_init(ctx, init);
- proj_context_destroy(ctx);
+ if (ctx != d->ctx_) {
+ proj_context_destroy(ctx);
+ }
if (!list) {
pj_dealloc(init);
throw ParsingException("cannot expand " + projString);
}
std::string expanded;
+ if (!d->title_.empty()) {
+ expanded = "title=" + d->title_;
+ }
bool first = true;
bool has_init_term = false;
for (auto t = list; t;) {
@@ -7403,6 +7538,14 @@ PROJStringParser::createFromPROJString(const std::string &projString) {
pj_dealloc(t);
t = n;
}
+ for (const auto &pair : d->steps_[0].paramValues) {
+ expanded += " +";
+ expanded += pair.key;
+ if (!pair.value.empty()) {
+ expanded += '=';
+ expanded += pair.value;
+ }
+ }
if (!has_init_term) {
return createFromPROJString(expanded);
@@ -7420,7 +7563,7 @@ PROJStringParser::createFromPROJString(const std::string &projString) {
int iFirstCart = -1;
int iSecondCart = -1;
int iMolodensky = -1;
- bool unexpectedStructure = false;
+ bool unexpectedStructure = d->steps_.empty();
for (int i = 0; i < static_cast<int>(d->steps_.size()); i++) {
const auto &stepName = d->steps_[i].name;
if (isGeographicStep(stepName)) {
@@ -7483,9 +7626,82 @@ PROJStringParser::createFromPROJString(const std::string &projString) {
}
}
+ if (iHelmert < 0 && iMolodensky < 0 && !d->steps_.empty()) {
+ // CRS candidate
+ if ((d->steps_.size() == 1 &&
+ d->getParamValue(d->steps_[0], "type") != "crs") ||
+ (d->steps_.size() > 1 && d->getGlobalParamValue("type") != "crs")) {
+ unexpectedStructure = true;
+ }
+ } else if (iHelmert >= 0 &&
+ (d->hasParamValue(d->steps_[iHelmert], "theta") ||
+ d->hasParamValue(d->steps_[iHelmert], "exact") ||
+ d->hasParamValue(d->steps_[iHelmert], "transpose") ||
+ d->hasParamValue(d->steps_[iHelmert], "towgs84"))) {
+ unexpectedStructure = true;
+ }
+
+ if (unexpectedStructure || iHelmert >= 0 || iMolodensky >= 0) {
+ struct Logger {
+ std::string msg{};
+
+ // cppcheck-suppress functionStatic
+ void setMessage(const char *msgIn) noexcept {
+ try {
+ msg = msgIn;
+ } catch (const std::exception &) {
+ }
+ }
+
+ static void log(void *user_data, int level, const char *msg) {
+ if (level == PJ_LOG_ERROR) {
+ static_cast<Logger *>(user_data)->setMessage(msg);
+ }
+ }
+ };
+
+ // If the structure is not recognized, then try to instantiate the
+ // pipeline, and if successful, wrap it in a PROJBasedOperation
+ Logger logger;
+ bool valid;
+
+ auto pj_context = d->ctx_ ? d->ctx_ : proj_context_create();
+ if (!pj_context) {
+ throw ParsingException("out of memory");
+ }
+ if (pj_context != d->ctx_) {
+ proj_log_func(pj_context, &logger, Logger::log);
+ proj_context_use_proj4_init_rules(pj_context,
+ d->usePROJ4InitRules_);
+ }
+ auto pj = pj_create_internal(pj_context, projString.c_str());
+ valid = pj != nullptr;
+ proj_destroy(pj);
+
+ if (!valid) {
+ std::string prefix("Error " +
+ toString(proj_context_errno(pj_context)) + ": ");
+ if (logger.msg.empty()) {
+ logger.msg =
+ prefix + proj_errno_string(proj_context_errno(pj_context));
+ } else {
+ logger.msg = prefix + logger.msg;
+ }
+ }
+
+ if (pj_context != d->ctx_) {
+ proj_context_destroy(pj_context);
+ }
+
+ if (!valid) {
+ throw ParsingException(logger.msg);
+ }
+ }
+
if (!unexpectedStructure) {
- if (iFirstGeogStep == 0 && iSecondGeogStep < 0 && iProjStep < 0 &&
- iHelmert < 0 && iFirstCart < 0 && iMolodensky < 0 &&
+ if (iFirstGeogStep == 0 && !d->steps_[iFirstGeogStep].inverted &&
+ iSecondGeogStep < 0 && iProjStep < 0 && iHelmert < 0 &&
+ iFirstCart < 0 && iMolodensky < 0 &&
(iFirstUnitConvert < 0 || iSecondUnitConvert < 0) &&
(iFirstAxisSwap < 0 || iSecondAxisSwap < 0)) {
const bool ignoreVUnits = false;
@@ -7515,9 +7731,6 @@ PROJStringParser::createFromPROJString(const std::string &projString) {
iFirstAxisSwap < iFirstGeogStep ? iSecondAxisSwap
: iFirstAxisSwap));
}
- if (d->steps_.size() == 1 && iHelmert == 0) {
- return d->buildHelmertTransformation(iHelmert);
- }
if (iProjStep < 0 && iHelmert > 0 && iMolodensky < 0 &&
(iFirstGeogStep < 0 || iFirstGeogStep == iFirstCart - 1 ||
@@ -7541,10 +7754,6 @@ PROJStringParser::createFromPROJString(const std::string &projString) {
iSecondAxisSwap, iSecondUnitConvert);
}
- if (d->steps_.size() == 1 && iMolodensky == 0) {
- return d->buildMolodenskyTransformation(iMolodensky);
- }
-
if (iProjStep < 0 && iHelmert < 0 && iMolodensky > 0 &&
(iFirstGeogStep < 0 || iFirstGeogStep == iMolodensky - 1 ||
(iFirstGeogStep == iMolodensky + 1 && iSecondGeogStep < 0)) &&
@@ -7565,47 +7774,6 @@ PROJStringParser::createFromPROJString(const std::string &projString) {
}
}
- struct Logger {
- std::string msg{};
-
- // cppcheck-suppress functionStatic
- void setMessage(const char *msgIn) noexcept {
- try {
- msg = msgIn;
- } catch (const std::exception &) {
- }
- }
-
- static void log(void *user_data, int level, const char *msg) {
- if (level == PJ_LOG_ERROR) {
- static_cast<Logger *>(user_data)->setMessage(msg);
- }
- }
- };
-
- // If the structure is not recognized, then try to instantiate the
- // pipeline, and if successful, wrap it in a PROJBasedOperation
- Logger logger;
- auto pj_context = proj_context_create();
- if (!pj_context) {
- throw ParsingException("out of memory");
- }
- proj_log_func(pj_context, &logger, Logger::log);
- proj_context_use_proj4_init_rules(pj_context, d->usePROJ4InitRules_);
- auto pj = proj_create(pj_context, projString.c_str());
- bool valid = pj != nullptr;
- proj_destroy(pj);
-
- if (!valid && logger.msg.empty()) {
- logger.setMessage(proj_errno_string(proj_context_errno(pj_context)));
- }
-
- proj_context_destroy(pj_context);
-
- if (!valid) {
- throw ParsingException(logger.msg);
- }
-
auto props = PropertyMap();
if (!d->title_.empty()) {
props.set(IdentifiedObject::NAME_KEY, d->title_);
diff --git a/src/pipeline.cpp b/src/pipeline.cpp
index b24f71e7..c4a9d2c0 100644
--- a/src/pipeline.cpp
+++ b/src/pipeline.cpp
@@ -456,7 +456,7 @@ PJ *OPERATION(pipeline,0) {
err = proj_errno_reset (P);
- next_step = proj_create_argv (P->ctx, current_argc, current_argv);
+ next_step = pj_create_argv_internal (P->ctx, current_argc, current_argv);
proj_log_trace (P, "Pipeline: Step %d (%s) at %p", i, current_argv[0], next_step);
if (nullptr==next_step) {
diff --git a/src/proj.h b/src/proj.h
index 2b4531ec..552f4b26 100644
--- a/src/proj.h
+++ b/src/proj.h
@@ -653,16 +653,16 @@ typedef enum
* \defgroup iso19111_functions Binding in C of basic methods from the C++ API
* Functions for ISO19111 C API
*
- * The PJ* objects returned by proj_create_from_user_input(), proj_create_from_wkt(),
- * proj_create_from_proj_string(), proj_create_from_database() and other functions
+ * The PJ* objects returned by proj_create_from_wkt(),
+ * proj_create_from_database() and other functions in that section
* will have generally minimal interaction with the functions declared in the
* upper section of this header file (calling those functions on those objects
* will either return an error or default/non-sensical values). The exception is
* for ISO19111 objects of type CoordinateOperation that can be exported as a
* valid PROJ pipeline. In this case, the PJ objects will work for example with
* proj_trans_generic().
- * Conversely, objects returned by proj_create() and proj_create_argv() will
- * return an error when used with functions of this section.
+ * Conversely, objects returned by proj_create() and proj_create_argv(), which
+ * are not of type CRS, will return an error when used with functions of this section.
* @{
*/
@@ -686,19 +686,11 @@ const char PROJ_DLL *proj_context_get_database_metadata(PJ_CONTEXT* ctx,
PJ_GUESSED_WKT_DIALECT PROJ_DLL proj_context_guess_wkt_dialect(PJ_CONTEXT *ctx,
const char *wkt);
-PJ PROJ_DLL *proj_create_from_user_input(PJ_CONTEXT *ctx,
- const char *text,
- const char* const *options);
-
PJ PROJ_DLL *proj_create_from_wkt(PJ_CONTEXT *ctx, const char *wkt,
const char* const *options,
PROJ_STRING_LIST *out_warnings,
PROJ_STRING_LIST *out_grammar_errors);
-PJ PROJ_DLL *proj_create_from_proj_string(PJ_CONTEXT *ctx,
- const char *proj_string,
- const char* const *options);
-
PJ PROJ_DLL *proj_create_from_database(PJ_CONTEXT *ctx,
const char *auth_name,
const char *code,
diff --git a/src/proj_internal.h b/src/proj_internal.h
index bbadb376..dcfd6797 100644
--- a/src/proj_internal.h
+++ b/src/proj_internal.h
@@ -899,6 +899,11 @@ void pj_freeup_plain (PJ *P);
PJ* pj_init_ctx_with_allow_init_epsg( projCtx_t *ctx, int argc, char **argv, int allow_init_epsg );
+std::string PROJ_DLL pj_add_type_crs_if_needed(const std::string& str);
+
+PJ *pj_create_internal (PJ_CONTEXT *ctx, const char *definition);
+PJ *pj_create_argv_internal (PJ_CONTEXT *ctx, int argc, char **argv);
+
/* classic public API */
#include "proj_api.h"
diff --git a/src/proj_symbol_rename.h b/src/proj_symbol_rename.h
index a7628e35..0ce342fd 100644
--- a/src/proj_symbol_rename.h
+++ b/src/proj_symbol_rename.h
@@ -102,6 +102,8 @@
#define proj_context_get_use_proj4_init_rules internal_proj_context_get_use_proj4_init_rules
#define proj_context_guess_wkt_dialect internal_proj_context_guess_wkt_dialect
#define proj_context_set_database_path internal_proj_context_set_database_path
+#define proj_context_set_file_finder internal_proj_context_set_file_finder
+#define proj_context_set_search_paths internal_proj_context_set_search_paths
#define proj_context_use_proj4_init_rules internal_proj_context_use_proj4_init_rules
#define proj_convert_conversion_to_other_method internal_proj_convert_conversion_to_other_method
#define proj_coord internal_proj_coord
@@ -190,8 +192,6 @@
#define proj_create_engineering_crs internal_proj_create_engineering_crs
#define proj_create_from_database internal_proj_create_from_database
#define proj_create_from_name internal_proj_create_from_name
-#define proj_create_from_proj_string internal_proj_create_from_proj_string
-#define proj_create_from_user_input internal_proj_create_from_user_input
#define proj_create_from_wkt internal_proj_create_from_wkt
#define proj_create_geocentric_crs internal_proj_create_geocentric_crs
#define proj_create_geocentric_crs_from_datum internal_proj_create_geocentric_crs_from_datum
diff --git a/test/cli/testprojinfo_out.dist b/test/cli/testprojinfo_out.dist
index 462e8062..ebc59c40 100644
--- a/test/cli/testprojinfo_out.dist
+++ b/test/cli/testprojinfo_out.dist
@@ -1,6 +1,6 @@
Testing projinfo EPSG:4326
PROJ.4 string:
-+proj=longlat +datum=WGS84 +no_defs
++proj=longlat +datum=WGS84 +no_defs +type=crs
WKT2_2018 string:
GEOGCRS["WGS 84",
@@ -78,7 +78,7 @@ GEOGCRS["WGS 84",
Testing projinfo -o ALL EPSG:4326
PROJ.4 string:
-+proj=longlat +datum=WGS84 +no_defs
++proj=longlat +datum=WGS84 +no_defs +type=crs
WKT2_2015 string:
GEODCRS["WGS 84",
@@ -555,7 +555,7 @@ Alternative non-deprecated CRS:
EPSG:3003
PROJ.4 string:
-+proj=tmerc +lat_0=0 +lon_0=9 +k=0.9996 +x_0=1500000 +y_0=0 +ellps=intl +pm=rome +units=m +no_defs
++proj=tmerc +lat_0=0 +lon_0=9 +k=0.9996 +x_0=1500000 +y_0=0 +ellps=intl +pm=rome +units=m +no_defs +type=crs
WKT2_2018 string:
PROJCRS["Monte Mario (Rome) / Italy zone 1",
@@ -602,7 +602,7 @@ Warning: Parsing error : syntax error, unexpected UNIT, expecting PRIMEM. Error
HEROID["WGS 84",6378137,298.257223563]],UNIT["degree",0.0174532925199433]]
^
PROJ.4 string:
-+proj=longlat +datum=WGS84 +no_defs
++proj=longlat +datum=WGS84 +no_defs +type=crs
WKT2_2018 string:
GEOGCRS["WGS 84",
@@ -623,5 +623,5 @@ GEOGCRS["WGS 84",
Testing CRS with towgs84: projinfo -o PROJ EPSG:25832
PROJ.4 string:
-+proj=utm +zone=32 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs
++proj=utm +zone=32 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs +type=crs
diff --git a/test/unit/pj_transform_test.cpp b/test/unit/pj_transform_test.cpp
index 22f7afca..9d8439ee 100644
--- a/test/unit/pj_transform_test.cpp
+++ b/test/unit/pj_transform_test.cpp
@@ -572,6 +572,7 @@ TEST(pj_transform_test, init_epsg) {
auto src = pj_init_plus("+init=epsg:4326");
ASSERT_TRUE(src != nullptr);
auto dst = pj_init_plus("+init=epsg:32631");
+ ASSERT_TRUE(dst != nullptr);
double x = 3 * DEG_TO_RAD;
double y = 0 * DEG_TO_RAD;
EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, nullptr), 0);
diff --git a/test/unit/test_c_api.cpp b/test/unit/test_c_api.cpp
index 6353d46f..ff29185f 100644
--- a/test/unit/test_c_api.cpp
+++ b/test/unit/test_c_api.cpp
@@ -148,15 +148,14 @@ class CApi : public ::testing::Test {
// ---------------------------------------------------------------------------
-TEST_F(CApi, proj_create_from_user_input) {
+TEST_F(CApi, proj_create) {
proj_destroy(nullptr);
- EXPECT_EQ(proj_create_from_user_input(m_ctxt, "invalid", nullptr), nullptr);
+ EXPECT_EQ(proj_create(m_ctxt, "invalid"), nullptr);
{
- auto obj = proj_create_from_user_input(
- m_ctxt,
- GeographicCRS::EPSG_4326->exportToWKT(WKTFormatter::create().get())
- .c_str(),
- nullptr);
+ auto obj =
+ proj_create(m_ctxt, GeographicCRS::EPSG_4326
+ ->exportToWKT(WKTFormatter::create().get())
+ .c_str());
ObjectKeeper keeper(obj);
EXPECT_NE(obj, nullptr);
@@ -182,7 +181,7 @@ TEST_F(CApi, proj_create_from_user_input) {
EXPECT_EQ(info.definition, std::string(""));
}
{
- auto obj = proj_create_from_user_input(m_ctxt, "EPSG:4326", nullptr);
+ auto obj = proj_create(m_ctxt, "EPSG:4326");
ObjectKeeper keeper(obj);
EXPECT_NE(obj, nullptr);
}
@@ -318,17 +317,6 @@ TEST_F(CApi, proj_create_from_wkt) {
// ---------------------------------------------------------------------------
-TEST_F(CApi, proj_create_from_proj_string) {
-
- EXPECT_EQ(proj_create_from_proj_string(m_ctxt, "invalid", nullptr),
- nullptr);
- auto obj = proj_create_from_proj_string(m_ctxt, "+proj=longlat", nullptr);
- ObjectKeeper keeper(obj);
- EXPECT_NE(obj, nullptr);
-}
-
-// ---------------------------------------------------------------------------
-
TEST_F(CApi, proj_as_wkt) {
auto obj = proj_create_from_wkt(
m_ctxt,
@@ -492,12 +480,14 @@ TEST_F(CApi, proj_as_proj_string) {
{
auto proj_5 = proj_as_proj_string(m_ctxt, obj, PJ_PROJ_5, nullptr);
ASSERT_NE(proj_5, nullptr);
- EXPECT_EQ(std::string(proj_5), "+proj=longlat +datum=WGS84 +no_defs");
+ EXPECT_EQ(std::string(proj_5),
+ "+proj=longlat +datum=WGS84 +no_defs +type=crs");
}
{
auto proj_4 = proj_as_proj_string(m_ctxt, obj, PJ_PROJ_4, nullptr);
ASSERT_NE(proj_4, nullptr);
- EXPECT_EQ(std::string(proj_4), "+proj=longlat +datum=WGS84 +no_defs");
+ EXPECT_EQ(std::string(proj_4),
+ "+proj=longlat +datum=WGS84 +no_defs +type=crs");
}
}
@@ -518,22 +508,22 @@ TEST_F(CApi, proj_as_proj_string_incompatible_WKT1) {
// ---------------------------------------------------------------------------
TEST_F(CApi, proj_as_proj_string_etmerc_option_yes) {
- auto obj = proj_create_from_proj_string(m_ctxt, "+proj=tmerc", nullptr);
+ auto obj = proj_create(m_ctxt, "+proj=tmerc +type=crs");
ObjectKeeper keeper(obj);
ASSERT_NE(obj, nullptr);
const char *options[] = {"USE_ETMERC=YES", nullptr};
auto str = proj_as_proj_string(m_ctxt, obj, PJ_PROJ_4, options);
ASSERT_NE(str, nullptr);
- EXPECT_EQ(str, std::string("+proj=etmerc +lat_0=0 +lon_0=0 +k=1 +x_0=0 "
- "+y_0=0 +datum=WGS84 +units=m +no_defs"));
+ EXPECT_EQ(str,
+ std::string("+proj=etmerc +lat_0=0 +lon_0=0 +k=1 +x_0=0 "
+ "+y_0=0 +datum=WGS84 +units=m +no_defs +type=crs"));
}
// ---------------------------------------------------------------------------
TEST_F(CApi, proj_as_proj_string_etmerc_option_no) {
- auto obj =
- proj_create_from_proj_string(m_ctxt, "+proj=utm +zone=31", nullptr);
+ auto obj = proj_create(m_ctxt, "+proj=utm +zone=31 +type=crs");
ObjectKeeper keeper(obj);
ASSERT_NE(obj, nullptr);
@@ -542,7 +532,7 @@ TEST_F(CApi, proj_as_proj_string_etmerc_option_no) {
ASSERT_NE(str, nullptr);
EXPECT_EQ(str, std::string("+proj=tmerc +lat_0=0 +lon_0=3 +k=0.9996 "
"+x_0=500000 +y_0=0 +datum=WGS84 +units=m "
- "+no_defs"));
+ "+no_defs +type=crs"));
}
// ---------------------------------------------------------------------------
@@ -563,7 +553,7 @@ TEST_F(CApi, proj_crs_create_bound_crs_to_WGS84) {
"+proj=sterea +lat_0=46 +lon_0=25 +k=0.99975 +x_0=500000 "
"+y_0=500000 +ellps=krass "
"+towgs84=2.329,-147.042,-92.08,-0.309,0.325,0.497,5.69 "
- "+units=m +no_defs");
+ "+units=m +no_defs +type=crs");
auto base_crs = proj_get_source_crs(m_ctxt, res);
ObjectKeeper keeper_base_crs(base_crs);
@@ -1694,8 +1684,7 @@ TEST_F(CApi, proj_get_area_of_use) {
EXPECT_EQ(std::string(name), "World");
}
{
- auto obj =
- proj_create_from_user_input(m_ctxt, "+proj=longlat", nullptr);
+ auto obj = proj_create(m_ctxt, "+proj=longlat +type=crs");
ObjectKeeper keeper(obj);
ASSERT_NE(obj, nullptr);
EXPECT_FALSE(proj_get_area_of_use(m_ctxt, obj, nullptr, nullptr,
@@ -1722,8 +1711,7 @@ TEST_F(CApi, proj_coordoperation_get_accuracy) {
EXPECT_EQ(proj_coordoperation_get_accuracy(m_ctxt, obj), 16.0);
}
{
- auto obj =
- proj_create_from_user_input(m_ctxt, "+proj=helmert", nullptr);
+ auto obj = proj_create(m_ctxt, "+proj=helmert");
ObjectKeeper keeper(obj);
ASSERT_NE(obj, nullptr);
EXPECT_EQ(proj_coordoperation_get_accuracy(m_ctxt, obj), -1.0);
@@ -1746,11 +1734,10 @@ TEST_F(CApi, proj_create_geographic_crs) {
ObjectKeeper keeper(obj);
ASSERT_NE(obj, nullptr);
- auto objRef = proj_create_from_user_input(
- m_ctxt,
- GeographicCRS::EPSG_4326->exportToWKT(WKTFormatter::create().get())
- .c_str(),
- nullptr);
+ auto objRef =
+ proj_create(m_ctxt, GeographicCRS::EPSG_4326
+ ->exportToWKT(WKTFormatter::create().get())
+ .c_str());
ObjectKeeper keeperobjRef(objRef);
EXPECT_NE(objRef, nullptr);
@@ -1783,11 +1770,10 @@ TEST_F(CApi, proj_create_geographic_crs) {
ObjectKeeper keeper(obj);
ASSERT_NE(obj, nullptr);
- auto objRef = proj_create_from_user_input(
- m_ctxt,
- GeographicCRS::EPSG_4326->exportToWKT(WKTFormatter::create().get())
- .c_str(),
- nullptr);
+ auto objRef =
+ proj_create(m_ctxt, GeographicCRS::EPSG_4326
+ ->exportToWKT(WKTFormatter::create().get())
+ .c_str());
ObjectKeeper keeperobjRef(objRef);
EXPECT_NE(objRef, nullptr);
@@ -1802,11 +1788,10 @@ TEST_F(CApi, proj_create_geographic_crs) {
ObjectKeeper keeper(obj);
ASSERT_NE(obj, nullptr);
- auto objRef = proj_create_from_user_input(
- m_ctxt,
- GeographicCRS::EPSG_4269->exportToWKT(WKTFormatter::create().get())
- .c_str(),
- nullptr);
+ auto objRef =
+ proj_create(m_ctxt, GeographicCRS::EPSG_4269
+ ->exportToWKT(WKTFormatter::create().get())
+ .c_str());
ObjectKeeper keeperobjRef(objRef);
EXPECT_NE(objRef, nullptr);
@@ -1861,11 +1846,10 @@ TEST_F(CApi, proj_create_geocentric_crs) {
ObjectKeeper keeper(obj);
ASSERT_NE(obj, nullptr);
- auto objRef = proj_create_from_user_input(
- m_ctxt,
- GeographicCRS::EPSG_4978->exportToWKT(WKTFormatter::create().get())
- .c_str(),
- nullptr);
+ auto objRef =
+ proj_create(m_ctxt, GeographicCRS::EPSG_4978
+ ->exportToWKT(WKTFormatter::create().get())
+ .c_str());
ObjectKeeper keeperobjRef(objRef);
EXPECT_NE(objRef, nullptr);
@@ -2411,7 +2395,7 @@ TEST_F(CApi, proj_context_get_database_metadata) {
// ---------------------------------------------------------------------------
TEST_F(CApi, proj_clone) {
- auto obj = proj_create_from_proj_string(m_ctxt, "+proj=longlat", nullptr);
+ auto obj = proj_create(m_ctxt, "+proj=longlat");
ObjectKeeper keeper(obj);
ASSERT_NE(obj, nullptr);
@@ -2432,8 +2416,7 @@ TEST_F(CApi, proj_crs_alter_geodetic_crs) {
ObjectKeeper keeper(projCRS);
ASSERT_NE(projCRS, nullptr);
- auto newGeodCRS =
- proj_create_from_proj_string(m_ctxt, "+proj=longlat", nullptr);
+ auto newGeodCRS = proj_create(m_ctxt, "+proj=longlat +type=crs");
ObjectKeeper keeper_newGeodCRS(newGeodCRS);
ASSERT_NE(newGeodCRS, nullptr);
diff --git a/test/unit/test_crs.cpp b/test/unit/test_crs.cpp
index d3309fb2..69cec01b 100644
--- a/test/unit/test_crs.cpp
+++ b/test/unit/test_crs.cpp
@@ -388,7 +388,7 @@ TEST(crs, EPSG_4326_as_WKT1_ESRI_without_database) {
TEST(crs, EPSG_4326_as_PROJ_string) {
auto crs = GeographicCRS::EPSG_4326;
EXPECT_EQ(crs->exportToPROJString(PROJStringFormatter::create().get()),
- "+proj=longlat +datum=WGS84 +no_defs");
+ "+proj=longlat +datum=WGS84 +no_defs +type=crs");
}
// ---------------------------------------------------------------------------
@@ -588,7 +588,7 @@ TEST(crs, EPSG_4807_as_WKT1_ESRI_without_database) {
TEST(crs, EPSG_4807_as_PROJ_string) {
auto crs = GeographicCRS::EPSG_4807;
EXPECT_EQ(crs->exportToPROJString(PROJStringFormatter::create().get()),
- "+proj=longlat +ellps=clrk80ign +pm=paris +no_defs");
+ "+proj=longlat +ellps=clrk80ign +pm=paris +no_defs +type=crs");
}
// ---------------------------------------------------------------------------
@@ -611,7 +611,7 @@ TEST(crs, EPSG_4267) {
" ANGLEUNIT[\"degree\",0.0174532925199433]],\n"
" ID[\"EPSG\",4267]]");
EXPECT_EQ(crs->exportToPROJString(PROJStringFormatter::create().get()),
- "+proj=longlat +datum=NAD27 +no_defs");
+ "+proj=longlat +datum=NAD27 +no_defs +type=crs");
}
// ---------------------------------------------------------------------------
@@ -647,7 +647,7 @@ TEST(crs, EPSG_4269) {
" ANGLEUNIT[\"degree\",0.0174532925199433]],\n"
" ID[\"EPSG\",4269]]");
EXPECT_EQ(crs->exportToPROJString(PROJStringFormatter::create().get()),
- "+proj=longlat +datum=NAD83 +no_defs");
+ "+proj=longlat +datum=NAD83 +no_defs +type=crs");
}
// ---------------------------------------------------------------------------
@@ -703,10 +703,10 @@ TEST(crs, EPSG_27561_projected_with_geodetic_in_grad_as_PROJ_string_and_WKT1) {
" ID[\"EPSG\",27561]]");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
- EXPECT_EQ(
- crs->exportToPROJString(PROJStringFormatter::create().get()),
- "+proj=lcc +lat_1=49.5 +lat_0=49.5 +lon_0=0 +k_0=0.999877341 "
- "+x_0=600000 +y_0=200000 +ellps=clrk80ign +pm=paris +units=m +no_defs");
+ EXPECT_EQ(crs->exportToPROJString(PROJStringFormatter::create().get()),
+ "+proj=lcc +lat_1=49.5 +lat_0=49.5 +lon_0=0 +k_0=0.999877341 "
+ "+x_0=600000 +y_0=200000 +ellps=clrk80ign +pm=paris +units=m "
+ "+no_defs +type=crs");
auto nn_crs = NN_CHECK_ASSERT(crs);
EXPECT_TRUE(nn_crs->isEquivalentTo(nn_crs.get()));
@@ -782,7 +782,7 @@ TEST(crs, EPSG_3040_projected_northing_easting_as_PROJ_string) {
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
EXPECT_EQ(crs->exportToPROJString(PROJStringFormatter::create().get()),
- "+proj=utm +zone=28 +ellps=GRS80 +units=m +no_defs");
+ "+proj=utm +zone=28 +ellps=GRS80 +units=m +no_defs +type=crs");
}
// ---------------------------------------------------------------------------
@@ -813,7 +813,7 @@ TEST(crs, EPSG_2222_projected_unit_foot_as_PROJ_string_and_WKT1) {
ASSERT_TRUE(crs != nullptr);
EXPECT_EQ(crs->exportToPROJString(PROJStringFormatter::create().get()),
"+proj=tmerc +lat_0=31 +lon_0=-110.166666666667 +k=0.9999 "
- "+x_0=213360 +y_0=0 +datum=NAD83 +units=ft +no_defs");
+ "+x_0=213360 +y_0=0 +datum=NAD83 +units=ft +no_defs +type=crs");
auto wkt1 = crs->exportToWKT(
WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get());
@@ -1109,7 +1109,7 @@ TEST(crs, EPSG_4978_as_WKT1_GDAL_with_database) {
TEST(crs, geocentricCRS_as_PROJ_string) {
auto crs = createGeocentric();
EXPECT_EQ(crs->exportToPROJString(PROJStringFormatter::create().get()),
- "+proj=geocent +datum=WGS84 +units=m +no_defs");
+ "+proj=geocent +datum=WGS84 +units=m +no_defs +type=crs");
}
// ---------------------------------------------------------------------------
@@ -1404,7 +1404,8 @@ TEST(crs, geodeticcrs_identify_db) {
{
// Identify by ellipsoid description
auto obj = PROJStringParser().createFromPROJString(
- "+proj=longlat +a=6378521.049 +rf=298.257222100883 +axis=neu");
+ "+proj=longlat +a=6378521.049 +rf=298.257222100883 +axis=neu "
+ "+type=crs");
auto crs = nn_dynamic_pointer_cast<GeodeticCRS>(obj);
ASSERT_TRUE(crs != nullptr);
auto factoryAll = AuthorityFactory::create(dbContext, std::string());
@@ -1511,7 +1512,7 @@ TEST(crs, projectedCRS_shallowClone) {
}
EXPECT_EQ(clone->baseCRS()->exportToPROJString(
PROJStringFormatter::create().get()),
- "+proj=geocent +datum=WGS84 +units=m +no_defs");
+ "+proj=geocent +datum=WGS84 +units=m +no_defs +type=crs");
}
}
@@ -1749,7 +1750,7 @@ TEST(crs, projectedCRS_as_PROJ_string) {
"+proj=unitconvert +xy_in=deg +xy_out=rad +step +proj=utm "
"+zone=31 +ellps=WGS84");
EXPECT_EQ(crs->exportToPROJString(PROJStringFormatter::create().get()),
- "+proj=utm +zone=31 +datum=WGS84 +units=m +no_defs");
+ "+proj=utm +zone=31 +datum=WGS84 +units=m +no_defs +type=crs");
}
// ---------------------------------------------------------------------------
@@ -1776,7 +1777,8 @@ TEST(crs, projectedCRS_Krovak_with_approximate_alpha_as_PROJ_string) {
// 30deg 17' 17.303'' = 30.288139722222223 as used in GDAL WKT1
auto obj = PROJStringParser().createFromPROJString(
"+proj=krovak +lat_0=49.5 +lon_0=42.5 +alpha=30.28813972222222 "
- "+k=0.9999 +x_0=0 +y_0=0 +ellps=bessel +pm=ferro +units=m +no_defs");
+ "+k=0.9999 +x_0=0 +y_0=0 +ellps=bessel +pm=ferro +units=m +no_defs "
+ "+type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
auto op = CoordinateOperationFactory::create()->createOperation(
crs->baseCRS(), NN_NO_CHECK(crs));
@@ -1865,7 +1867,7 @@ TEST(crs, projectedCRS_identify_no_db) {
{
// Tolerance on axis order
auto obj = PROJStringParser().createFromPROJString(
- "+proj=utm +zone=31 +datum=WGS84");
+ "+proj=utm +zone=31 +datum=WGS84 +type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
auto res = crs->identify(nullptr);
@@ -1975,7 +1977,7 @@ TEST(crs, projectedCRS_identify_db) {
{
// Identify from a PROJ string
auto obj = PROJStringParser().createFromPROJString(
- "+proj=pipeline +step +proj=axisswap +order=2,1 +step "
+ "+type=crs +proj=pipeline +step +proj=axisswap +order=2,1 +step "
"+proj=unitconvert +xy_in=deg +xy_out=rad +step +proj=omerc "
"+no_uoff +lat_0=4 +lonc=102.25 +alpha=323.025796466667 "
"+gamma=323.130102361111 +k=0.99984 +x_0=804671 +y_0=0 "
@@ -1993,7 +1995,7 @@ TEST(crs, projectedCRS_identify_db) {
auto obj = PROJStringParser().createFromPROJString(
"+proj=omerc +no_uoff +lat_0=4 +lonc=102.25 "
"+alpha=323.025796466667 +gamma=323.130102361111 +k=0.99984 "
- "+x_0=804671 +y_0=0 +ellps=GRS80");
+ "+x_0=804671 +y_0=0 +ellps=GRS80 +type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
auto res = crs->identify(factoryEPSG);
@@ -2090,8 +2092,8 @@ TEST(crs, projectedCRS_identify_db) {
}
{
// No equivalent CRS to input one in result set
- auto obj =
- PROJStringParser().createFromPROJString("+proj=tmerc +datum=WGS84");
+ auto obj = PROJStringParser().createFromPROJString(
+ "+proj=tmerc +datum=WGS84 +type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
auto res = crs->identify(factoryEPSG);
@@ -2106,7 +2108,8 @@ TEST(crs, projectedCRS_identify_db) {
"+proj=lcc +lat_0=43.5 +lon_0=-93.95 "
"+lat_1=43.5666666666667 "
"+lat_2=43.8 +x_0=152400.30480061 +y_0=30480.0609601219 "
- "+a=6378521.049 +rf=298.257222100883 +units=us-ft");
+ "+a=6378521.049 +rf=298.257222100883 +units=us-ft "
+ "+type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
auto factoryAll = AuthorityFactory::create(dbContext, std::string());
@@ -2130,7 +2133,7 @@ TEST(crs, projectedCRS_identify_db) {
.attachDatabaseContext(dbContext)
.createFromPROJString(
"+proj=tmerc +lat_0=0 +lon_0=75 +k=1 +x_0=13500000 +y_0=0 "
- "+a=6378140 +b=6356755.288157528 +units=m");
+ "+a=6378140 +b=6356755.288157528 +units=m +type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
auto res = crs->identify(factoryEPSG);
@@ -2140,12 +2143,12 @@ TEST(crs, projectedCRS_identify_db) {
}
{
// EPSG:6646 as PROJ.4 string, using clrk80 which is pretty generic
- auto obj =
- PROJStringParser()
- .attachDatabaseContext(dbContext)
- .createFromPROJString(
- "+proj=tmerc +lat_0=29.02626833333333 +lon_0=46.5 "
- "+k=0.9994 +x_0=800000 +y_0=0 +ellps=clrk80 +units=m");
+ auto obj = PROJStringParser()
+ .attachDatabaseContext(dbContext)
+ .createFromPROJString(
+ "+proj=tmerc +lat_0=29.02626833333333 +lon_0=46.5 "
+ "+k=0.9994 +x_0=800000 +y_0=0 +ellps=clrk80 "
+ "+units=m +type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
auto res = crs->identify(factoryEPSG);
@@ -2161,7 +2164,7 @@ TEST(crs, mercator_1SP_as_WKT1_ESRI) {
auto obj = PROJStringParser().createFromPROJString(
"+proj=merc +lon_0=110 +k=0.997 +x_0=3900000 +y_0=900000 "
- "+ellps=bessel");
+ "+ellps=bessel +type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
@@ -2188,7 +2191,7 @@ TEST(crs, mercator_1SP_as_WKT1_ESRI) {
TEST(crs, Plate_Carree_as_WKT1_ESRI) {
auto obj = PROJStringParser().createFromPROJString(
- "+title=my Plate carree +proj=eqc");
+ "+title=my Plate carree +proj=eqc +type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
@@ -2212,7 +2215,7 @@ TEST(crs, Plate_Carree_as_WKT1_ESRI) {
TEST(crs, Equidistant_Cylindrical_as_WKT1_ESRI) {
- auto obj = PROJStringParser().createFromPROJString("+proj=eqc");
+ auto obj = PROJStringParser().createFromPROJString("+proj=eqc +type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
@@ -2238,7 +2241,7 @@ TEST(crs, Equidistant_Cylindrical_as_WKT1_ESRI) {
TEST(crs, Hotine_Oblique_Mercator_Azimuth_Natural_Origin_as_WKT1_ESRI) {
auto obj = PROJStringParser().createFromPROJString(
- "+proj=omerc +no_uoff +gamma=295 +alpha=295");
+ "+proj=omerc +no_uoff +gamma=295 +alpha=295 +type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
@@ -2268,7 +2271,7 @@ TEST(crs, Hotine_Oblique_Mercator_Azimuth_Natural_Origin_as_WKT1_ESRI) {
TEST(crs, Rectified_Skew_Orthomorphic_Natural_Origin_as_WKT1_ESRI) {
auto obj = PROJStringParser().createFromPROJString(
- "+proj=omerc +no_uoff +gamma=3 +alpha=2");
+ "+proj=omerc +no_uoff +gamma=3 +alpha=2 +type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
@@ -2298,7 +2301,7 @@ TEST(crs, Rectified_Skew_Orthomorphic_Natural_Origin_as_WKT1_ESRI) {
TEST(crs, Hotine_Oblique_Mercator_Azimuth_Center_as_WKT1_ESRI) {
auto obj = PROJStringParser().createFromPROJString(
- "+proj=omerc +gamma=2 +alpha=2");
+ "+proj=omerc +gamma=2 +alpha=2 +type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
@@ -2327,7 +2330,7 @@ TEST(crs, Hotine_Oblique_Mercator_Azimuth_Center_as_WKT1_ESRI) {
TEST(crs, Rectified_Skew_Orthomorphic_Center_as_WKT1_ESRI) {
auto obj = PROJStringParser().createFromPROJString(
- "+proj=omerc +gamma=3 +alpha=2");
+ "+proj=omerc +gamma=3 +alpha=2 +type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
@@ -2357,7 +2360,7 @@ TEST(crs, Rectified_Skew_Orthomorphic_Center_as_WKT1_ESRI) {
TEST(crs, Gauss_Kruger_as_WKT1_ESRI) {
auto obj = PROJStringParser().createFromPROJString(
- "+title=my Gauss Kruger +proj=tmerc");
+ "+title=my Gauss Kruger +proj=tmerc +type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
@@ -2384,7 +2387,7 @@ TEST(crs, Gauss_Kruger_as_WKT1_ESRI) {
TEST(crs, Stereographic_North_Pole_as_WKT1_ESRI) {
auto obj = PROJStringParser().createFromPROJString(
- "+proj=stere +lat_0=90 +lat_ts=70");
+ "+proj=stere +lat_0=90 +lat_ts=70 +type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
@@ -2410,7 +2413,7 @@ TEST(crs, Stereographic_North_Pole_as_WKT1_ESRI) {
TEST(crs, Stereographic_South_Pole_as_WKT1_ESRI) {
auto obj = PROJStringParser().createFromPROJString(
- "+proj=stere +lat_0=-90 +lat_ts=-70");
+ "+proj=stere +lat_0=-90 +lat_ts=-70 +type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
@@ -2435,7 +2438,8 @@ TEST(crs, Stereographic_South_Pole_as_WKT1_ESRI) {
TEST(crs, Krovak_North_Orientated_as_WKT1_ESRI) {
- auto obj = PROJStringParser().createFromPROJString("+proj=krovak");
+ auto obj =
+ PROJStringParser().createFromPROJString("+proj=krovak +type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
@@ -2466,8 +2470,8 @@ TEST(crs, Krovak_North_Orientated_as_WKT1_ESRI) {
TEST(crs, Krovak_as_WKT1_ESRI) {
- auto obj =
- PROJStringParser().createFromPROJString("+proj=krovak +axis=swu");
+ auto obj = PROJStringParser().createFromPROJString(
+ "+proj=krovak +axis=swu +type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
@@ -2499,7 +2503,7 @@ TEST(crs, Krovak_as_WKT1_ESRI) {
TEST(crs, LCC_1SP_as_WKT1_ESRI) {
auto obj = PROJStringParser().createFromPROJString(
- "+proj=lcc +lat_1=1 +lat_0=1 +k=0.9");
+ "+proj=lcc +lat_1=1 +lat_0=1 +k=0.9 +type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
@@ -2527,7 +2531,7 @@ TEST(crs, LCC_1SP_as_WKT1_ESRI) {
TEST(crs, LCC_2SP_as_WKT1_ESRI) {
auto obj = PROJStringParser().createFromPROJString(
- "+proj=lcc +lat_0=1.5 +lat_1=1 +lat_2=2");
+ "+proj=lcc +lat_0=1.5 +lat_1=1 +lat_2=2 +type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
@@ -3122,7 +3126,8 @@ TEST(crs, compoundCRS_as_WKT1_GDAL) {
TEST(crs, compoundCRS_as_PROJ_string) {
auto crs = createCompoundCRS();
EXPECT_EQ(crs->exportToPROJString(PROJStringFormatter::create().get()),
- "+proj=utm +zone=31 +datum=WGS84 +units=m +vunits=m +no_defs");
+ "+proj=utm +zone=31 +datum=WGS84 +units=m +vunits=m +no_defs "
+ "+type=crs");
}
// ---------------------------------------------------------------------------
@@ -3539,8 +3544,9 @@ TEST(crs, boundCRS_geographicCRS_to_PROJ_string) {
auto crs = BoundCRS::createFromTOWGS84(
basecrs, std::vector<double>{1, 2, 3, 4, 5, 6, 7});
- EXPECT_EQ(crs->exportToPROJString(PROJStringFormatter::create().get()),
- "+proj=longlat +ellps=WGS84 +towgs84=1,2,3,4,5,6,7 +no_defs");
+ EXPECT_EQ(
+ crs->exportToPROJString(PROJStringFormatter::create().get()),
+ "+proj=longlat +ellps=WGS84 +towgs84=1,2,3,4,5,6,7 +no_defs +type=crs");
}
// ---------------------------------------------------------------------------
@@ -3561,7 +3567,7 @@ TEST(crs, boundCRS_projectedCRS_to_PROJ_string) {
EXPECT_EQ(crs->exportToPROJString(PROJStringFormatter::create().get()),
"+proj=utm +zone=31 +ellps=WGS84 +towgs84=1,2,3,4,5,6,7 +units=m "
- "+no_defs");
+ "+no_defs +type=crs");
}
// ---------------------------------------------------------------------------
@@ -3570,13 +3576,13 @@ TEST(crs, boundCRS_identify_db) {
auto dbContext = DatabaseContext::create();
auto factoryEPSG = AuthorityFactory::create(dbContext, "EPSG");
{
- auto obj =
- PROJStringParser()
- .attachDatabaseContext(dbContext)
- .createFromPROJString("+proj=tmerc +lat_0=-37.76111111111111 "
- "+lon_0=176.4661111111111 +k=1 "
- "+x_0=400000 +y_0=800000 +ellps=GRS80 "
- "+towgs84=0,0,0,0,0,0,0 +units=m");
+ auto obj = PROJStringParser()
+ .attachDatabaseContext(dbContext)
+ .createFromPROJString(
+ "+proj=tmerc +lat_0=-37.76111111111111 "
+ "+lon_0=176.4661111111111 +k=1 "
+ "+x_0=400000 +y_0=800000 +ellps=GRS80 "
+ "+towgs84=0,0,0,0,0,0,0 +units=m +type=crs");
auto crs = nn_dynamic_pointer_cast<BoundCRS>(obj);
ASSERT_TRUE(crs != nullptr);
auto res = crs->identify(factoryEPSG);
@@ -3687,9 +3693,10 @@ TEST(crs, WKT1_DATUM_EXTENSION_to_WKT1_and_PROJ_string) {
WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
wkt);
- EXPECT_EQ(crs->exportToPROJString(PROJStringFormatter::create().get()),
- "+proj=nzmg +lat_0=-41 +lon_0=173 +x_0=2510000 +y_0=6023150 "
- "+ellps=intl +nadgrids=nzgd2kgrid0005.gsb +units=m +no_defs");
+ EXPECT_EQ(
+ crs->exportToPROJString(PROJStringFormatter::create().get()),
+ "+proj=nzmg +lat_0=-41 +lon_0=173 +x_0=2510000 +y_0=6023150 "
+ "+ellps=intl +nadgrids=nzgd2kgrid0005.gsb +units=m +no_defs +type=crs");
}
// ---------------------------------------------------------------------------
@@ -3786,7 +3793,7 @@ TEST(crs, WKT1_VERT_DATUM_EXTENSION_to_PROJ_string) {
ASSERT_TRUE(crs != nullptr);
EXPECT_EQ(crs->exportToPROJString(PROJStringFormatter::create().get()),
- "+geoidgrids=egm08_25.gtx +vunits=m +no_defs");
+ "+geoidgrids=egm08_25.gtx +vunits=m +no_defs +type=crs");
}
// ---------------------------------------------------------------------------
@@ -4747,7 +4754,7 @@ TEST(crs, crs_createBoundCRSToWGS84IfPossible) {
"+proj=sterea +lat_0=46 +lon_0=25 +k=0.99975 +x_0=500000 "
"+y_0=500000 +ellps=krass "
"+towgs84=2.329,-147.042,-92.08,-0.309,0.325,0.497,5.69 "
- "+units=m +no_defs");
+ "+units=m +no_defs +type=crs");
}
{
// Pulkovo 42 Poland
@@ -4764,7 +4771,7 @@ TEST(crs, crs_createBoundCRSToWGS84IfPossible) {
"+proj=sterea +lat_0=50.625 +lon_0=21.0833333333333 "
"+k=0.9998 +x_0=4637000 +y_0=5647000 +ellps=krass "
"+towgs84=33.4,-146.6,-76.3,-0.359,-0.053,0.844,-0.84 "
- "+units=m +no_defs");
+ "+units=m +no_defs +type=crs");
}
{
// NTF (Paris)
@@ -4779,7 +4786,7 @@ TEST(crs, crs_createBoundCRSToWGS84IfPossible) {
EXPECT_EQ(
boundCRS->exportToPROJString(PROJStringFormatter::create().get()),
"+proj=longlat +ellps=clrk80ign +pm=paris "
- "+towgs84=-168,-60,320,0,0,0,0 +no_defs");
+ "+towgs84=-168,-60,320,0,0,0,0 +no_defs +type=crs");
}
{
// NTF (Paris) / Lambert zone II + NGF-IGN69 height
@@ -4796,7 +4803,7 @@ TEST(crs, crs_createBoundCRSToWGS84IfPossible) {
"+proj=lcc +lat_1=46.8 +lat_0=46.8 +lon_0=0 +k_0=0.99987742 "
"+x_0=600000 +y_0=2200000 +ellps=clrk80ign +pm=paris "
"+towgs84=-168,-60,320,0,0,0,0 +units=m "
- "+vunits=m +no_defs");
+ "+vunits=m +no_defs +type=crs");
}
{
auto crs = createVerticalCRS();
@@ -4814,7 +4821,7 @@ TEST(crs, crs_createBoundCRSToWGS84IfPossible) {
boundCRS->exportToPROJString(PROJStringFormatter::create().get()),
"+proj=stere +lat_0=-90 +lon_0=140 +k=0.960272946 "
"+x_0=300000 +y_0=-2299363.482 +ellps=intl "
- "+towgs84=324.8,153.6,172.1,0,0,0,0 +units=m +no_defs");
+ "+towgs84=324.8,153.6,172.1,0,0,0,0 +units=m +no_defs +type=crs");
}
{
auto factoryIGNF =
@@ -4827,7 +4834,7 @@ TEST(crs, crs_createBoundCRSToWGS84IfPossible) {
EXPECT_EQ(
boundCRS->exportToPROJString(PROJStringFormatter::create().get()),
"+proj=geocent +ellps=intl "
- "+towgs84=324.8,153.6,172.1,0,0,0,0 +units=m +no_defs");
+ "+towgs84=324.8,153.6,172.1,0,0,0,0 +units=m +no_defs +type=crs");
}
{
auto crs = factory->createCoordinateReferenceSystem("4269"); // NAD83
diff --git a/test/unit/test_factory.cpp b/test/unit/test_factory.cpp
index e9b29728..027c0188 100644
--- a/test/unit/test_factory.cpp
+++ b/test/unit/test_factory.cpp
@@ -409,7 +409,7 @@ TEST(factory, AuthorityFactory_createGeodeticCRS_geographic2D) {
EXPECT_TRUE(extent->isEquivalentTo(factory->createExtent("1262").get()));
EXPECT_EQ(crs->exportToPROJString(PROJStringFormatter::create().get()),
- "+proj=longlat +datum=WGS84 +no_defs");
+ "+proj=longlat +datum=WGS84 +no_defs +type=crs");
}
// ---------------------------------------------------------------------------
@@ -972,7 +972,7 @@ TEST(factory, AuthorityFactory_test_uom_9110) {
EXPECT_EQ(crs->exportToPROJString(PROJStringFormatter::create().get()),
"+proj=sterea +lat_0=53.0019444444444 +lon_0=21.5027777777778 "
"+k=0.9998 +x_0=4603000 +y_0=5806000 +ellps=krass +units=m "
- "+no_defs");
+ "+no_defs +type=crs");
}
// ---------------------------------------------------------------------------
@@ -2324,7 +2324,8 @@ TEST_F(FactoryWithTmpDatabase, custom_projected_crs) {
EXPECT_EQ(crs->identifiers().size(), 1);
EXPECT_EQ(crs->derivingConversion()->targetCRS().get(), crs.get());
EXPECT_EQ(crs->exportToPROJString(PROJStringFormatter::create().get()),
- "+proj=mbt_s +unused_flag +datum=WGS84 +units=m +no_defs");
+ "+proj=mbt_s +unused_flag +datum=WGS84 +units=m +no_defs "
+ "+type=crs");
EXPECT_TRUE(crs->canonicalBoundCRS() == nullptr);
}
{
@@ -2333,15 +2334,16 @@ TEST_F(FactoryWithTmpDatabase, custom_projected_crs) {
EXPECT_EQ(crs->identifiers().size(), 1);
EXPECT_EQ(crs->derivingConversion()->targetCRS().get(), crs.get());
EXPECT_EQ(crs->exportToPROJString(PROJStringFormatter::create().get()),
- "+proj=mbt_s +unused_flag +datum=WGS84 +units=m +no_defs");
+ "+proj=mbt_s +unused_flag +datum=WGS84 +units=m +no_defs "
+ "+type=crs");
EXPECT_TRUE(crs->canonicalBoundCRS() != nullptr);
}
EXPECT_THROW(factory->createProjectedCRS("TEST_WRONG"), FactoryException);
{
- auto obj =
- PROJStringParser().createFromPROJString("+proj=merc +a=1 +b=1");
+ auto obj = PROJStringParser().createFromPROJString(
+ "+proj=merc +a=1 +b=1 +type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
auto res = crs->identify(factory);
@@ -2352,8 +2354,8 @@ TEST_F(FactoryWithTmpDatabase, custom_projected_crs) {
}
{
- auto obj =
- PROJStringParser().createFromPROJString("+proj=merc +ellps=GRS80");
+ auto obj = PROJStringParser().createFromPROJString(
+ "+proj=merc +ellps=GRS80 +type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
auto res = crs->identify(factory);
@@ -2365,7 +2367,7 @@ TEST_F(FactoryWithTmpDatabase, custom_projected_crs) {
{
auto obj = PROJStringParser().createFromPROJString(
- "+proj=merc +a=6378137 +rf=298.257222101");
+ "+proj=merc +a=6378137 +rf=298.257222101 +type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
auto res = crs->identify(factory);
@@ -2376,8 +2378,8 @@ TEST_F(FactoryWithTmpDatabase, custom_projected_crs) {
}
{
- auto obj =
- PROJStringParser().createFromPROJString("+proj=merc +ellps=WGS84");
+ auto obj = PROJStringParser().createFromPROJString(
+ "+proj=merc +ellps=WGS84 +type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
auto res = crs->identify(factory);
diff --git a/test/unit/test_io.cpp b/test/unit/test_io.cpp
index 43b74fd8..15ba30f1 100644
--- a/test/unit/test_io.cpp
+++ b/test/unit/test_io.cpp
@@ -587,7 +587,7 @@ TEST(wkt_parse, wkt1_geographic_with_PROJ4_extension) {
crs->exportToPROJString(
PROJStringFormatter::create(PROJStringFormatter::Convention::PROJ_4)
.get()),
- "+proj=longlat +foo=bar +wktext");
+ "+proj=longlat +foo=bar +wktext +type=crs");
EXPECT_TRUE(
crs->exportToWKT(WKTFormatter::create().get()).find("EXTENSION") ==
@@ -624,7 +624,7 @@ TEST(wkt_parse, wkt1_geocentric_with_PROJ4_extension) {
crs->exportToPROJString(
PROJStringFormatter::create(PROJStringFormatter::Convention::PROJ_4)
.get()),
- "+proj=geocent +foo=bar +wktext");
+ "+proj=geocent +foo=bar +wktext +type=crs");
EXPECT_TRUE(
crs->exportToWKT(WKTFormatter::create().get()).find("EXTENSION") ==
@@ -1133,7 +1133,7 @@ TEST(wkt_parse, wkt1_projected_with_PROJ4_extension) {
crs->exportToPROJString(
PROJStringFormatter::create(PROJStringFormatter::Convention::PROJ_4)
.get()),
- "+proj=merc +wktext");
+ "+proj=merc +wktext +type=crs");
EXPECT_TRUE(
crs->exportToWKT(WKTFormatter::create().get()).find("EXTENSION") ==
@@ -1256,7 +1256,7 @@ TEST(wkt_parse, wkt1_krovak_south_west) {
auto expectedPROJString = "+proj=krovak +axis=swu +lat_0=49.5 "
"+lon_0=24.8333333333333 +alpha=30.2881397222222 "
"+k=0.9999 +x_0=0 +y_0=0 +ellps=bessel +units=m "
- "+no_defs";
+ "+no_defs +type=crs";
EXPECT_EQ(projString, expectedPROJString);
obj = PROJStringParser().createFromPROJString(projString);
@@ -1276,7 +1276,8 @@ TEST(wkt_parse, wkt1_krovak_south_west) {
expectedPROJString);
obj = PROJStringParser().createFromPROJString(
- "+proj=pipeline +step +proj=unitconvert +xy_in=deg +xy_out=rad "
+ "+type=crs +proj=pipeline +step +proj=unitconvert +xy_in=deg "
+ "+xy_out=rad "
"+step +proj=krovak +lat_0=49.5 "
"+lon_0=24.8333333333333 +alpha=30.2881397222222 "
"+k=0.9999 +x_0=0 +y_0=0 +ellps=bessel "
@@ -1369,7 +1370,7 @@ TEST(wkt_parse, wkt1_krovak_north_oriented) {
EXPECT_EQ(crs->exportToPROJString(PROJStringFormatter::create().get()),
"+proj=krovak +lat_0=49.5 +lon_0=24.8333333333333 "
"+alpha=30.2881397222222 +k=0.9999 +x_0=0 +y_0=0 +ellps=bessel "
- "+units=m +no_defs");
+ "+units=m +no_defs +type=crs");
}
// ---------------------------------------------------------------------------
@@ -1400,8 +1401,9 @@ TEST(wkt_parse, wkt1_polar_stereographic_latitude_of_origin_70) {
auto projString = crs->exportToPROJString(
PROJStringFormatter::create(PROJStringFormatter::Convention::PROJ_4)
.get());
- auto expectedPROJString = "+proj=stere +lat_0=90 +lat_ts=70 +lon_0=2 "
- "+x_0=3 +y_0=4 +datum=WGS84 +units=m +no_defs";
+ auto expectedPROJString =
+ "+proj=stere +lat_0=90 +lat_ts=70 +lon_0=2 "
+ "+x_0=3 +y_0=4 +datum=WGS84 +units=m +no_defs +type=crs";
EXPECT_EQ(projString, expectedPROJString);
EXPECT_EQ(crs->coordinateSystem()->axisList()[0]->nameStr(), "Easting");
@@ -1473,8 +1475,9 @@ TEST(wkt_parse, wkt1_polar_stereographic_latitude_of_origin_90) {
auto projString = crs->exportToPROJString(
PROJStringFormatter::create(PROJStringFormatter::Convention::PROJ_4)
.get());
- auto expectedPROJString = "+proj=stere +lat_0=90 +lat_ts=90 +lon_0=2 "
- "+x_0=3 +y_0=4 +datum=WGS84 +units=m +no_defs";
+ auto expectedPROJString =
+ "+proj=stere +lat_0=90 +lat_ts=90 +lon_0=2 "
+ "+x_0=3 +y_0=4 +datum=WGS84 +units=m +no_defs +type=crs";
EXPECT_EQ(projString, expectedPROJString);
}
@@ -1507,8 +1510,9 @@ TEST(wkt_parse, wkt1_polar_stereographic_latitude_of_origin_90_scale_factor_1) {
auto projString = crs->exportToPROJString(
PROJStringFormatter::create(PROJStringFormatter::Convention::PROJ_4)
.get());
- auto expectedPROJString = "+proj=stere +lat_0=90 +lat_ts=90 +lon_0=2 "
- "+x_0=3 +y_0=4 +datum=WGS84 +units=m +no_defs";
+ auto expectedPROJString =
+ "+proj=stere +lat_0=90 +lat_ts=90 +lon_0=2 "
+ "+x_0=3 +y_0=4 +datum=WGS84 +units=m +no_defs +type=crs";
EXPECT_EQ(projString, expectedPROJString);
}
@@ -1542,7 +1546,7 @@ TEST(wkt_parse, wkt1_polar_stereographic_scale_factor) {
PROJStringFormatter::create(PROJStringFormatter::Convention::PROJ_4)
.get());
auto expectedPROJString = "+proj=stere +lat_0=90 +lon_0=2 +k=0.99 +x_0=3 "
- "+y_0=4 +datum=WGS84 +units=m +no_defs";
+ "+y_0=4 +datum=WGS84 +units=m +no_defs +type=crs";
EXPECT_EQ(projString, expectedPROJString);
}
@@ -1575,7 +1579,7 @@ TEST(wkt_parse, wkt1_Spherical_Cross_Track_Height) {
PROJStringFormatter::create(PROJStringFormatter::Convention::PROJ_4)
.get());
auto expectedPROJString = "+proj=sch +plat_0=1 +plon_0=2 +phdg_0=3 +h_0=4 "
- "+datum=WGS84 +units=m +no_defs";
+ "+datum=WGS84 +units=m +no_defs +type=crs";
EXPECT_EQ(projString, expectedPROJString);
}
@@ -1694,7 +1698,7 @@ TEST(wkt_parse, wkt2_2018_projected_3D) {
PROJStringFormatter::create(PROJStringFormatter::Convention::PROJ_4)
.get()),
"+proj=tmerc +lat_0=0 +lon_0=3 +k=1 +x_0=0 +y_0=0 +ellps=WGS84 "
- "+units=m +no_defs");
+ "+units=m +no_defs +type=crs");
EXPECT_THROW(
crs->exportToWKT(
@@ -1739,7 +1743,7 @@ TEST(wkt_parse, wkt2_2018_projected_utm_3D) {
crs->exportToPROJString(
PROJStringFormatter::create(PROJStringFormatter::Convention::PROJ_4)
.get()),
- "+proj=utm +zone=31 +ellps=WGS84 +units=m +no_defs");
+ "+proj=utm +zone=31 +ellps=WGS84 +units=m +no_defs +type=crs");
EXPECT_THROW(
crs->exportToWKT(
@@ -6471,7 +6475,8 @@ TEST(io, projparse_longlat) {
" ANGLEUNIT[\"degree\",0.0174532925199433,\n"
" ID[\"EPSG\",9122]]]]";
{
- auto obj = PROJStringParser().createFromPROJString("+proj=longlat");
+ auto obj =
+ PROJStringParser().createFromPROJString("+proj=longlat +type=crs");
auto crs = nn_dynamic_pointer_cast<GeographicCRS>(obj);
ASSERT_TRUE(crs != nullptr);
WKTFormatterNNPtr f(WKTFormatter::create());
@@ -6481,7 +6486,7 @@ TEST(io, projparse_longlat) {
{
auto obj = PROJStringParser().createFromPROJString(
- "+proj=longlat +datum=WGS84");
+ "+proj=longlat +datum=WGS84 +type=crs");
auto crs = nn_dynamic_pointer_cast<GeographicCRS>(obj);
ASSERT_TRUE(crs != nullptr);
WKTFormatterNNPtr f(WKTFormatter::create());
@@ -6493,8 +6498,8 @@ TEST(io, projparse_longlat) {
// ---------------------------------------------------------------------------
TEST(io, projparse_longlat_datum_NAD83) {
- auto obj =
- PROJStringParser().createFromPROJString("+proj=longlat +datum=NAD83");
+ auto obj = PROJStringParser().createFromPROJString(
+ "+proj=longlat +datum=NAD83 +type=crs");
auto crs = nn_dynamic_pointer_cast<GeographicCRS>(obj);
ASSERT_TRUE(crs != nullptr);
WKTFormatterNNPtr f(WKTFormatter::create());
@@ -6522,8 +6527,8 @@ TEST(io, projparse_longlat_datum_NAD83) {
// ---------------------------------------------------------------------------
TEST(io, projparse_longlat_datum_NAD27) {
- auto obj =
- PROJStringParser().createFromPROJString("+proj=longlat +datum=NAD27");
+ auto obj = PROJStringParser().createFromPROJString(
+ "+proj=longlat +datum=NAD27 +type=crs");
auto crs = nn_dynamic_pointer_cast<GeographicCRS>(obj);
ASSERT_TRUE(crs != nullptr);
WKTFormatterNNPtr f(WKTFormatter::create());
@@ -6552,7 +6557,7 @@ TEST(io, projparse_longlat_datum_NAD27) {
TEST(io, projparse_longlat_datum_other) {
auto obj = PROJStringParser().createFromPROJString(
- "+proj=longlat +datum=carthage");
+ "+proj=longlat +datum=carthage +type=crs");
auto crs = nn_dynamic_pointer_cast<GeographicCRS>(obj);
ASSERT_TRUE(crs != nullptr);
WKTFormatterNNPtr f(WKTFormatter::create());
@@ -6580,8 +6585,8 @@ TEST(io, projparse_longlat_datum_other) {
// ---------------------------------------------------------------------------
TEST(io, projparse_longlat_ellps_WGS84) {
- auto obj =
- PROJStringParser().createFromPROJString("+proj=longlat +ellps=WGS84");
+ auto obj = PROJStringParser().createFromPROJString(
+ "+proj=longlat +ellps=WGS84 +type=crs");
auto crs = nn_dynamic_pointer_cast<GeographicCRS>(obj);
ASSERT_TRUE(crs != nullptr);
WKTFormatterNNPtr f(WKTFormatter::create());
@@ -6606,8 +6611,8 @@ TEST(io, projparse_longlat_ellps_WGS84) {
// ---------------------------------------------------------------------------
TEST(io, projparse_longlat_ellps_GRS80) {
- auto obj =
- PROJStringParser().createFromPROJString("+proj=longlat +ellps=GRS80");
+ auto obj = PROJStringParser().createFromPROJString(
+ "+proj=longlat +ellps=GRS80 +type=crs");
auto crs = nn_dynamic_pointer_cast<GeographicCRS>(obj);
ASSERT_TRUE(crs != nullptr);
WKTFormatterNNPtr f(WKTFormatter::create());
@@ -6632,8 +6637,8 @@ TEST(io, projparse_longlat_ellps_GRS80) {
// ---------------------------------------------------------------------------
TEST(io, projparse_longlat_a_b) {
- auto obj =
- PROJStringParser().createFromPROJString("+proj=longlat +a=2 +b=1.5");
+ auto obj = PROJStringParser().createFromPROJString(
+ "+proj=longlat +a=2 +b=1.5 +type=crs");
auto crs = nn_dynamic_pointer_cast<GeographicCRS>(obj);
ASSERT_TRUE(crs != nullptr);
WKTFormatterNNPtr f(WKTFormatter::create());
@@ -6660,7 +6665,7 @@ TEST(io, projparse_longlat_a_b) {
TEST(io, projparse_longlat_a_rf_WGS84) {
auto obj = PROJStringParser().createFromPROJString(
- "+proj=longlat +a=6378137 +rf=298.257223563");
+ "+proj=longlat +a=6378137 +rf=298.257223563 +type=crs");
auto crs = nn_dynamic_pointer_cast<GeographicCRS>(obj);
ASSERT_TRUE(crs != nullptr);
WKTFormatterNNPtr f(WKTFormatter::create());
@@ -6686,8 +6691,8 @@ TEST(io, projparse_longlat_a_rf_WGS84) {
// ---------------------------------------------------------------------------
TEST(io, projparse_longlat_a_rf) {
- auto obj =
- PROJStringParser().createFromPROJString("+proj=longlat +a=2 +rf=4");
+ auto obj = PROJStringParser().createFromPROJString(
+ "+proj=longlat +a=2 +rf=4 +type=crs");
auto crs = nn_dynamic_pointer_cast<GeographicCRS>(obj);
ASSERT_TRUE(crs != nullptr);
WKTFormatterNNPtr f(WKTFormatter::create());
@@ -6712,8 +6717,8 @@ TEST(io, projparse_longlat_a_rf) {
// ---------------------------------------------------------------------------
TEST(io, projparse_longlat_a_f_zero) {
- auto obj =
- PROJStringParser().createFromPROJString("+proj=longlat +a=2 +f=0");
+ auto obj = PROJStringParser().createFromPROJString(
+ "+proj=longlat +a=2 +f=0 +type=crs");
auto crs = nn_dynamic_pointer_cast<GeographicCRS>(obj);
ASSERT_TRUE(crs != nullptr);
WKTFormatterNNPtr f(WKTFormatter::create());
@@ -6738,8 +6743,8 @@ TEST(io, projparse_longlat_a_f_zero) {
// ---------------------------------------------------------------------------
TEST(io, projparse_longlat_a_f_non_zero) {
- auto obj =
- PROJStringParser().createFromPROJString("+proj=longlat +a=2 +f=0.5");
+ auto obj = PROJStringParser().createFromPROJString(
+ "+proj=longlat +a=2 +f=0.5 +type=crs");
auto crs = nn_dynamic_pointer_cast<GeographicCRS>(obj);
ASSERT_TRUE(crs != nullptr);
EXPECT_EQ(crs->ellipsoid()->semiMajorAxis().getSIValue(), 2);
@@ -6750,8 +6755,8 @@ TEST(io, projparse_longlat_a_f_non_zero) {
// ---------------------------------------------------------------------------
TEST(io, projparse_longlat_a_e) {
- auto obj =
- PROJStringParser().createFromPROJString("+proj=longlat +a=2 +e=0.5");
+ auto obj = PROJStringParser().createFromPROJString(
+ "+proj=longlat +a=2 +e=0.5 +type=crs");
auto crs = nn_dynamic_pointer_cast<GeographicCRS>(obj);
ASSERT_TRUE(crs != nullptr);
EXPECT_EQ(crs->ellipsoid()->semiMajorAxis().getSIValue(), 2);
@@ -6762,8 +6767,8 @@ TEST(io, projparse_longlat_a_e) {
// ---------------------------------------------------------------------------
TEST(io, projparse_longlat_a_es) {
- auto obj =
- PROJStringParser().createFromPROJString("+proj=longlat +a=2 +es=0.5");
+ auto obj = PROJStringParser().createFromPROJString(
+ "+proj=longlat +a=2 +es=0.5 +type=crs");
auto crs = nn_dynamic_pointer_cast<GeographicCRS>(obj);
ASSERT_TRUE(crs != nullptr);
EXPECT_EQ(crs->ellipsoid()->semiMajorAxis().getSIValue(), 2);
@@ -6774,7 +6779,8 @@ TEST(io, projparse_longlat_a_es) {
// ---------------------------------------------------------------------------
TEST(io, projparse_longlat_R) {
- auto obj = PROJStringParser().createFromPROJString("+proj=longlat +R=2");
+ auto obj =
+ PROJStringParser().createFromPROJString("+proj=longlat +R=2 +type=crs");
auto crs = nn_dynamic_pointer_cast<GeographicCRS>(obj);
ASSERT_TRUE(crs != nullptr);
EXPECT_TRUE(crs->ellipsoid()->isSphere());
@@ -6784,7 +6790,8 @@ TEST(io, projparse_longlat_R) {
// ---------------------------------------------------------------------------
TEST(io, projparse_longlat_a) {
- auto obj = PROJStringParser().createFromPROJString("+proj=longlat +a=2");
+ auto obj =
+ PROJStringParser().createFromPROJString("+proj=longlat +a=2 +type=crs");
auto crs = nn_dynamic_pointer_cast<GeographicCRS>(obj);
ASSERT_TRUE(crs != nullptr);
EXPECT_TRUE(crs->ellipsoid()->isSphere());
@@ -6795,7 +6802,7 @@ TEST(io, projparse_longlat_a) {
TEST(io, projparse_longlat_a_override_ellps) {
auto obj = PROJStringParser().createFromPROJString(
- "+proj=longlat +a=2 +ellps=WGS84");
+ "+proj=longlat +a=2 +ellps=WGS84 +type=crs");
auto crs = nn_dynamic_pointer_cast<GeographicCRS>(obj);
ASSERT_TRUE(crs != nullptr);
EXPECT_TRUE(!crs->ellipsoid()->isSphere());
@@ -6807,8 +6814,8 @@ TEST(io, projparse_longlat_a_override_ellps) {
// ---------------------------------------------------------------------------
TEST(io, projparse_longlat_pm_paris) {
- auto obj =
- PROJStringParser().createFromPROJString("+proj=longlat +pm=paris");
+ auto obj = PROJStringParser().createFromPROJString(
+ "+proj=longlat +pm=paris +type=crs");
auto crs = nn_dynamic_pointer_cast<GeographicCRS>(obj);
ASSERT_TRUE(crs != nullptr);
WKTFormatterNNPtr f(WKTFormatter::create());
@@ -6835,7 +6842,7 @@ TEST(io, projparse_longlat_pm_paris) {
TEST(io, projparse_longlat_pm_ferro) {
auto obj = PROJStringParser().createFromPROJString(
- "+proj=longlat +ellps=bessel +pm=ferro");
+ "+proj=longlat +ellps=bessel +pm=ferro +type=crs");
auto crs = nn_dynamic_pointer_cast<GeographicCRS>(obj);
ASSERT_TRUE(crs != nullptr);
WKTFormatterNNPtr f(WKTFormatter::create());
@@ -6862,7 +6869,8 @@ TEST(io, projparse_longlat_pm_ferro) {
// ---------------------------------------------------------------------------
TEST(io, projparse_longlat_pm_numeric) {
- auto obj = PROJStringParser().createFromPROJString("+proj=longlat +pm=2.5");
+ auto obj = PROJStringParser().createFromPROJString(
+ "+proj=longlat +pm=2.5 +type=crs");
auto crs = nn_dynamic_pointer_cast<GeographicCRS>(obj);
ASSERT_TRUE(crs != nullptr);
WKTFormatterNNPtr f(WKTFormatter::create());
@@ -6894,7 +6902,7 @@ TEST(io, projparse_longlat_pm_overriding_datum) {
// of GDAL. So let's keep the ellipsoid part of the datum in that case and
// use the specified prime meridian.
auto obj = PROJStringParser().createFromPROJString(
- "+proj=longlat +datum=WGS84 +pm=ferro");
+ "+proj=longlat +datum=WGS84 +pm=ferro +type=crs");
auto crs = nn_dynamic_pointer_cast<GeographicCRS>(obj);
ASSERT_TRUE(crs != nullptr);
EXPECT_EQ(crs->datum()->nameStr(), "Unknown based on WGS 84 ellipsoid");
@@ -6908,8 +6916,8 @@ TEST(io, projparse_longlat_complex) {
"+step +proj=longlat +ellps=clrk80ign "
"+pm=paris +step +proj=unitconvert +xy_in=rad +xy_out=grad +step "
"+proj=axisswap +order=2,1";
- auto obj =
- PROJStringParser().createFromPROJString("+proj=pipeline " + input);
+ auto obj = PROJStringParser().createFromPROJString(
+ "+type=crs +proj=pipeline " + input);
auto crs = nn_dynamic_pointer_cast<GeographicCRS>(obj);
ASSERT_TRUE(crs != nullptr);
auto op = CoordinateOperationFactory::create()->createOperation(
@@ -6925,7 +6933,7 @@ TEST(io, projparse_longlat_complex) {
TEST(io, projparse_longlat_towgs84_3_terms) {
auto obj = PROJStringParser().createFromPROJString(
- "+proj=longlat +ellps=GRS80 +towgs84=1.2,2,3");
+ "+proj=longlat +ellps=GRS80 +towgs84=1.2,2,3 +type=crs");
auto crs = nn_dynamic_pointer_cast<BoundCRS>(obj);
ASSERT_TRUE(crs != nullptr);
WKTFormatterNNPtr f(WKTFormatter::create());
@@ -6950,14 +6958,15 @@ TEST(io, projparse_longlat_towgs84_3_terms) {
crs->exportToPROJString(
PROJStringFormatter::create(PROJStringFormatter::Convention::PROJ_4)
.get()),
- "+proj=longlat +ellps=GRS80 +towgs84=1.2,2,3,0,0,0,0 +no_defs");
+ "+proj=longlat +ellps=GRS80 +towgs84=1.2,2,3,0,0,0,0 +no_defs "
+ "+type=crs");
}
// ---------------------------------------------------------------------------
TEST(io, projparse_longlat_towgs84_7_terms) {
auto obj = PROJStringParser().createFromPROJString(
- "+proj=longlat +ellps=GRS80 +towgs84=1.2,2,3,4,5,6,7");
+ "+proj=longlat +ellps=GRS80 +towgs84=1.2,2,3,4,5,6,7 +type=crs");
auto crs = nn_dynamic_pointer_cast<BoundCRS>(obj);
ASSERT_TRUE(crs != nullptr);
WKTFormatterNNPtr f(WKTFormatter::create());
@@ -6985,14 +6994,15 @@ TEST(io, projparse_longlat_towgs84_7_terms) {
crs->exportToPROJString(
PROJStringFormatter::create(PROJStringFormatter::Convention::PROJ_4)
.get()),
- "+proj=longlat +ellps=GRS80 +towgs84=1.2,2,3,4,5,6,7 +no_defs");
+ "+proj=longlat +ellps=GRS80 +towgs84=1.2,2,3,4,5,6,7 +no_defs "
+ "+type=crs");
}
// ---------------------------------------------------------------------------
TEST(io, projparse_longlat_nadgrids) {
auto obj = PROJStringParser().createFromPROJString(
- "+proj=longlat +ellps=GRS80 +nadgrids=foo.gsb");
+ "+proj=longlat +ellps=GRS80 +nadgrids=foo.gsb +type=crs");
auto crs = nn_dynamic_pointer_cast<BoundCRS>(obj);
ASSERT_TRUE(crs != nullptr);
WKTFormatterNNPtr f(WKTFormatter::create());
@@ -7009,14 +7019,14 @@ TEST(io, projparse_longlat_nadgrids) {
crs->exportToPROJString(
PROJStringFormatter::create(PROJStringFormatter::Convention::PROJ_4)
.get()),
- "+proj=longlat +ellps=GRS80 +nadgrids=foo.gsb +no_defs");
+ "+proj=longlat +ellps=GRS80 +nadgrids=foo.gsb +no_defs +type=crs");
}
// ---------------------------------------------------------------------------
TEST(io, projparse_longlat_geoidgrids) {
auto obj = PROJStringParser().createFromPROJString(
- "+proj=longlat +ellps=GRS80 +geoidgrids=foo.gtx");
+ "+proj=longlat +ellps=GRS80 +geoidgrids=foo.gtx +type=crs");
auto crs = nn_dynamic_pointer_cast<CompoundCRS>(obj);
ASSERT_TRUE(crs != nullptr);
WKTFormatterNNPtr f(WKTFormatter::create());
@@ -7037,14 +7047,15 @@ TEST(io, projparse_longlat_geoidgrids) {
crs->exportToPROJString(
PROJStringFormatter::create(PROJStringFormatter::Convention::PROJ_4)
.get()),
- "+proj=longlat +ellps=GRS80 +geoidgrids=foo.gtx +vunits=m +no_defs");
+ "+proj=longlat +ellps=GRS80 +geoidgrids=foo.gtx +vunits=m +no_defs "
+ "+type=crs");
}
// ---------------------------------------------------------------------------
TEST(io, projparse_longlat_geoidgrids_vunits) {
auto obj = PROJStringParser().createFromPROJString(
- "+proj=longlat +ellps=GRS80 +geoidgrids=foo.gtx +vunits=ft");
+ "+proj=longlat +ellps=GRS80 +geoidgrids=foo.gtx +vunits=ft +type=crs");
auto crs = nn_dynamic_pointer_cast<CompoundCRS>(obj);
ASSERT_TRUE(crs != nullptr);
WKTFormatterNNPtr f(WKTFormatter::create());
@@ -7063,7 +7074,7 @@ TEST(io, projparse_longlat_geoidgrids_vunits) {
TEST(io, projparse_longlat_vunits) {
auto obj = PROJStringParser().createFromPROJString(
- "+proj=longlat +ellps=GRS80 +vunits=ft");
+ "+proj=longlat +ellps=GRS80 +vunits=ft +type=crs");
auto crs = nn_dynamic_pointer_cast<GeographicCRS>(obj);
ASSERT_TRUE(crs != nullptr);
WKTFormatterNNPtr f(WKTFormatter::create());
@@ -7081,28 +7092,29 @@ TEST(io, projparse_longlat_vunits) {
// ---------------------------------------------------------------------------
TEST(io, projparse_vunits) {
- auto obj = PROJStringParser().createFromPROJString("+vunits=ft");
+ auto obj = PROJStringParser().createFromPROJString("+vunits=ft +type=crs");
auto crs = nn_dynamic_pointer_cast<VerticalCRS>(obj);
ASSERT_TRUE(crs != nullptr);
EXPECT_EQ(crs->exportToPROJString(PROJStringFormatter::create().get()),
- "+vunits=ft +no_defs");
+ "+vunits=ft +no_defs +type=crs");
}
// ---------------------------------------------------------------------------
TEST(io, projparse_vto_meter) {
- auto obj = PROJStringParser().createFromPROJString("+vto_meter=2");
+ auto obj =
+ PROJStringParser().createFromPROJString("+vto_meter=2 +type=crs");
auto crs = nn_dynamic_pointer_cast<VerticalCRS>(obj);
ASSERT_TRUE(crs != nullptr);
EXPECT_EQ(crs->exportToPROJString(PROJStringFormatter::create().get()),
- "+vto_meter=2 +no_defs");
+ "+vto_meter=2 +no_defs +type=crs");
}
// ---------------------------------------------------------------------------
TEST(io, projparse_longlat_axis_enu) {
auto obj = PROJStringParser().createFromPROJString(
- "+proj=longlat +ellps=GRS80 +axis=enu");
+ "+proj=longlat +ellps=GRS80 +axis=enu +type=crs");
auto crs = nn_dynamic_pointer_cast<GeographicCRS>(obj);
ASSERT_TRUE(crs != nullptr);
WKTFormatterNNPtr f(WKTFormatter::create());
@@ -7129,7 +7141,7 @@ TEST(io, projparse_longlat_axis_enu) {
TEST(io, projparse_longlat_axis_neu) {
auto obj = PROJStringParser().createFromPROJString(
- "+proj=longlat +ellps=GRS80 +axis=neu");
+ "+proj=longlat +ellps=GRS80 +axis=neu +type=crs");
auto crs = nn_dynamic_pointer_cast<GeographicCRS>(obj);
ASSERT_TRUE(crs != nullptr);
WKTFormatterNNPtr f(WKTFormatter::create());
@@ -7155,7 +7167,7 @@ TEST(io, projparse_longlat_axis_neu) {
TEST(io, projparse_longlat_axis_swu) {
auto obj = PROJStringParser().createFromPROJString(
- "+proj=longlat +ellps=GRS80 +axis=swu");
+ "+proj=longlat +ellps=GRS80 +axis=swu +type=crs");
auto crs = nn_dynamic_pointer_cast<GeographicCRS>(obj);
ASSERT_TRUE(crs != nullptr);
WKTFormatterNNPtr f(WKTFormatter::create());
@@ -7183,7 +7195,7 @@ TEST(io, projparse_longlat_axis_swu) {
TEST(io, projparse_longlat_unitconvert_deg) {
auto obj = PROJStringParser().createFromPROJString(
- "+proj=pipeline +step +proj=longlat +ellps=GRS80 +step "
+ "+type=crs +proj=pipeline +step +proj=longlat +ellps=GRS80 +step "
"+proj=unitconvert +xy_in=rad +xy_out=deg");
auto crs = nn_dynamic_pointer_cast<GeographicCRS>(obj);
ASSERT_TRUE(crs != nullptr);
@@ -7199,7 +7211,7 @@ TEST(io, projparse_longlat_unitconvert_deg) {
TEST(io, projparse_longlat_unitconvert_grad) {
auto obj = PROJStringParser().createFromPROJString(
- "+proj=pipeline +step +proj=longlat +ellps=GRS80 +step "
+ "+type=crs +proj=pipeline +step +proj=longlat +ellps=GRS80 +step "
"+proj=unitconvert +xy_in=rad +xy_out=grad");
auto crs = nn_dynamic_pointer_cast<GeographicCRS>(obj);
ASSERT_TRUE(crs != nullptr);
@@ -7217,7 +7229,7 @@ TEST(io, projparse_longlat_unitconvert_grad) {
TEST(io, projparse_longlat_unitconvert_rad) {
auto obj = PROJStringParser().createFromPROJString(
- "+proj=pipeline +step +proj=longlat +ellps=GRS80 +step "
+ "+type=crs +proj=pipeline +step +proj=longlat +ellps=GRS80 +step "
"+proj=unitconvert +xy_in=rad +xy_out=rad");
auto crs = nn_dynamic_pointer_cast<GeographicCRS>(obj);
ASSERT_TRUE(crs != nullptr);
@@ -7237,9 +7249,10 @@ TEST(io, projparse_longlat_axisswap) {
for (auto order2 : {"1", "-1", "2", "-2"}) {
if (std::abs(atoi(order1) * atoi(order2)) == 2 &&
!(atoi(order1) == 1 && atoi(order2) == 2)) {
- auto str = "+proj=pipeline +step +proj=longlat +ellps=GRS80 "
- "+step +proj=axisswap +order=" +
- std::string(order1) + "," + order2;
+ auto str =
+ "+type=crs +proj=pipeline +step +proj=longlat +ellps=GRS80 "
+ "+step +proj=axisswap +order=" +
+ std::string(order1) + "," + order2;
auto obj = PROJStringParser().createFromPROJString(str);
auto crs = nn_dynamic_pointer_cast<GeographicCRS>(obj);
ASSERT_TRUE(crs != nullptr);
@@ -7263,7 +7276,7 @@ TEST(io, projparse_longlat_axisswap) {
TEST(io, projparse_tmerc) {
auto obj = PROJStringParser().createFromPROJString(
- "+proj=tmerc +x_0=1 +lat_0=1 +k_0=2");
+ "+proj=tmerc +x_0=1 +lat_0=1 +k_0=2 +type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
WKTFormatterNNPtr f(WKTFormatter::create());
@@ -7309,7 +7322,7 @@ TEST(io, projparse_tmerc) {
TEST(io, projparse_tmerc_south_oriented) {
auto obj = PROJStringParser().createFromPROJString(
- "+proj=tmerc +axis=wsu +x_0=1 +lat_0=1 +k_0=2");
+ "+proj=tmerc +axis=wsu +x_0=1 +lat_0=1 +k_0=2 +type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
WKTFormatterNNPtr f(WKTFormatter::create());
@@ -7352,9 +7365,11 @@ TEST(io, projparse_tmerc_south_oriented) {
EXPECT_EQ(f->toString(), expected);
obj = PROJStringParser().createFromPROJString(
- "+proj=pipeline +step +proj=tmerc +x_0=1 +lat_0=1 +k_0=2 +step "
+ "+type=crs +proj=pipeline +step +proj=tmerc +x_0=1 +lat_0=1 +k_0=2 "
+ "+step "
"+proj=axisswap +order=-1,-2");
crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
+ ASSERT_TRUE(crs != nullptr);
EXPECT_EQ(crs->derivingConversion()->method()->nameStr(),
"Transverse Mercator (South Orientated)");
}
@@ -7363,7 +7378,7 @@ TEST(io, projparse_tmerc_south_oriented) {
TEST(io, projparse_lcc_as_lcc1sp) {
auto obj = PROJStringParser().createFromPROJString(
- "+proj=lcc +lat_0=45 +lat_1=45");
+ "+proj=lcc +lat_0=45 +lat_1=45 +type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
WKTFormatterNNPtr f(WKTFormatter::create());
@@ -7379,7 +7394,7 @@ TEST(io, projparse_lcc_as_lcc1sp) {
TEST(io, projparse_lcc_as_lcc2sp) {
auto obj = PROJStringParser().createFromPROJString(
- "+proj=lcc +lat_0=45 +lat_1=46");
+ "+proj=lcc +lat_0=45 +lat_1=46 +type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
WKTFormatterNNPtr f(WKTFormatter::create());
@@ -7395,7 +7410,7 @@ TEST(io, projparse_lcc_as_lcc2sp) {
TEST(io, projparse_lcc_as_lcc2sp_michigan) {
auto obj = PROJStringParser().createFromPROJString(
- "+proj=lcc +lat_0=45 +lat_1=46 +k_0=1.02");
+ "+proj=lcc +lat_0=45 +lat_1=46 +k_0=1.02 +type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
WKTFormatterNNPtr f(WKTFormatter::create());
@@ -7411,7 +7426,8 @@ TEST(io, projparse_lcc_as_lcc2sp_michigan) {
// ---------------------------------------------------------------------------
TEST(io, projparse_aeqd_guam) {
- auto obj = PROJStringParser().createFromPROJString("+proj=aeqd +guam");
+ auto obj =
+ PROJStringParser().createFromPROJString("+proj=aeqd +guam +type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
WKTFormatterNNPtr f(WKTFormatter::create());
@@ -7425,8 +7441,8 @@ TEST(io, projparse_aeqd_guam) {
// ---------------------------------------------------------------------------
TEST(io, projparse_cea_ellipsoidal) {
- auto obj =
- PROJStringParser().createFromPROJString("+proj=cea +ellps=GRS80");
+ auto obj = PROJStringParser().createFromPROJString(
+ "+proj=cea +ellps=GRS80 +type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
WKTFormatterNNPtr f(WKTFormatter::create());
@@ -7444,7 +7460,8 @@ TEST(io, projparse_cea_ellipsoidal) {
// ---------------------------------------------------------------------------
TEST(io, projparse_geos_sweep_x) {
- auto obj = PROJStringParser().createFromPROJString("+proj=geos +sweep=x");
+ auto obj = PROJStringParser().createFromPROJString(
+ "+proj=geos +sweep=x +type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
WKTFormatterNNPtr f(WKTFormatter::create());
@@ -7460,7 +7477,7 @@ TEST(io, projparse_geos_sweep_x) {
// ---------------------------------------------------------------------------
TEST(io, projparse_geos_sweep_y) {
- auto obj = PROJStringParser().createFromPROJString("+proj=geos");
+ auto obj = PROJStringParser().createFromPROJString("+proj=geos +type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
WKTFormatterNNPtr f(WKTFormatter::create());
@@ -7477,7 +7494,7 @@ TEST(io, projparse_geos_sweep_y) {
TEST(io, projparse_omerc_nouoff) {
auto obj = PROJStringParser().createFromPROJString(
- "+proj=omerc +no_uoff +alpha=2 +gamma=3");
+ "+proj=omerc +no_uoff +alpha=2 +gamma=3 +type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
WKTFormatterNNPtr f(WKTFormatter::create());
@@ -7500,7 +7517,7 @@ TEST(io, projparse_omerc_nouoff) {
TEST(io, projparse_omerc_tpno) {
auto obj = PROJStringParser().createFromPROJString(
- "+proj=omerc +lat_1=1 +lat_2=2 +lon_1=3 +lon_2=4");
+ "+proj=omerc +lat_1=1 +lat_2=2 +lon_1=3 +lon_2=4 +type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
WKTFormatterNNPtr f(WKTFormatter::create());
@@ -7518,7 +7535,8 @@ TEST(io, projparse_omerc_tpno) {
// ---------------------------------------------------------------------------
TEST(io, projparse_omerc_variant_b) {
- auto obj = PROJStringParser().createFromPROJString("+proj=omerc +alpha=2");
+ auto obj = PROJStringParser().createFromPROJString(
+ "+proj=omerc +alpha=2 +type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
WKTFormatterNNPtr f(WKTFormatter::create());
@@ -7538,7 +7556,7 @@ TEST(io, projparse_omerc_variant_b) {
TEST(io, projparse_somerc) {
auto obj = PROJStringParser().createFromPROJString(
- "+proj=somerc +lat_0=1 +lon_0=2 +k_0=3 +x_0=4 +y_0=5");
+ "+proj=somerc +lat_0=1 +lon_0=2 +k_0=3 +x_0=4 +y_0=5 +type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
WKTFormatterNNPtr f(WKTFormatter::create());
@@ -7574,7 +7592,8 @@ TEST(io, projparse_somerc) {
// ---------------------------------------------------------------------------
TEST(io, projparse_krovak) {
- auto obj = PROJStringParser().createFromPROJString("+proj=krovak");
+ auto obj =
+ PROJStringParser().createFromPROJString("+proj=krovak +type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
WKTFormatterNNPtr f(WKTFormatter::create());
@@ -7591,8 +7610,8 @@ TEST(io, projparse_krovak) {
// ---------------------------------------------------------------------------
TEST(io, projparse_krovak_axis_swu) {
- auto obj =
- PROJStringParser().createFromPROJString("+proj=krovak +axis=swu");
+ auto obj = PROJStringParser().createFromPROJString(
+ "+proj=krovak +axis=swu +type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
WKTFormatterNNPtr f(WKTFormatter::create());
@@ -7608,7 +7627,8 @@ TEST(io, projparse_krovak_axis_swu) {
// ---------------------------------------------------------------------------
TEST(io, projparse_etmerc) {
- auto obj = PROJStringParser().createFromPROJString("+proj=etmerc");
+ auto obj =
+ PROJStringParser().createFromPROJString("+proj=etmerc +type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
auto wkt2 = crs->exportToWKT(
@@ -7623,7 +7643,7 @@ TEST(io, projparse_etmerc) {
PROJStringFormatter::create(PROJStringFormatter::Convention::PROJ_4)
.get()),
"+proj=etmerc +lat_0=0 +lon_0=0 +k=1 +x_0=0 +y_0=0 "
- "+datum=WGS84 +units=m +no_defs");
+ "+datum=WGS84 +units=m +no_defs +type=crs");
auto wkt1 = crs->exportToWKT(
WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get());
@@ -7636,7 +7656,8 @@ TEST(io, projparse_etmerc) {
// ---------------------------------------------------------------------------
TEST(io, projparse_merc_variant_B) {
- auto obj = PROJStringParser().createFromPROJString("+proj=merc +lat_ts=1");
+ auto obj = PROJStringParser().createFromPROJString(
+ "+proj=merc +lat_ts=1 +type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
WKTFormatterNNPtr f(WKTFormatter::create());
@@ -7658,7 +7679,7 @@ TEST(io, projparse_merc_variant_B) {
TEST(io, projparse_merc_google_mercator) {
auto obj = PROJStringParser().createFromPROJString(
"+proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 "
- "+k=1 +units=m +nadgrids=@null");
+ "+k=1 +units=m +nadgrids=@null +type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
WKTFormatterNNPtr f(WKTFormatter::create());
@@ -7675,7 +7696,7 @@ TEST(io, projparse_merc_google_mercator) {
TEST(io, projparse_merc_stere_polar_variant_B) {
auto obj = PROJStringParser().createFromPROJString(
- "+proj=stere +lat_0=90 +lat_ts=70");
+ "+proj=stere +lat_0=90 +lat_ts=70 +type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
WKTFormatterNNPtr f(WKTFormatter::create());
@@ -7694,7 +7715,7 @@ TEST(io, projparse_merc_stere_polar_variant_B) {
TEST(io, projparse_merc_stere_polar_variant_A) {
auto obj = PROJStringParser().createFromPROJString(
- "+proj=stere +lat_0=-90 +k=0.994");
+ "+proj=stere +lat_0=-90 +k=0.994 +type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
WKTFormatterNNPtr f(WKTFormatter::create());
@@ -7713,7 +7734,7 @@ TEST(io, projparse_merc_stere_polar_variant_A) {
TEST(io, projparse_merc_stere_polar_k_and_lat_ts) {
auto obj = PROJStringParser().createFromPROJString(
- "+proj=stere +lat_0=90 +lat_ts=90 +k=1");
+ "+proj=stere +lat_0=90 +lat_ts=90 +k=1 +type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
auto wkt = crs->exportToWKT(
@@ -7731,21 +7752,22 @@ TEST(io, projparse_merc_stere_polar_k_and_lat_ts) {
PROJStringFormatter::create(PROJStringFormatter::Convention::PROJ_4)
.get()),
"+proj=stere +lat_0=90 +lat_ts=90 +lon_0=0 +x_0=0 +y_0=0 +datum=WGS84 "
- "+units=m +no_defs");
+ "+units=m +no_defs +type=crs");
}
// ---------------------------------------------------------------------------
TEST(io, projparse_merc_stere_polar_k_and_lat_ts_incompatible) {
EXPECT_THROW(PROJStringParser().createFromPROJString(
- "+proj=stere +lat_0=90 +lat_ts=70 +k=0.994"),
+ "+proj=stere +lat_0=90 +lat_ts=70 +k=0.994 +type=crs"),
ParsingException);
}
// ---------------------------------------------------------------------------
TEST(io, projparse_merc_stere) {
- auto obj = PROJStringParser().createFromPROJString("+proj=stere +lat_0=30");
+ auto obj = PROJStringParser().createFromPROJString(
+ "+proj=stere +lat_0=30 +type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
WKTFormatterNNPtr f(WKTFormatter::create());
@@ -7760,7 +7782,8 @@ TEST(io, projparse_merc_stere) {
// ---------------------------------------------------------------------------
TEST(io, projparse_utm) {
- auto obj = PROJStringParser().createFromPROJString("+proj=utm +zone=1");
+ auto obj =
+ PROJStringParser().createFromPROJString("+proj=utm +zone=1 +type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
WKTFormatterNNPtr f(WKTFormatter::create());
@@ -7780,8 +7803,8 @@ TEST(io, projparse_utm) {
// ---------------------------------------------------------------------------
TEST(io, projparse_utm_south) {
- auto obj =
- PROJStringParser().createFromPROJString("+proj=utm +zone=1 +south");
+ auto obj = PROJStringParser().createFromPROJString(
+ "+proj=utm +zone=1 +south +type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
WKTFormatterNNPtr f(WKTFormatter::create());
@@ -7802,7 +7825,8 @@ TEST(io, projparse_utm_south) {
// ---------------------------------------------------------------------------
TEST(io, projparse_laea_north_pole) {
- auto obj = PROJStringParser().createFromPROJString("+proj=laea +lat_0=90");
+ auto obj = PROJStringParser().createFromPROJString(
+ "+proj=laea +lat_0=90 +type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
WKTFormatterNNPtr f(WKTFormatter::create());
@@ -7817,7 +7841,8 @@ TEST(io, projparse_laea_north_pole) {
// ---------------------------------------------------------------------------
TEST(io, projparse_laea_south_pole) {
- auto obj = PROJStringParser().createFromPROJString("+proj=laea +lat_0=-90");
+ auto obj = PROJStringParser().createFromPROJString(
+ "+proj=laea +lat_0=-90 +type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
WKTFormatterNNPtr f(WKTFormatter::create());
@@ -7832,7 +7857,8 @@ TEST(io, projparse_laea_south_pole) {
// ---------------------------------------------------------------------------
TEST(io, projparse_laea_spherical) {
- auto obj = PROJStringParser().createFromPROJString("+proj=laea +R=6371228");
+ auto obj = PROJStringParser().createFromPROJString(
+ "+proj=laea +R=6371228 +type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
EXPECT_EQ(crs->derivingConversion()->method()->getEPSGCode(),
@@ -7855,7 +7881,8 @@ TEST(io, projparse_laea_spherical) {
// ---------------------------------------------------------------------------
TEST(io, projparse_eqc_spherical) {
- auto obj = PROJStringParser().createFromPROJString("+proj=eqc +R=6371228");
+ auto obj = PROJStringParser().createFromPROJString(
+ "+proj=eqc +R=6371228 +type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
EXPECT_EQ(crs->derivingConversion()->method()->getEPSGCode(),
@@ -7879,7 +7906,7 @@ TEST(io, projparse_eqc_spherical) {
TEST(io, projparse_non_earth_ellipsoid) {
std::string input("+proj=merc +lon_0=0 +k=1 +x_0=0 +y_0=0 +R=1 +units=m "
- "+no_defs");
+ "+no_defs +type=crs");
auto obj = PROJStringParser().createFromPROJString(input);
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
@@ -7894,7 +7921,7 @@ TEST(io, projparse_non_earth_ellipsoid) {
TEST(io, projparse_axisswap_unitconvert_longlat_proj) {
std::string input =
- "+proj=pipeline +step +proj=axisswap +order=2,1 +step "
+ "+type=crs +proj=pipeline +step +proj=axisswap +order=2,1 +step "
"+proj=unitconvert +xy_in=grad +xy_out=rad +step +inv +proj=longlat "
"+ellps=clrk80ign +pm=paris +step +proj=lcc +lat_1=49.5 "
"+lat_0=49.5 +lon_0=0 +k_0=0.999877341 +x_0=600000 +y_0=200000 "
@@ -7916,7 +7943,7 @@ TEST(io, projparse_axisswap_unitconvert_longlat_proj) {
TEST(io, projparse_axisswap_unitconvert_proj_axisswap) {
std::string input =
- "+proj=pipeline +step +proj=axisswap +order=2,1 +step "
+ "+type=crs +proj=pipeline +step +proj=axisswap +order=2,1 +step "
"+proj=unitconvert +xy_in=deg +xy_out=rad +step +proj=igh "
"+lon_0=0 +x_0=0 +y_0=0 +ellps=GRS80 +step +proj=axisswap +order=2,1";
auto obj = PROJStringParser().createFromPROJString(input);
@@ -7936,7 +7963,7 @@ TEST(io, projparse_axisswap_unitconvert_proj_axisswap) {
TEST(io, projparse_axisswap_unitconvert_proj_unitconvert) {
std::string input =
- "+proj=pipeline +step +proj=axisswap +order=2,1 +step "
+ "+type=crs +proj=pipeline +step +proj=axisswap +order=2,1 +step "
"+proj=unitconvert +xy_in=deg +xy_out=rad +step +proj=igh "
"+lon_0=0 +x_0=0 +y_0=0 +ellps=GRS80 +step +proj=unitconvert +xy_in=m "
"+z_in=m +xy_out=ft +z_out=ft";
@@ -7957,7 +7984,7 @@ TEST(io, projparse_axisswap_unitconvert_proj_unitconvert) {
TEST(io, projparse_axisswap_unitconvert_proj_unitconvert_numeric_axisswap) {
std::string input =
- "+proj=pipeline +step +proj=axisswap +order=2,1 +step "
+ "+type=crs +proj=pipeline +step +proj=axisswap +order=2,1 +step "
"+proj=unitconvert +xy_in=deg +xy_out=rad +step +proj=igh "
"+lon_0=0 +x_0=0 +y_0=0 +ellps=GRS80 +step +proj=unitconvert +xy_in=m "
"+z_in=m +xy_out=2.5 +z_out=2.5 +step +proj=axisswap +order=-2,-1";
@@ -7979,7 +8006,7 @@ TEST(io, projparse_axisswap_unitconvert_proj_unitconvert_numeric_axisswap) {
TEST(io, projparse_projected_units) {
auto obj = PROJStringParser().createFromPROJString(
- "+proj=tmerc +x_0=0.304800609601219 +units=us-ft");
+ "+proj=tmerc +x_0=0.304800609601219 +units=us-ft +type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
WKTFormatterNNPtr f(WKTFormatter::create());
@@ -7999,7 +8026,7 @@ TEST(io, projparse_projected_units) {
TEST(io, projparse_projected_to_meter_known) {
auto obj = PROJStringParser().createFromPROJString(
- "+proj=tmerc +to_meter=0.304800609601219");
+ "+proj=tmerc +to_meter=0.304800609601219 +type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
WKTFormatterNNPtr f(WKTFormatter::create());
@@ -8018,8 +8045,8 @@ TEST(io, projparse_projected_to_meter_known) {
// ---------------------------------------------------------------------------
TEST(io, projparse_projected_to_meter_unknown) {
- auto obj =
- PROJStringParser().createFromPROJString("+proj=tmerc +to_meter=0.1234");
+ auto obj = PROJStringParser().createFromPROJString(
+ "+proj=tmerc +to_meter=0.1234 +type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
WKTFormatterNNPtr f(WKTFormatter::create());
@@ -8041,8 +8068,8 @@ TEST(io, projparse_projected_to_meter_unknown) {
// ---------------------------------------------------------------------------
TEST(io, projparse_projected_vunits) {
- auto obj =
- PROJStringParser().createFromPROJString("+proj=tmerc +vunits=ft");
+ auto obj = PROJStringParser().createFromPROJString(
+ "+proj=tmerc +vunits=ft +type=crs");
auto crs = nn_dynamic_pointer_cast<CompoundCRS>(obj);
ASSERT_TRUE(crs != nullptr);
WKTFormatterNNPtr f(WKTFormatter::create());
@@ -8061,7 +8088,8 @@ TEST(io, projparse_projected_vunits) {
TEST(io, projparse_projected_unknown) {
auto obj = PROJStringParser().createFromPROJString(
- "+proj=mbt_s +unused_flag +lat_0=45 +lon_0=0 +k=1 +x_0=10 +y_0=0");
+ "+proj=mbt_s +unused_flag +lat_0=45 +lon_0=0 +k=1 +x_0=10 +y_0=0 "
+ "+type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
@@ -8106,7 +8134,7 @@ TEST(io, projparse_projected_unknown) {
EXPECT_EQ(crs->exportToPROJString(PROJStringFormatter::create().get()),
"+proj=mbt_s +unused_flag +lat_0=45 +lon_0=0 +k=1 +x_0=10 "
- "+y_0=0 +datum=WGS84 +units=m +no_defs");
+ "+y_0=0 +datum=WGS84 +units=m +no_defs +type=crs");
{
auto obj2 = WKTParser().createFromWKT(expected_wkt1);
@@ -8133,8 +8161,8 @@ TEST(io, projparse_projected_unknown) {
// ---------------------------------------------------------------------------
TEST(io, projparse_geocent) {
- auto obj =
- PROJStringParser().createFromPROJString("+proj=geocent +ellps=WGS84");
+ auto obj = PROJStringParser().createFromPROJString(
+ "+proj=geocent +ellps=WGS84 +type=crs");
auto crs = nn_dynamic_pointer_cast<GeodeticCRS>(obj);
ASSERT_TRUE(crs != nullptr);
WKTFormatterNNPtr f(WKTFormatter::create());
@@ -8156,7 +8184,7 @@ TEST(io, projparse_geocent) {
TEST(io, projparse_geocent_towgs84) {
auto obj = PROJStringParser().createFromPROJString(
- "+proj=geocent +ellps=WGS84 +towgs84=1,2,3");
+ "+proj=geocent +ellps=WGS84 +towgs84=1,2,3 +type=crs");
auto crs = nn_dynamic_pointer_cast<BoundCRS>(obj);
ASSERT_TRUE(crs != nullptr);
WKTFormatterNNPtr f(WKTFormatter::create());
@@ -8182,7 +8210,8 @@ TEST(io, projparse_geocent_towgs84) {
crs->exportToPROJString(
PROJStringFormatter::create(PROJStringFormatter::Convention::PROJ_4)
.get()),
- "+proj=geocent +ellps=WGS84 +towgs84=1,2,3,0,0,0,0 +units=m +no_defs");
+ "+proj=geocent +ellps=WGS84 +towgs84=1,2,3,0,0,0,0 +units=m +no_defs "
+ "+type=crs");
}
// ---------------------------------------------------------------------------
@@ -8226,7 +8255,7 @@ TEST(io, projparse_cart_unit_numeric) {
// ---------------------------------------------------------------------------
TEST(io, projparse_longlat_wktext) {
- std::string input("+proj=longlat +foo +wktext");
+ std::string input("+proj=longlat +foo +wktext +type=crs");
auto obj = PROJStringParser().createFromPROJString(input);
auto crs = nn_dynamic_pointer_cast<GeodeticCRS>(obj);
ASSERT_TRUE(crs != nullptr);
@@ -8240,7 +8269,7 @@ TEST(io, projparse_longlat_wktext) {
// ---------------------------------------------------------------------------
TEST(io, projparse_geocent_wktext) {
- std::string input("+proj=geocent +foo +wktext");
+ std::string input("+proj=geocent +foo +wktext +type=crs");
auto obj = PROJStringParser().createFromPROJString(input);
auto crs = nn_dynamic_pointer_cast<GeodeticCRS>(obj);
ASSERT_TRUE(crs != nullptr);
@@ -8254,7 +8283,7 @@ TEST(io, projparse_geocent_wktext) {
// ---------------------------------------------------------------------------
TEST(io, projparse_projected_wktext) {
- std::string input("+proj=merc +foo +wktext");
+ std::string input("+proj=merc +foo +wktext +type=crs");
auto obj = PROJStringParser().createFromPROJString(input);
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
@@ -8269,7 +8298,7 @@ TEST(io, projparse_projected_wktext) {
TEST(io, projparse_ob_tran_longlat) {
std::string input(
- "+proj=pipeline +step +proj=axisswap +order=2,1 +step "
+ "+type=crs +proj=pipeline +step +proj=axisswap +order=2,1 +step "
"+proj=unitconvert +xy_in=deg +xy_out=rad +step +proj=ob_tran "
"+o_proj=longlat +o_lat_p=52 +o_lon_p=-30 +lon_0=-25 +ellps=WGS84 "
"+step +proj=unitconvert +xy_in=rad +xy_out=deg +step "
@@ -8291,7 +8320,11 @@ TEST(io, projparse_ob_tran_longlat) {
// ---------------------------------------------------------------------------
TEST(io, projparse_helmert_translation) {
- std::string projString("+proj=helmert +x=1 +y=2 +z=3");
+ std::string projString("+proj=pipeline +step +proj=unitconvert +xy_in=deg "
+ "+xy_out=rad +step +proj=cart +ellps=GRS80 +step "
+ "+proj=helmert +x=1 +y=2 +z=3 +step +inv +proj=cart "
+ "+ellps=GRS80 +step +proj=unitconvert +xy_in=rad "
+ "+xy_out=deg");
auto obj = PROJStringParser().createFromPROJString(projString);
auto transf = nn_dynamic_pointer_cast<Transformation>(obj);
ASSERT_TRUE(transf != nullptr);
@@ -8305,8 +8338,11 @@ TEST(io, projparse_helmert_translation) {
// ---------------------------------------------------------------------------
TEST(io, projparse_helmert_translation_inv) {
- std::string projString(
- "+proj=pipeline +step +inv +proj=helmert +x=1 +y=2 +z=3");
+ std::string projString("+proj=pipeline +step +proj=unitconvert +xy_in=deg "
+ "+xy_out=rad +step +proj=cart +ellps=GRS80 +step "
+ "+inv +proj=helmert +x=1 +y=2 +z=3 +step +inv "
+ "+proj=cart +ellps=GRS80 +step +proj=unitconvert "
+ "+xy_in=rad +xy_out=deg");
auto obj = PROJStringParser().createFromPROJString(projString);
auto transf = nn_dynamic_pointer_cast<Transformation>(obj);
ASSERT_TRUE(transf != nullptr);
@@ -8314,14 +8350,20 @@ TEST(io, projparse_helmert_translation_inv) {
transf->exportToPROJString(
PROJStringFormatter::create(PROJStringFormatter::Convention::PROJ_5)
.get()),
- "+proj=helmert +x=-1 +y=-2 +z=-3");
+ "+proj=pipeline +step +proj=unitconvert +xy_in=deg +xy_out=rad +step "
+ "+proj=cart +ellps=GRS80 +step +proj=helmert +x=-1 +y=-2 +z=-3 +step "
+ "+inv +proj=cart +ellps=GRS80 +step +proj=unitconvert +xy_in=rad "
+ "+xy_out=deg");
}
// ---------------------------------------------------------------------------
TEST(io, projparse_helmert_position_vector) {
- std::string projString("+proj=helmert +x=1 +y=2 +z=3 +rx=4 +ry=5 +rz=6 "
- "+s=7 +convention=position_vector");
+ std::string projString(
+ "+proj=pipeline +step +proj=unitconvert +xy_in=deg +xy_out=rad +step "
+ "+proj=cart +ellps=GRS80 +step +proj=helmert +x=1 +y=2 +z=3 +rx=4 "
+ "+ry=5 +rz=6 +s=7 +convention=position_vector +step +inv +proj=cart "
+ "+ellps=GRS80 +step +proj=unitconvert +xy_in=rad +xy_out=deg");
auto obj = PROJStringParser().createFromPROJString(projString);
auto transf = nn_dynamic_pointer_cast<Transformation>(obj);
ASSERT_TRUE(transf != nullptr);
@@ -8335,9 +8377,11 @@ TEST(io, projparse_helmert_position_vector) {
// ---------------------------------------------------------------------------
TEST(io, projparse_helmert_position_vector_inv) {
- std::string projString("+proj=pipeline +step +inv +proj=helmert +x=1 +y=2 "
- "+z=3 +rx=4 +ry=5 +rz=6 "
- "+s=7 +convention=position_vector");
+ std::string projString(
+ "+proj=pipeline +step +proj=unitconvert +xy_in=deg +xy_out=rad +step "
+ "+proj=cart +ellps=GRS80 +step +inv +proj=helmert +x=1 +y=2 +z=3 +rx=4 "
+ "+ry=5 +rz=6 +s=7 +convention=position_vector +step +inv +proj=cart "
+ "+ellps=GRS80 +step +proj=unitconvert +xy_in=rad +xy_out=deg");
auto obj = PROJStringParser().createFromPROJString(projString);
auto transf = nn_dynamic_pointer_cast<CoordinateOperation>(obj);
ASSERT_TRUE(transf != nullptr);
@@ -8351,10 +8395,14 @@ TEST(io, projparse_helmert_position_vector_inv) {
// ---------------------------------------------------------------------------
TEST(io, projparse_helmert_time_dependent_position_vector) {
- std::string projString("+proj=helmert +x=1 +y=2 +z=3 +rx=4 +ry=5 +rz=6 "
+ std::string projString("+proj=pipeline +step +proj=unitconvert +xy_in=deg "
+ "+xy_out=rad +step +proj=cart +ellps=GRS80 +step "
+ "+proj=helmert +x=1 +y=2 +z=3 +rx=4 +ry=5 +rz=6 "
"+s=7 +dx=0.1 +dy=0.2 +dz=0.3 +drx=0.4 +dry=0.5 "
"+drz=0.6 +ds=0.7 +t_epoch=2018.5 "
- "+convention=position_vector");
+ "+convention=position_vector +step +inv +proj=cart "
+ "+ellps=GRS80 +step +proj=unitconvert +xy_in=rad "
+ "+xy_out=deg");
auto obj = PROJStringParser().createFromPROJString(projString);
auto transf = nn_dynamic_pointer_cast<Transformation>(obj);
ASSERT_TRUE(transf != nullptr);
@@ -8368,8 +8416,11 @@ TEST(io, projparse_helmert_time_dependent_position_vector) {
// ---------------------------------------------------------------------------
TEST(io, projparse_helmert_coordinate_frame) {
- std::string projString("+proj=helmert +x=1 +y=2 +z=3 +rx=4 +ry=5 +rz=6 "
- "+s=7 +convention=coordinate_frame");
+ std::string projString(
+ "+proj=pipeline +step +proj=unitconvert +xy_in=deg +xy_out=rad +step "
+ "+proj=cart +ellps=GRS80 +step +proj=helmert +x=1 +y=2 +z=3 +rx=4 "
+ "+ry=5 +rz=6 +s=7 +convention=coordinate_frame +step +inv +proj=cart "
+ "+ellps=GRS80 +step +proj=unitconvert +xy_in=rad +xy_out=deg");
auto obj = PROJStringParser().createFromPROJString(projString);
auto transf = nn_dynamic_pointer_cast<Transformation>(obj);
ASSERT_TRUE(transf != nullptr);
@@ -8383,10 +8434,14 @@ TEST(io, projparse_helmert_coordinate_frame) {
// ---------------------------------------------------------------------------
TEST(io, projparse_helmert_time_dependent_coordinate_frame) {
- std::string projString("+proj=helmert +x=1 +y=2 +z=3 +rx=4 +ry=5 +rz=6 "
+ std::string projString("+proj=pipeline +step +proj=unitconvert +xy_in=deg "
+ "+xy_out=rad +step +proj=cart +ellps=GRS80 +step "
+ "+proj=helmert +x=1 +y=2 +z=3 +rx=4 +ry=5 +rz=6 "
"+s=7 +dx=0.1 +dy=0.2 +dz=0.3 +drx=0.4 +dry=0.5 "
"+drz=0.6 +ds=0.7 +t_epoch=2018.5 "
- "+convention=coordinate_frame");
+ "+convention=coordinate_frame +step +inv +proj=cart "
+ "+ellps=GRS80 +step +proj=unitconvert +xy_in=rad "
+ "+xy_out=deg");
auto obj = PROJStringParser().createFromPROJString(projString);
auto transf = nn_dynamic_pointer_cast<Transformation>(obj);
ASSERT_TRUE(transf != nullptr);
@@ -8401,28 +8456,6 @@ TEST(io, projparse_helmert_time_dependent_coordinate_frame) {
TEST(io, projparse_helmert_complex_pipeline) {
std::string projString(
- "+proj=pipeline +step +proj=cart "
- "+ellps=WGS84 +step +proj=helmert +x=-1 +y=-2 +z=-3 +rx=-4 "
- "+ry=-5 +rz=-6 +s=-7 +convention=position_vector +step +inv "
- "+proj=cart +ellps=clrk80ign");
- auto obj = PROJStringParser().createFromPROJString(projString);
- auto transf = nn_dynamic_pointer_cast<Transformation>(obj);
- ASSERT_TRUE(transf != nullptr);
- EXPECT_EQ(
- transf->exportToPROJString(
- PROJStringFormatter::create(PROJStringFormatter::Convention::PROJ_5)
- .get()),
- "+proj=pipeline +step +proj=unitconvert +xy_in=deg +xy_out=rad "
- "+step +proj=cart +ellps=WGS84 +step +proj=helmert +x=-1 +y=-2 "
- "+z=-3 +rx=-4 +ry=-5 +rz=-6 +s=-7 +convention=position_vector "
- "+step +inv +proj=cart +ellps=clrk80ign +step +proj=unitconvert "
- "+xy_in=rad +xy_out=deg");
-}
-
-// ---------------------------------------------------------------------------
-
-TEST(io, projparse_helmert_complex_pipeline_2) {
- std::string projString(
"+proj=pipeline +step +proj=axisswap +order=2,1 +step "
"+proj=unitconvert +xy_in=deg +xy_out=rad +step +proj=cart "
"+ellps=WGS84 +step +proj=helmert +x=-1 +y=-2 +z=-3 +rx=-4 "
@@ -8447,21 +8480,18 @@ TEST(io, projparse_helmert_errors) {
// Missing convention
EXPECT_THROW(PROJStringParser().createFromPROJString("+proj=helmert +rx=4"),
ParsingException);
-
- EXPECT_THROW(PROJStringParser().createFromPROJString(
- "+proj=helmert +convention=unhandled"),
- ParsingException);
-
- EXPECT_THROW(PROJStringParser().createFromPROJString(
- "+proj=helmert +unhandled_keyword"),
- ParsingException);
}
// ---------------------------------------------------------------------------
TEST(io, projparse_molodensky) {
- std::string projString("+proj=molodensky +ellps=WGS84 +dx=84.87 +dy=96.49 "
- "+dz=116.95 +da=251 +df=1.41927e-05");
+ std::string projString(
+ "+proj=pipeline +step +proj=unitconvert +xy_in=deg +xy_out=rad "
+ "+proj=longlat +ellps=WGS84 +step +proj=molodensky +ellps=WGS84 "
+ "+dx=84.87 +dy=96.49 "
+ "+dz=116.95 +da=251 +df=1.41927e-05 +step +proj=longlat "
+ "+ellps=GRS80 +step +proj=unitconvert "
+ "+xy_in=rad +xy_out=deg");
auto obj = PROJStringParser().createFromPROJString(projString);
auto transf = nn_dynamic_pointer_cast<Transformation>(obj);
ASSERT_TRUE(transf != nullptr);
@@ -8480,12 +8510,13 @@ TEST(io, projparse_molodensky) {
"ellipsoidal,2],AXIS[\"longitude\",east,ORDER[1],ANGLEUNIT[\"degree\","
"0.0174532925199433]],AXIS[\"latitude\",north,ORDER[2],ANGLEUNIT["
"\"degree\",0.0174532925199433]]]],TARGETCRS[GEODCRS[\"unknown\",DATUM["
- "\"unknown\",ELLIPSOID[\"unknown\",6378388,297.000000198989,LENGTHUNIT["
- "\"metre\",1]]],PRIMEM[\"Greenwich\",0,ANGLEUNIT[\"degree\",0."
- "0174532925199433]],CS[ellipsoidal,2],AXIS[\"longitude\",east,ORDER[1],"
- "ANGLEUNIT[\"degree\",0.0174532925199433]],AXIS[\"latitude\",north,"
- "ORDER[2],ANGLEUNIT[\"degree\",0.0174532925199433]]]],METHOD["
- "\"Molodensky\",ID[\"EPSG\",9604]],PARAMETER[\"X-axis "
+ "\"Unknown based on GRS80 ellipsoid\",ELLIPSOID[\"GRS "
+ "1980\",6378137,298.257222101,LENGTHUNIT[\"metre\",1]]],PRIMEM["
+ "\"Greenwich\",0,ANGLEUNIT[\"degree\",0.0174532925199433]],CS["
+ "ellipsoidal,2],AXIS[\"longitude\",east,ORDER[1],ANGLEUNIT[\"degree\","
+ "0.0174532925199433]],AXIS[\"latitude\",north,ORDER[2],ANGLEUNIT["
+ "\"degree\",0.0174532925199433]]]],METHOD[\"Molodensky\",ID[\"EPSG\","
+ "9604]],PARAMETER[\"X-axis "
"translation\",84.87,LENGTHUNIT[\"metre\",1],ID[\"EPSG\",8605]],"
"PARAMETER[\"Y-axis "
"translation\",96.49,LENGTHUNIT[\"metre\",1],ID[\"EPSG\",8606]],"
@@ -8499,19 +8530,21 @@ TEST(io, projparse_molodensky) {
transf->exportToPROJString(
PROJStringFormatter::create(PROJStringFormatter::Convention::PROJ_5)
.get()),
- "+proj=pipeline +step +proj=unitconvert +xy_in=deg +xy_out=rad "
- "+step +proj=molodensky +ellps=WGS84 +dx=84.87 +dy=96.49 "
- "+dz=116.95 +da=251 +df=1.41927e-05 +step +proj=longlat "
- "+a=6378388 +rf=297.000000198989 +step +proj=unitconvert "
- "+xy_in=rad +xy_out=deg");
+ "+proj=pipeline +step +proj=unitconvert +xy_in=deg +xy_out=rad +step "
+ "+proj=molodensky +ellps=WGS84 +dx=84.87 +dy=96.49 +dz=116.95 +da=251 "
+ "+df=1.41927e-05 +step +proj=unitconvert +xy_in=rad +xy_out=deg");
}
// ---------------------------------------------------------------------------
TEST(io, projparse_molodensky_inv) {
- std::string projString("+proj=pipeline +step +inv +proj=molodensky "
- "+ellps=WGS84 +dx=84.87 +dy=96.49 "
- "+dz=116.95 +da=251 +df=1.41927e-05");
+ std::string projString(
+ "+proj=pipeline +step +proj=unitconvert +xy_in=deg +xy_out=rad "
+ "+proj=longlat +ellps=WGS84 +step +inv +proj=molodensky "
+ "+ellps=WGS84 +dx=84.87 +dy=96.49 "
+ "+dz=116.95 +da=251 +df=1.41927e-05 +step +proj=longlat "
+ "+ellps=GRS80 +step +proj=unitconvert "
+ "+xy_in=rad +xy_out=deg");
auto obj = PROJStringParser().createFromPROJString(projString);
auto transf = nn_dynamic_pointer_cast<CoordinateOperation>(obj);
ASSERT_TRUE(transf != nullptr);
@@ -8519,66 +8552,33 @@ TEST(io, projparse_molodensky_inv) {
transf->exportToPROJString(
PROJStringFormatter::create(PROJStringFormatter::Convention::PROJ_5)
.get()),
- "+proj=pipeline +step +proj=unitconvert +xy_in=deg +xy_out=rad "
- "+step +inv +proj=longlat +a=6378388 +rf=297.000000198989 +step "
- "+proj=molodensky +a=6378388 +rf=297.000000198989 +dx=-84.87 "
- "+dy=-96.49 +dz=-116.95 +da=-251 +df=-1.41927e-05 +step "
- "+proj=unitconvert +xy_in=rad +xy_out=deg");
+ "+proj=pipeline +step +proj=unitconvert +xy_in=deg +xy_out=rad +step "
+ "+proj=molodensky +ellps=GRS80 +dx=-84.87 +dy=-96.49 +dz=-116.95 "
+ "+da=-251 +df=-1.41927e-05 +step +proj=unitconvert +xy_in=rad "
+ "+xy_out=deg");
}
// ---------------------------------------------------------------------------
TEST(io, projparse_molodensky_abridged) {
- std::string projString("+proj=molodensky +ellps=WGS84 +dx=84.87 +dy=96.49 "
- "+dz=116.95 +da=251 +df=1.41927e-05 +abridged");
- auto obj = PROJStringParser().createFromPROJString(projString);
- auto transf = nn_dynamic_pointer_cast<Transformation>(obj);
- ASSERT_TRUE(transf != nullptr);
- EXPECT_EQ(
- transf->exportToPROJString(
- PROJStringFormatter::create(PROJStringFormatter::Convention::PROJ_5)
- .get()),
- "+proj=pipeline +step +proj=unitconvert +xy_in=deg +xy_out=rad "
- "+step +proj=molodensky +ellps=WGS84 +dx=84.87 +dy=96.49 "
- "+dz=116.95 +da=251 +df=1.41927e-05 +abridged +step +proj=longlat "
- "+a=6378388 +rf=297.000000198989 +step "
- "+proj=unitconvert +xy_in=rad +xy_out=deg");
-}
-
-// ---------------------------------------------------------------------------
-
-TEST(io, projparse_molodensky_complex_pipeline) {
std::string projString(
"+proj=pipeline +step +proj=unitconvert +xy_in=deg +xy_out=rad "
"+proj=longlat +ellps=WGS84 +step +proj=molodensky +ellps=WGS84 "
"+dx=84.87 +dy=96.49 "
- "+dz=116.95 +da=251 +df=1.41927e-05 +step +proj=longlat "
+ "+dz=116.95 +da=251 +df=1.41927e-05 +abridged +step +proj=longlat "
"+ellps=GRS80 +step +proj=unitconvert "
"+xy_in=rad +xy_out=deg");
auto obj = PROJStringParser().createFromPROJString(projString);
auto transf = nn_dynamic_pointer_cast<Transformation>(obj);
ASSERT_TRUE(transf != nullptr);
-
- WKTFormatterNNPtr f(WKTFormatter::create());
- f->simulCurNodeHasId();
- f->setMultiLine(false);
- transf->exportToWKT(f.get());
- auto wkt = f->toString();
- EXPECT_TRUE(wkt.find("SOURCECRS[GEODCRS[\"unknown\",DATUM[\"Unknown based "
- "on WGS84 ellipsoid\"") != std::string::npos)
- << wkt;
- EXPECT_TRUE(wkt.find("TARGETCRS[GEODCRS[\"unknown\",DATUM[\"Unknown based "
- "on GRS80 ellipsoid\"") != std::string::npos)
- << wkt;
-
EXPECT_EQ(
transf->exportToPROJString(
PROJStringFormatter::create(PROJStringFormatter::Convention::PROJ_5)
.get()),
- "+proj=pipeline +step +proj=unitconvert +xy_in=deg +xy_out=rad "
- "+step +proj=molodensky +ellps=WGS84 +dx=84.87 +dy=96.49 "
- "+dz=116.95 +da=251 +df=1.41927e-05 +step +proj=unitconvert "
- "+xy_in=rad +xy_out=deg");
+ "+proj=pipeline +step +proj=unitconvert +xy_in=deg +xy_out=rad +step "
+ "+proj=molodensky +ellps=WGS84 +dx=84.87 +dy=96.49 +dz=116.95 +da=251 "
+ "+df=1.41927e-05 +abridged +step +proj=unitconvert +xy_in=rad "
+ "+xy_out=deg");
}
// ---------------------------------------------------------------------------
@@ -8587,7 +8587,7 @@ TEST(io, projparse_longlat_title) {
std::string projString("+title=Ile d'Amsterdam 1963 +proj=longlat "
"+towgs84=109.7530,-528.1330,-362.2440 "
"+a=6378388.0000 +rf=297.0000000000000 +units=m "
- "+no_defs");
+ "+no_defs +type=crs");
auto obj = PROJStringParser().createFromPROJString(projString);
auto crs = nn_dynamic_pointer_cast<BoundCRS>(obj);
ASSERT_TRUE(crs != nullptr);
@@ -8600,7 +8600,7 @@ TEST(io, projparse_longlat_title) {
PROJStringFormatter::create(PROJStringFormatter::Convention::PROJ_4)
.get()),
"+proj=longlat +ellps=intl +towgs84=109.753,-528.133,-362.244,0,0,0,0 "
- "+no_defs");
+ "+no_defs +type=crs");
}
// ---------------------------------------------------------------------------
@@ -8610,7 +8610,8 @@ TEST(io, projparse_projected_title) {
"+title=Amsterdam 1963 +proj=tmerc "
"+towgs84=109.7530,-528.1330,-362.2440 +a=6378388.0000 "
"+rf=297.0000000000000 +lat_0=0.000000000 +lon_0=75.000000000 "
- "+k_0=0.99960000 +x_0=500000.000 +y_0=10000000.000 +units=m +no_defs");
+ "+k_0=0.99960000 +x_0=500000.000 +y_0=10000000.000 +units=m +no_defs "
+ "+type=crs");
auto obj = PROJStringParser().createFromPROJString(projString);
auto crs = nn_dynamic_pointer_cast<BoundCRS>(obj);
ASSERT_TRUE(crs != nullptr);
@@ -8623,7 +8624,8 @@ TEST(io, projparse_projected_title) {
PROJStringFormatter::create(PROJStringFormatter::Convention::PROJ_4)
.get()),
"+proj=utm +zone=43 +south +ellps=intl "
- "+towgs84=109.753,-528.133,-362.244,0,0,0,0 +units=m +no_defs");
+ "+towgs84=109.753,-528.133,-362.244,0,0,0,0 +units=m +no_defs "
+ "+type=crs");
}
// ---------------------------------------------------------------------------
@@ -8632,24 +8634,26 @@ TEST(io, projparse_init) {
auto dbContext = DatabaseContext::create();
// Not allowed in non-compatibillity mode
- EXPECT_THROW(PROJStringParser().createFromPROJString("init=epsg:4326"),
- ParsingException);
+ EXPECT_THROW(
+ PROJStringParser().createFromPROJString("init=epsg:4326 +type=crs"),
+ ParsingException);
{
// EPSG:4326 is normally latitude-longitude order with degree,
- // but in compatibillity mode it will be long-lat radian
+ // but in compatibillity mode it will be long-lat
auto obj = createFromUserInput("init=epsg:4326", dbContext, true);
auto crs = nn_dynamic_pointer_cast<GeographicCRS>(obj);
ASSERT_TRUE(crs != nullptr);
EXPECT_TRUE(crs->coordinateSystem()->isEquivalentTo(
- EllipsoidalCS::createLongitudeLatitude(UnitOfMeasure::RADIAN)
+ EllipsoidalCS::createLongitudeLatitude(UnitOfMeasure::DEGREE)
.get()));
}
{
// EPSG:3040 is normally northing-easting order, but in compatibillity
// mode it will be easting-northing
- auto obj = createFromUserInput("init=epsg:3040", dbContext, true);
+ auto obj =
+ createFromUserInput("init=epsg:3040 +type=crs", dbContext, true);
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
EXPECT_TRUE(crs->coordinateSystem()->isEquivalentTo(
@@ -8662,20 +8666,19 @@ TEST(io, projparse_init) {
auto co = nn_dynamic_pointer_cast<CoordinateOperation>(obj);
ASSERT_TRUE(co != nullptr);
EXPECT_EQ(co->exportToPROJString(PROJStringFormatter::create().get()),
- "+proj=helmert +x=-0.0001 +y=0.0008 +z=0.0058 +rx=0 +ry=0 "
- "+rz=0 +s=-0.0004 +dx=0.0002 +dy=-0.0001 +dz=0.0018 +drx=0 "
- "+dry=0 +drz=0 +ds=-8e-06 +t_epoch=2000 "
- "+convention=position_vector");
+ "+proj=helmert +x=-0.0001 +y=0.0008 +z=0.0058 +s=-0.0004 "
+ "+dx=0.0002 +dy=-0.0001 +dz=0.0018 +ds=-0.000008 "
+ "+t_epoch=2000.0 +convention=position_vector");
}
{
- auto obj = createFromUserInput(
- "title=mytitle init=epsg:4326 ellps=WGS84", dbContext, true);
- auto co = nn_dynamic_pointer_cast<CoordinateOperation>(obj);
- ASSERT_TRUE(co != nullptr);
- EXPECT_EQ(co->nameStr(), "mytitle");
- EXPECT_EQ(co->exportToPROJString(PROJStringFormatter::create().get()),
- "+init=epsg:4326 +ellps=WGS84");
+ auto obj = createFromUserInput("+title=mytitle +geoc +init=epsg:4326",
+ dbContext, true);
+ auto crs = nn_dynamic_pointer_cast<GeographicCRS>(obj);
+ ASSERT_TRUE(crs != nullptr);
+ EXPECT_EQ(crs->nameStr(), "mytitle");
+ EXPECT_EQ(crs->exportToPROJString(PROJStringFormatter::create().get()),
+ "+proj=longlat +geoc +datum=WGS84 +no_defs +type=crs");
}
{
@@ -8688,15 +8691,6 @@ TEST(io, projparse_init) {
"+proj=pipeline +step +init=epsg:4326 +step +proj=longlat "
"+ellps=WGS84");
}
-
- {
- auto obj = createFromUserInput(
- "init=epsg:4326 proj=longlat ellps=GRS80", dbContext, true);
- auto crs = nn_dynamic_pointer_cast<GeographicCRS>(obj);
- ASSERT_TRUE(crs != nullptr);
- EXPECT_EQ(crs->exportToPROJString(PROJStringFormatter::create().get()),
- "+proj=longlat +ellps=GRS80 +no_defs");
- }
}
// ---------------------------------------------------------------------------
@@ -8713,8 +8707,9 @@ TEST(io, projparse_errors) {
EXPECT_THROW(PROJStringParser().createFromPROJString("step"),
ParsingException);
- EXPECT_THROW(PROJStringParser().createFromPROJString("proj=unknown"),
- ParsingException);
+ EXPECT_THROW(
+ PROJStringParser().createFromPROJString("proj=unknown +type=crs"),
+ ParsingException);
EXPECT_THROW(
PROJStringParser().createFromPROJString(
@@ -8733,61 +8728,64 @@ TEST(io, projparse_errors) {
// ---------------------------------------------------------------------------
TEST(io, projparse_longlat_errors) {
- EXPECT_THROW(
- PROJStringParser().createFromPROJString("+proj=longlat +datum=unknown"),
- ParsingException);
-
- EXPECT_THROW(
- PROJStringParser().createFromPROJString("+proj=longlat +ellps=unknown"),
- ParsingException);
-
EXPECT_THROW(PROJStringParser().createFromPROJString(
- "+proj=longlat +a=invalid +b=1"),
+ "+proj=longlat +datum=unknown +type=crs"),
ParsingException);
EXPECT_THROW(PROJStringParser().createFromPROJString(
- "+proj=longlat +a=1 +b=invalid"),
+ "+proj=longlat +ellps=unknown +type=crs"),
ParsingException);
EXPECT_THROW(PROJStringParser().createFromPROJString(
- "+proj=longlat +a=invalid +rf=1"),
+ "+proj=longlat +a=invalid +b=1 +type=crs"),
ParsingException);
EXPECT_THROW(PROJStringParser().createFromPROJString(
- "+proj=longlat +a=1 +rf=invalid"),
+ "+proj=longlat +a=1 +b=invalid +type=crs"),
ParsingException);
EXPECT_THROW(PROJStringParser().createFromPROJString(
- "+proj=longlat +a=1 +f=invalid"),
+ "+proj=longlat +a=invalid +rf=1 +type=crs"),
ParsingException);
- EXPECT_THROW(
- PROJStringParser().createFromPROJString("+proj=longlat +R=invalid"),
- ParsingException);
-
- EXPECT_THROW(PROJStringParser().createFromPROJString("+proj=longlat +b=1"),
+ EXPECT_THROW(PROJStringParser().createFromPROJString(
+ "+proj=longlat +a=1 +rf=invalid +type=crs"),
ParsingException);
- EXPECT_THROW(PROJStringParser().createFromPROJString("+proj=longlat +rf=1"),
+ EXPECT_THROW(PROJStringParser().createFromPROJString(
+ "+proj=longlat +a=1 +f=invalid +type=crs"),
ParsingException);
- EXPECT_THROW(PROJStringParser().createFromPROJString("+proj=longlat +f=0"),
+ EXPECT_THROW(PROJStringParser().createFromPROJString(
+ "+proj=longlat +R=invalid +type=crs"),
ParsingException);
EXPECT_THROW(
- PROJStringParser().createFromPROJString("+proj=longlat +pm=unknown"),
+ PROJStringParser().createFromPROJString("+proj=longlat +b=1 +type=crs"),
ParsingException);
- EXPECT_THROW(
- PROJStringParser().createFromPROJString(
- "+proj=longlat +ellps=GRS80 +towgs84=1.2,2,3,4,5,6,invalid"),
- ParsingException);
+ EXPECT_THROW(PROJStringParser().createFromPROJString(
+ "+proj=longlat +rf=1 +type=crs"),
+ ParsingException);
EXPECT_THROW(
- PROJStringParser().createFromPROJString("+proj=longlat +axis=foo"),
+ PROJStringParser().createFromPROJString("+proj=longlat +f=0 +type=crs"),
ParsingException);
EXPECT_THROW(PROJStringParser().createFromPROJString(
+ "+proj=longlat +pm=unknown +type=crs"),
+ ParsingException);
+
+ EXPECT_THROW(PROJStringParser().createFromPROJString(
+ "+proj=longlat +ellps=GRS80 "
+ "+towgs84=1.2,2,3,4,5,6,invalid +type=crs"),
+ ParsingException);
+
+ EXPECT_THROW(PROJStringParser().createFromPROJString(
+ "+proj=longlat +axis=foo +type=crs"),
+ ParsingException);
+
+ EXPECT_THROW(PROJStringParser().createFromPROJString(
"+proj=pipeline +step +proj=longlat +ellps=GRS80 +step "
"+proj=unitconvert +xy_in=rad +xy_out=foo"),
ParsingException);
@@ -8806,20 +8804,21 @@ TEST(io, projparse_longlat_errors) {
// ---------------------------------------------------------------------------
TEST(io, projparse_projected_errors) {
- EXPECT_THROW(
- PROJStringParser().createFromPROJString("+proj=tmerc +units=foo"),
- ParsingException);
- EXPECT_THROW(
- PROJStringParser().createFromPROJString("+proj=tmerc +x_0=foo"),
- ParsingException);
- EXPECT_THROW(
- PROJStringParser().createFromPROJString("+proj=tmerc +lat_0=foo"),
- ParsingException);
- // Inconsistent pm values between geogCRS and projectedCRS
EXPECT_THROW(PROJStringParser().createFromPROJString(
- "+proj=pipeline +step +proj=longlat +ellps=WGS84 "
- "+proj=tmerc +ellps=WGS84 +lat_0=foo +pm=paris"),
+ "+proj=tmerc +units=foo +type=crs"),
+ ParsingException);
+ EXPECT_THROW(PROJStringParser().createFromPROJString(
+ "+proj=tmerc +x_0=foo +type=crs"),
ParsingException);
+ EXPECT_THROW(PROJStringParser().createFromPROJString(
+ "+proj=tmerc +lat_0=foo +type=crs"),
+ ParsingException);
+ // Inconsistent pm values between geogCRS and projectedCRS
+ EXPECT_THROW(
+ PROJStringParser().createFromPROJString(
+ "+type=crs +proj=pipeline +step +proj=longlat +ellps=WGS84 "
+ "+step +proj=tmerc +ellps=WGS84 +lat_0=0 +pm=paris"),
+ ParsingException);
}
// ---------------------------------------------------------------------------
@@ -8828,7 +8827,7 @@ TEST(io, createFromUserInput) {
auto dbContext = DatabaseContext::create();
EXPECT_THROW(createFromUserInput("foo", nullptr), ParsingException);
EXPECT_THROW(createFromUserInput("GEOGCRS", nullptr), ParsingException);
- EXPECT_THROW(createFromUserInput("+proj=unhandled", nullptr),
+ EXPECT_THROW(createFromUserInput("+proj=unhandled +type=crs", nullptr),
ParsingException);
EXPECT_THROW(createFromUserInput("EPSG:4326", nullptr), ParsingException);
EXPECT_THROW(
diff --git a/test/unit/test_operation.cpp b/test/unit/test_operation.cpp
index bdadd830..d134f086 100644
--- a/test/unit/test_operation.cpp
+++ b/test/unit/test_operation.cpp
@@ -1378,7 +1378,7 @@ TEST(operation, tmerc_south_oriented_export) {
ASSERT_TRUE(crs != nullptr);
EXPECT_EQ(crs->exportToPROJString(PROJStringFormatter::create().get()),
"+proj=tmerc +axis=wsu +lat_0=0 +lon_0=29 +k=1 +x_0=0 +y_0=0 "
- "+ellps=WGS84 +units=m +no_defs");
+ "+ellps=WGS84 +units=m +no_defs +type=crs");
}
// ---------------------------------------------------------------------------
@@ -1630,7 +1630,7 @@ TEST(operation, bonne_export) {
ASSERT_TRUE(crs != nullptr);
EXPECT_EQ(crs->exportToPROJString(PROJStringFormatter::create().get()),
"+proj=bonne +lat_1=1 +lon_0=2 +x_0=3 +y_0=4 +ellps=WGS84 "
- "+units=m +no_defs");
+ "+units=m +no_defs +type=crs");
}
// ---------------------------------------------------------------------------
@@ -2127,7 +2127,7 @@ TEST(operation, createEquidistantCylindricalSpherical) {
TEST(operation, equidistant_cylindrical_lat_0) {
auto obj = PROJStringParser().createFromPROJString(
- "+proj=eqc +ellps=sphere +lat_0=-2 +lat_ts=1 +lon_0=-10");
+ "+proj=eqc +ellps=sphere +lat_0=-2 +lat_ts=1 +lon_0=-10 +type=crs");
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
@@ -2141,7 +2141,7 @@ TEST(operation, equidistant_cylindrical_lat_0) {
.get());
EXPECT_EQ(projString,
"+proj=eqc +lat_ts=1 +lat_0=-2 +lon_0=-10 +x_0=0 +y_0=0 "
- "+ellps=sphere +units=m +no_defs");
+ "+ellps=sphere +units=m +no_defs +type=crs");
}
// ---------------------------------------------------------------------------
@@ -3073,9 +3073,10 @@ TEST(operation, webmerc_export) {
"+proj=unitconvert +xy_in=deg +xy_out=rad +step +proj=webmerc "
"+lat_0=0 +lon_0=2 +x_0=3 +y_0=4 +ellps=WGS84");
- EXPECT_EQ(projCRS->exportToPROJString(PROJStringFormatter::create().get()),
- "+proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=2 +x_0=3 "
- "+y_0=4 +k=1 +units=m +nadgrids=@null +wktext +no_defs");
+ EXPECT_EQ(
+ projCRS->exportToPROJString(PROJStringFormatter::create().get()),
+ "+proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=2 +x_0=3 "
+ "+y_0=4 +k=1 +units=m +nadgrids=@null +wktext +no_defs +type=crs");
}
// ---------------------------------------------------------------------------
@@ -3172,9 +3173,10 @@ TEST(operation, webmerc_import_from_GDAL_wkt1_EPSG_3785_deprecated) {
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
- EXPECT_EQ(crs->exportToPROJString(PROJStringFormatter::create().get()),
- "+proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 "
- "+y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defs");
+ EXPECT_EQ(
+ crs->exportToPROJString(PROJStringFormatter::create().get()),
+ "+proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 "
+ "+y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defs +type=crs");
auto convGot = crs->derivingConversion();
@@ -3237,9 +3239,10 @@ TEST(operation, webmerc_import_from_WKT2_EPSG_3785_deprecated) {
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
- EXPECT_EQ(crs->exportToPROJString(PROJStringFormatter::create().get()),
- "+proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 "
- "+y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defs");
+ EXPECT_EQ(
+ crs->exportToPROJString(PROJStringFormatter::create().get()),
+ "+proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 "
+ "+y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defs +type=crs");
EXPECT_EQ(
crs->exportToWKT(
@@ -4080,7 +4083,7 @@ TEST(operation, laborde_oblique_mercator) {
// Content of EPSG:29701 "Tananarive (Paris) / Laborde Grid"
auto projString = "+proj=labrd +lat_0=-18.9 +lon_0=44.1 +azi=18.9 "
"+k=0.9995 +x_0=400000 +y_0=800000 +ellps=intl +pm=paris "
- "+units=m +no_defs";
+ "+units=m +no_defs +type=crs";
auto obj = PROJStringParser().createFromPROJString(projString);
auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(crs != nullptr);
@@ -4113,14 +4116,11 @@ TEST(operation, PROJ_based) {
->exportToPROJString(PROJStringFormatter::create().get()),
str);
- EXPECT_THROW(SingleOperation::createPROJBased(PropertyMap(), "+inv",
- nullptr, nullptr)
+ EXPECT_THROW(SingleOperation::createPROJBased(
+ PropertyMap(), "+proj=pipeline +step +proj=pipeline",
+ nullptr, nullptr)
->exportToPROJString(PROJStringFormatter::create().get()),
FormattingException);
- EXPECT_THROW(
- SingleOperation::createPROJBased(PropertyMap(), "foo", nullptr, nullptr)
- ->exportToPROJString(PROJStringFormatter::create().get()),
- FormattingException);
}
// ---------------------------------------------------------------------------
@@ -4687,20 +4687,22 @@ TEST(operation, geogCRS_to_geogCRS_init_IGNF_to_init_IGNF_context) {
EXPECT_EQ(list[0]->nameStr(),
"NOUVELLE TRIANGULATION DE LA FRANCE (NTF) vers RGF93 (ETRS89)");
EXPECT_EQ(list[0]->exportToPROJString(PROJStringFormatter::create().get()),
- "+proj=hgridshift +grids=ntf_r93.gsb");
+ "+proj=pipeline +step +proj=unitconvert +xy_in=deg +xy_out=rad "
+ "+step +proj=hgridshift +grids=ntf_r93.gsb +step "
+ "+proj=unitconvert +xy_in=rad +xy_out=deg");
}
// ---------------------------------------------------------------------------
TEST(operation, geogCRS_to_geogCRS_3D) {
- auto geogcrs_m_obj =
- PROJStringParser().createFromPROJString("+proj=longlat +vunits=m");
+ auto geogcrs_m_obj = PROJStringParser().createFromPROJString(
+ "+proj=longlat +vunits=m +type=crs");
auto geogcrs_m = nn_dynamic_pointer_cast<CRS>(geogcrs_m_obj);
ASSERT_TRUE(geogcrs_m != nullptr);
- auto geogcrs_ft_obj =
- PROJStringParser().createFromPROJString("+proj=longlat +vunits=ft");
+ auto geogcrs_ft_obj = PROJStringParser().createFromPROJString(
+ "+proj=longlat +vunits=ft +type=crs");
auto geogcrs_ft = nn_dynamic_pointer_cast<CRS>(geogcrs_ft_obj);
ASSERT_TRUE(geogcrs_ft != nullptr);
@@ -4721,7 +4723,7 @@ TEST(operation, geogCRS_to_geogCRS_3D) {
}
auto geogcrs_m_with_pm_obj = PROJStringParser().createFromPROJString(
- "+proj=longlat +pm=paris +vunits=m");
+ "+proj=longlat +pm=paris +vunits=m +type=crs");
auto geogcrs_m_with_pm =
nn_dynamic_pointer_cast<CRS>(geogcrs_m_with_pm_obj);
ASSERT_TRUE(geogcrs_m_with_pm != nullptr);
@@ -5345,14 +5347,14 @@ TEST(operation, boundCRS_of_geogCRS_to_unrelated_geogCRS) {
// ---------------------------------------------------------------------------
TEST(operation, createOperation_boundCRS_identified_by_datum) {
- auto objSrc =
- PROJStringParser().createFromPROJString("+proj=longlat +datum=WGS84");
+ auto objSrc = PROJStringParser().createFromPROJString(
+ "+proj=longlat +datum=WGS84 +type=crs");
auto src = nn_dynamic_pointer_cast<GeographicCRS>(objSrc);
ASSERT_TRUE(src != nullptr);
auto objDest = PROJStringParser().createFromPROJString(
"+proj=utm +zone=32 +a=6378249.2 +b=6356515 "
- "+towgs84=-263.0,6.0,431.0 +no_defs");
+ "+towgs84=-263.0,6.0,431.0 +no_defs +type=crs");
auto dest = nn_dynamic_pointer_cast<BoundCRS>(objDest);
ASSERT_TRUE(dest != nullptr);
@@ -5379,12 +5381,12 @@ TEST(operation, createOperation_boundCRS_identified_by_datum) {
TEST(operation, boundCRS_of_clrk_66_geogCRS_to_nad83_geogCRS) {
auto objSrc = PROJStringParser().createFromPROJString(
- "+proj=latlong +ellps=clrk66 +nadgrids=ntv1_can.dat,conus");
+ "+proj=latlong +ellps=clrk66 +nadgrids=ntv1_can.dat,conus +type=crs");
auto src = nn_dynamic_pointer_cast<CRS>(objSrc);
ASSERT_TRUE(src != nullptr);
- auto objDest =
- PROJStringParser().createFromPROJString("+proj=latlong +datum=NAD83");
+ auto objDest = PROJStringParser().createFromPROJString(
+ "+proj=latlong +datum=NAD83 +type=crs");
auto dest = nn_dynamic_pointer_cast<CRS>(objDest);
ASSERT_TRUE(dest != nullptr);
@@ -5401,12 +5403,13 @@ TEST(operation, boundCRS_of_clrk_66_geogCRS_to_nad83_geogCRS) {
TEST(operation, boundCRS_of_clrk_66_projCRS_to_nad83_geogCRS) {
auto objSrc = PROJStringParser().createFromPROJString(
- "+proj=utm +zone=17 +ellps=clrk66 +nadgrids=ntv1_can.dat,conus");
+ "+proj=utm +zone=17 +ellps=clrk66 +nadgrids=ntv1_can.dat,conus "
+ "+type=crs");
auto src = nn_dynamic_pointer_cast<CRS>(objSrc);
ASSERT_TRUE(src != nullptr);
- auto objDest =
- PROJStringParser().createFromPROJString("+proj=latlong +datum=NAD83");
+ auto objDest = PROJStringParser().createFromPROJString(
+ "+proj=latlong +datum=NAD83 +type=crs");
auto dest = nn_dynamic_pointer_cast<CRS>(objDest);
ASSERT_TRUE(dest != nullptr);
@@ -5553,12 +5556,12 @@ TEST(operation, boundCRS_to_boundCRS_unralated_hub) {
TEST(operation, boundCRS_of_projCRS_towgs84_to_boundCRS_of_projCRS_nadgrids) {
auto objSrc = PROJStringParser().createFromPROJString(
"+proj=utm +zone=15 +datum=NAD83 +units=m +no_defs +ellps=GRS80 "
- "+towgs84=0,0,0");
+ "+towgs84=0,0,0 +type=crs");
auto src = nn_dynamic_pointer_cast<CRS>(objSrc);
ASSERT_TRUE(src != nullptr);
auto objDst = PROJStringParser().createFromPROJString(
"+proj=utm +zone=15 +datum=NAD27 +units=m +no_defs +ellps=clrk66 "
- "+nadgrids=@conus,@alaska,@ntv2_0.gsb,@ntv1_can.dat");
+ "+nadgrids=@conus,@alaska,@ntv2_0.gsb,@ntv1_can.dat +type=crs");
auto dst = nn_dynamic_pointer_cast<CRS>(objDst);
ASSERT_TRUE(dst != nullptr);
auto op = CoordinateOperationFactory::create()->createOperation(
@@ -6140,13 +6143,13 @@ TEST(operation, vertCRS_to_vertCRS) {
TEST(operation, compoundCRS_to_geogCRS_3D) {
- auto compoundcrs_ft_obj =
- PROJStringParser().createFromPROJString("+proj=merc +vunits=ft");
+ auto compoundcrs_ft_obj = PROJStringParser().createFromPROJString(
+ "+proj=merc +vunits=ft +type=crs");
auto compoundcrs_ft = nn_dynamic_pointer_cast<CRS>(compoundcrs_ft_obj);
ASSERT_TRUE(compoundcrs_ft != nullptr);
- auto geogcrs_m_obj =
- PROJStringParser().createFromPROJString("+proj=longlat +vunits=m");
+ auto geogcrs_m_obj = PROJStringParser().createFromPROJString(
+ "+proj=longlat +vunits=m +type=crs");
auto geogcrs_m = nn_dynamic_pointer_cast<CRS>(geogcrs_m_obj);
ASSERT_TRUE(geogcrs_m != nullptr);
@@ -6300,7 +6303,7 @@ TEST(operation, createOperation_on_crs_with_canonical_bound_crs) {
TEST(operation, createOperation_fallback_to_proj4_strings) {
auto objDest = PROJStringParser().createFromPROJString(
- "+proj=longlat +geoc +ellps=WGS84");
+ "+proj=longlat +geoc +ellps=WGS84 +type=crs");
auto dest = nn_dynamic_pointer_cast<GeographicCRS>(objDest);
ASSERT_TRUE(dest != nullptr);