aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Bell <andrew.bell.ia@gmail.com>2019-05-15 10:47:03 -0400
committerAndrew Bell <andrew.bell.ia@gmail.com>2019-05-15 10:47:03 -0400
commit8f268409d37cea329d263e177b83e42f8384d3c7 (patch)
treec4d0f3dd19456600f718a6e0c8573577f433549b /src
parent886ced02f0aaab5d66d16459435f7447cf976650 (diff)
parentd67203a6f76a74f5ac029ff052dbcc72e3b59624 (diff)
downloadPROJ-8f268409d37cea329d263e177b83e42f8384d3c7.tar.gz
PROJ-8f268409d37cea329d263e177b83e42f8384d3c7.zip
Merge remote-tracking branch 'origin/master'
Diffstat (limited to 'src')
-rw-r--r--src/4D_api.cpp37
-rw-r--r--src/CMakeLists.txt64
-rw-r--r--src/Makefile.am11
-rw-r--r--src/apply_gridshift.cpp4
-rw-r--r--src/apply_vgridshift.cpp80
-rw-r--r--src/apps/cct.cpp3
-rw-r--r--src/apps/cs2cs.cpp48
-rw-r--r--src/apps/emess.cpp3
-rw-r--r--src/apps/geod.cpp2
-rw-r--r--src/apps/gie.cpp104
-rw-r--r--src/apps/optargpm.h6
-rw-r--r--src/apps/proj.cpp14
-rw-r--r--src/apps/proj_strtod.cpp2
-rw-r--r--src/apps/projinfo.cpp308
-rw-r--r--src/apps/utils.cpp58
-rw-r--r--src/apps/utils.h29
-rw-r--r--src/bin_cct.cmake12
-rw-r--r--src/bin_cs2cs.cmake14
-rw-r--r--src/bin_geod.cmake16
-rw-r--r--src/bin_geodtest.cmake11
-rw-r--r--src/bin_gie.cmake14
-rw-r--r--src/bin_proj.cmake19
-rw-r--r--src/bin_projinfo.cmake13
-rw-r--r--src/conversions/axisswap.cpp1
-rw-r--r--src/conversions/cart.cpp7
-rw-r--r--src/conversions/geoc.cpp1
-rw-r--r--src/conversions/noop.cpp19
-rw-r--r--src/conversions/unitconvert.cpp25
-rw-r--r--src/ell_set.cpp35
-rw-r--r--src/factors.cpp1
-rw-r--r--src/fwd.cpp1
-rw-r--r--src/gauss.cpp16
-rw-r--r--src/general_doc.dox11
-rw-r--r--src/gridcatalog.cpp10
-rw-r--r--src/gridinfo.cpp7
-rw-r--r--src/init.cpp9
-rw-r--r--src/internal.cpp4
-rw-r--r--src/inv.cpp1
-rw-r--r--src/iso19111/c_api.cpp275
-rw-r--r--src/iso19111/common.cpp6
-rw-r--r--src/iso19111/coordinateoperation.cpp1696
-rw-r--r--src/iso19111/coordinatesystem.cpp4
-rw-r--r--src/iso19111/crs.cpp266
-rw-r--r--src/iso19111/datum.cpp14
-rw-r--r--src/iso19111/factory.cpp109
-rw-r--r--src/iso19111/internal.cpp17
-rw-r--r--src/iso19111/io.cpp407
-rw-r--r--src/iso19111/metadata.cpp2
-rw-r--r--src/iso19111/static.cpp16
-rw-r--r--src/iso19111/util.cpp2
-rw-r--r--src/jniproj.cpp2
-rw-r--r--src/lib_proj.cmake584
-rw-r--r--src/mutex.cpp8
-rw-r--r--src/nad_init.cpp4
-rw-r--r--src/nad_intr.cpp3
-rw-r--r--src/open_lib.cpp57
-rw-r--r--src/pipeline.cpp1
-rw-r--r--src/pj_list.h1
-rw-r--r--src/proj.h8
-rw-r--r--src/proj_api.h2
-rw-r--r--src/proj_internal.h13
-rw-r--r--src/proj_symbol_rename.h2
-rw-r--r--src/projections/aea.cpp14
-rw-r--r--src/projections/aeqd.cpp17
-rw-r--r--src/projections/airy.cpp8
-rw-r--r--src/projections/aitoff.cpp41
-rw-r--r--src/projections/august.cpp4
-rw-r--r--src/projections/bacon.cpp8
-rw-r--r--src/projections/bertin1953.cpp5
-rw-r--r--src/projections/bipc.cpp8
-rw-r--r--src/projections/boggs.cpp4
-rw-r--r--src/projections/bonne.cpp27
-rw-r--r--src/projections/calcofi.cpp16
-rw-r--r--src/projections/cass.cpp16
-rw-r--r--src/projections/cc.cpp8
-rw-r--r--src/projections/ccon.cpp8
-rw-r--r--src/projections/cea.cpp16
-rw-r--r--src/projections/chamb.cpp4
-rw-r--r--src/projections/collg.cpp8
-rw-r--r--src/projections/comill.cpp8
-rw-r--r--src/projections/crast.cpp8
-rw-r--r--src/projections/denoy.cpp4
-rw-r--r--src/projections/eck1.cpp8
-rw-r--r--src/projections/eck2.cpp8
-rw-r--r--src/projections/eck3.cpp8
-rw-r--r--src/projections/eck4.cpp8
-rw-r--r--src/projections/eck5.cpp8
-rw-r--r--src/projections/eqc.cpp8
-rw-r--r--src/projections/eqdc.cpp18
-rw-r--r--src/projections/eqearth.cpp10
-rw-r--r--src/projections/fahey.cpp8
-rw-r--r--src/projections/fouc_s.cpp8
-rw-r--r--src/projections/gall.cpp8
-rw-r--r--src/projections/geos.cpp21
-rw-r--r--src/projections/gins8.cpp4
-rw-r--r--src/projections/gn_sinu.cpp16
-rw-r--r--src/projections/gnom.cpp8
-rw-r--r--src/projections/goode.cpp8
-rw-r--r--src/projections/gstmerc.cpp8
-rw-r--r--src/projections/hammer.cpp17
-rw-r--r--src/projections/hatano.cpp8
-rw-r--r--src/projections/healpix.cpp11
-rw-r--r--src/projections/igh.cpp10
-rw-r--r--src/projections/imw_p.cpp24
-rw-r--r--src/projections/isea.cpp46
-rw-r--r--src/projections/krovak.cpp30
-rw-r--r--src/projections/labrd.cpp8
-rw-r--r--src/projections/laea.cpp19
-rw-r--r--src/projections/lagrng.cpp22
-rw-r--r--src/projections/larr.cpp4
-rw-r--r--src/projections/lask.cpp4
-rw-r--r--src/projections/latlong.cpp1
-rw-r--r--src/projections/lcc.cpp31
-rw-r--r--src/projections/lcca.cpp8
-rw-r--r--src/projections/loxim.cpp8
-rw-r--r--src/projections/lsat.cpp17
-rw-r--r--src/projections/mbt_fps.cpp8
-rw-r--r--src/projections/mbtfpp.cpp8
-rw-r--r--src/projections/mbtfpq.cpp8
-rw-r--r--src/projections/merc.cpp23
-rw-r--r--src/projections/mill.cpp8
-rw-r--r--src/projections/misrsom.cpp16
-rw-r--r--src/projections/mod_ster.cpp16
-rw-r--r--src/projections/moll.cpp12
-rw-r--r--src/projections/natearth.cpp8
-rw-r--r--src/projections/natearth2.cpp8
-rw-r--r--src/projections/nell.cpp8
-rw-r--r--src/projections/nell_h.cpp8
-rw-r--r--src/projections/nicol.cpp4
-rw-r--r--src/projections/nsper.cpp29
-rw-r--r--src/projections/nzmg.cpp8
-rw-r--r--src/projections/ob_tran.cpp16
-rw-r--r--src/projections/ocea.cpp47
-rw-r--r--src/projections/oea.cpp8
-rw-r--r--src/projections/omerc.cpp28
-rw-r--r--src/projections/ortho.cpp9
-rw-r--r--src/projections/patterson.cpp8
-rw-r--r--src/projections/poly.cpp16
-rw-r--r--src/projections/putp2.cpp8
-rw-r--r--src/projections/putp3.cpp12
-rw-r--r--src/projections/putp4p.cpp12
-rw-r--r--src/projections/putp5.cpp12
-rw-r--r--src/projections/putp6.cpp12
-rw-r--r--src/projections/qsc.cpp8
-rw-r--r--src/projections/robin.cpp21
-rw-r--r--src/projections/rouss.cpp8
-rw-r--r--src/projections/rpoly.cpp4
-rw-r--r--src/projections/sch.cpp10
-rw-r--r--src/projections/sconics.cpp8
-rw-r--r--src/projections/somerc.cpp8
-rw-r--r--src/projections/stere.cpp35
-rw-r--r--src/projections/sterea.cpp15
-rw-r--r--src/projections/sts.cpp8
-rw-r--r--src/projections/tcc.cpp4
-rw-r--r--src/projections/tcea.cpp8
-rw-r--r--src/projections/times.cpp8
-rw-r--r--src/projections/tmerc.cpp4
-rw-r--r--src/projections/tobmerc.cpp11
-rw-r--r--src/projections/tpeqd.cpp12
-rw-r--r--src/projections/urm5.cpp10
-rw-r--r--src/projections/urmfps.cpp8
-rw-r--r--src/projections/vandg.cpp17
-rw-r--r--src/projections/vandg2.cpp6
-rw-r--r--src/projections/vandg4.cpp4
-rw-r--r--src/projections/wag2.cpp8
-rw-r--r--src/projections/wag3.cpp8
-rw-r--r--src/projections/wag7.cpp4
-rw-r--r--src/projections/wink1.cpp8
-rw-r--r--src/projections/wink2.cpp4
-rw-r--r--src/release.cpp2
-rw-r--r--src/strerrno.cpp12
-rw-r--r--src/strtod.cpp7
-rw-r--r--src/transformations/affine.cpp1
-rw-r--r--src/transformations/deformation.cpp3
-rw-r--r--src/transformations/helmert.cpp5
-rw-r--r--src/transformations/hgridshift.cpp1
-rw-r--r--src/transformations/horner.cpp1
-rw-r--r--src/transformations/molodensky.cpp33
-rw-r--r--src/transformations/vgridshift.cpp5
-rw-r--r--src/wkt2_generated_parser.c2582
-rw-r--r--src/wkt2_generated_parser.h141
-rw-r--r--src/wkt2_grammar.y92
-rw-r--r--src/wkt2_parser.cpp2
183 files changed, 5473 insertions, 3207 deletions
diff --git a/src/4D_api.cpp b/src/4D_api.cpp
index 1b3374f3..81e16600 100644
--- a/src/4D_api.cpp
+++ b/src/4D_api.cpp
@@ -51,6 +51,7 @@
#include "proj/common.hpp"
#include "proj/coordinateoperation.hpp"
#include "proj/internal/internal.hpp"
+#include "proj/internal/io_internal.hpp"
using namespace NS_PROJ::internal;
@@ -192,6 +193,8 @@ similarly, but prefers the 2D resp. 3D interfaces if available.
direction = opposite_direction(direction);
if( !P->alternativeCoordinateOperations.empty() ) {
+ // Do a first pass and select the first coordinate operation whose area
+ // of use is compatible with the input coordinate
int i = 0;
for( const auto &alt: P->alternativeCoordinateOperations ) {
if( direction == PJ_FWD ) {
@@ -223,6 +226,35 @@ similarly, but prefers the 2D resp. 3D interfaces if available.
}
i ++;
}
+
+ // In case we did not find an operation whose area of use is compatible
+ // with the input coordinate, then goes through again the list, and
+ // use the first operation that does not require grids.
+ i = 0;
+ for( const auto &alt: P->alternativeCoordinateOperations ) {
+ auto coordOperation = dynamic_cast<
+ NS_PROJ::operation::CoordinateOperation*>(alt.pj->iso_obj.get());
+ if( coordOperation ) {
+ if( coordOperation->gridsNeeded(P->ctx->cpp_context ?
+ P->ctx->cpp_context->databaseContext.as_nullable() :
+ nullptr).empty() ) {
+ if( P->iCurCoordOp != i ) {
+ std::string msg("Using coordinate operation ");
+ msg += alt.name;
+ pj_log(P->ctx, PJ_LOG_TRACE, msg.c_str());
+ P->iCurCoordOp = i;
+ }
+ if( direction == PJ_FWD ) {
+ return pj_fwd4d( coord, alt.pj );
+ }
+ else {
+ return pj_inv4d( coord, alt.pj );
+ }
+ }
+ }
+ i++;
+ }
+
proj_errno_set (P, EINVAL);
return proj_coord_error ();
}
@@ -1102,8 +1134,8 @@ PJ *proj_create_crs_to_crs (PJ_CONTEXT *ctx, const char *source_crs, const char
double north_lat = 0.0;
const char* name = proj_get_name(op);
- if( name && (strstr(name, "Null geographic offset") ||
- strstr(name, "Null geocentric translation")) )
+ if( name && (strstr(name, "Ballpark geographic offset") ||
+ strstr(name, "Ballpark geocentric translation")) )
{
// Skip default transformations
}
@@ -1333,6 +1365,7 @@ static char *path_append (char *buf, const char *app, size_t *buf_size) {
pj_dealloc (buf);
buf = p;
}
+ assert(buf);
/* Only append a semicolon if something's already there */
if (0 != buflen)
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 122227bf..48c785a5 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -3,71 +3,77 @@
include(lib_proj.cmake)
# configure executable build
-option(BUILD_CCT "Build cct (coordinate conversion and transformation tool)" ON)
-option(BUILD_CS2CS "Build cs2cs (coordinate systems to coordinate systems translation tool)" ON)
-option(BUILD_GEOD "Build geod (computation of geodesic lines)" ON)
-option(BUILD_GIE "Build gie (geospatial integrity investigation environment - a PROJ.4 test tool)" ON)
-option(BUILD_PROJ "Build proj (cartographic projection tool : latlong <-> projected coordinates)" ON)
-option(BUILD_PROJINFO "Build projinfo (SRS and coordinate operation metadata/query tool)" ON)
+option(BUILD_CCT
+ "Build cct (coordinate conversion and transformation tool)" ON)
+option(BUILD_CS2CS
+ "Build cs2cs (coordinate systems to coordinate systems translation tool)" ON)
+option(BUILD_GEOD
+ "Build geod (computation of geodesic lines)" ON)
+option(BUILD_GIE
+ "Build gie (geospatial integrity investigation environment)" ON)
+option(BUILD_PROJ
+ "Build proj (cartographic projection tool)" ON)
+option(BUILD_PROJINFO
+ "Build projinfo (SRS and coordinate operation metadata/query tool)" ON)
if(NOT MSVC)
- if (NOT APPLE)
+ if(NOT APPLE)
# Use relative path so that package is relocatable
set(CMAKE_INSTALL_RPATH "\$ORIGIN/../${LIBDIR}")
- else ()
- set (CMAKE_INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/${LIBDIR}")
+ else()
+ set(CMAKE_INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/${LIBDIR}")
# TO DO: cmake 2.8.12 introduces a way to make the install tree
# relocatable with OSX via
# (1) set(CMAKE_MACOSX_RPATH ON) and
# (2) setting the INSTALL_RPATH property on the executables to
# "@loader_path/../${LIBDIR}"
- endif ()
+ endif()
-else ()
+else()
# Linking to setargv.obj enables wildcard globbing for the
# command line utilities, when compiling with MSVC
- # https://docs.microsoft.com/da-dk/cpp/c-language/expanding-wildcard-arguments
+ # https://docs.microsoft.com/cpp/c-language/expanding-wildcard-arguments
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} setargv.obj")
-endif ()
+endif()
if(BUILD_CCT)
- include(bin_cct.cmake)
- set(BIN_TARGETS ${BIN_TARGETS} cct)
-endif(BUILD_CCT)
+ include(bin_cct.cmake)
+ set(BIN_TARGETS ${BIN_TARGETS} cct)
+endif()
if(BUILD_CS2CS)
- include(bin_cs2cs.cmake)
- set(BIN_TARGETS ${BIN_TARGETS} cs2cs)
-endif(BUILD_CS2CS)
+ include(bin_cs2cs.cmake)
+ set(BIN_TARGETS ${BIN_TARGETS} cs2cs)
+endif()
if(BUILD_GEOD)
include(bin_geod.cmake)
include(bin_geodtest.cmake)
set(BIN_TARGETS ${BIN_TARGETS} geod)
-endif(BUILD_GEOD)
+endif()
if(BUILD_PROJ)
include(bin_proj.cmake)
set(BIN_TARGETS ${BIN_TARGETS} binproj)
-endif(BUILD_PROJ)
+endif()
if(BUILD_PROJINFO)
include(bin_projinfo.cmake)
set(BIN_TARGETS ${BIN_TARGETS} binprojinfo)
-endif(BUILD_PROJINFO)
+endif()
if(BUILD_GIE)
- include(bin_gie.cmake)
- set(BIN_TARGETS ${BIN_TARGETS} gie)
-endif(BUILD_GIE)
+ include(bin_gie.cmake)
+ set(BIN_TARGETS ${BIN_TARGETS} gie)
+endif()
-if (MSVC OR CMAKE_CONFIGURATION_TYPES)
+if(MSVC OR CMAKE_CONFIGURATION_TYPES)
if(BIN_TARGETS)
# Add _d suffix for your debug versions of the tools
- set_target_properties (${BIN_TARGETS} PROPERTIES
+ set_target_properties(${BIN_TARGETS} PROPERTIES
DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})
- endif(BIN_TARGETS)
-endif ()
+ endif()
+endif()
diff --git a/src/Makefile.am b/src/Makefile.am
index b62a11b0..aed5a393 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -8,7 +8,7 @@ check_PROGRAMS = geodtest
AM_CPPFLAGS = -DPROJ_LIB=\"$(pkgdatadir)\" \
-DMUTEX_@MUTEX_SETTING@ @JNI_INCLUDE@ -I$(top_srcdir)/include @SQLITE3_CFLAGS@
-AM_CXXFLAGS = @CXX_WFLAGS@ @FLTO_FLAG@ -DPROJ_COMPILATION
+AM_CXXFLAGS = @CXX_WFLAGS@ @FLTO_FLAG@
include_HEADERS = proj.h proj_experimental.h proj_constants.h proj_api.h geodesic.h \
org_proj4_PJ.h proj_symbol_rename.h
@@ -16,11 +16,11 @@ include_HEADERS = proj.h proj_experimental.h proj_constants.h proj_api.h geodesi
EXTRA_DIST = bin_cct.cmake bin_gie.cmake bin_cs2cs.cmake \
bin_geod.cmake bin_proj.cmake bin_projinfo.cmake \
lib_proj.cmake CMakeLists.txt bin_geodtest.cmake tests/geodtest.cpp \
- wkt1_grammar.y wkt2_grammar.y apps/emess.h
+ wkt1_grammar.y wkt2_grammar.y apps/emess.h apps/utils.h
-proj_SOURCES = apps/proj.cpp apps/emess.cpp
+proj_SOURCES = apps/proj.cpp apps/emess.cpp apps/utils.cpp
projinfo_SOURCES = apps/projinfo.cpp
-cs2cs_SOURCES = apps/cs2cs.cpp apps/emess.cpp
+cs2cs_SOURCES = apps/cs2cs.cpp apps/emess.cpp apps/utils.cpp
cct_SOURCES = apps/cct.cpp apps/proj_strtod.cpp apps/proj_strtod.h apps/optargpm.h
geod_SOURCES = apps/geod.cpp apps/geod_set.cpp apps/geod_interface.cpp apps/geod_interface.h apps/emess.cpp
@@ -42,7 +42,7 @@ geodtest_LDADD = libproj.la
lib_LTLIBRARIES = libproj.la
-libproj_la_LDFLAGS = -no-undefined -version-info 15:0:0
+libproj_la_LDFLAGS = -no-undefined -version-info 16:0:1
libproj_la_LIBADD = @SQLITE3_LIBS@
libproj_la_SOURCES = \
@@ -173,6 +173,7 @@ libproj_la_SOURCES = \
conversions/cart.cpp \
conversions/geoc.cpp \
conversions/geocent.cpp \
+ conversions/noop.cpp \
conversions/unitconvert.cpp \
\
transformations/affine.cpp \
diff --git a/src/apply_gridshift.cpp b/src/apply_gridshift.cpp
index c7070432..fcd9fa01 100644
--- a/src/apply_gridshift.cpp
+++ b/src/apply_gridshift.cpp
@@ -34,7 +34,6 @@
#include <stdio.h>
#include <string.h>
-#include "proj_internal.h"
#include "proj.h"
#include "proj_internal.h"
@@ -59,7 +58,10 @@ int pj_apply_gridshift( projCtx ctx, const char *nadgrids, int inverse,
gridlist = pj_gridlist_from_nadgrids( ctx, nadgrids, &grid_count );
if( gridlist == nullptr || grid_count == 0 )
+ {
+ pj_dalloc( gridlist );
return ctx->last_errno;
+ }
ret = pj_apply_gridshift_3( ctx, gridlist, grid_count, inverse,
point_count, point_offset, x, y, z );
diff --git a/src/apply_vgridshift.cpp b/src/apply_vgridshift.cpp
index 61e0c528..377e36e0 100644
--- a/src/apply_vgridshift.cpp
+++ b/src/apply_vgridshift.cpp
@@ -28,23 +28,23 @@
#define PJ_LIB__
+#include <assert.h>
#include <stdio.h>
#include <string.h>
#include "proj_math.h"
#include "proj_internal.h"
-#include "proj_internal.h"
-static int is_nodata(float value)
+static int is_nodata(float value, double vmultiplier)
{
/* nodata? */
/* GTX official nodata value if -88.88880f, but some grids also */
/* use other big values for nodata (e.g naptrans2008.gtx has */
/* nodata values like -2147479936), so test them too */
- return value > 1000 || value < -1000 || value == -88.88880f;
+ return value * vmultiplier > 1000 || value * vmultiplier < -1000 || value == -88.88880f;
}
-static double read_vgrid_value( PJ *defn, PJ_LP input, int *gridlist_count_p, PJ_GRIDINFO **tables, struct CTABLE *ct) {
+static double read_vgrid_value( PJ *defn, PJ_LP input, double vmultiplier, int *gridlist_count_p, PJ_GRIDINFO **tables, struct CTABLE *ct) {
int itable = 0;
double value = HUGE_VAL;
double grid_x, grid_y;
@@ -63,9 +63,19 @@ static double read_vgrid_value( PJ *defn, PJ_LP input, int *gridlist_count_p, PJ
ct = gi->ct;
- /* skip tables that don't match our point at all. */
- if( ct->ll.phi > input.phi || ct->ll.lam > input.lam
- || ct->ll.phi + (ct->lim.phi-1) * ct->del.phi < input.phi
+ /* skip tables that don't match our point at all (latitude check). */
+ if( ct->ll.phi > input.phi
+ || ct->ll.phi + (ct->lim.phi-1) * ct->del.phi < input.phi )
+ continue;
+
+ bool fullWorldLongExtent = false;
+ if( fabs(ct->lim.lam * ct->del.lam - 2 * M_PI) < 1e-10 )
+ {
+ fullWorldLongExtent = true;
+ }
+
+ /* skip tables that don't match our point at all (longitude check). */
+ else if( ct->ll.lam > input.lam
|| ct->ll.lam + (ct->lim.lam-1) * ct->del.lam < input.lam )
continue;
@@ -78,8 +88,17 @@ static double read_vgrid_value( PJ *defn, PJ_LP input, int *gridlist_count_p, PJ
{
struct CTABLE *ct1 = child->ct;
- if( ct1->ll.phi > input.phi || ct1->ll.lam > input.lam
- || ct1->ll.phi+(ct1->lim.phi-1)*ct1->del.phi < input.phi
+ fullWorldLongExtent = false;
+
+ if( ct1->ll.phi > input.phi
+ || ct1->ll.phi+(ct1->lim.phi-1)*ct1->del.phi < input.phi)
+ continue;
+
+ if( fabs(ct1->lim.lam * ct1->del.lam - 2 * M_PI) < 1e-10 )
+ {
+ fullWorldLongExtent = true;
+ }
+ else if( ct1->ll.lam > input.lam
|| ct1->ll.lam+(ct1->lim.lam-1)*ct1->del.lam < input.lam)
continue;
@@ -98,24 +117,41 @@ static double read_vgrid_value( PJ *defn, PJ_LP input, int *gridlist_count_p, PJ
}
/* load the grid shift info if we don't have it. */
- if( ct->cvs == nullptr && !pj_gridinfo_load( pj_get_ctx(defn), gi ) )
+ if( ct->cvs == nullptr )
{
- pj_ctx_set_errno( defn->ctx, PJD_ERR_FAILED_TO_LOAD_GRID );
- return PJD_ERR_FAILED_TO_LOAD_GRID;
+ if( !pj_gridinfo_load( pj_get_ctx(defn), gi ) || ct->cvs == nullptr )
+ {
+ pj_ctx_set_errno( defn->ctx, PJD_ERR_FAILED_TO_LOAD_GRID );
+ return PJD_ERR_FAILED_TO_LOAD_GRID;
+ }
}
/* Interpolation a location within the grid */
grid_x = (input.lam - ct->ll.lam) / ct->del.lam;
+ if( fullWorldLongExtent ) {
+ // The first fmod goes to ]-lim, lim[ range
+ // So we add lim again to be in ]0, 2*lim[ and fmod again
+ grid_x = fmod(
+ fmod(grid_x + ct->lim.lam, ct->lim.lam) + ct->lim.lam,
+ ct->lim.lam);
+ }
grid_y = (input.phi - ct->ll.phi) / ct->del.phi;
grid_ix = lround(floor(grid_x));
+ assert(grid_ix >= 0 && grid_ix < ct->lim.lam);
grid_iy = lround(floor(grid_y));
+ assert(grid_iy >= 0 && grid_iy < ct->lim.phi);
grid_x -= grid_ix;
grid_y -= grid_iy;
grid_ix2 = grid_ix + 1;
- if( grid_ix2 >= ct->lim.lam )
- grid_ix2 = ct->lim.lam - 1;
+ if( grid_ix2 >= ct->lim.lam ) {
+ if( fullWorldLongExtent ) {
+ grid_ix2 = 0;
+ } else {
+ grid_ix2 = ct->lim.lam - 1;
+ }
+ }
grid_iy2 = grid_iy + 1;
if( grid_iy2 >= ct->lim.phi )
grid_iy2 = ct->lim.phi - 1;
@@ -129,28 +165,28 @@ static double read_vgrid_value( PJ *defn, PJ_LP input, int *gridlist_count_p, PJ
double total_weight = 0.0;
int n_weights = 0;
value = 0.0f;
- if( !is_nodata(value_a) )
+ if( !is_nodata(value_a, vmultiplier) )
{
double weight = (1.0-grid_x) * (1.0-grid_y);
value += value_a * weight;
total_weight += weight;
n_weights ++;
}
- if( !is_nodata(value_b) )
+ if( !is_nodata(value_b, vmultiplier) )
{
double weight = (grid_x) * (1.0-grid_y);
value += value_b * weight;
total_weight += weight;
n_weights ++;
}
- if( !is_nodata(value_c) )
+ if( !is_nodata(value_c, vmultiplier) )
{
double weight = (1.0-grid_x) * (grid_y);
value += value_c * weight;
total_weight += weight;
n_weights ++;
}
- if( !is_nodata(value_d) )
+ if( !is_nodata(value_d, vmultiplier) )
{
double weight = (grid_x) * (grid_y);
value += value_d * weight;
@@ -165,7 +201,7 @@ static double read_vgrid_value( PJ *defn, PJ_LP input, int *gridlist_count_p, PJ
}
- return value;
+ return value * vmultiplier;
}
/************************************************************************/
@@ -218,7 +254,7 @@ int pj_apply_vgridshift( PJ *defn, const char *listname,
input.phi = y[io];
input.lam = x[io];
- value = read_vgrid_value(defn, input, gridlist_count_p, tables, &ct);
+ value = read_vgrid_value(defn, input, 1.0, gridlist_count_p, tables, &ct);
if( inverse )
z[io] -= value;
@@ -310,7 +346,7 @@ int proj_vgrid_init(PJ* P, const char *grids) {
}
/***********************************************/
-double proj_vgrid_value(PJ *P, PJ_LP lp){
+double proj_vgrid_value(PJ *P, PJ_LP lp, double vmultiplier){
/***********************************************
Read grid value at position lp in grids loaded
@@ -324,7 +360,7 @@ double proj_vgrid_value(PJ *P, PJ_LP lp){
double value;
memset(&used_grid, 0, sizeof(struct CTABLE));
- value = read_vgrid_value(P, lp, &(P->vgridlist_geoid_count), P->vgridlist_geoid, &used_grid);
+ value = read_vgrid_value(P, lp, vmultiplier, &(P->vgridlist_geoid_count), P->vgridlist_geoid, &used_grid);
proj_log_trace(P, "proj_vgrid_value: (%f, %f) = %f", lp.lam*RAD_TO_DEG, lp.phi*RAD_TO_DEG, value);
return value;
diff --git a/src/apps/cct.cpp b/src/apps/cct.cpp
index 34bf0777..d29b58fb 100644
--- a/src/apps/cct.cpp
+++ b/src/apps/cct.cpp
@@ -81,7 +81,6 @@ Thomas Knudsen, thokn@sdfe.dk, 2016-05-25/2017-10-26
#include "proj.h"
#include "proj_internal.h"
#include "proj_strtod.h"
-#include "proj_internal.h"
#include "optargpm.h"
@@ -228,6 +227,7 @@ int main(int argc, char **argv) {
fout = stdout;
+ /* coverity[tainted_data] */
o = opt_parse (argc, argv, "hvI", "cdozts", longflags, longkeys);
if (nullptr==o)
return 0;
@@ -368,6 +368,7 @@ int main(int argc, char **argv) {
point.lpzt.phi = proj_torad (point.lpzt.phi);
}
err = proj_errno_reset (P);
+ /* coverity[returned_value] */
point = proj_trans (P, direction, point);
if (HUGE_VAL==point.xyzt.x) {
diff --git a/src/apps/cs2cs.cpp b/src/apps/cs2cs.cpp
index 150548c5..20e5e73c 100644
--- a/src/apps/cs2cs.cpp
+++ b/src/apps/cs2cs.cpp
@@ -45,6 +45,7 @@
#include "proj.h"
#include "proj_internal.h"
#include "emess.h"
+#include "utils.h"
// clang-format on
#define MAX_LINE 1000
@@ -68,8 +69,8 @@ static const char *oform =
static char oform_buffer[16]; /* buffer for oform when using -d */
static const char *oterr = "*\t*"; /* output line for unprojectable input */
static const char *usage =
- "%s\nusage: %s [ -dDeEfIlrstvwW [args] ] [ +opts[=arg] ]\n"
- " [+to [+opts[=arg] [ files ]\n";
+ "%s\nusage: %s [-dDeEfIlrstvwW [args]] [+opt[=arg] ...]\n"
+ " [+to +opt[=arg] ...] [file ...]\n";
static double (*informat)(const char *,
char **); /* input data deformatter function */
@@ -113,6 +114,19 @@ static void process(FILE *fid)
z = strtod(s, &s);
+ /* To avoid breaking existing tests, we read what is a possible t */
+ /* component of the input and rewind the s-pointer so that the final */
+ /* output has consistant behaviour, with or without t values. */
+ /* This is a bit of a hack, in most cases 4D coordinates will be */
+ /* written to STDOUT (except when using -E) but the output format */
+ /* speficied with -f is not respected for the t component, rather it */
+ /* is forward verbatim from the input. */
+ char *before_time = s;
+ double t = strtod(s, &s);
+ if( s == before_time )
+ t = HUGE_VAL;
+ s = before_time;
+
if (data.v == HUGE_VAL)
data.u = HUGE_VAL;
@@ -120,11 +134,11 @@ static void process(FILE *fid)
--s; /* assumed we gobbled \n */
if (echoin) {
- char t;
- t = *s;
+ char temp;
+ temp = *s;
*s = '\0';
(void)fputs(line, stdout);
- *s = t;
+ *s = temp;
putchar('\t');
}
@@ -141,7 +155,7 @@ static void process(FILE *fid)
coord.xyzt.x = data.u;
coord.xyzt.y = data.v;
coord.xyzt.z = z;
- coord.xyzt.t = HUGE_VAL;
+ coord.xyzt.t = t;
coord = proj_trans(transformation, PJ_FWD, coord);
data.u = coord.xyz.x;
data.v = coord.xyz.y;
@@ -206,10 +220,10 @@ static void process(FILE *fid)
}
/************************************************************************/
-/* instanciate_crs() */
+/* instantiate_crs() */
/************************************************************************/
-static PJ *instanciate_crs(const std::string &definition,
+static PJ *instantiate_crs(const std::string &definition,
bool &isGeog, double &toRadians,
bool &isLatFirst) {
PJ *crs = proj_create(nullptr,
@@ -263,13 +277,6 @@ static std::string get_geog_crs_proj_string_from_proj_crs(PJ *src,
double &toRadians,
bool &isLatFirst) {
auto srcType = proj_get_type(src);
- if (srcType == PJ_TYPE_BOUND_CRS) {
- auto base = proj_get_source_crs(nullptr, src);
- assert(base);
- proj_destroy(src);
- src = base;
- srcType = proj_get_type(src);
- }
if (srcType != PJ_TYPE_PROJECTED_CRS) {
return std::string();
}
@@ -518,6 +525,13 @@ int main(int argc, char **argv) {
if (eargc == 0) /* if no specific files force sysin */
eargv[eargc++] = const_cast<char *>("-");
+ if( oform ) {
+ if( !validate_form_string_for_numbers(oform) ) {
+ emess(3, "invalid format string");
+ exit(0);
+ }
+ }
+
/*
* If the user has requested inverse, then just reverse the
* coordinate systems.
@@ -541,7 +555,7 @@ int main(int argc, char **argv) {
PJ *src = nullptr;
if (!fromStr.empty()) {
bool ignored;
- src = instanciate_crs(fromStr, srcIsGeog,
+ src = instantiate_crs(fromStr, srcIsGeog,
srcToRadians, ignored);
if (!src) {
emess(3, "cannot instantiate source coordinate system");
@@ -550,7 +564,7 @@ int main(int argc, char **argv) {
PJ *dst = nullptr;
if (!toStr.empty()) {
- dst = instanciate_crs(toStr, destIsGeog,
+ dst = instantiate_crs(toStr, destIsGeog,
destToRadians, destIsLatLong);
if (!dst) {
emess(3, "cannot instantiate target coordinate system");
diff --git a/src/apps/emess.cpp b/src/apps/emess.cpp
index 144e9e23..53018ba8 100644
--- a/src/apps/emess.cpp
+++ b/src/apps/emess.cpp
@@ -20,6 +20,7 @@
#include <string.h>
#include "proj_api.h"
+#include "proj_config.h"
#define EMESS_ROUTINE
#include "emess.h"
@@ -29,7 +30,7 @@ emess(int code, const char *fmt, ...) {
va_start(args, fmt);
/* prefix program name, if given */
- if (fmt != nullptr)
+ if (emess_dat.Prog_name != nullptr)
(void)fprintf(stderr,"%s\n<%s>: ",pj_get_release(),
emess_dat.Prog_name);
/* print file name and line, if given */
diff --git a/src/apps/geod.cpp b/src/apps/geod.cpp
index 7225856e..b46188d3 100644
--- a/src/apps/geod.cpp
+++ b/src/apps/geod.cpp
@@ -22,7 +22,7 @@ static const char *osform = "%.3f"; /* output format for S */
static char pline[50]; /* work string */
static const char *usage =
-"%s\nusage: %s [ -afFIlptwW [args] ] [ +opts[=arg] ] [ files ]\n";
+"%s\nusage: %s [-afFIlptwW [args]] [+opt[=arg] ...] [file ...]\n";
static void
printLL(double p, double l) {
diff --git a/src/apps/gie.cpp b/src/apps/gie.cpp
index abed11c0..2f401984 100644
--- a/src/apps/gie.cpp
+++ b/src/apps/gie.cpp
@@ -117,7 +117,6 @@ Thomas Knudsen, thokn@sdfe.dk, 2017-10-01/2017-10-08
#include "proj_internal.h"
#include "proj_math.h"
#include "proj_strtod.h"
-#include "proj_internal.h"
#include "optargpm.h"
@@ -148,7 +147,7 @@ static ffio *ffio_destroy (ffio *G);
static ffio *ffio_create (const char **tags, size_t n_tags, size_t max_record_size);
static const char *gie_tags[] = {
- "<gie>", "operation", "use_proj4_init_rules",
+ "<gie>", "operation", "crs_src", "crs_dst", "use_proj4_init_rules",
"accept", "expect", "roundtrip", "banner", "verbose",
"direction", "tolerance", "ignore", "require_grid", "echo", "skip", "</gie>"
};
@@ -175,6 +174,8 @@ static const char *err_const_from_errno (int err);
typedef struct {
char operation[MAX_OPERATION+1];
+ char crs_dst[MAX_OPERATION+1];
+ char crs_src[MAX_OPERATION+1];
PJ *P;
PJ_COORD a, b, c, e;
PJ_DIRECTION dir;
@@ -247,6 +248,7 @@ int main (int argc, char **argv) {
T.ignore = 5555; /* Error code that will not be issued by proj_create() */
T.use_proj4_init_rules = FALSE;
+ /* coverity[tainted_data] */
o = opt_parse (argc, argv, "hlvq", "o", longflags, longkeys);
if (nullptr==o)
return 0;
@@ -300,6 +302,20 @@ int main (int argc, char **argv) {
return 1;
}
+ for (i = 0; i < o->fargc; i++ ) {
+ FILE* f = fopen (o->fargv[i], "rt");
+ if (f == nullptr) {
+ fprintf (
+ T.fout,
+ "%sCannot open specified input file '%s' - bye!\n",
+ delim,
+ o->fargv[i]
+ );
+ return 1;
+ }
+ fclose(f);
+ }
+
for (i = 0; i < o->fargc; i++)
process_file (o->fargv[i]);
@@ -370,8 +386,6 @@ static int another_failing_roundtrip (void) {
}
static int process_file (const char *fname) {
- FILE *f;
-
F->lineno = F->next_lineno = F->level = 0;
T.op_ok = T.total_ok = 0;
T.op_ko = T.total_ko = 0;
@@ -383,15 +397,8 @@ static int process_file (const char *fname) {
return 0;
}
- f = fopen (fname, "rt");
- if (nullptr==f) {
- if (T.verbosity > 0) {
- fprintf (T.fout, "%sCannot open spec'd input file '%s' - bye!\n", delim, fname);
- return 2;
- }
- errmsg (2, "Cannot open spec'd input file '%s' - bye!\n", fname);
- }
- F->f = f;
+ /* We have already tested in main that the file exists */
+ F->f = fopen (fname, "rt");
if (T.verbosity > 0)
fprintf (T.fout, "%sReading file '%s'\n", delim, fname);
@@ -405,7 +412,7 @@ static int process_file (const char *fname) {
}
}
- fclose (f);
+ fclose (F->f);
F->lineno = F->next_lineno = 0;
T.grand_ok += T.total_ok;
@@ -602,6 +609,65 @@ either a conversion or a transformation)
return 0;
}
+static int crs_to_crs_operation() {
+ T.op_id++;
+ T.operation_lineno = F->lineno;
+
+ if (T.verbosity > 1) {
+ char buffer[80];
+ finish_previous_operation (F->args);
+ snprintf(buffer, 80, "%-36.36s -> %-36.36s", T.crs_src, T.crs_dst);
+ banner (buffer);
+ }
+
+ T.op_ok = 0;
+ T.op_ko = 0;
+ T.op_skip = 0;
+ T.skip_test = 0;
+
+ direction ("forward");
+ tolerance ("0.5 mm");
+ ignore ("pjd_err_dont_skip");
+
+ proj_errno_reset (T.P);
+
+ if (T.P)
+ proj_destroy (T.P);
+ proj_errno_reset (nullptr);
+ proj_context_use_proj4_init_rules(nullptr, T.use_proj4_init_rules);
+
+
+ T.P = proj_create_crs_to_crs(nullptr, T.crs_src, T.crs_dst, nullptr);
+
+ strcpy(T.crs_src, "");
+ strcpy(T.crs_dst, "");
+ return 0;
+}
+
+static int crs_src(const char *args) {
+ strncpy (&(T.crs_src[0]), F->args, MAX_OPERATION);
+ T.crs_src[MAX_OPERATION] = '\0';
+ (void) args;
+
+ if (strcmp(T.crs_src, "") != 0 && strcmp(T.crs_dst, "") != 0) {
+ crs_to_crs_operation();
+ }
+
+ return 0;
+}
+
+static int crs_dst(const char *args) {
+ strncpy (&(T.crs_dst[0]), F->args, MAX_OPERATION);
+ T.crs_dst[MAX_OPERATION] = '\0';
+ (void) args;
+
+ if (strcmp(T.crs_src, "") != 0 && strcmp(T.crs_dst, "") != 0) {
+ crs_to_crs_operation();
+ }
+
+ return 0;
+}
+
static PJ_COORD torad_coord (PJ *P, PJ_DIRECTION dir, PJ_COORD a) {
size_t i, n;
const char *axis = "enut";
@@ -939,7 +1005,8 @@ Tell GIE what to expect, when transforming the ACCEPTed input
else
d = proj_xyz_dist (co, ce);
- if (d > T.tolerance)
+ // Test written like that to handle NaN
+ if (!(d <= T.tolerance))
return expect_message (d, args);
succs++;
@@ -995,6 +1062,8 @@ static int dispatch (const char *cmnd, const char *args) {
if (T.skip)
return SKIP;
if (0==strcmp (cmnd, "operation")) return operation ((char *) args);
+ if (0==strcmp (cmnd, "crs_src")) return crs_src (args);
+ if (0==strcmp (cmnd, "crs_dst")) return crs_dst (args);
if (T.skip_test)
{
if (0==strcmp (cmnd, "expect")) return another_skip();
@@ -1028,7 +1097,7 @@ static const struct errno_vs_err_const lookup[] = {
{"pjd_err_no_colon_in_init_string" , -3},
{"pjd_err_proj_not_named" , -4},
{"pjd_err_unknown_projection_id" , -5},
- {"pjd_err_eccentricity_is_one" , -6},
+ {"pjd_err_invalid_eccentricity" , -6},
{"pjd_err_unknown_unit_id" , -7},
{"pjd_err_invalid_boolean_param" , -8},
{"pjd_err_unknown_ellp_param" , -9},
@@ -1052,7 +1121,7 @@ static const struct errno_vs_err_const lookup[] = {
{"pjd_err_w_or_m_zero_or_less" , -27},
{"pjd_err_lsat_not_in_range" , -28},
{"pjd_err_path_not_in_range" , -29},
- {"pjd_err_h_less_than_zero" , -30},
+ {"pjd_err_invalid_h" , -30},
{"pjd_err_k_less_than_zero" , -31},
{"pjd_err_lat_1_or_2_zero_or_90" , -32},
{"pjd_err_lat_0_or_alpha_eq_90" , -33},
@@ -1083,6 +1152,7 @@ static const struct errno_vs_err_const lookup[] = {
{"pjd_err_invalid_arg" , -58},
{"pjd_err_inconsistent_unit" , -59},
{"pjd_err_mutually_exclusive_args" , -60},
+ {"pjd_err_generic_error" , -61},
{"pjd_err_dont_skip" , 5555},
{"pjd_err_unknown" , 9999},
{"pjd_err_enomem" , ENOMEM},
diff --git a/src/apps/optargpm.h b/src/apps/optargpm.h
index 035c6f92..f293ad98 100644
--- a/src/apps/optargpm.h
+++ b/src/apps/optargpm.h
@@ -526,6 +526,7 @@ OPTARGS *opt_parse (int argc, char **argv, const char *flags, const char *keys,
c = opt_ordinal (o, crepr);
if (0==c) {
fprintf (stderr, "Invalid option \"%s\"\n", crepr);
+ free (o);
return nullptr;
}
@@ -534,6 +535,7 @@ OPTARGS *opt_parse (int argc, char **argv, const char *flags, const char *keys,
*equals = '=';
if (opt_is_flag (o, c)) {
fprintf (stderr, "Option \"%s\" takes no arguments\n", crepr);
+ free (o);
return nullptr;
}
o->optarg[c] = equals + 1;
@@ -544,6 +546,7 @@ OPTARGS *opt_parse (int argc, char **argv, const char *flags, const char *keys,
if (!opt_is_flag (o, c)) {
if ((argc==i + 1) || ('+'==argv[i+1][0]) || ('-'==argv[i+1][0])) {
fprintf (stderr, "Missing argument for option \"%s\"\n", crepr);
+ free (o);
return nullptr;
}
o->optarg[c] = argv[i + 1];
@@ -553,6 +556,7 @@ OPTARGS *opt_parse (int argc, char **argv, const char *flags, const char *keys,
if (!opt_is_flag (o, c)) {
fprintf (stderr, "Expected flag style long option here, but got \"%s\"\n", crepr);
+ free (o);
return nullptr;
}
@@ -564,6 +568,7 @@ OPTARGS *opt_parse (int argc, char **argv, const char *flags, const char *keys,
/* classic short options */
if (nullptr==o->optarg[c]) {
fprintf (stderr, "Invalid option \"%s\"\n", crepr);
+ free (o);
return nullptr;
}
@@ -580,6 +585,7 @@ OPTARGS *opt_parse (int argc, char **argv, const char *flags, const char *keys,
if ((argc==i + 1) || ('+'==argv[i+1][0]) || ('-'==argv[i+1][0]))
{
fprintf (stderr, "Bad or missing arg for option \"%s\"\n", crepr);
+ free (o);
return nullptr;
}
o->optarg[(int) c] = argv[i + 1];
diff --git a/src/apps/proj.cpp b/src/apps/proj.cpp
index 298a44e8..888d723f 100644
--- a/src/apps/proj.cpp
+++ b/src/apps/proj.cpp
@@ -7,6 +7,7 @@
#include <string.h>
#include <math.h>
#include "emess.h"
+#include "utils.h"
#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__WIN32__)
# include <fcntl.h>
@@ -22,7 +23,6 @@
static PJ *Proj;
static union {
- PJ_UV (*generic)(PJ_UV, PJ *);
PJ_XY (*fwd)(PJ_LP, PJ *);
PJ_LP (*inv)(PJ_XY, PJ *);
} proj;
@@ -46,7 +46,7 @@ static char oform_buffer[16]; /* Buffer for oform when using -d */
static const char
*oterr = "*\t*", /* output line for unprojectable input */
- *usage = "%s\nusage: %s [ -bdeEfiIlmorsStTvVwW [args] ] [ +opts[=arg] ] [ files ]\n";
+ *usage = "%s\nusage: %s [-bdeEfiIlmorsStTvVwW [args]] [+opt[=arg] ...] [file ...]\n";
static PJ_FACTORS facs;
@@ -462,6 +462,13 @@ int main(int argc, char **argv) {
if (eargc == 0) /* if no specific files force sysin */
eargv[eargc++] = const_cast<char*>("-");
+ if( oform ) {
+ if( !validate_form_string_for_numbers(oform) ) {
+ emess(3, "invalid format string");
+ exit(0);
+ }
+ }
+
/* done with parameter and control input */
if (inverse && postscale) {
prescale = 1;
@@ -488,7 +495,6 @@ int main(int argc, char **argv) {
proj.inv = pj_inv;
} else
proj.fwd = pj_fwd;
-
/* set input formatting control */
if (mon) {
pj_pr_list(Proj);
@@ -533,7 +539,7 @@ int main(int argc, char **argv) {
} else {
if ((fid = fopen(*eargv, "rb")) == nullptr) {
- emess(-2, *eargv, "input file");
+ emess(-2, "input file: %s", *eargv);
continue;
}
emess_dat.File_name = *eargv;
diff --git a/src/apps/proj_strtod.cpp b/src/apps/proj_strtod.cpp
index b8edc6a3..d4674705 100644
--- a/src/apps/proj_strtod.cpp
+++ b/src/apps/proj_strtod.cpp
@@ -309,7 +309,7 @@ double proj_strtod(const char *str, char **endptr) {
number = exponent < 0? number / ex: number * ex;
}
else
- number *= pow (10, exponent);
+ number *= pow (10.0, static_cast<double>(exponent));
return number;
}
diff --git a/src/apps/projinfo.cpp b/src/apps/projinfo.cpp
index 9f908c8a..9d724522 100644
--- a/src/apps/projinfo.cpp
+++ b/src/apps/projinfo.cpp
@@ -77,7 +77,8 @@ struct OutputOptions {
static void usage() {
std::cerr
- << "usage: projinfo [-o formats] [-k crs|operation] [--summary] [-q]"
+ << "usage: projinfo [-o formats] [-k crs|operation|ellipsoid] "
+ "[--summary] [-q]"
<< std::endl
<< " ([--area name_or_code] | "
"[--bbox west_long,south_lat,east_long,north_lat]) "
@@ -136,11 +137,12 @@ static std::string c_ify_string(const std::string &str) {
// ---------------------------------------------------------------------------
-static BaseObjectNNPtr buildObject(DatabaseContextPtr dbContext,
- const std::string &user_string,
- bool kindIsCRS, const std::string &context,
- bool buildBoundCRSToWGS84, CoordinateOperationContext::IntermediateCRSUse allowUseIntermediateCRS,
- bool quiet) {
+static BaseObjectNNPtr buildObject(
+ DatabaseContextPtr dbContext, const std::string &user_string,
+ const std::string &kind, const std::string &context,
+ bool buildBoundCRSToWGS84,
+ CoordinateOperationContext::IntermediateCRSUse allowUseIntermediateCRS,
+ bool quiet) {
BaseObjectPtr obj;
std::string l_user_string(user_string);
@@ -174,10 +176,13 @@ static BaseObjectNNPtr buildObject(DatabaseContextPtr dbContext,
try {
auto tokens = split(l_user_string, ':');
- if (!kindIsCRS && tokens.size() == 2) {
+ if (kind == "operation" && tokens.size() == 2) {
auto urn = "urn:ogc:def:coordinateOperation:" + tokens[0] + "::" +
tokens[1];
obj = createFromUserInput(urn, dbContext).as_nullable();
+ } else if (kind == "ellipsoid" && tokens.size() == 2) {
+ auto urn = "urn:ogc:def:ellipsoid:" + tokens[0] + "::" + tokens[1];
+ obj = createFromUserInput(urn, dbContext).as_nullable();
} else {
// Convenience to be able to use C escaped strings...
if (l_user_string.size() > 2 && l_user_string[0] == '"' &&
@@ -213,7 +218,8 @@ static BaseObjectNNPtr buildObject(DatabaseContextPtr dbContext,
if (buildBoundCRSToWGS84) {
auto crs = std::dynamic_pointer_cast<CRS>(obj);
if (crs) {
- obj = crs->createBoundCRSToWGS84IfPossible(dbContext, allowUseIntermediateCRS)
+ obj = crs->createBoundCRSToWGS84IfPossible(dbContext,
+ allowUseIntermediateCRS)
.as_nullable();
}
}
@@ -223,8 +229,10 @@ static BaseObjectNNPtr buildObject(DatabaseContextPtr dbContext,
// ---------------------------------------------------------------------------
-static void outputObject(DatabaseContextPtr dbContext, BaseObjectNNPtr obj,
- CoordinateOperationContext::IntermediateCRSUse allowUseIntermediateCRS, const OutputOptions &outputOpt) {
+static void outputObject(
+ DatabaseContextPtr dbContext, BaseObjectNNPtr obj,
+ CoordinateOperationContext::IntermediateCRSUse allowUseIntermediateCRS,
+ const OutputOptions &outputOpt) {
auto identified = dynamic_cast<const IdentifiedObject *>(obj.get());
if (!outputOpt.quiet && identified && identified->isDeprecated()) {
@@ -260,7 +268,7 @@ static void outputObject(DatabaseContextPtr dbContext, BaseObjectNNPtr obj,
}
auto crs = nn_dynamic_pointer_cast<CRS>(obj);
if (!outputOpt.quiet) {
- if( crs ) {
+ if (crs) {
std::cout << "PROJ.4 string:" << std::endl;
} else {
std::cout << "PROJ string:" << std::endl;
@@ -271,8 +279,8 @@ static void outputObject(DatabaseContextPtr dbContext, BaseObjectNNPtr obj,
if (crs) {
objToExport =
nn_dynamic_pointer_cast<IPROJStringExportable>(
- crs->createBoundCRSToWGS84IfPossible(dbContext,
- allowUseIntermediateCRS));
+ crs->createBoundCRSToWGS84IfPossible(
+ dbContext, allowUseIntermediateCRS));
}
if (!objToExport) {
objToExport = projStringExportable;
@@ -411,8 +419,8 @@ static void outputObject(DatabaseContextPtr dbContext, BaseObjectNNPtr obj,
std::shared_ptr<IWKTExportable> objToExport;
if (crs) {
objToExport = nn_dynamic_pointer_cast<IWKTExportable>(
- crs->createBoundCRSToWGS84IfPossible(dbContext,
- allowUseIntermediateCRS));
+ crs->createBoundCRSToWGS84IfPossible(
+ dbContext, allowUseIntermediateCRS));
}
if (!objToExport) {
objToExport = wktExportable;
@@ -461,11 +469,42 @@ static void outputObject(DatabaseContextPtr dbContext, BaseObjectNNPtr obj,
}
}
}
+
+ auto op = dynamic_cast<CoordinateOperation *>(obj.get());
+ if (op && dbContext && getenv("PROJINFO_NO_GRID_CHECK") == nullptr) {
+ try {
+ auto setGrids = op->gridsNeeded(dbContext);
+ bool firstWarning = true;
+ for (const auto &grid : setGrids) {
+ if (!grid.available) {
+ if (firstWarning) {
+ std::cout << std::endl;
+ firstWarning = false;
+ }
+ std::cout << "Grid " << grid.shortName
+ << " needed but not found on the system.";
+ if (!grid.packageName.empty()) {
+ std::cout << " Can be obtained from the "
+ << grid.packageName << " package";
+ if (!grid.url.empty()) {
+ std::cout << " at " << grid.url;
+ }
+ } else if (!grid.url.empty()) {
+ std::cout << " Can be obtained at " << grid.url;
+ }
+ std::cout << std::endl;
+ }
+ }
+ } catch (const std::exception &e) {
+ std::cerr << "Error in gridsNeeded(): " << e.what() << std::endl;
+ }
+ }
}
// ---------------------------------------------------------------------------
-static void outputOperationSummary(const CoordinateOperationNNPtr &op) {
+static void outputOperationSummary(const CoordinateOperationNNPtr &op,
+ const DatabaseContextPtr &dbContext) {
auto ids = op->identifiers();
if (!ids.empty()) {
std::cout << *(ids[0]->codeSpace()) << ":" << ids[0]->code();
@@ -505,6 +544,22 @@ static void outputOperationSummary(const CoordinateOperationNNPtr &op) {
std::cout << "unknown domain of validity";
}
+ if (op->hasBallparkTransformation()) {
+ std::cout << ", has ballpark transformation";
+ }
+
+ if (dbContext && getenv("PROJINFO_NO_GRID_CHECK") == nullptr) {
+ try {
+ auto setGrids = op->gridsNeeded(dbContext);
+ for (const auto &grid : setGrids) {
+ if (!grid.available) {
+ std::cout << ", at least one grid missing";
+ break;
+ }
+ }
+ } catch (const std::exception &) {
+ }
+ }
std::cout << std::endl;
}
@@ -514,26 +569,25 @@ static void outputOperations(
DatabaseContextPtr dbContext, const std::string &sourceCRSStr,
const std::string &targetCRSStr, const ExtentPtr &bboxFilter,
CoordinateOperationContext::SpatialCriterion spatialCriterion,
+ bool spatialCriterionExplicitlySpecified,
CoordinateOperationContext::SourceTargetCRSExtentUse crsExtentUse,
CoordinateOperationContext::GridAvailabilityUse gridAvailabilityUse,
CoordinateOperationContext::IntermediateCRSUse allowUseIntermediateCRS,
const std::vector<std::pair<std::string, std::string>> &pivots,
const std::string &authority, bool usePROJGridAlternatives,
bool showSuperseded, const OutputOptions &outputOpt, bool summary) {
- auto sourceObj = buildObject(dbContext, sourceCRSStr, true, "source CRS",
- false,
- CoordinateOperationContext::IntermediateCRSUse::NEVER,
- outputOpt.quiet);
+ auto sourceObj = buildObject(
+ dbContext, sourceCRSStr, "crs", "source CRS", false,
+ CoordinateOperationContext::IntermediateCRSUse::NEVER, outputOpt.quiet);
auto sourceCRS = nn_dynamic_pointer_cast<CRS>(sourceObj);
if (!sourceCRS) {
std::cerr << "source CRS string is not a CRS" << std::endl;
std::exit(1);
}
- auto targetObj = buildObject(dbContext, targetCRSStr, true, "target CRS",
- false,
- CoordinateOperationContext::IntermediateCRSUse::NEVER,
- outputOpt.quiet);
+ auto targetObj = buildObject(
+ dbContext, targetCRSStr, "crs", "target CRS", false,
+ CoordinateOperationContext::IntermediateCRSUse::NEVER, outputOpt.quiet);
auto targetCRS = nn_dynamic_pointer_cast<CRS>(targetObj);
if (!targetCRS) {
std::cerr << "target CRS string is not a CRS" << std::endl;
@@ -541,6 +595,7 @@ static void outputOperations(
}
std::vector<CoordinateOperationNNPtr> list;
+ size_t spatialCriterionPartialIntersectionResultCount = 0;
try {
auto authFactory =
dbContext
@@ -558,6 +613,21 @@ static void outputOperations(
ctxt->setDiscardSuperseded(!showSuperseded);
list = CoordinateOperationFactory::create()->createOperations(
NN_NO_CHECK(sourceCRS), NN_NO_CHECK(targetCRS), ctxt);
+ if (!spatialCriterionExplicitlySpecified &&
+ spatialCriterion == CoordinateOperationContext::SpatialCriterion::
+ STRICT_CONTAINMENT) {
+ try {
+ ctxt->setSpatialCriterion(
+ CoordinateOperationContext::SpatialCriterion::
+ PARTIAL_INTERSECTION);
+ spatialCriterionPartialIntersectionResultCount =
+ CoordinateOperationFactory::create()
+ ->createOperations(NN_NO_CHECK(sourceCRS),
+ NN_NO_CHECK(targetCRS), ctxt)
+ .size();
+ } catch (const std::exception &) {
+ }
+ }
} catch (const std::exception &e) {
std::cerr << "createOperations() failed with: " << e.what()
<< std::endl;
@@ -567,28 +637,31 @@ static void outputOperations(
outputObject(dbContext, list[0], allowUseIntermediateCRS, outputOpt);
return;
}
+ std::cout << "Candidate operations found: " << list.size() << std::endl;
+ if (spatialCriterionPartialIntersectionResultCount > list.size()) {
+ std::cout << "Note: using '--spatial-test intersects' would bring "
+ "more results ("
+ << spatialCriterionPartialIntersectionResultCount << ")"
+ << std::endl;
+ }
if (summary) {
- std::cout << "Candidate operations found: " << list.size() << std::endl;
for (const auto &op : list) {
- outputOperationSummary(op);
+ outputOperationSummary(op, dbContext);
}
} else {
bool first = true;
for (size_t i = 0; i < list.size(); ++i) {
const auto &op = list[i];
- if (list.size() > 1) {
- if (!first) {
- std::cout << std::endl;
- }
- first = false;
- std::cout << "-------------------------------------"
- << std::endl;
- std::cout << "Operation n"
- "\xC2\xB0"
- << (i + 1) << ":" << std::endl
- << std::endl;
+ if (!first) {
+ std::cout << std::endl;
}
- outputOperationSummary(op);
+ first = false;
+ std::cout << "-------------------------------------" << std::endl;
+ std::cout << "Operation n"
+ "\xC2\xB0"
+ << (i + 1) << ":" << std::endl
+ << std::endl;
+ outputOperationSummary(op, dbContext);
std::cout << std::endl;
outputObject(dbContext, op, allowUseIntermediateCRS, outputOpt);
}
@@ -610,10 +683,11 @@ int main(int argc, char **argv) {
std::string targetCRSStr;
bool outputSwithSpecified = false;
OutputOptions outputOpt;
- bool kindIsCRS = true;
+ std::string objectKind;
bool summary = false;
ExtentPtr bboxFilter = nullptr;
std::string area;
+ bool spatialCriterionExplicitlySpecified = false;
CoordinateOperationContext::SpatialCriterion spatialCriterion =
CoordinateOperationContext::SpatialCriterion::STRICT_CONTAINMENT;
CoordinateOperationContext::SourceTargetCRSExtentUse crsExtentUse =
@@ -622,7 +696,8 @@ int main(int argc, char **argv) {
CoordinateOperationContext::GridAvailabilityUse gridAvailabilityUse =
CoordinateOperationContext::GridAvailabilityUse::USE_FOR_SORTING;
CoordinateOperationContext::IntermediateCRSUse allowUseIntermediateCRS =
- CoordinateOperationContext::IntermediateCRSUse::IF_NO_DIRECT_TRANSFORMATION;
+ CoordinateOperationContext::IntermediateCRSUse::
+ IF_NO_DIRECT_TRANSFORMATION;
std::vector<std::pair<std::string, std::string>> pivots;
bool usePROJGridAlternatives = true;
std::string mainDBPath;
@@ -736,9 +811,11 @@ int main(int argc, char **argv) {
i++;
std::string kind(argv[i]);
if (ci_equal(kind, "crs") || ci_equal(kind, "srs")) {
- kindIsCRS = true;
+ objectKind = "crs";
} else if (ci_equal(kind, "operation")) {
- kindIsCRS = false;
+ objectKind = "operation";
+ } else if (ci_equal(kind, "ellipsoid")) {
+ objectKind = "ellipsoid";
} else {
std::cerr << "Unrecognized value for option -k: " << kind
<< std::endl;
@@ -768,6 +845,7 @@ int main(int argc, char **argv) {
} else if (arg == "--spatial-test" && i + 1 < argc) {
i++;
std::string value(argv[i]);
+ spatialCriterionExplicitlySpecified = true;
if (ci_equal(value, "contains")) {
spatialCriterion = CoordinateOperationContext::
SpatialCriterion::STRICT_CONTAINMENT;
@@ -822,9 +900,10 @@ int main(int argc, char **argv) {
if (ci_equal(std::string(value), "always")) {
allowUseIntermediateCRS =
CoordinateOperationContext::IntermediateCRSUse::ALWAYS;
- } else if (ci_equal(std::string(value), "if_no_direct_transformation")) {
- allowUseIntermediateCRS =
- CoordinateOperationContext::IntermediateCRSUse::IF_NO_DIRECT_TRANSFORMATION;
+ } else if (ci_equal(std::string(value),
+ "if_no_direct_transformation")) {
+ allowUseIntermediateCRS = CoordinateOperationContext::
+ IntermediateCRSUse::IF_NO_DIRECT_TRANSFORMATION;
} else if (ci_equal(std::string(value), "never")) {
allowUseIntermediateCRS =
CoordinateOperationContext::IntermediateCRSUse::NEVER;
@@ -918,77 +997,86 @@ int main(int argc, char **argv) {
}
if (outputOpt.quiet &&
- (outputOpt.PROJ5 + outputOpt.WKT2_2018 +
- outputOpt.WKT2_2015 + outputOpt.WKT1_GDAL) != 1) {
+ (outputOpt.PROJ5 + outputOpt.WKT2_2018 + outputOpt.WKT2_2015 +
+ outputOpt.WKT1_GDAL) != 1) {
std::cerr << "-q can only be used with a single output format"
<< std::endl;
usage();
}
if (!user_string.empty()) {
- auto obj(buildObject(dbContext, user_string, kindIsCRS, "input string",
- buildBoundCRSToWGS84, allowUseIntermediateCRS,
- outputOpt.quiet));
- if (guessDialect) {
- auto dialect = WKTParser().guessDialect(user_string);
- std::cout << "Guessed WKT dialect: ";
- if (dialect == WKTParser::WKTGuessedDialect::WKT2_2018) {
- std::cout << "WKT2_2018";
- } else if (dialect == WKTParser::WKTGuessedDialect::WKT2_2015) {
- std::cout << "WKT2_2015";
- } else if (dialect == WKTParser::WKTGuessedDialect::WKT1_GDAL) {
- std::cout << "WKT1_GDAL";
- } else if (dialect == WKTParser::WKTGuessedDialect::WKT1_ESRI) {
- std::cout << "WKT1_ESRI";
- } else {
- std::cout << "Not WKT / unknown";
+ try {
+ auto obj(buildObject(dbContext, user_string, objectKind,
+ "input string", buildBoundCRSToWGS84,
+ allowUseIntermediateCRS, outputOpt.quiet));
+ if (guessDialect) {
+ auto dialect = WKTParser().guessDialect(user_string);
+ std::cout << "Guessed WKT dialect: ";
+ if (dialect == WKTParser::WKTGuessedDialect::WKT2_2018) {
+ std::cout << "WKT2_2018";
+ } else if (dialect == WKTParser::WKTGuessedDialect::WKT2_2015) {
+ std::cout << "WKT2_2015";
+ } else if (dialect == WKTParser::WKTGuessedDialect::WKT1_GDAL) {
+ std::cout << "WKT1_GDAL";
+ } else if (dialect == WKTParser::WKTGuessedDialect::WKT1_ESRI) {
+ std::cout << "WKT1_ESRI";
+ } else {
+ std::cout << "Not WKT / unknown";
+ }
+ std::cout << std::endl;
}
- std::cout << std::endl;
- }
- outputObject(dbContext, obj, allowUseIntermediateCRS, outputOpt);
- if (identify) {
- auto crs = dynamic_cast<CRS *>(obj.get());
- if (crs) {
- try {
- auto res = crs->identify(
- dbContext
- ? AuthorityFactory::create(NN_NO_CHECK(dbContext),
- authority)
- .as_nullable()
- : nullptr);
- std::cout << std::endl;
- std::cout << "Identification match count: " << res.size()
- << std::endl;
- for (const auto &pair : res) {
- const auto &identifiedCRS = pair.first;
- const auto &ids = identifiedCRS->identifiers();
- if (!ids.empty()) {
- std::cout << *ids[0]->codeSpace() << ":"
- << ids[0]->code() << ": " << pair.second
- << " %" << std::endl;
- } else {
- auto boundCRS =
- dynamic_cast<BoundCRS *>(identifiedCRS.get());
- if (boundCRS &&
- !boundCRS->baseCRS()->identifiers().empty()) {
- const auto &idsBase =
- boundCRS->baseCRS()->identifiers();
- std::cout << "BoundCRS of "
- << *idsBase[0]->codeSpace() << ":"
- << idsBase[0]->code() << ": "
+ outputObject(dbContext, obj, allowUseIntermediateCRS, outputOpt);
+ if (identify) {
+ auto crs = dynamic_cast<CRS *>(obj.get());
+ if (crs) {
+ try {
+ auto res = crs->identify(
+ dbContext
+ ? AuthorityFactory::create(
+ NN_NO_CHECK(dbContext), authority)
+ .as_nullable()
+ : nullptr);
+ std::cout << std::endl;
+ std::cout
+ << "Identification match count: " << res.size()
+ << std::endl;
+ for (const auto &pair : res) {
+ const auto &identifiedCRS = pair.first;
+ const auto &ids = identifiedCRS->identifiers();
+ if (!ids.empty()) {
+ std::cout << *ids[0]->codeSpace() << ":"
+ << ids[0]->code() << ": "
<< pair.second << " %" << std::endl;
} else {
- std::cout
- << "un-identifier CRS: " << pair.second
- << " %" << std::endl;
+ auto boundCRS = dynamic_cast<BoundCRS *>(
+ identifiedCRS.get());
+ if (boundCRS &&
+ !boundCRS->baseCRS()
+ ->identifiers()
+ .empty()) {
+ const auto &idsBase =
+ boundCRS->baseCRS()->identifiers();
+ std::cout << "BoundCRS of "
+ << *idsBase[0]->codeSpace() << ":"
+ << idsBase[0]->code() << ": "
+ << pair.second << " %"
+ << std::endl;
+ } else {
+ std::cout
+ << "un-identifier CRS: " << pair.second
+ << " %" << std::endl;
+ }
}
}
+ } catch (const std::exception &e) {
+ std::cerr << "Identification failed: " << e.what()
+ << std::endl;
}
- } catch (const std::exception &e) {
- std::cerr << "Identification failed: " << e.what()
- << std::endl;
}
}
+ } catch (const std::exception &e) {
+ std::cerr << "buildObject failed: " << e.what() << std::endl;
+ std::exit(1);
}
} else {
@@ -1053,10 +1141,18 @@ int main(int argc, char **argv) {
}
}
- outputOperations(
- dbContext, sourceCRSStr, targetCRSStr, bboxFilter, spatialCriterion,
- crsExtentUse, gridAvailabilityUse, allowUseIntermediateCRS, pivots, authority,
- usePROJGridAlternatives, showSuperseded, outputOpt, summary);
+ try {
+ outputOperations(dbContext, sourceCRSStr, targetCRSStr, bboxFilter,
+ spatialCriterion,
+ spatialCriterionExplicitlySpecified, crsExtentUse,
+ gridAvailabilityUse, allowUseIntermediateCRS,
+ pivots, authority, usePROJGridAlternatives,
+ showSuperseded, outputOpt, summary);
+ } catch (const std::exception &e) {
+ std::cerr << "outputOperations() failed with: " << e.what()
+ << std::endl;
+ std::exit(1);
+ }
}
return 0;
diff --git a/src/apps/utils.cpp b/src/apps/utils.cpp
new file mode 100644
index 00000000..7dc809c9
--- /dev/null
+++ b/src/apps/utils.cpp
@@ -0,0 +1,58 @@
+/******************************************************************************
+ *
+ * Project: PROJ
+ * Purpose: Utilities for command line arguments
+ * Author: Even Rouault <even dot rouault at spatialys dot com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2019, Even Rouault <even dot rouault at spatialys dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "utils.h"
+
+#include <string.h>
+
+bool validate_form_string_for_numbers(const char* formatString) {
+ /* Only accepts '%[+]?[number]?[.]?[number]?[e|E|f|F|g|G]' */
+ bool valid = true;
+ if( formatString[0] != '%' )
+ valid = false;
+ else {
+ auto oformLen = strlen(formatString);
+ for( int i = 1; i < static_cast<int>(oformLen) - 1; i++ ) {
+ if( !(formatString[i] == '.' ||
+ formatString[i] == '+' ||
+ (formatString[i] >= '0' && formatString[i] <= '9')) ) {
+ valid = false;
+ break;
+ }
+ }
+ if( valid ) {
+ valid = formatString[oformLen-1] == 'e' ||
+ formatString[oformLen-1] == 'E' ||
+ formatString[oformLen-1] == 'f' ||
+ formatString[oformLen-1] == 'F' ||
+ formatString[oformLen-1] == 'g' ||
+ formatString[oformLen-1] == 'G';
+ }
+ }
+ return valid;
+}
diff --git a/src/apps/utils.h b/src/apps/utils.h
new file mode 100644
index 00000000..99c14091
--- /dev/null
+++ b/src/apps/utils.h
@@ -0,0 +1,29 @@
+/******************************************************************************
+ *
+ * Project: PROJ
+ * Purpose: Utilities for command line arguments
+ * Author: Even Rouault <even dot rouault at spatialys dot com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2019, Even Rouault <even dot rouault at spatialys dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+bool validate_form_string_for_numbers(const char* formatString);
diff --git a/src/bin_cct.cmake b/src/bin_cct.cmake
index e400caf3..d2d61cf5 100644
--- a/src/bin_cct.cmake
+++ b/src/bin_cct.cmake
@@ -1,13 +1,19 @@
-set(CCT_SRC apps/cct.cpp apps/proj_strtod.cpp apps/proj_strtod.h)
+set(CCT_SRC
+ apps/cct.cpp
+ apps/proj_strtod.cpp
+ apps/proj_strtod.h
+)
set(CCT_INCLUDE apps/optargpm.h)
source_group("Source Files\\Bin" FILES ${CCT_SRC})
add_executable(cct ${CCT_SRC} ${CCT_INCLUDE})
target_link_libraries(cct ${PROJ_LIBRARIES})
+target_compile_options(cct PRIVATE ${PROJ_CXX_WARN_FLAGS})
+
install(TARGETS cct
- RUNTIME DESTINATION ${BINDIR})
+ RUNTIME DESTINATION ${BINDIR})
if(MSVC AND BUILD_LIBPROJ_SHARED)
- target_compile_definitions(cct PRIVATE PROJ_MSVC_DLL_IMPORT=1)
+ target_compile_definitions(cct PRIVATE PROJ_MSVC_DLL_IMPORT=1)
endif()
diff --git a/src/bin_cs2cs.cmake b/src/bin_cs2cs.cmake
index d520192c..d2bb3b97 100644
--- a/src/bin_cs2cs.cmake
+++ b/src/bin_cs2cs.cmake
@@ -1,14 +1,18 @@
-set(CS2CS_SRC apps/cs2cs.cpp
- apps/emess.cpp
+set(CS2CS_SRC
+ apps/cs2cs.cpp
+ apps/emess.cpp
+ apps/utils.cpp
)
source_group("Source Files\\Bin" FILES ${CS2CS_SRC})
add_executable(cs2cs ${CS2CS_SRC} ${CS2CS_INCLUDE})
target_link_libraries(cs2cs ${PROJ_LIBRARIES})
-install(TARGETS cs2cs
- RUNTIME DESTINATION ${BINDIR})
+target_compile_options(cs2cs PRIVATE ${PROJ_CXX_WARN_FLAGS})
+
+install(TARGETS cs2cs
+ RUNTIME DESTINATION ${BINDIR})
if(MSVC AND BUILD_LIBPROJ_SHARED)
- target_compile_definitions(cs2cs PRIVATE PROJ_MSVC_DLL_IMPORT=1)
+ target_compile_definitions(cs2cs PRIVATE PROJ_MSVC_DLL_IMPORT=1)
endif()
diff --git a/src/bin_geod.cmake b/src/bin_geod.cmake
index 049da318..84d2cd5b 100644
--- a/src/bin_geod.cmake
+++ b/src/bin_geod.cmake
@@ -1,18 +1,20 @@
-set(GEOD_SRC apps/geod.cpp
- apps/geod_set.cpp
- apps/geod_interface.cpp
- apps/emess.cpp
+set(GEOD_SRC
+ apps/geod.cpp
+ apps/geod_set.cpp
+ apps/geod_interface.cpp
+ apps/emess.cpp
)
set(GEOD_INCLUDE apps/geod_interface.h)
source_group("Source Files\\Bin" FILES ${GEOD_SRC} ${GEOD_INCLUDE})
-#Executable
add_executable(geod ${GEOD_SRC} ${GEOD_INCLUDE})
target_link_libraries(geod ${PROJ_LIBRARIES})
+target_compile_options(geod PRIVATE ${PROJ_CXX_WARN_FLAGS})
+
install(TARGETS geod
- RUNTIME DESTINATION ${BINDIR})
+ RUNTIME DESTINATION ${BINDIR})
if(MSVC AND BUILD_LIBPROJ_SHARED)
- target_compile_definitions(geod PRIVATE PROJ_MSVC_DLL_IMPORT=1)
+ target_compile_definitions(geod PRIVATE PROJ_MSVC_DLL_IMPORT=1)
endif()
diff --git a/src/bin_geodtest.cmake b/src/bin_geodtest.cmake
index 31de499d..c911e95f 100644
--- a/src/bin_geodtest.cmake
+++ b/src/bin_geodtest.cmake
@@ -1,16 +1,15 @@
-set(GEODTEST_SRC tests/geodtest.cpp )
+set(GEODTEST_SRC tests/geodtest.cpp)
set(GEODTEST_INCLUDE)
source_group("Source Files\\Bin" FILES ${GEODTEST_SRC} ${GEODTEST_INCLUDE})
-#Executable
add_executable(geodtest ${GEODTEST_SRC} ${GEODTEST_INCLUDE})
target_link_libraries(geodtest ${PROJ_LIBRARIES})
-# Do not install
+target_compile_options(geodtest PRIVATE ${PROJ_CXX_WARN_FLAGS})
-# Instead run as a test
-add_test (NAME geodesic-test COMMAND geodtest)
+# Do not install, instead run as a test
+add_test(NAME geodesic-test COMMAND geodtest)
if(MSVC AND BUILD_LIBPROJ_SHARED)
- target_compile_definitions(geodtest PRIVATE PROJ_MSVC_DLL_IMPORT=1)
+ target_compile_definitions(geodtest PRIVATE PROJ_MSVC_DLL_IMPORT=1)
endif()
diff --git a/src/bin_gie.cmake b/src/bin_gie.cmake
index 497315f9..49c57483 100644
--- a/src/bin_gie.cmake
+++ b/src/bin_gie.cmake
@@ -1,15 +1,19 @@
-set(GIE_SRC apps/gie.cpp
- apps/proj_strtod.cpp
- apps/proj_strtod.h)
+set(GIE_SRC
+ apps/gie.cpp
+ apps/proj_strtod.cpp
+ apps/proj_strtod.h
+)
set(GIE_INCLUDE apps/optargpm.h)
source_group("Source Files\\Bin" FILES ${GIE_SRC})
add_executable(gie ${GIE_SRC} ${GIE_INCLUDE})
target_link_libraries(gie ${PROJ_LIBRARIES})
+target_compile_options(gie PRIVATE ${PROJ_CXX_WARN_FLAGS})
+
install(TARGETS gie
- RUNTIME DESTINATION ${BINDIR})
+ RUNTIME DESTINATION ${BINDIR})
if(MSVC AND BUILD_LIBPROJ_SHARED)
- target_compile_definitions(gie PRIVATE PROJ_MSVC_DLL_IMPORT=1)
+ target_compile_definitions(gie PRIVATE PROJ_MSVC_DLL_IMPORT=1)
endif()
diff --git a/src/bin_proj.cmake b/src/bin_proj.cmake
index 76e2ae9f..ce282fc6 100644
--- a/src/bin_proj.cmake
+++ b/src/bin_proj.cmake
@@ -1,18 +1,21 @@
-set(PROJ_SRC apps/proj.cpp
- apps/emess.cpp
+set(PROJ_SRC
+ apps/proj.cpp
+ apps/emess.cpp
+ apps/utils.cpp
)
source_group("Source Files\\Bin" FILES ${PROJ_SRC})
-#Executable
add_executable(binproj ${PROJ_SRC})
set_target_properties(binproj
- PROPERTIES
- OUTPUT_NAME proj)
+ PROPERTIES
+ OUTPUT_NAME proj)
target_link_libraries(binproj ${PROJ_LIBRARIES})
-install(TARGETS binproj
- RUNTIME DESTINATION ${BINDIR})
+target_compile_options(binproj PRIVATE ${PROJ_CXX_WARN_FLAGS})
+
+install(TARGETS binproj
+ RUNTIME DESTINATION ${BINDIR})
if(MSVC AND BUILD_LIBPROJ_SHARED)
- target_compile_definitions(binproj PRIVATE PROJ_MSVC_DLL_IMPORT=1)
+ target_compile_definitions(binproj PRIVATE PROJ_MSVC_DLL_IMPORT=1)
endif()
diff --git a/src/bin_projinfo.cmake b/src/bin_projinfo.cmake
index ea6f1006..c2447262 100644
--- a/src/bin_projinfo.cmake
+++ b/src/bin_projinfo.cmake
@@ -2,15 +2,16 @@ set(PROJINFO_SRC apps/projinfo.cpp)
source_group("Source Files\\Bin" FILES ${PROJINFO_SRC})
-#Executable
add_executable(binprojinfo ${PROJINFO_SRC})
set_target_properties(binprojinfo
- PROPERTIES
- OUTPUT_NAME projinfo)
+ PROPERTIES
+ OUTPUT_NAME projinfo)
target_link_libraries(binprojinfo ${PROJ_LIBRARIES})
-install(TARGETS binprojinfo
- RUNTIME DESTINATION ${BINDIR})
+target_compile_options(binprojinfo PRIVATE ${PROJ_CXX_WARN_FLAGS})
+
+install(TARGETS binprojinfo
+ RUNTIME DESTINATION ${BINDIR})
if(MSVC AND BUILD_LIBPROJ_SHARED)
- target_compile_definitions(binprojinfo PRIVATE PROJ_MSVC_DLL_IMPORT=1)
+ target_compile_definitions(binprojinfo PRIVATE PROJ_MSVC_DLL_IMPORT=1)
endif()
diff --git a/src/conversions/axisswap.cpp b/src/conversions/axisswap.cpp
index 97c8899a..15ec016b 100644
--- a/src/conversions/axisswap.cpp
+++ b/src/conversions/axisswap.cpp
@@ -59,7 +59,6 @@ operation:
#include "proj.h"
#include "proj_internal.h"
-#include "proj_internal.h"
PROJ_HEAD(axisswap, "Axis ordering");
diff --git a/src/conversions/cart.cpp b/src/conversions/cart.cpp
index d9aea9b8..c1f6f09d 100644
--- a/src/conversions/cart.cpp
+++ b/src/conversions/cart.cpp
@@ -43,7 +43,6 @@
#define PJ_LIB__
#include "proj_internal.h"
-#include "proj_internal.h"
#include "proj_math.h"
PROJ_HEAD(cart, "Geodetic/cartesian conversions");
@@ -163,6 +162,12 @@ static PJ_LPZ geodetic (PJ_XYZ cart, PJ *P) {
c = cos(theta);
s = sin(theta);
lpz.phi = atan2 (cart.z + P->e2s*P->b*s*s*s, p - P->es*P->a*c*c*c);
+ if( fabs(lpz.phi) > M_HALFPI ) {
+ // this happen on non-sphere ellipsoid when x,y,z is very close to 0
+ // there is no single solution to the cart->geodetic conversion in
+ // that case, so arbitrarily pickup phi = 0.
+ lpz.phi = 0;
+ }
lpz.lam = atan2 (cart.y, cart.x);
N = normal_radius_of_curvature (P->a, P->es, lpz.phi);
diff --git a/src/conversions/geoc.cpp b/src/conversions/geoc.cpp
index e0ca3df3..3d86b531 100644
--- a/src/conversions/geoc.cpp
+++ b/src/conversions/geoc.cpp
@@ -32,7 +32,6 @@
#include "proj.h"
#include "proj_internal.h"
-#include "proj_internal.h"
PROJ_HEAD(geoc, "Geocentric Latitude");
diff --git a/src/conversions/noop.cpp b/src/conversions/noop.cpp
new file mode 100644
index 00000000..a5dd6023
--- /dev/null
+++ b/src/conversions/noop.cpp
@@ -0,0 +1,19 @@
+#define PJ_LIB__
+
+#include "proj_internal.h"
+
+PROJ_HEAD(noop, "No operation");
+
+static PJ_COORD noop(PJ_COORD coord, PJ *P) {
+ (void) P;
+ return coord;
+}
+
+PJ *CONVERSION(noop, 0) {
+ P->fwd4d = noop;
+ P->inv4d = noop;
+ P->left = PJ_IO_UNITS_WHATEVER;
+ P->right = PJ_IO_UNITS_WHATEVER;
+ return P;
+}
+
diff --git a/src/conversions/unitconvert.cpp b/src/conversions/unitconvert.cpp
index 1e3372d6..7ef07311 100644
--- a/src/conversions/unitconvert.cpp
+++ b/src/conversions/unitconvert.cpp
@@ -72,7 +72,6 @@ Last update: 2017-05-16
#include "proj_internal.h"
#include "proj_math.h"
-#include "proj_internal.h"
PROJ_HEAD(unitconvert, "Unit conversion");
@@ -473,11 +472,11 @@ PJ *CONVERSION(unitconvert,0) {
if (f != 0.0) {
proj_log_debug(P, "xy_in unit: %s", normalized_name);
} else {
- if ( (f = pj_param (P->ctx, P->params, "dxy_in").f) == 0.0)
+ f = pj_param (P->ctx, P->params, "dxy_in").f;
+ if (f == 0.0 || 1.0 / f == 0.0)
return pj_default_destructor(P, PJD_ERR_UNKNOWN_UNIT_ID);
}
- if (f != 0.0)
- Q->xy_factor *= f;
+ Q->xy_factor = f;
if (normalized_name != nullptr && strcmp(normalized_name, "Radian") == 0)
P->left = PJ_IO_UNITS_RADIANS;
}
@@ -488,11 +487,11 @@ PJ *CONVERSION(unitconvert,0) {
if (f != 0.0) {
proj_log_debug(P, "xy_out unit: %s", normalized_name);
} else {
- if ( (f = pj_param (P->ctx, P->params, "dxy_out").f) == 0.0)
+ f = pj_param (P->ctx, P->params, "dxy_out").f;
+ if (f == 0.0 || 1.0 / f == 0.0)
return pj_default_destructor(P, PJD_ERR_UNKNOWN_UNIT_ID);
}
- if (f != 0.0)
- Q->xy_factor /= f;
+ Q->xy_factor /= f;
if (normalized_name != nullptr && strcmp(normalized_name, "Radian") == 0)
P->right= PJ_IO_UNITS_RADIANS;
}
@@ -509,11 +508,11 @@ PJ *CONVERSION(unitconvert,0) {
if (f != 0.0) {
proj_log_debug(P, "z_in unit: %s", normalized_name);
} else {
- if ( (f = pj_param (P->ctx, P->params, "dz_in").f) == 0.0)
+ f = pj_param (P->ctx, P->params, "dz_in").f;
+ if (f == 0.0 || 1.0 / f == 0.0)
return pj_default_destructor(P, PJD_ERR_UNKNOWN_UNIT_ID);
}
- if (f != 0.0)
- Q->z_factor *= f;
+ Q->z_factor = f;
}
if ((name = pj_param (P->ctx, P->params, "sz_out").s) != nullptr) {
@@ -522,11 +521,11 @@ PJ *CONVERSION(unitconvert,0) {
if (f != 0.0) {
proj_log_debug(P, "z_out unit: %s", normalized_name);
} else {
- if ( (f = pj_param (P->ctx, P->params, "dz_out").f) == 0.0)
+ f = pj_param (P->ctx, P->params, "dz_out").f;
+ if (f == 0.0 || 1.0 / f == 0.0)
return pj_default_destructor(P, PJD_ERR_UNKNOWN_UNIT_ID);
}
- if (f != 0.0)
- Q->z_factor /= f;
+ Q->z_factor /= f;
}
if( z_in_is_linear >= 0 && z_out_is_linear >= 0 &&
diff --git a/src/ell_set.cpp b/src/ell_set.cpp
index 4c9fc892..0d7fb6d5 100644
--- a/src/ell_set.cpp
+++ b/src/ell_set.cpp
@@ -6,7 +6,6 @@
#include "proj.h"
#include "proj_internal.h"
-#include "proj_internal.h"
/* Prototypes of the pj_ellipsoid helper functions */
@@ -280,8 +279,8 @@ static int ellps_shape (PJ *P) {
P->es = pj_atof (pj_param_value (par));
if (HUGE_VAL==P->es)
return proj_errno_set (P, PJD_ERR_INVALID_ARG);
- if (1==P->es)
- return proj_errno_set (P, PJD_ERR_ECCENTRICITY_IS_ONE);
+ if (P->es >= 1)
+ return proj_errno_set (P, PJD_ERR_INVALID_ECCENTRICITY);
break;
/* eccentricity, e */
@@ -289,10 +288,8 @@ static int ellps_shape (PJ *P) {
P->e = pj_atof (pj_param_value (par));
if (HUGE_VAL==P->e)
return proj_errno_set (P, PJD_ERR_INVALID_ARG);
- if (0==P->e)
- return proj_errno_set (P, PJD_ERR_INVALID_ARG);
- if (1==P->e)
- return proj_errno_set (P, PJD_ERR_ECCENTRICITY_IS_ONE);
+ if (P->e < 0 || P->e >= 1)
+ return proj_errno_set (P, PJD_ERR_INVALID_ECCENTRICITY);
P->es = P->e * P->e;
break;
@@ -301,8 +298,8 @@ static int ellps_shape (PJ *P) {
P->b = pj_atof (pj_param_value (par));
if (HUGE_VAL==P->b)
return proj_errno_set (P, PJD_ERR_INVALID_ARG);
- if (0==P->b)
- return proj_errno_set (P, PJD_ERR_ECCENTRICITY_IS_ONE);
+ if (P->b <= 0)
+ return proj_errno_set (P, PJD_ERR_INVALID_ECCENTRICITY);
if (P->b==P->a)
break;
P->f = (P->a - P->b) / P->a;
@@ -399,6 +396,10 @@ static int ellps_spherification (PJ *P) {
break;
}
+ if (P->a <= 0.) {
+ return proj_errno_set(P, PJD_ERR_MAJOR_AXIS_NOT_GIVEN);
+ }
+
/* Clean up the ellipsoidal parameters to reflect the sphere */
P->es = P->e = P->f = 0;
P->rf = HUGE_VAL;
@@ -538,6 +539,10 @@ int pj_calc_ellipsoid_params (PJ *P, double a, double es) {
/* flattening */
if (0==P->f)
P->f = 1 - cos (P->alpha); /* = 1 - sqrt (1 - PIN->es); */
+ if (P->f == 1.0) {
+ pj_ctx_set_errno( P->ctx, PJD_ERR_INVALID_ECCENTRICITY);
+ return PJD_ERR_INVALID_ECCENTRICITY;
+ }
P->rf = P->f != 0.0 ? 1.0/P->f: HUGE_VAL;
/* second flattening */
@@ -556,8 +561,8 @@ int pj_calc_ellipsoid_params (PJ *P, double a, double es) {
P->one_es = 1. - P->es;
if (P->one_es == 0.) {
- pj_ctx_set_errno( P->ctx, PJD_ERR_ECCENTRICITY_IS_ONE);
- return PJD_ERR_ECCENTRICITY_IS_ONE;
+ pj_ctx_set_errno( P->ctx, PJD_ERR_INVALID_ECCENTRICITY);
+ return PJD_ERR_INVALID_ECCENTRICITY;
}
P->rone_es = 1./P->one_es;
@@ -644,6 +649,10 @@ int pj_ell_set (projCtx ctx, paralist *pl, double *a, double *es) {
*es = pj_param(ctx,pl, "des").f;
else if (pj_param(ctx,pl, "te").i) { /* eccentricity */
e = pj_param(ctx,pl, "de").f;
+ if (e < 0) {
+ pj_ctx_set_errno(ctx, PJD_ERR_INVALID_ECCENTRICITY);
+ return 1;
+ }
*es = e * e;
} else if (pj_param(ctx,pl, "trf").i) { /* recip flattening */
*es = pj_param(ctx,pl, "drf").f;
@@ -712,6 +721,10 @@ bomb:
pj_ctx_set_errno(ctx, PJD_ERR_ES_LESS_THAN_ZERO);
return 1;
}
+ if (*es >= 1.) {
+ pj_ctx_set_errno(ctx, PJD_ERR_INVALID_ECCENTRICITY);
+ return 1;
+ }
if (*a <= 0.) {
pj_ctx_set_errno(ctx, PJD_ERR_MAJOR_AXIS_NOT_GIVEN);
return 1;
diff --git a/src/factors.cpp b/src/factors.cpp
index f50c8e21..7c59ee7a 100644
--- a/src/factors.cpp
+++ b/src/factors.cpp
@@ -3,7 +3,6 @@
#include "proj.h"
#include "proj_internal.h"
#include "proj_math.h"
-#include "proj_internal.h"
#include <errno.h>
diff --git a/src/fwd.cpp b/src/fwd.cpp
index a8c51934..c267045a 100644
--- a/src/fwd.cpp
+++ b/src/fwd.cpp
@@ -33,7 +33,6 @@
#include "proj_internal.h"
#include "proj_math.h"
-#include "proj_internal.h"
#define INPUT_UNITS P->left
#define OUTPUT_UNITS P->right
diff --git a/src/gauss.cpp b/src/gauss.cpp
index b7a27191..a34a8f5b 100644
--- a/src/gauss.cpp
+++ b/src/gauss.cpp
@@ -65,9 +65,19 @@ void *pj_gauss_ini(double e, double phi0, double *chi, double *rc) {
}
*chi = asin(sphi / en->C);
en->ratexp = 0.5 * en->C * e;
- en->K = tan(.5 * *chi + M_FORTPI) / (
- pow(tan(.5 * phi0 + M_FORTPI), en->C) *
- srat(en->e * sphi, en->ratexp) );
+ double srat_val = srat(en->e * sphi, en->ratexp);
+ if (srat_val == 0.0) {
+ free(en);
+ return nullptr;
+ }
+ if( .5 * phi0 + M_FORTPI < 1e-10 ) {
+ en->K = 1.0 / srat_val;
+ }
+ else {
+ en->K = tan(.5 * *chi + M_FORTPI) / (
+ pow(tan(.5 * phi0 + M_FORTPI), en->C) *
+ srat_val );
+ }
return ((void *)en);
}
diff --git a/src/general_doc.dox b/src/general_doc.dox
index ce5a8130..04248ae5 100644
--- a/src/general_doc.dox
+++ b/src/general_doc.dox
@@ -4,7 +4,7 @@
\section general_api_design General API design
-The design of the class hierarchy is strongly derived from \ref ISO_19111_2018.
+The design of the class hierarchy is strongly derived from \ref ISO_19111_2019.
Classes for which the constructors are not directly accessible have their
instances constructed with create() methods. The returned object is a non-null
@@ -78,13 +78,12 @@ Coordinate Reference Systems (CRS), coordinate systems (CS) and coordinate
transformation or coordinate conversion between two different coordinate
reference systems.
-\subsubsection ISO_19111_2018 ISO 19111:2018
+\subsubsection ISO_19111_2019 ISO 19111:2019
This is the revision mostly used for PROJ C++ modelling.
-[OGC 18-005r1, 2018-04-04, ISO 19111:2018]
-(https://portal.opengeospatial.org/files/?artifact_id=78556)
-(not yet adopted, at time of writing)
+[OGC 18-005r4, 2019-02-08, ISO 19111:2019]
+(http://docs.opengeospatial.org/as/18-005r4/18-005r4.html)
\subsubsection ISO_19111_2007 ISO 19111:2007
@@ -111,7 +110,7 @@ PROJ implements the two following revisions of the standard:
\subsubsection WKT2_2015 WKT2:2015
-[OGC 12-063r5, 2015-05-01, WKT2-2015]
+[OGC 12-063r5, 2015-05-01, ISO 19162:2015(E), WKT2-2015]
(http://docs.opengeospatial.org/is/12-063r5/12-063r5.html)
\subsection WKT1 WKT1 specification
diff --git a/src/gridcatalog.cpp b/src/gridcatalog.cpp
index ca5750ab..15d81dd7 100644
--- a/src/gridcatalog.cpp
+++ b/src/gridcatalog.cpp
@@ -37,6 +37,13 @@
static PJ_GridCatalog *grid_catalog_list = nullptr;
+static
+PJ_GRIDINFO *pj_gc_findgrid( projCtx_t *ctx,
+ PJ_GridCatalog *catalog, int after,
+ PJ_LP location, double date,
+ PJ_Region *optional_region,
+ double *grid_date );
+
/************************************************************************/
/* pj_gc_unloadall() */
/* */
@@ -236,6 +243,7 @@ int pj_gc_apply_gridshift( PJ *defn, int inverse,
/* pj_c_findgrid() */
/************************************************************************/
+static
PJ_GRIDINFO *pj_gc_findgrid( projCtx ctx, PJ_GridCatalog *catalog, int after,
PJ_LP location, double date,
PJ_Region *optional_region,
@@ -287,6 +295,8 @@ PJ_GRIDINFO *pj_gc_findgrid( projCtx ctx, PJ_GridCatalog *catalog, int after,
int grid_count = 0;
gridlist = pj_gridlist_from_nadgrids( ctx, entry->definition,
&grid_count);
+ // FIXME: this leaks gridlist itself, and memory ownership of
+ // entry->gridinfo is also confusing. Coverity CID 193539
if( grid_count == 1 )
entry->gridinfo = gridlist[0];
}
diff --git a/src/gridinfo.cpp b/src/gridinfo.cpp
index 14759557..7f7d930f 100644
--- a/src/gridinfo.cpp
+++ b/src/gridinfo.cpp
@@ -36,7 +36,6 @@
#include <string.h>
#include "proj_internal.h"
-#include "proj_internal.h"
/************************************************************************/
/* swap_words() */
@@ -851,7 +850,6 @@ static int pj_gridinfo_init_gtx( projCtx ctx, PAFile fid, PJ_GRIDINFO *gi )
PJ_GRIDINFO *pj_gridinfo_init( projCtx ctx, const char *gridname )
{
- char fname[MAX_PATH_FILENAME+1];
PJ_GRIDINFO *gilist;
PAFile fp;
char header[160];
@@ -885,13 +883,12 @@ PJ_GRIDINFO *pj_gridinfo_init( projCtx ctx, const char *gridname )
/* -------------------------------------------------------------------- */
/* Open the file using the usual search rules. */
/* -------------------------------------------------------------------- */
- strcpy(fname, gridname);
- if (!(fp = pj_open_lib(ctx, fname, "rb"))) {
+ if (!(fp = pj_open_lib(ctx, gridname, "rb"))) {
ctx->last_errno = 0; /* don't treat as a persistent error */
return gilist;
}
- gilist->filename = pj_strdup(fname);
+ gilist->filename = pj_strdup(gridname);
if (!gilist->filename) {
pj_dalloc(gilist->gridname);
pj_dalloc(gilist);
diff --git a/src/init.cpp b/src/init.cpp
index 2961bcca..ba9cddd2 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -40,7 +40,6 @@
#include "proj.h"
#include "proj_internal.h"
#include "proj_math.h"
-#include "proj_internal.h"
/**************************************************************************************/
@@ -673,14 +672,14 @@ pj_init_ctx_with_allow_init_epsg(projCtx ctx, int argc, char **argv, int allow_i
if (PJD_ERR_MAJOR_AXIS_NOT_GIVEN==proj_errno (PIN))
proj_errno_reset (PIN);
PIN->f = 1.0/298.257223563;
- PIN->a_orig = PIN->a = 6378137.0;
- PIN->es_orig = PIN->es = PIN->f*(2-PIN->f);
+ PIN->a = 6378137.0;
+ PIN->es = PIN->f*(2-PIN->f);
}
}
PIN->a_orig = PIN->a;
PIN->es_orig = PIN->es;
if (pj_calc_ellipsoid_params (PIN, PIN->a, PIN->es))
- return pj_default_destructor (PIN, PJD_ERR_ECCENTRICITY_IS_ONE);
+ return pj_default_destructor (PIN, PJD_ERR_INVALID_ECCENTRICITY);
/* Now that we have ellipse information check for WGS84 datum */
if( PIN->datum_type == PJD_3PARAM
@@ -737,6 +736,8 @@ pj_init_ctx_with_allow_init_epsg(projCtx ctx, int argc, char **argv, int allow_i
/* Central latitude */
PIN->phi0 = pj_param(ctx, start, "rlat_0").f;
+ if( fabs(PIN->phi0) > M_HALFPI )
+ return pj_default_destructor (PIN, PJD_ERR_LAT_LARGER_THAN_90);
/* False easting and northing */
PIN->x0 = pj_param(ctx, start, "dx_0").f;
diff --git a/src/internal.cpp b/src/internal.cpp
index 44246842..b4b7a683 100644
--- a/src/internal.cpp
+++ b/src/internal.cpp
@@ -491,9 +491,7 @@ void proj_log_func (PJ_CONTEXT *ctx, void *app_data, PJ_LOG_FUNCTION logf) {
passed as first arg at each call to the logger
******************************************************************************/
if (nullptr==ctx)
- pj_get_default_ctx ();
- if (nullptr==ctx)
- return;
+ ctx = pj_get_default_ctx ();
ctx->logger_app_data = app_data;
if (nullptr!=logf)
ctx->logger = logf;
diff --git a/src/inv.cpp b/src/inv.cpp
index a05f8376..b9520c53 100644
--- a/src/inv.cpp
+++ b/src/inv.cpp
@@ -32,7 +32,6 @@
#include "proj_internal.h"
#include "proj_math.h"
-#include "proj_internal.h"
#define INPUT_UNITS P->right
#define OUTPUT_UNITS P->left
diff --git a/src/iso19111/c_api.cpp b/src/iso19111/c_api.cpp
index b3f200fe..5d2216e8 100644
--- a/src/iso19111/c_api.cpp
+++ b/src/iso19111/c_api.cpp
@@ -30,10 +30,12 @@
#define FROM_PROJ_CPP
#endif
+#include <algorithm>
#include <cassert>
#include <cstdarg>
#include <cstring>
#include <map>
+#include <memory>
#include <new>
#include <utility>
#include <vector>
@@ -77,6 +79,11 @@ static void PROJ_NO_INLINE proj_log_error(PJ_CONTEXT *ctx, const char *function,
msg += ": ";
msg += text;
ctx->logger(ctx->logger_app_data, PJ_LOG_ERROR, msg.c_str());
+ auto previous_errno = pj_ctx_get_errno(ctx);
+ if (previous_errno == 0) {
+ // only set errno if it wasn't set deeper down the call stack
+ pj_ctx_set_errno(ctx, PJD_ERR_GENERIC_ERROR);
+ }
}
// ---------------------------------------------------------------------------
@@ -134,8 +141,7 @@ static PJ *pj_obj_create(PJ_CONTEXT *ctx, const IdentifiedObjectNNPtr &objIn) {
auto formatter = PROJStringFormatter::create(
PROJStringFormatter::Convention::PROJ_5, dbContext);
auto projString = coordop->exportToPROJString(formatter.get());
- auto pj = pj_create_internal(
- ctx, projString.empty() ? "+proj=affine" : projString.c_str());
+ auto pj = pj_create_internal(ctx, projString.c_str());
if (pj) {
pj->iso_obj = objIn;
return pj;
@@ -147,6 +153,7 @@ static PJ *pj_obj_create(PJ_CONTEXT *ctx, const IdentifiedObjectNNPtr &objIn) {
}
auto pj = pj_new();
if (pj) {
+ pj->ctx = ctx;
pj->descr = "ISO-19111 object";
pj->iso_obj = objIn;
}
@@ -975,29 +982,18 @@ int proj_is_equivalent_to(const PJ *obj, const PJ *other,
return false;
}
- // Make sure that the C and C++ enumerations match
- static_assert(static_cast<int>(PJ_COMP_STRICT) ==
- static_cast<int>(IComparable::Criterion::STRICT),
- "");
- static_assert(static_cast<int>(PJ_COMP_EQUIVALENT) ==
- static_cast<int>(IComparable::Criterion::EQUIVALENT),
- "");
- static_assert(
- static_cast<int>(PJ_COMP_EQUIVALENT_EXCEPT_AXIS_ORDER_GEOGCRS) ==
- static_cast<int>(
- IComparable::Criterion::EQUIVALENT_EXCEPT_AXIS_ORDER_GEOGCRS),
- "");
+ const auto cppCriterion = ([](PJ_COMPARISON_CRITERION l_criterion) {
+ switch (l_criterion) {
+ case PJ_COMP_STRICT:
+ return IComparable::Criterion::STRICT;
+ case PJ_COMP_EQUIVALENT:
+ return IComparable::Criterion::EQUIVALENT;
+ case PJ_COMP_EQUIVALENT_EXCEPT_AXIS_ORDER_GEOGCRS:
+ break;
+ }
+ return IComparable::Criterion::EQUIVALENT_EXCEPT_AXIS_ORDER_GEOGCRS;
+ })(criterion);
- // Make sure we enumerate all values. If adding a new value, as we
- // don't have a default clause, the compiler will warn.
- switch (criterion) {
- case PJ_COMP_STRICT:
- case PJ_COMP_EQUIVALENT:
- case PJ_COMP_EQUIVALENT_EXCEPT_AXIS_ORDER_GEOGCRS:
- break;
- }
- const IComparable::Criterion cppCriterion =
- static_cast<IComparable::Criterion>(criterion);
return obj->iso_obj->isEquivalentTo(other->iso_obj.get(), cppCriterion);
}
@@ -1121,40 +1117,24 @@ const char *proj_as_wkt(PJ_CONTEXT *ctx, const PJ *obj, PJ_WKT_TYPE type,
return nullptr;
}
- // Make sure that the C and C++ enumerations match
- static_assert(static_cast<int>(PJ_WKT2_2015) ==
- static_cast<int>(WKTFormatter::Convention::WKT2_2015),
- "");
- static_assert(
- static_cast<int>(PJ_WKT2_2015_SIMPLIFIED) ==
- static_cast<int>(WKTFormatter::Convention::WKT2_2015_SIMPLIFIED),
- "");
- static_assert(static_cast<int>(PJ_WKT2_2018) ==
- static_cast<int>(WKTFormatter::Convention::WKT2_2018),
- "");
- static_assert(
- static_cast<int>(PJ_WKT2_2018_SIMPLIFIED) ==
- static_cast<int>(WKTFormatter::Convention::WKT2_2018_SIMPLIFIED),
- "");
- static_assert(static_cast<int>(PJ_WKT1_GDAL) ==
- static_cast<int>(WKTFormatter::Convention::WKT1_GDAL),
- "");
- static_assert(static_cast<int>(PJ_WKT1_ESRI) ==
- static_cast<int>(WKTFormatter::Convention::WKT1_ESRI),
- "");
- // Make sure we enumerate all values. If adding a new value, as we
- // don't have a default clause, the compiler will warn.
- switch (type) {
- case PJ_WKT2_2015:
- case PJ_WKT2_2015_SIMPLIFIED:
- case PJ_WKT2_2018:
- case PJ_WKT2_2018_SIMPLIFIED:
- case PJ_WKT1_GDAL:
- case PJ_WKT1_ESRI:
- break;
- }
- const WKTFormatter::Convention convention =
- static_cast<WKTFormatter::Convention>(type);
+ const auto convention = ([](PJ_WKT_TYPE l_type) {
+ switch (l_type) {
+ case PJ_WKT2_2015:
+ return WKTFormatter::Convention::WKT2_2015;
+ case PJ_WKT2_2015_SIMPLIFIED:
+ return WKTFormatter::Convention::WKT2_2015_SIMPLIFIED;
+ case PJ_WKT2_2018:
+ return WKTFormatter::Convention::WKT2_2018;
+ case PJ_WKT2_2018_SIMPLIFIED:
+ return WKTFormatter::Convention::WKT2_2018_SIMPLIFIED;
+ case PJ_WKT1_GDAL:
+ return WKTFormatter::Convention::WKT1_GDAL;
+ case PJ_WKT1_ESRI:
+ break;
+ }
+ return WKTFormatter::Convention::WKT1_ESRI;
+ })(type);
+
try {
auto dbContext = getDBcontextNoException(ctx, __FUNCTION__);
auto formatter = WKTFormatter::create(convention, dbContext);
@@ -1365,7 +1345,7 @@ static const GeodeticCRS *extractGeodeticCRS(PJ_CONTEXT *ctx, const PJ *crs,
* It should be used by at most one thread at a time.
*
* @param ctx PROJ context, or NULL for default context
- * @param crs Objet of type CRS (must not be NULL)
+ * @param crs Object of type CRS (must not be NULL)
* @return Object that must be unreferenced with proj_destroy(), or NULL
* in case of error.
*/
@@ -1389,7 +1369,7 @@ PJ *proj_crs_get_geodetic_crs(PJ_CONTEXT *ctx, const PJ *crs) {
* It should be used by at most one thread at a time.
*
* @param ctx PROJ context, or NULL for default context
- * @param crs Objet of type CRS (must not be NULL)
+ * @param crs Object of type CRS (must not be NULL)
* @param index Index of the CRS component (typically 0 = horizontal, 1 =
* vertical)
* @return Object that must be unreferenced with proj_destroy(), or NULL
@@ -1471,7 +1451,7 @@ PJ *proj_crs_create_bound_crs(PJ_CONTEXT *ctx, const PJ *base_crs,
* osgeo::proj::crs::CRS::createBoundCRSToWGS84IfPossible()
*
* @param ctx PROJ context, or NULL for default context
- * @param crs Objet of type CRS (must not be NULL)
+ * @param crs Object of type CRS (must not be NULL)
* @param options null-terminated list of options, or NULL. Currently
* supported options are:
* <ul>
@@ -1530,7 +1510,7 @@ PJ *proj_crs_create_bound_crs_to_WGS84(PJ_CONTEXT *ctx, const PJ *crs,
* It should be used by at most one thread at a time.
*
* @param ctx PROJ context, or NULL for default context
- * @param obj Objet of type CRS or GeodeticReferenceFrame (must not be NULL)
+ * @param obj Object of type CRS or GeodeticReferenceFrame (must not be NULL)
* @return Object that must be unreferenced with proj_destroy(), or NULL
* in case of error.
*/
@@ -1562,7 +1542,7 @@ PJ *proj_get_ellipsoid(PJ_CONTEXT *ctx, const PJ *obj) {
* It should be used by at most one thread at a time.
*
* @param ctx PROJ context, or NULL for default context
- * @param crs Objet of type CRS (must not be NULL)
+ * @param crs Object of type CRS (must not be NULL)
* @return Object that must be unreferenced with proj_destroy(), or NULL
* in case of error.
*/
@@ -1645,7 +1625,7 @@ int proj_ellipsoid_get_parameters(PJ_CONTEXT *ctx, const PJ *ellipsoid,
* It should be used by at most one thread at a time.
*
* @param ctx PROJ context, or NULL for default context
- * @param obj Objet of type CRS or GeodeticReferenceFrame (must not be NULL)
+ * @param obj Object of type CRS or GeodeticReferenceFrame (must not be NULL)
* @return Object that must be unreferenced with proj_destroy(), or NULL
* in case of error.
*/
@@ -1720,7 +1700,7 @@ int proj_prime_meridian_get_parameters(PJ_CONTEXT *ctx,
* It should be used by at most one thread at a time.
*
* @param ctx PROJ context, or NULL for default context
- * @param obj Objet of type BoundCRS or CoordinateOperation (must not be NULL)
+ * @param obj Object of type BoundCRS or CoordinateOperation (must not be NULL)
* @return Object that must be unreferenced with proj_destroy(), or NULL
* in case of error, or missing source CRS.
*/
@@ -1763,7 +1743,7 @@ PJ *proj_get_source_crs(PJ_CONTEXT *ctx, const PJ *obj) {
* It should be used by at most one thread at a time.
*
* @param ctx PROJ context, or NULL for default context
- * @param obj Objet of type BoundCRS or CoordinateOperation (must not be NULL)
+ * @param obj Object of type BoundCRS or CoordinateOperation (must not be NULL)
* @return Object that must be unreferenced with proj_destroy(), or NULL
* in case of error, or missing target CRS.
*/
@@ -1797,7 +1777,7 @@ PJ *proj_get_target_crs(PJ_CONTEXT *ctx, const PJ *obj) {
/** \brief Identify the CRS with reference CRSs.
*
* The candidate CRSs are either hard-coded, or looked in the database when
- * authorityFactory is not null.
+ * it is available.
*
* The method returns a list of matching reference CRS, and the percentage
* (0-100) of confidence in the match. The list is sorted by decreasing
@@ -1950,7 +1930,7 @@ void proj_string_list_destroy(PROJ_STRING_LIST list) {
// ---------------------------------------------------------------------------
-/** \brief Instanciate a default set of parameters to be used by
+/** \brief Instantiate a default set of parameters to be used by
* proj_get_crs_list().
*
* @return a new object to free with proj_get_crs_list_parameters_destroy() */
@@ -1987,7 +1967,7 @@ void proj_get_crs_list_parameters_destroy(PROJ_CRS_LIST_PARAMETERS *params) {
* entry is NULL. This array should be freed with proj_crs_info_list_destroy()
*
* When no filter parameters are set, this is functionnaly equivalent to
- * proj_get_crs_info_list_from_database(), instanciating a PJ* object for each
+ * proj_get_crs_info_list_from_database(), instantiating a PJ* object for each
* of the proj_create_from_database() and retrieving information with the
* various getters. However this function will be much faster.
*
@@ -2167,7 +2147,7 @@ void proj_crs_info_list_destroy(PROJ_CRS_INFO **list) {
* It should be used by at most one thread at a time.
*
* @param ctx PROJ context, or NULL for default context
- * @param crs Objet of type DerivedCRS or BoundCRSs (must not be NULL)
+ * @param crs Object of type DerivedCRS or BoundCRSs (must not be NULL)
* @return Object of type SingleOperation that must be unreferenced with
* proj_destroy(), or NULL in case of error.
*/
@@ -2198,7 +2178,7 @@ PJ *proj_crs_get_coordoperation(PJ_CONTEXT *ctx, const PJ *crs) {
/** \brief Return information on the operation method of the SingleOperation.
*
* @param ctx PROJ context, or NULL for default context
- * @param coordoperation Objet of type SingleOperation (typically a Conversion
+ * @param coordoperation Object of type SingleOperation (typically a Conversion
* or Transformation) (must not be NULL)
* @param out_method_name Pointer to a string value to store the method
* (projection) name. or NULL
@@ -5729,12 +5709,12 @@ PJ *proj_create_conversion_equal_earth(PJ_CONTEXT *ctx, double center_long,
* available.
*
* @param ctx PROJ context, or NULL for default context
- * @param coordoperation Objet of type CoordinateOperation or derived classes
+ * @param coordoperation Object of type CoordinateOperation or derived classes
* (must not be NULL)
* @return TRUE or FALSE.
*/
-int proj_coordoperation_is_instanciable(PJ_CONTEXT *ctx,
+int proj_coordoperation_is_instantiable(PJ_CONTEXT *ctx,
const PJ *coordoperation) {
assert(coordoperation);
auto op = dynamic_cast<const CoordinateOperation *>(
@@ -5746,7 +5726,7 @@ int proj_coordoperation_is_instanciable(PJ_CONTEXT *ctx,
}
auto dbContext = getDBcontextNoException(ctx, __FUNCTION__);
try {
- return op->isPROJInstanciable(dbContext) ? 1 : 0;
+ return op->isPROJInstantiable(dbContext) ? 1 : 0;
} catch (const std::exception &) {
return 0;
}
@@ -5754,10 +5734,40 @@ int proj_coordoperation_is_instanciable(PJ_CONTEXT *ctx,
// ---------------------------------------------------------------------------
+/** \brief Return whether a coordinate operation has a "ballpark"
+ * transformation,
+ * that is a very approximate one, due to lack of more accurate transformations.
+ *
+ * Typically a null geographic offset between two horizontal datum, or a
+ * null vertical offset (or limited to unit changes) between two vertical
+ * datum. Errors of several tens to one hundred meters might be expected,
+ * compared to more accurate transformations.
+ *
+ * @param ctx PROJ context, or NULL for default context
+ * @param coordoperation Object of type CoordinateOperation or derived classes
+ * (must not be NULL)
+ * @return TRUE or FALSE.
+ */
+
+int proj_coordoperation_has_ballpark_transformation(PJ_CONTEXT *ctx,
+ const PJ *coordoperation) {
+ assert(coordoperation);
+ auto op = dynamic_cast<const CoordinateOperation *>(
+ coordoperation->iso_obj.get());
+ if (!op) {
+ proj_log_error(ctx, __FUNCTION__,
+ "Object is not a CoordinateOperation");
+ return 0;
+ }
+ return op->hasBallparkTransformation();
+}
+
+// ---------------------------------------------------------------------------
+
/** \brief Return the number of parameters of a SingleOperation
*
* @param ctx PROJ context, or NULL for default context
- * @param coordoperation Objet of type SingleOperation or derived classes
+ * @param coordoperation Object of type SingleOperation or derived classes
* (must not be NULL)
*/
@@ -5779,7 +5789,7 @@ int proj_coordoperation_get_param_count(PJ_CONTEXT *ctx,
/** \brief Return the index of a parameter of a SingleOperation
*
* @param ctx PROJ context, or NULL for default context
- * @param coordoperation Objet of type SingleOperation or derived classes
+ * @param coordoperation Object of type SingleOperation or derived classes
* (must not be NULL)
* @param name Parameter name. Must not be NULL
* @return index (>=0), or -1 in case of error.
@@ -5812,7 +5822,7 @@ int proj_coordoperation_get_param_index(PJ_CONTEXT *ctx,
/** \brief Return a parameter of a SingleOperation
*
* @param ctx PROJ context, or NULL for default context
- * @param coordoperation Objet of type SingleOperation or derived classes
+ * @param coordoperation Object of type SingleOperation or derived classes
* (must not be NULL)
* @param index Parameter index.
* @param out_name Pointer to a string value to store the parameter name. or
@@ -5952,10 +5962,14 @@ int proj_coordoperation_get_param(
* values.
*
* @param ctx PROJ context, or NULL for default context
- * @param coordoperation Objet of type Transformation, that can be represented
+ * @param coordoperation Object of type Transformation, that can be represented
* as a WKT1 TOWGS84 node (must not be NULL)
* @param out_values Pointer to an array of value_count double values.
- * @param value_count Size of out_values array.
+ * @param value_count Size of out_values array. The suggested size is 7 to get
+ * translation, rotation and scale difference parameters. Rotation and scale
+ * difference terms might be zero if the transformation only includes
+ * translation
+ * parameters. In that case, value_count could be set to 3.
* @param emit_error_if_incompatible Boolean to inicate if an error must be
* logged if coordoperation is not compatible with a WKT1 TOWGS84
* representation.
@@ -5997,7 +6011,7 @@ int proj_coordoperation_get_towgs84_values(PJ_CONTEXT *ctx,
/** \brief Return the number of grids used by a CoordinateOperation
*
* @param ctx PROJ context, or NULL for default context
- * @param coordoperation Objet of type CoordinateOperation or derived classes
+ * @param coordoperation Object of type CoordinateOperation or derived classes
* (must not be NULL)
*/
@@ -6033,7 +6047,7 @@ int proj_coordoperation_get_grid_used_count(PJ_CONTEXT *ctx,
/** \brief Return a parameter of a SingleOperation
*
* @param ctx PROJ context, or NULL for default context
- * @param coordoperation Objet of type SingleOperation or derived classes
+ * @param coordoperation Object of type SingleOperation or derived classes
* (must not be NULL)
* @param index Parameter index.
* @param out_short_name Pointer to a string value to store the grid short name.
@@ -6508,7 +6522,7 @@ proj_create_operations(PJ_CONTEXT *ctx, const PJ *source_crs,
/** \brief Return the number of objects in the result set
*
- * @param result Objet of type PJ_OBJ_LIST (must not be NULL)
+ * @param result Object of type PJ_OBJ_LIST (must not be NULL)
*/
int proj_list_get_count(const PJ_OBJ_LIST *result) {
assert(result);
@@ -6524,7 +6538,7 @@ int proj_list_get_count(const PJ_OBJ_LIST *result) {
* It should be used by at most one thread at a time.
*
* @param ctx PROJ context, or NULL for default context
- * @param result Objet of type PJ_OBJ_LIST (must not be NULL)
+ * @param result Object of type PJ_OBJ_LIST (must not be NULL)
* @param index Index
* @return a new object that must be unreferenced with proj_destroy(),
* or nullptr in case of error.
@@ -6590,7 +6604,7 @@ double proj_coordoperation_get_accuracy(PJ_CONTEXT *ctx,
* It should be used by at most one thread at a time.
*
* @param ctx PROJ context, or NULL for default context
- * @param crs Objet of type SingleCRS (must not be NULL)
+ * @param crs Object of type SingleCRS (must not be NULL)
* @return Object that must be unreferenced with proj_destroy(), or NULL
* in case of error (or if there is no datum)
*/
@@ -6618,7 +6632,7 @@ PJ *proj_crs_get_datum(PJ_CONTEXT *ctx, const PJ *crs) {
* It should be used by at most one thread at a time.
*
* @param ctx PROJ context, or NULL for default context
- * @param crs Objet of type SingleCRS (must not be NULL)
+ * @param crs Object of type SingleCRS (must not be NULL)
* @return Object that must be unreferenced with proj_destroy(), or NULL
* in case of error.
*/
@@ -6638,7 +6652,7 @@ PJ *proj_crs_get_coordinate_system(PJ_CONTEXT *ctx, const PJ *crs) {
/** \brief Returns the type of the coordinate system.
*
* @param ctx PROJ context, or NULL for default context
- * @param cs Objet of type CoordinateSystem (must not be NULL)
+ * @param cs Object of type CoordinateSystem (must not be NULL)
* @return type, or PJ_CS_TYPE_UNKNOWN in case of error.
*/
PJ_COORDINATE_SYSTEM_TYPE proj_cs_get_type(PJ_CONTEXT *ctx, const PJ *cs) {
@@ -6684,7 +6698,7 @@ PJ_COORDINATE_SYSTEM_TYPE proj_cs_get_type(PJ_CONTEXT *ctx, const PJ *cs) {
/** \brief Returns the number of axis of the coordinate system.
*
* @param ctx PROJ context, or NULL for default context
- * @param cs Objet of type CoordinateSystem (must not be NULL)
+ * @param cs Object of type CoordinateSystem (must not be NULL)
* @return number of axis, or -1 in case of error.
*/
int proj_cs_get_axis_count(PJ_CONTEXT *ctx, const PJ *cs) {
@@ -6703,7 +6717,7 @@ int proj_cs_get_axis_count(PJ_CONTEXT *ctx, const PJ *cs) {
/** \brief Returns information on an axis
*
* @param ctx PROJ context, or NULL for default context
- * @param cs Objet of type CoordinateSystem (must not be NULL)
+ * @param cs Object of type CoordinateSystem (must not be NULL)
* @param index Index of the coordinate system (between 0 and
* proj_cs_get_axis_count() - 1)
* @param out_name Pointer to a string value to store the axis name. or NULL
@@ -6764,3 +6778,88 @@ int proj_cs_get_axis_info(PJ_CONTEXT *ctx, const PJ *cs, int index,
}
return true;
}
+
+// ---------------------------------------------------------------------------
+
+/** \brief Returns a PJ* object whose axis order is the one expected for
+ * visualization purposes.
+ *
+ * The input object must be a coordinate operation, that has been created with
+ * proj_create_crs_to_crs().
+ * If the axis order of its source or target CRS is northing,easting, then an
+ * axis swap operation will be inserted.
+ *
+ * @param ctx PROJ context, or NULL for default context
+ * @param obj Object of type CoordinateOperation,
+ * created with proj_create_crs_to_crs() (must not be NULL)
+ * @return a new PJ* object to free with proj_destroy() in case of success, or
+ * nullptr in case of error
+ */
+PJ *proj_normalize_for_visualization(PJ_CONTEXT *ctx, const PJ *obj) {
+
+ SANITIZE_CTX(ctx);
+ if (!obj->alternativeCoordinateOperations.empty()) {
+ try {
+ auto pjNew = std::unique_ptr<PJ>(pj_new());
+ if (!pjNew)
+ return nullptr;
+ pjNew->ctx = ctx;
+ for (const auto &alt : obj->alternativeCoordinateOperations) {
+ auto co = dynamic_cast<const CoordinateOperation *>(
+ alt.pj->iso_obj.get());
+ if (co) {
+ double minxSrc = alt.minxSrc;
+ double minySrc = alt.minySrc;
+ double maxxSrc = alt.maxxSrc;
+ double maxySrc = alt.maxySrc;
+ double minxDst = alt.minxDst;
+ double minyDst = alt.minyDst;
+ double maxxDst = alt.maxxDst;
+ double maxyDst = alt.maxyDst;
+
+ auto l_sourceCRS = co->sourceCRS();
+ auto l_targetCRS = co->targetCRS();
+ if (l_sourceCRS && l_targetCRS) {
+ const bool swapSource =
+ l_sourceCRS
+ ->mustAxisOrderBeSwitchedForVisualization();
+ if (swapSource) {
+ std::swap(minxSrc, minySrc);
+ std::swap(maxxSrc, maxySrc);
+ }
+ const bool swapTarget =
+ l_targetCRS
+ ->mustAxisOrderBeSwitchedForVisualization();
+ if (swapTarget) {
+ std::swap(minxDst, minyDst);
+ std::swap(maxxDst, maxyDst);
+ }
+ }
+ pjNew->alternativeCoordinateOperations.emplace_back(
+ minxSrc, minySrc, maxxSrc, maxySrc, minxDst, minyDst,
+ maxxDst, maxyDst,
+ pj_obj_create(ctx, co->normalizeForVisualization()),
+ co->nameStr());
+ }
+ }
+ return pjNew.release();
+ } catch (const std::exception &e) {
+ proj_log_debug(ctx, __FUNCTION__, e.what());
+ return nullptr;
+ }
+ }
+
+ auto co = dynamic_cast<const CoordinateOperation *>(obj->iso_obj.get());
+ if (!co) {
+ proj_log_error(ctx, __FUNCTION__, "Object is not a CoordinateOperation "
+ "created with "
+ "proj_create_crs_to_crs");
+ return nullptr;
+ }
+ try {
+ return pj_obj_create(ctx, co->normalizeForVisualization());
+ } catch (const std::exception &e) {
+ proj_log_debug(ctx, __FUNCTION__, e.what());
+ return nullptr;
+ }
+}
diff --git a/src/iso19111/common.cpp b/src/iso19111/common.cpp
index bdd836e1..d46da0da 100644
--- a/src/iso19111/common.cpp
+++ b/src/iso19111/common.cpp
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Project: PROJ
- * Purpose: ISO19111:2018 implementation
+ * Purpose: ISO19111:2019 implementation
* Author: Even Rouault <even dot rouault at spatialys dot com>
*
******************************************************************************
@@ -641,7 +641,7 @@ const std::string &IdentifiedObject::remarks() PROJ_PURE_DEFN {
/** \brief Return whether the object is deprecated.
*
- * \remark Extension of \ref ISO_19111_2018
+ * \remark Extension of \ref ISO_19111_2019
*/
bool IdentifiedObject::isDeprecated() PROJ_PURE_DEFN { return d->isDeprecated; }
@@ -1073,7 +1073,7 @@ void ObjectUsage::setProperties(
void ObjectUsage::baseExportToWKT(WKTFormatter *formatter) const {
const bool isWKT2 = formatter->version() == WKTFormatter::Version::WKT2;
- if (isWKT2 && formatter->outputId()) {
+ if (isWKT2 && formatter->outputUsage()) {
auto l_domains = domains();
if (!l_domains.empty()) {
if (formatter->use2018Keywords()) {
diff --git a/src/iso19111/coordinateoperation.cpp b/src/iso19111/coordinateoperation.cpp
index 2128124b..348a776a 100644
--- a/src/iso19111/coordinateoperation.cpp
+++ b/src/iso19111/coordinateoperation.cpp
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Project: PROJ
- * Purpose: ISO19111:2018 implementation
+ * Purpose: ISO19111:2019 implementation
* Author: Even Rouault <even dot rouault at spatialys dot com>
*
******************************************************************************
@@ -56,6 +56,10 @@
#include <string>
#include <vector>
+#ifdef DEBUG
+#include <iostream>
+#endif
+
using namespace NS_PROJ::internal;
#if 0
@@ -104,8 +108,17 @@ constexpr double UTM_NORTH_FALSE_NORTHING = 0.0;
constexpr double UTM_SOUTH_FALSE_NORTHING = 10000000.0;
static const std::string INVERSE_OF = "Inverse of ";
-static const char *NULL_GEOCENTRIC_TRANSLATION = "Null geocentric translation";
+static const char *BALLPARK_GEOCENTRIC_TRANSLATION =
+ "Ballpark geocentric translation";
static const char *NULL_GEOGRAPHIC_OFFSET = "Null geographic offset";
+static const char *BALLPARK_GEOGRAPHIC_OFFSET = "Ballpark geographic offset";
+static const char *BALLPARK_VERTICAL_TRANSFORMATION_PREFIX =
+ " (ballpark vertical transformation";
+static const char *BALLPARK_VERTICAL_TRANSFORMATION =
+ " (ballpark vertical transformation)";
+static const char *BALLPARK_VERTICAL_TRANSFORMATION_NO_ELLIPSOID_VERT_HEIGHT =
+ " (ballpark vertical transformation, without ellipsoid height to vertical "
+ "height correction)";
//! @endcond
//! @cond Doxygen_Suppress
@@ -513,6 +526,7 @@ struct CoordinateOperation::Private {
crs::CRSPtr interpolationCRS_{};
util::optional<common::DataEpoch> sourceCoordinateEpoch_{};
util::optional<common::DataEpoch> targetCoordinateEpoch_{};
+ bool hasBallparkTransformation_ = false;
// do not set this for a ProjectedCRS.definingConversion
struct CRSStrongRef {
@@ -542,7 +556,9 @@ struct CoordinateOperation::Private {
// ---------------------------------------------------------------------------
-GridDescription::GridDescription() = default;
+GridDescription::GridDescription()
+ : shortName{}, fullName{}, packageName{}, url{}, directDownload(false),
+ openLicense(false), available(false) {}
GridDescription::~GridDescription() = default;
@@ -706,7 +722,7 @@ void CoordinateOperation::setAccuracies(
* a PROJ pipeline, checking in particular that referenced grids are
* available.
*/
-bool CoordinateOperation::isPROJInstanciable(
+bool CoordinateOperation::isPROJInstantiable(
const io::DatabaseContextPtr &databaseContext) const {
try {
exportToPROJString(io::PROJStringFormatter::create().get());
@@ -723,6 +739,84 @@ bool CoordinateOperation::isPROJInstanciable(
// ---------------------------------------------------------------------------
+/** \brief Return whether a coordinate operation has a "ballpark"
+ * transformation,
+ * that is a very approximate one, due to lack of more accurate transformations.
+ *
+ * Typically a null geographic offset between two horizontal datum, or a
+ * null vertical offset (or limited to unit changes) between two vertical
+ * datum. Errors of several tens to one hundred meters might be expected,
+ * compared to more accurate transformations.
+ */
+bool CoordinateOperation::hasBallparkTransformation() const {
+ return d->hasBallparkTransformation_;
+}
+
+// ---------------------------------------------------------------------------
+
+void CoordinateOperation::setHasBallparkTransformation(bool b) {
+ d->hasBallparkTransformation_ = b;
+}
+
+// ---------------------------------------------------------------------------
+
+void CoordinateOperation::setProperties(
+ const util::PropertyMap &properties) // throw(InvalidValueTypeException)
+{
+ ObjectUsage::setProperties(properties);
+ properties.getStringValue(OPERATION_VERSION_KEY, d->operationVersion_);
+}
+
+// ---------------------------------------------------------------------------
+
+/** \brief Return a variation of the current coordinate operation whose axis
+ * order is the one expected for visualization purposes.
+ */
+CoordinateOperationNNPtr
+CoordinateOperation::normalizeForVisualization() const {
+ auto l_sourceCRS = sourceCRS();
+ auto l_targetCRS = targetCRS();
+ if (!l_sourceCRS || !l_targetCRS) {
+ throw util::UnsupportedOperationException(
+ "Cannot retrieve source or target CRS");
+ }
+ const bool swapSource =
+ l_sourceCRS->mustAxisOrderBeSwitchedForVisualization();
+ const bool swapTarget =
+ l_targetCRS->mustAxisOrderBeSwitchedForVisualization();
+ auto l_this = NN_NO_CHECK(std::dynamic_pointer_cast<CoordinateOperation>(
+ shared_from_this().as_nullable()));
+ if (!swapSource && !swapTarget) {
+ return l_this;
+ }
+ std::vector<CoordinateOperationNNPtr> subOps;
+ if (swapSource) {
+ auto op = Conversion::createAxisOrderReversal(false);
+ op->setCRSs(l_sourceCRS->normalizeForVisualization(),
+ NN_NO_CHECK(l_sourceCRS), nullptr);
+ subOps.emplace_back(op);
+ }
+ subOps.emplace_back(l_this);
+ if (swapTarget) {
+ auto op = Conversion::createAxisOrderReversal(false);
+ op->setCRSs(NN_NO_CHECK(l_targetCRS),
+ l_targetCRS->normalizeForVisualization(), nullptr);
+ subOps.emplace_back(op);
+ }
+ return util::nn_static_pointer_cast<CoordinateOperation>(
+ ConcatenatedOperation::createComputeMetadata(subOps, true));
+}
+
+// ---------------------------------------------------------------------------
+
+//! @cond Doxygen_Suppress
+CoordinateOperationNNPtr CoordinateOperation::shallowClone() const {
+ return _shallowClone();
+}
+//! @endcond
+
+// ---------------------------------------------------------------------------
+
//! @cond Doxygen_Suppress
struct OperationMethod::Private {
util::optional<std::string> formula_{};
@@ -1523,11 +1617,12 @@ static SingleOperationNNPtr createPROJBased(
const util::PropertyMap &properties,
const io::IPROJStringExportableNNPtr &projExportable,
const crs::CRSNNPtr &sourceCRS, const crs::CRSNNPtr &targetCRS,
- const std::vector<metadata::PositionalAccuracyNNPtr> &accuracies =
- std::vector<metadata::PositionalAccuracyNNPtr>()) {
+ const std::vector<metadata::PositionalAccuracyNNPtr> &accuracies,
+ bool hasBallparkTransformation) {
return util::nn_static_pointer_cast<SingleOperation>(
PROJBasedOperation::create(properties, projExportable, false, sourceCRS,
- targetCRS, accuracies));
+ targetCRS, accuracies,
+ hasBallparkTransformation));
}
//! @endcond
@@ -2124,52 +2219,55 @@ void ParameterValue::_exportToWKT(io::WKTFormatter *formatter) const {
const bool isWKT2 = formatter->version() == io::WKTFormatter::Version::WKT2;
const auto &l_type = type();
- const auto &l_value = value();
- if (formatter->abridgedTransformation() && l_type == Type::MEASURE) {
- const auto &unit = l_value.unit();
- const auto &unitType = unit.type();
- if (unitType == common::UnitOfMeasure::Type::LINEAR) {
- formatter->add(l_value.getSIValue());
- } else if (unitType == common::UnitOfMeasure::Type::ANGULAR) {
- formatter->add(
- l_value.convertToUnit(common::UnitOfMeasure::ARC_SECOND));
- } else if (unit == common::UnitOfMeasure::PARTS_PER_MILLION) {
- formatter->add(1.0 + l_value.value() * 1e-6);
- } else {
- formatter->add(l_value.value());
- }
- } else if (l_type == Type::MEASURE) {
- const auto &unit = l_value.unit();
- if (isWKT2) {
- formatter->add(l_value.value());
- } else {
- // In WKT1, as we don't output the natural unit, output to the
- // registered linear / angular unit.
+ if (l_type == Type::MEASURE) {
+ const auto &l_value = value();
+ if (formatter->abridgedTransformation()) {
+ const auto &unit = l_value.unit();
const auto &unitType = unit.type();
if (unitType == common::UnitOfMeasure::Type::LINEAR) {
- const auto &targetUnit = *(formatter->axisLinearUnit());
- if (targetUnit.conversionToSI() == 0.0) {
- throw io::FormattingException(
- "cannot convert value to target linear unit");
- }
- formatter->add(l_value.convertToUnit(targetUnit));
+ formatter->add(l_value.getSIValue());
} else if (unitType == common::UnitOfMeasure::Type::ANGULAR) {
- const auto &targetUnit = *(formatter->axisAngularUnit());
- if (targetUnit.conversionToSI() == 0.0) {
- throw io::FormattingException(
- "cannot convert value to target angular unit");
- }
- formatter->add(l_value.convertToUnit(targetUnit));
+ formatter->add(
+ l_value.convertToUnit(common::UnitOfMeasure::ARC_SECOND));
+ } else if (unit == common::UnitOfMeasure::PARTS_PER_MILLION) {
+ formatter->add(1.0 + l_value.value() * 1e-6);
} else {
- formatter->add(l_value.getSIValue());
+ formatter->add(l_value.value());
}
- }
- if (isWKT2 && unit != common::UnitOfMeasure::NONE) {
- if (!formatter->primeMeridianOrParameterUnitOmittedIfSameAsAxis() ||
- (unit != common::UnitOfMeasure::SCALE_UNITY &&
- unit != *(formatter->axisLinearUnit()) &&
- unit != *(formatter->axisAngularUnit()))) {
- unit._exportToWKT(formatter);
+ } else {
+ const auto &unit = l_value.unit();
+ if (isWKT2) {
+ formatter->add(l_value.value());
+ } else {
+ // In WKT1, as we don't output the natural unit, output to the
+ // registered linear / angular unit.
+ const auto &unitType = unit.type();
+ if (unitType == common::UnitOfMeasure::Type::LINEAR) {
+ const auto &targetUnit = *(formatter->axisLinearUnit());
+ if (targetUnit.conversionToSI() == 0.0) {
+ throw io::FormattingException(
+ "cannot convert value to target linear unit");
+ }
+ formatter->add(l_value.convertToUnit(targetUnit));
+ } else if (unitType == common::UnitOfMeasure::Type::ANGULAR) {
+ const auto &targetUnit = *(formatter->axisAngularUnit());
+ if (targetUnit.conversionToSI() == 0.0) {
+ throw io::FormattingException(
+ "cannot convert value to target angular unit");
+ }
+ formatter->add(l_value.convertToUnit(targetUnit));
+ } else {
+ formatter->add(l_value.getSIValue());
+ }
+ }
+ if (isWKT2 && unit != common::UnitOfMeasure::NONE) {
+ if (!formatter
+ ->primeMeridianOrParameterUnitOmittedIfSameAsAxis() ||
+ (unit != common::UnitOfMeasure::SCALE_UNITY &&
+ unit != *(formatter->axisLinearUnit()) &&
+ unit != *(formatter->axisAngularUnit()))) {
+ unit._exportToWKT(formatter);
+ }
}
}
} else if (l_type == Type::STRING || l_type == Type::FILENAME) {
@@ -2256,6 +2354,10 @@ ConversionNNPtr Conversion::shallowClone() const {
conv->setCRSs(this, false);
return conv;
}
+
+CoordinateOperationNNPtr Conversion::_shallowClone() const {
+ return util::nn_static_pointer_cast<CoordinateOperation>(shallowClone());
+}
//! @endcond
// ---------------------------------------------------------------------------
@@ -4593,6 +4695,16 @@ InverseConversion::create(const ConversionNNPtr &forward) {
return conv;
}
+// ---------------------------------------------------------------------------
+
+CoordinateOperationNNPtr InverseConversion::_shallowClone() const {
+ auto op = InverseConversion::nn_make_shared<InverseConversion>(
+ inverseAsConversion()->shallowClone());
+ op->assignSelf(op);
+ op->setCRSs(this, false);
+ return util::nn_static_pointer_cast<CoordinateOperation>(op);
+}
+
//! @endcond
// ---------------------------------------------------------------------------
@@ -4779,7 +4891,7 @@ ConversionPtr Conversion::convertToOtherMethod(int targetEPSGCode) const {
common::Length(
parameterValueMeasure(EPSG_CODE_PARAMETER_FALSE_NORTHING)));
conv->setCRSs(this, false);
- return std::move(conv);
+ return conv.as_nullable();
}
if (current_epsg_code == EPSG_CODE_METHOD_MERCATOR_VARIANT_B &&
@@ -4800,7 +4912,7 @@ ConversionPtr Conversion::convertToOtherMethod(int targetEPSGCode) const {
common::Length(
parameterValueMeasure(EPSG_CODE_PARAMETER_FALSE_NORTHING)));
conv->setCRSs(this, false);
- return std::move(conv);
+ return conv.as_nullable();
}
if (current_epsg_code == EPSG_CODE_METHOD_LAMBERT_CONIC_CONFORMAL_1SP &&
@@ -4835,7 +4947,7 @@ ConversionPtr Conversion::convertToOtherMethod(int targetEPSGCode) const {
common::Length(
parameterValueMeasure(EPSG_CODE_PARAMETER_FALSE_NORTHING)));
conv->setCRSs(this, false);
- return std::move(conv);
+ return conv.as_nullable();
} else {
const double K = k0 * m0 / std::pow(t0, n);
const double phi1 =
@@ -4891,7 +5003,7 @@ ConversionPtr Conversion::convertToOtherMethod(int targetEPSGCode) const {
EPSG_CODE_PARAMETER_FALSE_EASTING)),
common::Length(FN_corrected_rounded));
conv->setCRSs(this, false);
- return std::move(conv);
+ return conv.as_nullable();
}
}
@@ -4905,7 +5017,7 @@ ConversionPtr Conversion::convertToOtherMethod(int targetEPSGCode) const {
parameterValueMeasure(EPSG_CODE_PARAMETER_FALSE_EASTING)),
common::Length(FN));
conv->setCRSs(this, false);
- return std::move(conv);
+ return conv.as_nullable();
}
}
@@ -4969,7 +5081,7 @@ ConversionPtr Conversion::convertToOtherMethod(int targetEPSGCode) const {
EPSG_CODE_PARAMETER_NORTHING_FALSE_ORIGIN) +
(std::fabs(FN_correction) > 1e-8 ? FN_correction : 0)));
conv->setCRSs(this, false);
- return std::move(conv);
+ return conv.as_nullable();
}
return nullptr;
@@ -5008,10 +5120,11 @@ static void getESRIMethodNameAndParams(const Conversion *conv,
}
} else if (esriMapping->epsg_code ==
EPSG_CODE_METHOD_TRANSVERSE_MERCATOR) {
- if (l_targetCRS &&
- (ci_find(l_targetCRS->nameStr(), "Gauss") !=
- std::string::npos ||
- ci_find(l_targetCRS->nameStr(), "GK_") != std::string::npos)) {
+ if (ci_find(conv->nameStr(), "Gauss Kruger") != std::string::npos ||
+ (l_targetCRS && (ci_find(l_targetCRS->nameStr(), "Gauss") !=
+ std::string::npos ||
+ ci_find(l_targetCRS->nameStr(), "GK_") !=
+ std::string::npos))) {
esriParams = paramsESRI_Gauss_Kruger;
esriMethodName = "Gauss_Kruger";
} else {
@@ -5095,6 +5208,7 @@ const char *Conversion::getWKT1GDALMethodName() const {
// ---------------------------------------------------------------------------
//! @cond Doxygen_Suppress
+
void Conversion::_exportToWKT(io::WKTFormatter *formatter) const {
const auto &l_method = method();
const auto &methodName = l_method->nameStr();
@@ -5124,6 +5238,17 @@ void Conversion::_exportToWKT(io::WKTFormatter *formatter) const {
formatter->pushOutputId(false);
}
+#ifdef DEBUG_CONVERSION_ID
+ if (sourceCRS() && targetCRS()) {
+ formatter->startNode("SOURCECRS_ID", false);
+ sourceCRS()->formatID(formatter);
+ formatter->endNode();
+ formatter->startNode("TARGETCRS_ID", false);
+ targetCRS()->formatID(formatter);
+ formatter->endNode();
+ }
+#endif
+
bool bAlreadyWritten = false;
if (!isWKT2 && formatter->useESRIDialect()) {
const ESRIParamMapping *esriParams = nullptr;
@@ -5644,7 +5769,9 @@ void Conversion::_exportToPROJString(
common::UnitOfMeasure(std::string(), 1.0 / convFactor,
common::UnitOfMeasure::Type::LINEAR)
.exportToPROJString();
- if (!uom.empty()) {
+ if (uom == "m") {
+ // do nothing
+ } else if (!uom.empty()) {
formatter->addStep("unitconvert");
formatter->addParam("z_in", uom);
formatter->addParam("z_out", "m");
@@ -5948,10 +6075,14 @@ const crs::CRSNNPtr &Transformation::targetCRS() PROJ_PURE_DEFN {
//! @cond Doxygen_Suppress
TransformationNNPtr Transformation::shallowClone() const {
- auto conv = Transformation::nn_make_shared<Transformation>(*this);
- conv->assignSelf(conv);
- conv->setCRSs(this, false);
- return conv;
+ auto transf = Transformation::nn_make_shared<Transformation>(*this);
+ transf->assignSelf(transf);
+ transf->setCRSs(this, false);
+ return transf;
+}
+
+CoordinateOperationNNPtr Transformation::_shallowClone() const {
+ return util::nn_static_pointer_cast<CoordinateOperation>(shallowClone());
}
//! @endcond
@@ -6136,12 +6267,17 @@ TransformationNNPtr Transformation::create(
throw InvalidOperation(
"Inconsistent number of parameters and parameter values");
}
- auto conv = Transformation::nn_make_shared<Transformation>(
+ auto transf = Transformation::nn_make_shared<Transformation>(
sourceCRSIn, targetCRSIn, interpolationCRSIn, methodIn, values,
accuracies);
- conv->assignSelf(conv);
- conv->setProperties(properties);
- return conv;
+ transf->assignSelf(transf);
+ transf->setProperties(properties);
+ std::string name;
+ if (properties.getStringValue(common::IdentifiedObject::NAME_KEY, name) &&
+ ci_find(name, "ballpark") != std::string::npos) {
+ transf->setHasBallparkTransformation(true);
+ }
+ return transf;
}
// ---------------------------------------------------------------------------
@@ -6822,11 +6958,11 @@ TransformationNNPtr Transformation::createNTv2(
static TransformationNNPtr _createGravityRelatedHeightToGeographic3D(
const util::PropertyMap &properties, bool inverse,
const crs::CRSNNPtr &sourceCRSIn, const crs::CRSNNPtr &targetCRSIn,
- const std::string &filename,
+ const crs::CRSPtr &interpolationCRSIn, const std::string &filename,
const std::vector<metadata::PositionalAccuracyNNPtr> &accuracies) {
return Transformation::create(
- properties, sourceCRSIn, targetCRSIn, nullptr,
+ properties, sourceCRSIn, targetCRSIn, interpolationCRSIn,
util::PropertyMap().set(
common::IdentifiedObject::NAME_KEY,
inverse ? INVERSE_OF + PROJ_WKT2_NAME_METHOD_HEIGHT_TO_GEOG3D
@@ -6845,17 +6981,20 @@ static TransformationNNPtr _createGravityRelatedHeightToGeographic3D(
* At minimum the name should be defined.
* @param sourceCRSIn Source CRS.
* @param targetCRSIn Target CRS.
+ * @param interpolationCRSIn Interpolation CRS. (might be null)
* @param filename GRID filename.
* @param accuracies Vector of positional accuracy (might be empty).
* @return new Transformation.
*/
TransformationNNPtr Transformation::createGravityRelatedHeightToGeographic3D(
const util::PropertyMap &properties, const crs::CRSNNPtr &sourceCRSIn,
- const crs::CRSNNPtr &targetCRSIn, const std::string &filename,
+ const crs::CRSNNPtr &targetCRSIn, const crs::CRSPtr &interpolationCRSIn,
+ const std::string &filename,
const std::vector<metadata::PositionalAccuracyNNPtr> &accuracies) {
return _createGravityRelatedHeightToGeographic3D(
- properties, false, sourceCRSIn, targetCRSIn, filename, accuracies);
+ properties, false, sourceCRSIn, targetCRSIn, interpolationCRSIn,
+ filename, accuracies);
}
// ---------------------------------------------------------------------------
@@ -7054,6 +7193,39 @@ TransformationNNPtr Transformation::createVerticalOffset(
// ---------------------------------------------------------------------------
+/** \brief Instantiate a transformation based on the Change of Vertical Unit
+ * method.
+ *
+ * This method is defined as [EPSG:1069]
+ * (https://www.epsg-registry.org/export.htm?gml=urn:ogc:def:method:EPSG::1069)
+ *
+ * @param properties See \ref general_properties of the conversion. If the name
+ * is not provided, it is automatically set.
+ * @param sourceCRSIn Source CRS.
+ * @param targetCRSIn Target CRS.
+ * @param factor Conversion factor
+ * @param accuracies Vector of positional accuracy (might be empty).
+ * @return a new Transformation.
+ */
+TransformationNNPtr Transformation::createChangeVerticalUnit(
+ const util::PropertyMap &properties, const crs::CRSNNPtr &sourceCRSIn,
+ const crs::CRSNNPtr &targetCRSIn, const common::Scale &factor,
+ const std::vector<metadata::PositionalAccuracyNNPtr> &accuracies) {
+ return create(
+ properties, sourceCRSIn, targetCRSIn, nullptr,
+ createMethodMapNameEPSGCode(EPSG_CODE_METHOD_CHANGE_VERTICAL_UNIT),
+ VectorOfParameters{
+ createOpParamNameEPSGCode(
+ EPSG_CODE_PARAMETER_UNIT_CONVERSION_SCALAR),
+ },
+ VectorOfValues{
+ factor,
+ },
+ accuracies);
+}
+
+// ---------------------------------------------------------------------------
+
static const char *getCRSQualifierStr(const crs::CRSPtr &crs) {
auto geod = dynamic_cast<crs::GeodeticCRS *>(crs.get());
if (geod) {
@@ -7114,8 +7286,10 @@ createPropertiesForInverse(const CoordinateOperation *op, bool derivedFrom,
// Forge a name for the inverse, either from the forward name, or
// from the source and target CRS names
const char *opType;
- if (starts_with(forwardName, NULL_GEOCENTRIC_TRANSLATION)) {
- opType = NULL_GEOCENTRIC_TRANSLATION;
+ if (starts_with(forwardName, BALLPARK_GEOCENTRIC_TRANSLATION)) {
+ opType = BALLPARK_GEOCENTRIC_TRANSLATION;
+ } else if (starts_with(forwardName, BALLPARK_GEOGRAPHIC_OFFSET)) {
+ opType = BALLPARK_GEOGRAPHIC_OFFSET;
} else if (starts_with(forwardName, NULL_GEOGRAPHIC_OFFSET)) {
opType = NULL_GEOGRAPHIC_OFFSET;
} else if (dynamic_cast<const Transformation *>(op) ||
@@ -7131,8 +7305,20 @@ createPropertiesForInverse(const CoordinateOperation *op, bool derivedFrom,
auto targetCRS = op->targetCRS();
std::string name;
if (!forwardName.empty()) {
- if (starts_with(forwardName, INVERSE_OF)) {
- name = forwardName.substr(INVERSE_OF.size());
+ if (starts_with(forwardName, INVERSE_OF) ||
+ forwardName.find(" + ") != std::string::npos) {
+ auto tokens = split(forwardName, " + ");
+ for (size_t i = tokens.size(); i > 0;) {
+ i--;
+ if (!name.empty()) {
+ name += " + ";
+ }
+ if (starts_with(tokens[i], INVERSE_OF)) {
+ name += tokens[i].substr(INVERSE_OF.size());
+ } else {
+ name += INVERSE_OF + tokens[i];
+ }
+ }
} else if (!sourceCRS || !targetCRS ||
forwardName != buildOpName(opType, sourceCRS, targetCRS)) {
name = INVERSE_OF + forwardName;
@@ -7314,6 +7500,8 @@ Transformation::Private::registerInv(util::BaseObjectNNPtr thisIn,
TransformationNNPtr invTransform) {
invTransform->d->forwardOperation_ =
util::nn_dynamic_pointer_cast<Transformation>(thisIn);
+ invTransform->setHasBallparkTransformation(
+ invTransform->d->forwardOperation_->hasBallparkTransformation());
return invTransform;
}
//! @endcond
@@ -7481,6 +7669,17 @@ TransformationNNPtr Transformation::inverseAsTransformation() const {
coordinateOperationAccuracies()));
}
+ if (methodEPSGCode == EPSG_CODE_METHOD_CHANGE_VERTICAL_UNIT) {
+ const double convFactor = parameterValueNumericAsSI(
+ EPSG_CODE_PARAMETER_UNIT_CONVERSION_SCALAR);
+ return d->registerInv(
+ shared_from_this(),
+ createChangeVerticalUnit(
+ createPropertiesForInverse(this, false, false), l_targetCRS,
+ l_sourceCRS, common::Scale(1.0 / convFactor),
+ coordinateOperationAccuracies()));
+ }
+
return InverseTransformation::create(NN_NO_CHECK(
util::nn_dynamic_pointer_cast<Transformation>(shared_from_this())));
}
@@ -7517,6 +7716,13 @@ InverseTransformation::create(const TransformationNNPtr &forward) {
// ---------------------------------------------------------------------------
+TransformationNNPtr InverseTransformation::inverseAsTransformation() const {
+ return NN_NO_CHECK(
+ util::nn_dynamic_pointer_cast<Transformation>(forwardOperation_));
+}
+
+// ---------------------------------------------------------------------------
+
void InverseTransformation::_exportToWKT(io::WKTFormatter *formatter) const {
auto approxInverse = createApproximateInverseIfPossible(
@@ -7528,6 +7734,16 @@ void InverseTransformation::_exportToWKT(io::WKTFormatter *formatter) const {
}
}
+// ---------------------------------------------------------------------------
+
+CoordinateOperationNNPtr InverseTransformation::_shallowClone() const {
+ auto op = InverseTransformation::nn_make_shared<InverseTransformation>(
+ inverseAsTransformation()->shallowClone());
+ op->assignSelf(op);
+ op->setCRSs(this, false);
+ return util::nn_static_pointer_cast<CoordinateOperation>(op);
+}
+
//! @endcond
// ---------------------------------------------------------------------------
@@ -7540,6 +7756,53 @@ void Transformation::_exportToWKT(io::WKTFormatter *formatter) const {
// ---------------------------------------------------------------------------
+static void exportSourceCRSAndTargetCRSToWKT(const CoordinateOperation *co,
+ io::WKTFormatter *formatter) {
+ auto l_sourceCRS = co->sourceCRS();
+ assert(l_sourceCRS);
+ auto l_targetCRS = co->targetCRS();
+ assert(l_targetCRS);
+ const bool isWKT2 = formatter->version() == io::WKTFormatter::Version::WKT2;
+ const bool canExportCRSId =
+ (isWKT2 && formatter->use2018Keywords() &&
+ !(formatter->idOnTopLevelOnly() && formatter->topLevelHasId()));
+
+ const bool hasDomains = !co->domains().empty();
+ if (hasDomains) {
+ formatter->pushDisableUsage();
+ }
+
+ formatter->startNode(io::WKTConstants::SOURCECRS, false);
+ if (canExportCRSId && !l_sourceCRS->identifiers().empty()) {
+ // fake that top node has no id, so that the sourceCRS id is
+ // considered
+ formatter->pushHasId(false);
+ l_sourceCRS->_exportToWKT(formatter);
+ formatter->popHasId();
+ } else {
+ l_sourceCRS->_exportToWKT(formatter);
+ }
+ formatter->endNode();
+
+ formatter->startNode(io::WKTConstants::TARGETCRS, false);
+ if (canExportCRSId && !l_targetCRS->identifiers().empty()) {
+ // fake that top node has no id, so that the targetCRS id is
+ // considered
+ formatter->pushHasId(false);
+ l_targetCRS->_exportToWKT(formatter);
+ formatter->popHasId();
+ } else {
+ l_targetCRS->_exportToWKT(formatter);
+ }
+ formatter->endNode();
+
+ if (hasDomains) {
+ formatter->popDisableUsage();
+ }
+}
+
+// ---------------------------------------------------------------------------
+
void SingleOperation::exportTransformationToWKT(
io::WKTFormatter *formatter) const {
const bool isWKT2 = formatter->version() == io::WKTFormatter::Version::WKT2;
@@ -7548,11 +7811,6 @@ void SingleOperation::exportTransformationToWKT(
"Transformation can only be exported to WKT2");
}
- auto l_sourceCRS = sourceCRS();
- assert(l_sourceCRS);
- auto l_targetCRS = targetCRS();
- assert(l_targetCRS);
-
if (formatter->abridgedTransformation()) {
formatter->startNode(io::WKTConstants::ABRIDGEDTRANSFORMATION,
!identifiers().empty());
@@ -7563,22 +7821,23 @@ void SingleOperation::exportTransformationToWKT(
formatter->addQuotedString(nameStr());
- if (!formatter->abridgedTransformation()) {
- formatter->startNode(io::WKTConstants::SOURCECRS, false);
- l_sourceCRS->_exportToWKT(formatter);
- formatter->endNode();
+ if (formatter->use2018Keywords()) {
+ const auto &version = operationVersion();
+ if (version.has_value()) {
+ formatter->startNode(io::WKTConstants::VERSION, false);
+ formatter->addQuotedString(*version);
+ formatter->endNode();
+ }
+ }
- formatter->startNode(io::WKTConstants::TARGETCRS, false);
- l_targetCRS->_exportToWKT(formatter);
- formatter->endNode();
+ if (!formatter->abridgedTransformation()) {
+ exportSourceCRSAndTargetCRSToWKT(this, formatter);
}
method()->_exportToWKT(formatter);
- const MethodMapping *mapping =
- !isWKT2 ? getMapping(method().get()) : nullptr;
for (const auto &paramValue : parameterValues()) {
- paramValue->_exportToWKT(formatter, mapping);
+ paramValue->_exportToWKT(formatter, nullptr);
}
if (!formatter->abridgedTransformation()) {
@@ -7951,13 +8210,14 @@ TransformationNNPtr Transformation::substitutePROJAlternativeGridNames(
return createGravityRelatedHeightToGeographic3D(
createPropertiesForInverse(self.as_nullable().get(),
true, false),
- targetCRS(), sourceCRS(), projFilename,
- coordinateOperationAccuracies())
+ targetCRS(), sourceCRS(), interpolationCRS(),
+ projFilename, coordinateOperationAccuracies())
->inverseAsTransformation();
} else {
return createGravityRelatedHeightToGeographic3D(
createSimilarPropertiesTransformation(self), sourceCRS(),
- targetCRS(), projFilename, coordinateOperationAccuracies());
+ targetCRS(), interpolationCRS(), projFilename,
+ coordinateOperationAccuracies());
}
}
}
@@ -8001,6 +8261,46 @@ TransformationNNPtr Transformation::substitutePROJAlternativeGridNames(
}
}
+ if (methodEPSGCode == EPSG_CODE_METHOD_VERTCON) {
+ auto fileParameter =
+ parameterValue(EPSG_NAME_PARAMETER_VERTICAL_OFFSET_FILE,
+ EPSG_CODE_PARAMETER_VERTICAL_OFFSET_FILE);
+ if (fileParameter &&
+ fileParameter->type() == ParameterValue::Type::FILENAME) {
+
+ auto filename = fileParameter->valueFile();
+ if (databaseContext->lookForGridAlternative(
+ filename, projFilename, projGridFormat, inverseDirection)) {
+
+ if (filename == projFilename) {
+ assert(!inverseDirection);
+ return self;
+ }
+
+ auto parameters = std::vector<OperationParameterNNPtr>{
+ createOpParamNameEPSGCode(
+ EPSG_CODE_PARAMETER_VERTICAL_OFFSET_FILE)};
+ if (inverseDirection) {
+ return create(createPropertiesForInverse(
+ self.as_nullable().get(), true, false),
+ targetCRS(), sourceCRS(), nullptr,
+ createSimilarPropertiesMethod(method()),
+ parameters, {ParameterValue::createFilename(
+ projFilename)},
+ coordinateOperationAccuracies())
+ ->inverseAsTransformation();
+ } else {
+ return create(
+ createSimilarPropertiesTransformation(self),
+ sourceCRS(), targetCRS(), nullptr,
+ createSimilarPropertiesMethod(method()), parameters,
+ {ParameterValue::createFilename(projFilename)},
+ coordinateOperationAccuracies());
+ }
+ }
+ }
+ }
+
return self;
}
// ---------------------------------------------------------------------------
@@ -8016,7 +8316,7 @@ static void ThrowExceptionNotGeodeticGeographic(const char *trfrm_name) {
// ---------------------------------------------------------------------------
static void setupPROJGeodeticSourceCRS(io::PROJStringFormatter *formatter,
- const crs::CRSNNPtr &crs,
+ const crs::CRSNNPtr &crs, bool addPushV3,
const char *trfrm_name) {
auto sourceCRSGeog = dynamic_cast<const crs::GeographicCRS *>(crs.get());
if (sourceCRSGeog) {
@@ -8024,6 +8324,11 @@ static void setupPROJGeodeticSourceCRS(io::PROJStringFormatter *formatter,
sourceCRSGeog->_exportToPROJString(formatter);
formatter->stopInversion();
+ if (addPushV3) {
+ formatter->addStep("push");
+ formatter->addParam("v_3");
+ }
+
formatter->addStep("cart");
sourceCRSGeog->ellipsoid()->_exportToPROJString(formatter);
} else {
@@ -8039,7 +8344,7 @@ static void setupPROJGeodeticSourceCRS(io::PROJStringFormatter *formatter,
// ---------------------------------------------------------------------------
static void setupPROJGeodeticTargetCRS(io::PROJStringFormatter *formatter,
- const crs::CRSNNPtr &crs,
+ const crs::CRSNNPtr &crs, bool addPopV3,
const char *trfrm_name) {
auto targetCRSGeog = dynamic_cast<const crs::GeographicCRS *>(crs.get());
if (targetCRSGeog) {
@@ -8047,6 +8352,11 @@ static void setupPROJGeodeticTargetCRS(io::PROJStringFormatter *formatter,
formatter->setCurrentStepInverted(true);
targetCRSGeog->ellipsoid()->_exportToPROJString(formatter);
+ if (addPopV3) {
+ formatter->addStep("pop");
+ formatter->addParam("v_3");
+ }
+
targetCRSGeog->_exportToPROJString(formatter);
} else {
auto targetCRSGeod = dynamic_cast<const crs::GeodeticCRS *>(crs.get());
@@ -8138,19 +8448,19 @@ void Transformation::_exportToPROJString(
double z =
parameterValueNumericAsSI(EPSG_CODE_PARAMETER_Z_AXIS_TRANSLATION);
- if (methodEPSGCode == EPSG_CODE_METHOD_COORDINATE_FRAME_GEOGRAPHIC_2D ||
- methodEPSGCode ==
- EPSG_CODE_METHOD_TIME_DEPENDENT_COORDINATE_FRAME_GEOGRAPHIC_2D ||
- methodEPSGCode == EPSG_CODE_METHOD_POSITION_VECTOR_GEOGRAPHIC_2D ||
- methodEPSGCode ==
- EPSG_CODE_METHOD_TIME_DEPENDENT_POSITION_VECTOR_GEOGRAPHIC_2D ||
- methodEPSGCode ==
- EPSG_CODE_METHOD_GEOCENTRIC_TRANSLATION_GEOGRAPHIC_2D) {
- formatter->addStep("push");
- formatter->addParam("v_3");
- }
+ bool addPushPopV3 =
+ (methodEPSGCode ==
+ EPSG_CODE_METHOD_COORDINATE_FRAME_GEOGRAPHIC_2D ||
+ methodEPSGCode ==
+ EPSG_CODE_METHOD_TIME_DEPENDENT_COORDINATE_FRAME_GEOGRAPHIC_2D ||
+ methodEPSGCode == EPSG_CODE_METHOD_POSITION_VECTOR_GEOGRAPHIC_2D ||
+ methodEPSGCode ==
+ EPSG_CODE_METHOD_TIME_DEPENDENT_POSITION_VECTOR_GEOGRAPHIC_2D ||
+ methodEPSGCode ==
+ EPSG_CODE_METHOD_GEOCENTRIC_TRANSLATION_GEOGRAPHIC_2D);
- setupPROJGeodeticSourceCRS(formatter, sourceCRS(), "Helmert");
+ setupPROJGeodeticSourceCRS(formatter, sourceCRS(), addPushPopV3,
+ "Helmert");
formatter->addStep("helmert");
formatter->addParam("x", x);
@@ -8214,19 +8524,8 @@ void Transformation::_exportToPROJString(
}
}
- setupPROJGeodeticTargetCRS(formatter, targetCRS(), "Helmert");
-
- if (methodEPSGCode == EPSG_CODE_METHOD_COORDINATE_FRAME_GEOGRAPHIC_2D ||
- methodEPSGCode ==
- EPSG_CODE_METHOD_TIME_DEPENDENT_COORDINATE_FRAME_GEOGRAPHIC_2D ||
- methodEPSGCode == EPSG_CODE_METHOD_POSITION_VECTOR_GEOGRAPHIC_2D ||
- methodEPSGCode ==
- EPSG_CODE_METHOD_TIME_DEPENDENT_POSITION_VECTOR_GEOGRAPHIC_2D ||
- methodEPSGCode ==
- EPSG_CODE_METHOD_GEOCENTRIC_TRANSLATION_GEOGRAPHIC_2D) {
- formatter->addStep("pop");
- formatter->addParam("v_3");
- }
+ setupPROJGeodeticTargetCRS(formatter, targetCRS(), addPushPopV3,
+ "Helmert");
return;
}
@@ -8274,15 +8573,13 @@ void Transformation::_exportToPROJString(
double pz = parameterValueNumericAsSI(
EPSG_CODE_PARAMETER_ORDINATE_3_EVAL_POINT);
- if (methodEPSGCode ==
- EPSG_CODE_METHOD_MOLODENSKY_BADEKAS_PV_GEOGRAPHIC_2D ||
- methodEPSGCode ==
- EPSG_CODE_METHOD_MOLODENSKY_BADEKAS_CF_GEOGRAPHIC_2D) {
- formatter->addStep("push");
- formatter->addParam("v_3");
- }
+ bool addPushPopV3 =
+ (methodEPSGCode ==
+ EPSG_CODE_METHOD_MOLODENSKY_BADEKAS_PV_GEOGRAPHIC_2D ||
+ methodEPSGCode ==
+ EPSG_CODE_METHOD_MOLODENSKY_BADEKAS_CF_GEOGRAPHIC_2D);
- setupPROJGeodeticSourceCRS(formatter, sourceCRS(),
+ setupPROJGeodeticSourceCRS(formatter, sourceCRS(), addPushPopV3,
"Molodensky-Badekas");
formatter->addStep("molobadekas");
@@ -8302,17 +8599,9 @@ void Transformation::_exportToPROJString(
formatter->addParam("convention", "coordinate_frame");
}
- setupPROJGeodeticTargetCRS(formatter, targetCRS(),
+ setupPROJGeodeticTargetCRS(formatter, targetCRS(), addPushPopV3,
"Molodensky-Badekas");
- if (methodEPSGCode ==
- EPSG_CODE_METHOD_MOLODENSKY_BADEKAS_PV_GEOGRAPHIC_2D ||
- methodEPSGCode ==
- EPSG_CODE_METHOD_MOLODENSKY_BADEKAS_CF_GEOGRAPHIC_2D) {
- formatter->addStep("pop");
- formatter->addParam("v_3");
- }
-
return;
}
@@ -8605,13 +8894,25 @@ void Transformation::_exportToPROJString(
if (fileParameter &&
fileParameter->type() == ParameterValue::Type::FILENAME) {
auto filename = fileParameter->valueFile();
- if (isMethodInverseOf) {
+ bool doInversion = isMethodInverseOf;
+ if (!identifiers().empty() &&
+ *identifiers().front()->codeSpace() ==
+ metadata::Identifier::EPSG &&
+ method()->nameStr() ==
+ "Geographic3D to GravityRelatedHeight (US .gtx)" &&
+ ends_with(filename, ".gtx")) {
+ // gtx files, from straight EPSG definition, must be applied in
+ // reverse order for "Geographic3D to GravityRelatedHeight"
+ // method
+ doInversion = !doInversion;
+ }
+ if (doInversion) {
formatter->startInversion();
}
formatter->addStep("vgridshift");
formatter->addParam("grids", filename);
formatter->addParam("multiplier", 1.0);
- if (isMethodInverseOf) {
+ if (doInversion) {
formatter->stopInversion();
}
return;
@@ -8795,6 +9096,33 @@ bool SingleOperation::exportToPROJStringGeneric(
"conversion");
}
+ if (methodEPSGCode == EPSG_CODE_METHOD_CHANGE_VERTICAL_UNIT) {
+ double convFactor = parameterValueNumericAsSI(
+ EPSG_CODE_PARAMETER_UNIT_CONVERSION_SCALAR);
+ auto uom = common::UnitOfMeasure(std::string(), convFactor,
+ common::UnitOfMeasure::Type::LINEAR)
+ .exportToPROJString();
+ auto reverse_uom =
+ common::UnitOfMeasure(std::string(), 1.0 / convFactor,
+ common::UnitOfMeasure::Type::LINEAR)
+ .exportToPROJString();
+ if (uom == "m") {
+ // do nothing
+ } else if (!uom.empty()) {
+ formatter->addStep("unitconvert");
+ formatter->addParam("z_in", uom);
+ formatter->addParam("z_out", "m");
+ } else if (!reverse_uom.empty()) {
+ formatter->addStep("unitconvert");
+ formatter->addParam("z_in", "m");
+ formatter->addParam("z_out", reverse_uom);
+ } else {
+ formatter->addStep("affine");
+ formatter->addParam("s33", convFactor);
+ }
+ return true;
+ }
+
return false;
}
@@ -8813,6 +9141,7 @@ struct ConcatenatedOperation::Private {
explicit Private(const std::vector<CoordinateOperationNNPtr> &operationsIn)
: operations_(operationsIn) {}
+ Private(const Private &) = default;
};
//! @endcond
@@ -8824,6 +9153,14 @@ ConcatenatedOperation::~ConcatenatedOperation() = default;
// ---------------------------------------------------------------------------
+//! @cond Doxygen_Suppress
+ConcatenatedOperation::ConcatenatedOperation(const ConcatenatedOperation &other)
+ : CoordinateOperation(other),
+ d(internal::make_unique<Private>(*(other.d))) {}
+//! @endcond
+
+// ---------------------------------------------------------------------------
+
ConcatenatedOperation::ConcatenatedOperation(
const std::vector<CoordinateOperationNNPtr> &operationsIn)
: CoordinateOperation(), d(internal::make_unique<Private>(operationsIn)) {}
@@ -8886,6 +9223,22 @@ ConcatenatedOperationNNPtr ConcatenatedOperation::create(
}
if (i >= 1) {
if (!compareStepCRS(l_sourceCRS.get(), lastTargetCRS.get())) {
+#ifdef DEBUG_CONCATENATED_OPERATION
+ {
+ auto f(io::WKTFormatter::create(
+ io::WKTFormatter::Convention::WKT2_2018));
+ std::cerr << "Source CRS of step " << i << ":" << std::endl;
+ std::cerr << l_sourceCRS->exportToWKT(f.get()) << std::endl;
+ }
+ {
+ auto f(io::WKTFormatter::create(
+ io::WKTFormatter::Convention::WKT2_2018));
+ std::cerr << "Target CRS of step " << i - 1 << ":"
+ << std::endl;
+ std::cerr << lastTargetCRS->exportToWKT(f.get())
+ << std::endl;
+ }
+#endif
throw InvalidOperation(
"Inconsistent chaining of CRS in operations");
}
@@ -8899,6 +9252,14 @@ ConcatenatedOperationNNPtr ConcatenatedOperation::create(
op->setCRSs(NN_NO_CHECK(operationsIn[0]->sourceCRS()),
NN_NO_CHECK(operationsIn.back()->targetCRS()), nullptr);
op->setAccuracies(accuracies);
+#ifdef DEBUG_CONCATENATED_OPERATION
+ {
+ auto f(
+ io::WKTFormatter::create(io::WKTFormatter::Convention::WKT2_2018));
+ std::cerr << "ConcatenatedOperation::create()" << std::endl;
+ std::cerr << op->exportToWKT(f.get()) << std::endl;
+ }
+#endif
return op;
}
@@ -8951,6 +9312,7 @@ void ConcatenatedOperation::fixStepsDirection(
op = op->inverse();
}
} else if (i + 1 < operationsInOut.size()) {
+ /* coverity[copy_paste_error] */
l_targetCRS = operationsInOut[i + 1]->sourceCRS();
if (l_targetCRS) {
op->setCRSs(concatOpSourceCRS, NN_NO_CHECK(l_targetCRS),
@@ -9080,7 +9442,9 @@ CoordinateOperationNNPtr ConcatenatedOperation::createComputeMetadata(
}
std::vector<CoordinateOperationNNPtr> flattenOps;
+ bool hasBallparkTransformation = false;
for (const auto &subOp : operationsIn) {
+ hasBallparkTransformation |= subOp->hasBallparkTransformation();
auto subOpConcat =
dynamic_cast<const ConcatenatedOperation *>(subOp.get());
if (subOpConcat) {
@@ -9120,6 +9484,7 @@ CoordinateOperationNNPtr ConcatenatedOperation::createComputeMetadata(
}
auto op = create(properties, flattenOps, accuracies);
+ op->setHasBallparkTransformation(hasBallparkTransformation);
op->d->computedName_ = true;
return op;
}
@@ -9144,6 +9509,7 @@ CoordinateOperationNNPtr ConcatenatedOperation::inverse() const {
auto op =
create(properties, inversedOperations, coordinateOperationAccuracies());
op->d->computedName_ = d->computedName_;
+ op->setHasBallparkTransformation(hasBallparkTransformation());
return op;
}
@@ -9161,20 +9527,43 @@ void ConcatenatedOperation::_exportToWKT(io::WKTFormatter *formatter) const {
!identifiers().empty());
formatter->addQuotedString(nameStr());
- formatter->startNode(io::WKTConstants::SOURCECRS, false);
- sourceCRS()->_exportToWKT(formatter);
- formatter->endNode();
+ if (isWKT2 && formatter->use2018Keywords()) {
+ const auto &version = operationVersion();
+ if (version.has_value()) {
+ formatter->startNode(io::WKTConstants::VERSION, false);
+ formatter->addQuotedString(*version);
+ formatter->endNode();
+ }
+ }
- formatter->startNode(io::WKTConstants::TARGETCRS, false);
- targetCRS()->_exportToWKT(formatter);
- formatter->endNode();
+ exportSourceCRSAndTargetCRSToWKT(this, formatter);
+
+ const bool canExportOperationId =
+ !(formatter->idOnTopLevelOnly() && formatter->topLevelHasId());
+
+ const bool hasDomains = !domains().empty();
+ if (hasDomains) {
+ formatter->pushDisableUsage();
+ }
for (const auto &operation : operations()) {
formatter->startNode(io::WKTConstants::STEP, false);
- operation->_exportToWKT(formatter);
+ if (canExportOperationId && !operation->identifiers().empty()) {
+ // fake that top node has no id, so that the operation id is
+ // considered
+ formatter->pushHasId(false);
+ operation->_exportToWKT(formatter);
+ formatter->popHasId();
+ } else {
+ operation->_exportToWKT(formatter);
+ }
formatter->endNode();
}
+ if (hasDomains) {
+ formatter->popDisableUsage();
+ }
+
ObjectUsage::baseExportToWKT(formatter);
formatter->endNode();
}
@@ -9182,6 +9571,18 @@ void ConcatenatedOperation::_exportToWKT(io::WKTFormatter *formatter) const {
// ---------------------------------------------------------------------------
+//! @cond Doxygen_Suppress
+CoordinateOperationNNPtr ConcatenatedOperation::_shallowClone() const {
+ auto op =
+ ConcatenatedOperation::nn_make_shared<ConcatenatedOperation>(*this);
+ op->assignSelf(op);
+ op->setCRSs(this, false);
+ return util::nn_static_pointer_cast<CoordinateOperation>(op);
+}
+//! @endcond
+
+// ---------------------------------------------------------------------------
+
void ConcatenatedOperation::_exportToPROJString(
io::PROJStringFormatter *formatter) const // throw(FormattingException)
{
@@ -9627,14 +10028,18 @@ struct PrecomputedOpCharacteristics {
bool gridsAvailable_ = false;
bool gridsKnown_ = false;
size_t stepCount_ = 0;
+ bool isApprox_ = false;
+ bool isNullTransformation_ = false;
PrecomputedOpCharacteristics() = default;
PrecomputedOpCharacteristics(double area, double accuracy, bool hasGrids,
bool gridsAvailable, bool gridsKnown,
- size_t stepCount)
+ size_t stepCount, bool isApprox,
+ bool isNullTransformation)
: area_(area), accuracy_(accuracy), hasGrids_(hasGrids),
gridsAvailable_(gridsAvailable), gridsKnown_(gridsKnown),
- stepCount_(stepCount) {}
+ stepCount_(stepCount), isApprox_(isApprox),
+ isNullTransformation_(isNullTransformation) {}
};
// ---------------------------------------------------------------------------
@@ -9661,6 +10066,22 @@ struct SortFunction {
// CAUTION: the order of the comparisons is extremely important
// to get the intended result.
+ if (!iterA->second.isApprox_ && iterB->second.isApprox_) {
+ return true;
+ }
+ if (iterA->second.isApprox_ && !iterB->second.isApprox_) {
+ return false;
+ }
+
+ if (!iterA->second.isNullTransformation_ &&
+ iterB->second.isNullTransformation_) {
+ return true;
+ }
+ if (iterA->second.isNullTransformation_ &&
+ !iterB->second.isNullTransformation_) {
+ return false;
+ }
+
if (iterA->second.hasGrids_ && iterB->second.hasGrids_) {
// Operations where grids are all available go before other
if (iterA->second.gridsAvailable_ &&
@@ -9691,6 +10112,17 @@ struct SortFunction {
return false;
}
+ if (accuracyA < 0 && accuracyB < 0) {
+ // unknown accuracy ? then prefer operations with grids, which
+ // are likely to have best practical accuracy
+ if (iterA->second.hasGrids_ && !iterB->second.hasGrids_) {
+ return true;
+ }
+ if (!iterA->second.hasGrids_ && iterB->second.hasGrids_) {
+ return false;
+ }
+ }
+
// Operations with larger non-zero area of use go before those with
// lower one
const double areaA = iterA->second.area_;
@@ -9722,15 +10154,6 @@ struct SortFunction {
if (iterA->second.hasGrids_ && !iterB->second.hasGrids_) {
return false;
}
- } else if (accuracyA < 0 && accuracyB < 0) {
- // unknown accuracy ? then prefer operations with grids, which
- // are likely to have best practical accuracy
- if (iterA->second.hasGrids_ && !iterB->second.hasGrids_) {
- return true;
- }
- if (!iterA->second.hasGrids_ && iterB->second.hasGrids_) {
- return false;
- }
}
// The less intermediate steps, the better
@@ -9882,11 +10305,7 @@ struct FilterResults {
bool extentContains =
extent->contains(NN_NO_CHECK(areaOfInterest));
if (extentContains) {
- const auto &name = op->nameStr();
- if (name.find(NULL_GEOGRAPHIC_OFFSET) ==
- std::string::npos &&
- name.find(NULL_GEOCENTRIC_TRANSLATION) ==
- std::string::npos) {
+ if (!op->hasBallparkTransformation()) {
hasOpThatContainsAreaOfInterest = true;
}
}
@@ -9917,11 +10336,7 @@ struct FilterResults {
!targetCRSExtent ||
extent->contains(NN_NO_CHECK(targetCRSExtent));
if (extentContainsSource && extentContainsTarget) {
- const auto &name = op->nameStr();
- if (name.find(NULL_GEOGRAPHIC_OFFSET) ==
- std::string::npos &&
- name.find(NULL_GEOCENTRIC_TRANSLATION) ==
- std::string::npos) {
+ if (!op->hasBallparkTransformation()) {
hasOpThatContainsAreaOfInterest = true;
}
}
@@ -10002,13 +10417,7 @@ struct FilterResults {
bool hasGrids = false;
bool gridsAvailable = true;
bool gridsKnown = true;
- if (context->getAuthorityFactory() &&
- (gridAvailabilityUse ==
- CoordinateOperationContext::GridAvailabilityUse::
- USE_FOR_SORTING ||
- gridAvailabilityUse ==
- CoordinateOperationContext::GridAvailabilityUse::
- IGNORE_GRID_AVAILABILITY)) {
+ if (context->getAuthorityFactory()) {
const auto gridsNeeded = op->gridsNeeded(
context->getAuthorityFactory()->databaseContext());
for (const auto &gridDesc : gridsNeeded) {
@@ -10027,9 +10436,19 @@ struct FilterResults {
const auto stepCount = getStepCount(op);
+ const bool isApprox =
+ op->nameStr().find(BALLPARK_VERTICAL_TRANSFORMATION_PREFIX) !=
+ std::string::npos;
+ const bool isNullTransformation =
+ op->nameStr().find(BALLPARK_GEOGRAPHIC_OFFSET) !=
+ std::string::npos ||
+ op->nameStr().find(NULL_GEOGRAPHIC_OFFSET) !=
+ std::string::npos ||
+ op->nameStr().find(BALLPARK_GEOCENTRIC_TRANSLATION) !=
+ std::string::npos;
map[op.get()] = PrecomputedOpCharacteristics(
area, getAccuracy(op), hasGrids, gridsAvailable, gridsKnown,
- stepCount);
+ stepCount, isApprox, isNullTransformation);
}
// Sort !
@@ -10041,13 +10460,17 @@ struct FilterResults {
void removeSyntheticNullTransforms() {
// If we have more than one result, and than the last result is the
- // default "Null geographic offset" or "Null geocentric translation"
- // operations we have synthetized, remove it as
+ // default "Ballpark geographic offset" or "Ballpark geocentric
+ // translation"
+ // operations we have synthetized, and that at least one operation
+ // has the desired area of interest, remove it as
// all previous results are necessarily better
if (hasOpThatContainsAreaOfInterest && res.size() > 1) {
const std::string &name = res.back()->nameStr();
- if (name.find(NULL_GEOGRAPHIC_OFFSET) != std::string::npos ||
- name.find(NULL_GEOCENTRIC_TRANSLATION) != std::string::npos) {
+ if (name.find(BALLPARK_GEOGRAPHIC_OFFSET) != std::string::npos ||
+ name.find(NULL_GEOGRAPHIC_OFFSET) != std::string::npos ||
+ name.find(BALLPARK_GEOCENTRIC_TRANSLATION) !=
+ std::string::npos) {
std::vector<CoordinateOperationNNPtr> resTemp;
for (size_t i = 0; i < res.size() - 1; i++) {
resTemp.emplace_back(res[i]);
@@ -10460,9 +10883,20 @@ static std::vector<CoordinateOperationNNPtr> findsOpsInRegistryWithIntermediate(
//! @cond Doxygen_Suppress
static TransformationNNPtr
-createNullGeographicOffset(const crs::CRSNNPtr &sourceCRS,
- const crs::CRSNNPtr &targetCRS) {
- std::string name(NULL_GEOGRAPHIC_OFFSET);
+createBallparkGeographicOffset(const crs::CRSNNPtr &sourceCRS,
+ const crs::CRSNNPtr &targetCRS) {
+
+ const crs::GeographicCRS *geogSrc =
+ dynamic_cast<const crs::GeographicCRS *>(sourceCRS.get());
+ const crs::GeographicCRS *geogDst =
+ dynamic_cast<const crs::GeographicCRS *>(targetCRS.get());
+ const bool isSameDatum =
+ geogSrc && geogDst && geogSrc->datum() && geogDst->datum() &&
+ geogSrc->datum()->_isEquivalentTo(
+ geogDst->datum().get(), util::IComparable::Criterion::EQUIVALENT);
+
+ std::string name(isSameDatum ? NULL_GEOGRAPHIC_OFFSET
+ : BALLPARK_GEOGRAPHIC_OFFSET);
name += " from ";
name += sourceCRS->nameStr();
name += " to ";
@@ -10481,6 +10915,12 @@ createNullGeographicOffset(const crs::CRSNNPtr &sourceCRS,
sameExtent ? NN_NO_CHECK(sourceCRSExtent)
: metadata::Extent::WORLD);
const common::Angle angle0(0);
+
+ std::vector<metadata::PositionalAccuracyNNPtr> accuracies;
+ if (isSameDatum) {
+ accuracies.emplace_back(metadata::PositionalAccuracy::create("0"));
+ }
+
if (dynamic_cast<const crs::SingleCRS *>(sourceCRS.get())
->coordinateSystem()
->axisList()
@@ -10490,10 +10930,11 @@ createNullGeographicOffset(const crs::CRSNNPtr &sourceCRS,
->axisList()
.size() == 3) {
return Transformation::createGeographic3DOffsets(
- map, sourceCRS, targetCRS, angle0, angle0, common::Length(0), {});
+ map, sourceCRS, targetCRS, angle0, angle0, common::Length(0),
+ accuracies);
} else {
return Transformation::createGeographic2DOffsets(
- map, sourceCRS, targetCRS, angle0, angle0, {});
+ map, sourceCRS, targetCRS, angle0, angle0, accuracies);
}
}
//! @endcond
@@ -10547,19 +10988,19 @@ struct MyPROJStringExportableHorizVertical final
// cppcheck-suppress functionStatic
_exportToPROJString(io::PROJStringFormatter *formatter) const override {
- formatter->setOmitZUnitConversion(true);
+ formatter->pushOmitZUnitConversion();
horizTransform->_exportToPROJString(formatter);
formatter->startInversion();
geogDst->addAngularUnitConvertAndAxisSwap(formatter);
formatter->stopInversion();
- formatter->setOmitZUnitConversion(false);
+ formatter->popOmitZUnitConversion();
verticalTransform->_exportToPROJString(formatter);
- formatter->setOmitZUnitConversion(true);
+ formatter->pushOmitZUnitConversion();
geogDst->addAngularUnitConvertAndAxisSwap(formatter);
- formatter->setOmitZUnitConversion(false);
+ formatter->popOmitZUnitConversion();
}
};
@@ -10591,7 +11032,7 @@ struct MyPROJStringExportableHorizVerticalHorizPROJBased final
// cppcheck-suppress functionStatic
_exportToPROJString(io::PROJStringFormatter *formatter) const override {
- formatter->setOmitZUnitConversion(true);
+ formatter->pushOmitZUnitConversion();
opSrcCRSToGeogCRS->_exportToPROJString(formatter);
@@ -10599,23 +11040,23 @@ struct MyPROJStringExportableHorizVerticalHorizPROJBased final
interpolationGeogCRS->addAngularUnitConvertAndAxisSwap(formatter);
formatter->stopInversion();
- formatter->setOmitZUnitConversion(false);
+ formatter->popOmitZUnitConversion();
verticalTransform->_exportToPROJString(formatter);
- formatter->setOmitZUnitConversion(true);
+ formatter->pushOmitZUnitConversion();
interpolationGeogCRS->addAngularUnitConvertAndAxisSwap(formatter);
opGeogCRStoDstCRS->_exportToPROJString(formatter);
- formatter->setOmitZUnitConversion(false);
+ formatter->popOmitZUnitConversion();
}
};
MyPROJStringExportableHorizVerticalHorizPROJBased::
~MyPROJStringExportableHorizVerticalHorizPROJBased() = default;
-}
+} // namespace operation
NS_PROJ_END
#if 0
@@ -10653,7 +11094,7 @@ createGeodToGeodPROJBased(const crs::CRSNNPtr &geodSrc,
auto properties = util::PropertyMap().set(
common::IdentifiedObject::NAME_KEY,
buildTransfName(geodSrc->nameStr(), geodDst->nameStr()));
- return createPROJBased(properties, exportable, geodSrc, geodDst);
+ return createPROJBased(properties, exportable, geodSrc, geodDst, {}, false);
}
// ---------------------------------------------------------------------------
@@ -10669,28 +11110,58 @@ static CoordinateOperationNNPtr createHorizVerticalPROJBased(
auto exportable = util::nn_make_shared<MyPROJStringExportableHorizVertical>(
horizTransform, verticalTransform, geogDst);
- bool dummy = false;
- auto ops = std::vector<CoordinateOperationNNPtr>{horizTransform,
- verticalTransform};
- auto extent = getExtent(ops, true, dummy);
- auto properties = util::PropertyMap();
- properties.set(common::IdentifiedObject::NAME_KEY,
- computeConcatenatedName(ops));
-
- if (extent) {
- properties.set(common::ObjectUsage::DOMAIN_OF_VALIDITY_KEY,
- NN_NO_CHECK(extent));
+ bool horizTransformIsNoOp = horizTransform->sourceCRS()->_isEquivalentTo(
+ horizTransform->targetCRS().get());
+ if (!horizTransformIsNoOp) {
+ const crs::GeographicCRS *geogSrc =
+ dynamic_cast<const crs::GeographicCRS *>(
+ horizTransform->sourceCRS().get());
+ if (geogSrc) {
+ horizTransformIsNoOp =
+ geogSrc->is2DPartOf3D(NN_NO_CHECK(geogDst.get()));
+ }
}
- std::vector<metadata::PositionalAccuracyNNPtr> accuracies;
- const double accuracy = getAccuracy(ops);
- if (accuracy >= 0.0) {
- accuracies.emplace_back(
- metadata::PositionalAccuracy::create(toString(accuracy)));
- }
+ if (horizTransformIsNoOp) {
+ auto properties = util::PropertyMap();
+ properties.set(common::IdentifiedObject::NAME_KEY,
+ verticalTransform->nameStr());
+ bool dummy = false;
+ auto extent = getExtent(verticalTransform, true, dummy);
+ if (extent) {
+ properties.set(common::ObjectUsage::DOMAIN_OF_VALIDITY_KEY,
+ NN_NO_CHECK(extent));
+ }
+ return createPROJBased(
+ properties, exportable, sourceCRS, targetCRS,
+ verticalTransform->coordinateOperationAccuracies(),
+ verticalTransform->hasBallparkTransformation());
+ } else {
+ bool dummy = false;
+ auto ops = std::vector<CoordinateOperationNNPtr>{horizTransform,
+ verticalTransform};
+ auto extent = getExtent(ops, true, dummy);
+ auto properties = util::PropertyMap();
+ properties.set(common::IdentifiedObject::NAME_KEY,
+ computeConcatenatedName(ops));
- return createPROJBased(properties, exportable, sourceCRS, targetCRS,
- accuracies);
+ if (extent) {
+ properties.set(common::ObjectUsage::DOMAIN_OF_VALIDITY_KEY,
+ NN_NO_CHECK(extent));
+ }
+
+ std::vector<metadata::PositionalAccuracyNNPtr> accuracies;
+ const double accuracy = getAccuracy(ops);
+ if (accuracy >= 0.0) {
+ accuracies.emplace_back(
+ metadata::PositionalAccuracy::create(toString(accuracy)));
+ }
+
+ return createPROJBased(
+ properties, exportable, sourceCRS, targetCRS, accuracies,
+ horizTransform->hasBallparkTransformation() ||
+ verticalTransform->hasBallparkTransformation());
+ }
}
// ---------------------------------------------------------------------------
@@ -10708,8 +11179,17 @@ static CoordinateOperationNNPtr createHorizVerticalHorizPROJBased(
interpolationGeogCRS);
bool dummy = false;
- auto ops = std::vector<CoordinateOperationNNPtr>{
- opSrcCRSToGeogCRS, verticalTransform, opGeogCRStoDstCRS};
+ auto ops = opSrcCRSToGeogCRS->sourceCRS()->_isEquivalentTo(
+ opSrcCRSToGeogCRS->targetCRS().get())
+ ? std::vector<CoordinateOperationNNPtr>{verticalTransform,
+ opGeogCRStoDstCRS}
+ : std::vector<CoordinateOperationNNPtr>{opSrcCRSToGeogCRS,
+ verticalTransform,
+ opGeogCRStoDstCRS};
+ bool hasBallparkTransformation = false;
+ for (const auto &op : ops) {
+ hasBallparkTransformation |= op->hasBallparkTransformation();
+ }
auto extent = getExtent(ops, true, dummy);
auto properties = util::PropertyMap();
properties.set(common::IdentifiedObject::NAME_KEY,
@@ -10728,7 +11208,7 @@ static CoordinateOperationNNPtr createHorizVerticalHorizPROJBased(
}
return createPROJBased(properties, exportable, sourceCRS, targetCRS,
- accuracies);
+ accuracies, hasBallparkTransformation);
}
//! @endcond
@@ -10784,6 +11264,11 @@ CoordinateOperationFactory::Private::createOperationsGeogToGeog(
std::string name(buildTransfName(geogSrc->nameStr(), geogDst->nameStr()));
+ const bool sameDatum =
+ geogSrc->datum() != nullptr && geogDst->datum() != nullptr &&
+ geogSrc->datum()->_isEquivalentTo(
+ geogDst->datum().get(), util::IComparable::Criterion::EQUIVALENT);
+
// Do they differ by vertical units ?
if (vconvSrc != vconvDst &&
geogSrc->ellipsoid()->_isEquivalentTo(
@@ -10799,18 +11284,19 @@ CoordinateOperationFactory::Private::createOperationsGeogToGeog(
name),
common::Scale(factor));
conv->setCRSs(sourceCRS, targetCRS, nullptr);
+ conv->setHasBallparkTransformation(!sameDatum);
res.push_back(conv);
return res;
} else {
- res.emplace_back(createGeodToGeodPROJBased(sourceCRS, targetCRS));
+ auto op = createGeodToGeodPROJBased(sourceCRS, targetCRS);
+ op->setHasBallparkTransformation(!sameDatum);
+ res.emplace_back(op);
return res;
}
}
// Do the CRS differ only by their axis order ?
- if (geogSrc->datum() != nullptr && geogDst->datum() != nullptr &&
- geogSrc->datum()->_isEquivalentTo(
- geogDst->datum().get(), util::IComparable::Criterion::EQUIVALENT) &&
+ if (sameDatum &&
!srcCS->_isEquivalentTo(dstCS.get(),
util::IComparable::Criterion::EQUIVALENT)) {
auto srcOrder = srcCS->axisOrder();
@@ -10871,7 +11357,8 @@ CoordinateOperationFactory::Private::createOperationsGeogToGeog(
metadata::Extent::WORLD),
datum, dstCS));
- steps.emplace_back(createNullGeographicOffset(sourceCRS, interm_crs));
+ steps.emplace_back(
+ createBallparkGeographicOffset(sourceCRS, interm_crs));
steps.emplace_back(Transformation::createLongitudeRotation(
util::PropertyMap()
@@ -10906,15 +11393,17 @@ CoordinateOperationFactory::Private::createOperationsGeogToGeog(
metadata::Extent::WORLD),
sourceCRS, interm_crs, offset_pm));
steps.emplace_back(
- createNullGeographicOffset(interm_crs, targetCRS));
+ createBallparkGeographicOffset(interm_crs, targetCRS));
} else {
steps.emplace_back(
- createNullGeographicOffset(sourceCRS, targetCRS));
+ createBallparkGeographicOffset(sourceCRS, targetCRS));
}
}
- res.emplace_back(ConcatenatedOperation::createComputeMetadata(
- steps, !allowEmptyIntersection));
+ auto op = ConcatenatedOperation::createComputeMetadata(
+ steps, !allowEmptyIntersection);
+ op->setHasBallparkTransformation(!sameDatum);
+ res.emplace_back(op);
return res;
}
@@ -10946,16 +11435,37 @@ static bool hasIdentifiers(const CoordinateOperationNNPtr &op) {
static std::vector<crs::CRSNNPtr>
findCandidateGeodCRSForDatum(const io::AuthorityFactoryPtr &authFactory,
- const datum::GeodeticReferenceFramePtr &datum) {
+ const datum::GeodeticReferenceFrame *datum) {
std::vector<crs::CRSNNPtr> candidates;
- for (const auto &id : datum->identifiers()) {
- const auto &authName = *(id->codeSpace());
- const auto &code = id->code();
- if (!authName.empty()) {
- auto l_candidates = authFactory->createGeodeticCRSFromDatum(
- authName, code, std::string());
- for (const auto &candidate : l_candidates) {
- candidates.emplace_back(candidate);
+ assert(datum);
+ const auto &ids = datum->identifiers();
+ const auto &datumName = datum->nameStr();
+ if (!ids.empty()) {
+ for (const auto &id : ids) {
+ const auto &authName = *(id->codeSpace());
+ const auto &code = id->code();
+ if (!authName.empty()) {
+ auto l_candidates = authFactory->createGeodeticCRSFromDatum(
+ authName, code, std::string());
+ for (const auto &candidate : l_candidates) {
+ candidates.emplace_back(candidate);
+ }
+ }
+ }
+ } else if (datumName != "unknown" && datumName != "unnamed") {
+ auto matches = authFactory->createObjectsFromName(
+ datumName,
+ {io::AuthorityFactory::ObjectType::GEODETIC_REFERENCE_FRAME}, false,
+ 2);
+ if (matches.size() == 1) {
+ const auto &match = matches.front();
+ if (datum->_isEquivalentTo(
+ match.get(), util::IComparable::Criterion::EQUIVALENT) &&
+ !match->identifiers().empty()) {
+ return findCandidateGeodCRSForDatum(
+ authFactory,
+ dynamic_cast<const datum::GeodeticReferenceFrame *>(
+ match.get()));
}
}
}
@@ -10966,17 +11476,53 @@ findCandidateGeodCRSForDatum(const io::AuthorityFactoryPtr &authFactory,
static bool isNullTransformation(const std::string &name) {
- return starts_with(name, NULL_GEOCENTRIC_TRANSLATION) ||
+ return starts_with(name, BALLPARK_GEOCENTRIC_TRANSLATION) ||
+ starts_with(name, BALLPARK_GEOGRAPHIC_OFFSET) ||
starts_with(name, NULL_GEOGRAPHIC_OFFSET);
}
// ---------------------------------------------------------------------------
+#ifdef DEBUG
+
+static int nCallLevel = 0;
+
+struct EnterDebugLevel {
+ EnterDebugLevel() { ++nCallLevel; }
+ ~EnterDebugLevel() { --nCallLevel; }
+};
+
+static void debugTrace(const std::string &str) {
+ for (int i = 1; i < nCallLevel; i++)
+ std::cerr << " ";
+ std::cerr << str << std::endl;
+}
+
+static std::string objectAsStr(const common::IdentifiedObject *obj) {
+ std::string ret(obj->nameStr());
+ const auto &ids = obj->identifiers();
+ if (!ids.empty()) {
+ ret += " (";
+ ret += (*ids[0]->codeSpace()) + ":" + ids[0]->code();
+ ret += ")";
+ }
+ return ret;
+}
+#endif
+
+// ---------------------------------------------------------------------------
+
void CoordinateOperationFactory::Private::createOperationsWithDatumPivot(
std::vector<CoordinateOperationNNPtr> &res, const crs::CRSNNPtr &sourceCRS,
const crs::CRSNNPtr &targetCRS, const crs::GeodeticCRS *geodSrc,
const crs::GeodeticCRS *geodDst, Private::Context &context) {
+#ifdef DEBUG
+ EnterDebugLevel enterFunction;
+ debugTrace("createOperationsWithDatumPivot(" +
+ objectAsStr(sourceCRS.get()) + "," +
+ objectAsStr(targetCRS.get()) + ")");
+#endif
const bool allowEmptyIntersection = true;
struct CreateOperationsWithDatumPivotAntiRecursion {
@@ -10996,9 +11542,9 @@ void CoordinateOperationFactory::Private::createOperationsWithDatumPivot(
const auto &authFactory = context.context->getAuthorityFactory();
const auto candidatesSrcGeod(
- findCandidateGeodCRSForDatum(authFactory, geodSrc->datum()));
+ findCandidateGeodCRSForDatum(authFactory, geodSrc->datum().get()));
const auto candidatesDstGeod(
- findCandidateGeodCRSForDatum(authFactory, geodDst->datum()));
+ findCandidateGeodCRSForDatum(authFactory, geodDst->datum().get()));
auto createTransformations = [&](const crs::CRSNNPtr &candidateSrcGeod,
const crs::CRSNNPtr &candidateDstGeod,
@@ -11024,20 +11570,73 @@ void CoordinateOperationFactory::Private::createOperationsWithDatumPivot(
}
std::vector<CoordinateOperationNNPtr> subOps;
+ const bool isNullThird =
+ isNullTransformation(opsThird[0]->nameStr());
+ CoordinateOperationNNPtr opSecondCloned(
+ (isNullFirst || isNullThird) ? opSecond->shallowClone()
+ : opSecond);
+ CoordinateOperation *invCOForward = nullptr;
+ if (isNullFirst || isNullThird) {
+ if (opSecondCloned->identifiers().size() == 1 &&
+ (*opSecondCloned->identifiers()[0]->codeSpace())
+ .find("DERIVED_FROM") == std::string::npos) {
+ {
+ util::PropertyMap map;
+ addModifiedIdentifier(map, opSecondCloned.get(), false,
+ true);
+ opSecondCloned->setProperties(map);
+ }
+ auto invCO = dynamic_cast<InverseCoordinateOperation *>(
+ opSecondCloned.get());
+ if (invCO) {
+ invCOForward = invCO->forwardOperation().get();
+ if (invCOForward->identifiers().size() == 1 &&
+ (*invCOForward->identifiers()[0]->codeSpace())
+ .find("DERIVED_FROM") ==
+ std::string::npos) {
+ util::PropertyMap map;
+ addModifiedIdentifier(map, invCOForward, false,
+ true);
+ invCOForward->setProperties(map);
+ }
+ }
+ }
+ }
if (isNullFirst) {
- opSecond->setCRSs(
- sourceCRS, NN_CHECK_ASSERT(opSecond->targetCRS()), nullptr);
+ auto oldTarget(NN_CHECK_ASSERT(opSecondCloned->targetCRS()));
+ opSecondCloned->setCRSs(sourceCRS, oldTarget, nullptr);
+ if (invCOForward) {
+ invCOForward->setCRSs(oldTarget, sourceCRS, nullptr);
+ }
} else {
subOps.emplace_back(opFirst);
}
- if (isNullTransformation(opsThird[0]->nameStr())) {
- opSecond->setCRSs(NN_CHECK_ASSERT(opSecond->sourceCRS()),
- targetCRS, nullptr);
- subOps.emplace_back(opSecond);
+ if (isNullThird) {
+ auto oldSource(NN_CHECK_ASSERT(opSecondCloned->sourceCRS()));
+ opSecondCloned->setCRSs(oldSource, targetCRS, nullptr);
+ if (invCOForward) {
+ invCOForward->setCRSs(targetCRS, oldSource, nullptr);
+ }
+ subOps.emplace_back(opSecondCloned);
} else {
- subOps.emplace_back(opSecond);
+ subOps.emplace_back(opSecondCloned);
subOps.emplace_back(opsThird[0]);
}
+#ifdef DEBUG
+ std::string debugStr;
+ for (const auto &op : subOps) {
+ if (!debugStr.empty()) {
+ debugStr += " + ";
+ }
+ debugStr += objectAsStr(op.get());
+ debugStr += " (";
+ debugStr += objectAsStr(op->sourceCRS().get());
+ debugStr += "->";
+ debugStr += objectAsStr(op->targetCRS().get());
+ debugStr += ")";
+ }
+ debugTrace("transformation " + debugStr);
+#endif
res.emplace_back(ConcatenatedOperation::createComputeMetadata(
subOps, !allowEmptyIntersection));
}
@@ -11049,6 +11648,14 @@ void CoordinateOperationFactory::Private::createOperationsWithDatumPivot(
if (candidateSrcGeod->nameStr() == sourceCRS->nameStr()) {
for (const auto &candidateDstGeod : candidatesDstGeod) {
if (candidateDstGeod->nameStr() == targetCRS->nameStr()) {
+#ifdef DEBUG
+ EnterDebugLevel loopLevel;
+ debugTrace("try " + objectAsStr(sourceCRS.get()) + "->" +
+ objectAsStr(candidateSrcGeod.get()) + "->" +
+ objectAsStr(candidateDstGeod.get()) + "->" +
+ objectAsStr(targetCRS.get()) + ")");
+ EnterDebugLevel loopLevel2;
+#endif
const auto opsFirst =
createOperations(sourceCRS, candidateSrcGeod, context);
assert(!opsFirst.empty());
@@ -11067,17 +11674,28 @@ void CoordinateOperationFactory::Private::createOperationsWithDatumPivot(
}
for (const auto &candidateSrcGeod : candidatesSrcGeod) {
+#ifdef DEBUG
+ EnterDebugLevel loopLevel;
+#endif
const auto opsFirst =
createOperations(sourceCRS, candidateSrcGeod, context);
assert(!opsFirst.empty());
const bool isNullFirst = isNullTransformation(opsFirst[0]->nameStr());
for (const auto &candidateDstGeod : candidatesDstGeod) {
+#ifdef DEBUG
+ EnterDebugLevel loopLevel2;
+ debugTrace("try " + objectAsStr(sourceCRS.get()) + "->" +
+ objectAsStr(candidateSrcGeod.get()) + "->" +
+ objectAsStr(candidateDstGeod.get()) + "->" +
+ objectAsStr(targetCRS.get()) + ")");
+ EnterDebugLevel loopLevel3;
+#endif
createTransformations(candidateSrcGeod, candidateDstGeod,
opsFirst[0], isNullFirst);
- }
- if (!res.empty()) {
- return;
+ if (!res.empty()) {
+ return;
+ }
}
}
}
@@ -11085,9 +11703,9 @@ void CoordinateOperationFactory::Private::createOperationsWithDatumPivot(
// ---------------------------------------------------------------------------
static CoordinateOperationNNPtr
-createNullGeocentricTranslation(const crs::CRSNNPtr &sourceCRS,
- const crs::CRSNNPtr &targetCRS) {
- std::string name(NULL_GEOCENTRIC_TRANSLATION);
+createBallparkGeocentricTranslation(const crs::CRSNNPtr &sourceCRS,
+ const crs::CRSNNPtr &targetCRS) {
+ std::string name(BALLPARK_GEOCENTRIC_TRANSLATION);
name += " from ";
name += sourceCRS->nameStr();
name += " to ";
@@ -11132,6 +11750,13 @@ CoordinateOperationFactory::Private::createOperations(
const crs::CRSNNPtr &sourceCRS, const crs::CRSNNPtr &targetCRS,
Private::Context &context) {
+#ifdef DEBUG
+ EnterDebugLevel enterFunction;
+ auto debugStr("createOperations(" + objectAsStr(sourceCRS.get()) + "," +
+ objectAsStr(targetCRS.get()) + ")");
+ debugTrace(debugStr);
+#endif
+
std::vector<CoordinateOperationNNPtr> res;
const bool allowEmptyIntersection = true;
@@ -11211,15 +11836,48 @@ CoordinateOperationFactory::Private::createOperations(
doFilterAndCheckPerfectOp = false;
+ bool sameGeodeticDatum = false;
+ if (geodSrc && geodDst) {
+ const auto &srcDatum = geodSrc->datum();
+ const auto &dstDatum = geodDst->datum();
+ sameGeodeticDatum =
+ srcDatum != nullptr && dstDatum != nullptr &&
+ srcDatum->_isEquivalentTo(
+ dstDatum.get(),
+ util::IComparable::Criterion::EQUIVALENT);
+ }
+
+ if (res.empty() && !sameGeodeticDatum &&
+ !context.inCreateOperationsWithDatumPivotAntiRecursion &&
+ geodSrc && geodDst) {
+ // If we still didn't find a transformation, and that the source
+ // and target are GeodeticCRS, then go through their underlying
+ // datum to find potential transformations between other
+ // GeodeticRSs
+ // that are made of those datum
+ // The typical example is if transforming between two
+ // GeographicCRS,
+ // but transformations are only available between their
+ // corresponding geocentric CRS.
+ const auto &srcDatum = geodSrc->datum();
+ const auto &dstDatum = geodDst->datum();
+ if (srcDatum != nullptr && dstDatum != nullptr) {
+ createOperationsWithDatumPivot(res, sourceCRS, targetCRS,
+ geodSrc, geodDst, context);
+ doFilterAndCheckPerfectOp = !res.empty();
+ }
+ }
+
// NAD27 to NAD83 has tens of results already. No need to look
// for a pivot
- if ((res.empty() &&
+ if (!sameGeodeticDatum &&
+ ((res.empty() &&
+ context.context->getAllowUseIntermediateCRS() ==
+ CoordinateOperationContext::IntermediateCRSUse::
+ IF_NO_DIRECT_TRANSFORMATION) ||
context.context->getAllowUseIntermediateCRS() ==
- CoordinateOperationContext::IntermediateCRSUse::
- IF_NO_DIRECT_TRANSFORMATION) ||
- context.context->getAllowUseIntermediateCRS() ==
- CoordinateOperationContext::IntermediateCRSUse::ALWAYS ||
- getenv("PROJ_FORCE_SEARCH_PIVOT")) {
+ CoordinateOperationContext::IntermediateCRSUse::ALWAYS ||
+ getenv("PROJ_FORCE_SEARCH_PIVOT"))) {
auto resWithIntermediate = findsOpsInRegistryWithIntermediate(
sourceCRS, targetCRS, context.context);
res.insert(res.end(), resWithIntermediate.begin(),
@@ -11228,31 +11886,6 @@ CoordinateOperationFactory::Private::createOperations(
}
}
- if (res.empty() &&
- !context.inCreateOperationsWithDatumPivotAntiRecursion && geodSrc &&
- geodDst) {
- // If we still didn't find a transformation, and that the source
- // and target are GeodeticCRS, then go through their underlying
- // datum to find potential transformations between other GeodeticRSs
- // that are made of those datum
- // The typical example is if transforming between two GeographicCRS,
- // but transformations are only available between their
- // corresponding geocentric CRS.
- const auto &srcDatum = geodSrc->datum();
- const bool srcHasDatumWithId =
- srcDatum && !srcDatum->identifiers().empty();
- const auto &dstDatum = geodDst->datum();
- const bool dstHasDatumWithId =
- dstDatum && !dstDatum->identifiers().empty();
- if (srcHasDatumWithId && dstHasDatumWithId &&
- !srcDatum->_isEquivalentTo(
- dstDatum.get(), util::IComparable::Criterion::EQUIVALENT)) {
- createOperationsWithDatumPivot(res, sourceCRS, targetCRS,
- geodSrc, geodDst, context);
- doFilterAndCheckPerfectOp = !res.empty();
- }
- }
-
if (doFilterAndCheckPerfectOp) {
// If we get at least a result with perfect accuracy, do not bother
// generating synthetic transforms.
@@ -11309,7 +11942,7 @@ CoordinateOperationFactory::Private::createOperations(
util::nn_dynamic_pointer_cast<cs::CartesianCS>(
geodSrc->coordinateSystem()))));
auto opFirst =
- createNullGeocentricTranslation(sourceCRS, interm_crs);
+ createBallparkGeocentricTranslation(sourceCRS, interm_crs);
auto opSecond =
createGeographicGeocentric(interm_crs, targetCRS);
res.emplace_back(ConcatenatedOperation::createComputeMetadata(
@@ -11324,7 +11957,7 @@ CoordinateOperationFactory::Private::createOperations(
if (isSrcGeocentric && isTargetGeocentric) {
res.emplace_back(
- createNullGeocentricTranslation(sourceCRS, targetCRS));
+ createBallparkGeocentricTranslation(sourceCRS, targetCRS));
return res;
}
@@ -11363,7 +11996,6 @@ CoordinateOperationFactory::Private::createOperations(
return applyInverse(createOperations(targetCRS, sourceCRS, context));
}
- // boundCRS to a geogCRS that is the same as the hubCRS
auto boundSrc = dynamic_cast<const crs::BoundCRS *>(sourceCRS.get());
auto geogDst = dynamic_cast<const crs::GeographicCRS *>(targetCRS.get());
if (boundSrc && geogDst) {
@@ -11372,6 +12004,7 @@ CoordinateOperationFactory::Private::createOperations(
dynamic_cast<const crs::GeographicCRS *>(hubSrc.get());
auto geogCRSOfBaseOfBoundSrc =
boundSrc->baseCRS()->extractGeographicCRS();
+ // Is it: boundCRS to a geogCRS that is the same as the hubCRS ?
if (hubSrcGeog && geogCRSOfBaseOfBoundSrc &&
(hubSrcGeog->_isEquivalentTo(
geogDst, util::IComparable::Criterion::EQUIVALENT) ||
@@ -11489,6 +12122,66 @@ CoordinateOperationFactory::Private::createOperations(
return res;
}
+ if (hubSrcGeog && geogCRSOfBaseOfBoundSrc) {
+ // This one should go to the above 'Is it: boundCRS to a geogCRS
+ // that is the same as the hubCRS ?' case
+ auto opsFirst = createOperations(sourceCRS, hubSrc, context);
+ auto opsLast = createOperations(hubSrc, targetCRS, context);
+ if (!opsFirst.empty() && !opsLast.empty()) {
+ for (const auto &opFirst : opsFirst) {
+ for (const auto &opLast : opsLast) {
+ // Exclude artificial transformations from the hub
+ // to the target CRS
+ if (!opLast->hasBallparkTransformation()) {
+ try {
+ res.emplace_back(
+ ConcatenatedOperation::
+ createComputeMetadata(
+ {opFirst, opLast},
+ !allowEmptyIntersection));
+ } catch (
+ const InvalidOperationEmptyIntersection &) {
+ }
+ }
+ }
+ }
+ if (!res.empty()) {
+ return res;
+ }
+ }
+ }
+
+ auto vertCRSOfBaseOfBoundSrc =
+ dynamic_cast<const crs::VerticalCRS *>(boundSrc->baseCRS().get());
+ if (vertCRSOfBaseOfBoundSrc && hubSrcGeog &&
+ hubSrcGeog->coordinateSystem()->axisList().size() == 3 &&
+ geogDst->coordinateSystem()->axisList().size() == 3) {
+ auto opsFirst = createOperations(sourceCRS, hubSrc, context);
+ auto opsSecond = createOperations(hubSrc, targetCRS, context);
+ if (!opsFirst.empty() && !opsSecond.empty()) {
+ for (const auto &opFirst : opsFirst) {
+ for (const auto &opLast : opsSecond) {
+ // Exclude artificial transformations from the hub
+ // to the target CRS
+ if (!opLast->hasBallparkTransformation()) {
+ try {
+ res.emplace_back(
+ ConcatenatedOperation::
+ createComputeMetadata(
+ {opFirst, opLast},
+ !allowEmptyIntersection));
+ } catch (
+ const InvalidOperationEmptyIntersection &) {
+ }
+ }
+ }
+ }
+ if (!res.empty()) {
+ return res;
+ }
+ }
+ }
+
return createOperations(boundSrc->baseCRS(), targetCRS, context);
}
@@ -11526,35 +12219,65 @@ CoordinateOperationFactory::Private::createOperations(
if (vertSrc && vertDst) {
const auto &srcDatum = vertSrc->datum();
const auto &dstDatum = vertDst->datum();
- if (srcDatum && dstDatum &&
- srcDatum->_isEquivalentTo(
- dstDatum.get(), util::IComparable::Criterion::EQUIVALENT)) {
- const double convSrc = vertSrc->coordinateSystem()
- ->axisList()[0]
- ->unit()
- .conversionToSI();
- const double convDst = vertDst->coordinateSystem()
- ->axisList()[0]
- ->unit()
- .conversionToSI();
- if (convSrc != convDst) {
- const double factor = convSrc / convDst;
- auto conv = Conversion::createChangeVerticalUnit(
- util::PropertyMap().set(
- common::IdentifiedObject::NAME_KEY,
- buildTransfName(sourceCRS->nameStr(),
- targetCRS->nameStr())),
- common::Scale(factor));
- conv->setCRSs(sourceCRS, targetCRS, nullptr);
- res.push_back(conv);
- return res;
- }
+ const bool equivalentVDatum =
+ (srcDatum && dstDatum &&
+ srcDatum->_isEquivalentTo(
+ dstDatum.get(), util::IComparable::Criterion::EQUIVALENT));
+
+ const double convSrc =
+ vertSrc->coordinateSystem()->axisList()[0]->unit().conversionToSI();
+ const double convDst =
+ vertDst->coordinateSystem()->axisList()[0]->unit().conversionToSI();
+
+ const double factor = convSrc / convDst;
+ auto name = buildTransfName(sourceCRS->nameStr(), targetCRS->nameStr());
+ if (!equivalentVDatum) {
+ name += BALLPARK_VERTICAL_TRANSFORMATION;
+ auto conv = Transformation::createChangeVerticalUnit(
+ util::PropertyMap().set(common::IdentifiedObject::NAME_KEY,
+ name),
+ sourceCRS, targetCRS, common::Scale(factor), {});
+ conv->setHasBallparkTransformation(true);
+ res.push_back(conv);
+ } else if (convSrc != convDst) {
+ auto conv = Conversion::createChangeVerticalUnit(
+ util::PropertyMap().set(common::IdentifiedObject::NAME_KEY,
+ name),
+ common::Scale(factor));
+ conv->setCRSs(sourceCRS, targetCRS, nullptr);
+ res.push_back(conv);
}
+ return res;
}
// A bit odd case as we are comparing apples to oranges, but in case
// the vertical unit differ, do something useful.
if (vertSrc && geogDst) {
+
+ if (vertSrc->identifiers().empty()) {
+ const auto &authFactory = context.context->getAuthorityFactory();
+ const auto &vertSrcName = vertSrc->nameStr();
+ if (authFactory != nullptr && vertSrcName != "unnamed" &&
+ vertSrcName != "unknown") {
+ auto matches = authFactory->createObjectsFromName(
+ vertSrcName,
+ {io::AuthorityFactory::ObjectType::VERTICAL_CRS}, false, 2);
+ if (matches.size() == 1) {
+ const auto &match = matches.front();
+ if (vertSrc->_isEquivalentTo(
+ match.get(),
+ util::IComparable::Criterion::EQUIVALENT) &&
+ !match->identifiers().empty()) {
+ return createOperations(
+ NN_NO_CHECK(
+ util::nn_dynamic_pointer_cast<crs::VerticalCRS>(
+ match)),
+ targetCRS, context);
+ }
+ }
+ }
+ }
+
const double convSrc =
vertSrc->coordinateSystem()->axisList()[0]->unit().conversionToSI();
double convDst = 1.0;
@@ -11562,17 +12285,17 @@ CoordinateOperationFactory::Private::createOperations(
if (geogAxis.size() == 3) {
convDst = geogAxis[2]->unit().conversionToSI();
}
- if (convSrc != convDst) {
- const double factor = convSrc / convDst;
- auto conv = Conversion::createChangeVerticalUnit(
- util::PropertyMap().set(common::IdentifiedObject::NAME_KEY,
- buildTransfName(sourceCRS->nameStr(),
- targetCRS->nameStr())),
- common::Scale(factor));
- conv->setCRSs(sourceCRS, targetCRS, nullptr);
- res.push_back(conv);
- return res;
- }
+
+ const double factor = convSrc / convDst;
+ auto conv = Transformation::createChangeVerticalUnit(
+ util::PropertyMap().set(
+ common::IdentifiedObject::NAME_KEY,
+ buildTransfName(sourceCRS->nameStr(), targetCRS->nameStr()) +
+ BALLPARK_VERTICAL_TRANSFORMATION_NO_ELLIPSOID_VERT_HEIGHT),
+ sourceCRS, targetCRS, common::Scale(factor), {});
+ conv->setHasBallparkTransformation(true);
+ res.push_back(conv);
+ return res;
}
// reverse of previous case
@@ -11636,6 +12359,34 @@ CoordinateOperationFactory::Private::createOperations(
}
}
+ auto vertCRSOfBaseOfBoundSrc =
+ boundSrc->baseCRS()->extractVerticalCRS();
+ auto vertCRSOfBaseOfBoundDst =
+ boundDst->baseCRS()->extractVerticalCRS();
+ if (hubSrcGeog && hubDstGeog &&
+ hubSrcGeog->_isEquivalentTo(
+ hubDstGeog, util::IComparable::Criterion::EQUIVALENT) &&
+ vertCRSOfBaseOfBoundSrc && vertCRSOfBaseOfBoundDst) {
+ auto opsFirst = createOperations(sourceCRS, hubSrc, context);
+ auto opsLast = createOperations(hubSrc, targetCRS, context);
+ if (!opsFirst.empty() && !opsLast.empty()) {
+ for (const auto &opFirst : opsFirst) {
+ for (const auto &opLast : opsLast) {
+ try {
+ res.emplace_back(
+ ConcatenatedOperation::createComputeMetadata(
+ {opFirst, opLast},
+ !allowEmptyIntersection));
+ } catch (const InvalidOperationEmptyIntersection &) {
+ }
+ }
+ }
+ if (!res.empty()) {
+ return res;
+ }
+ }
+ }
+
return createOperations(boundSrc->baseCRS(), boundDst->baseCRS(),
context);
}
@@ -11645,7 +12396,8 @@ CoordinateOperationFactory::Private::createOperations(
const auto &componentsSrc = compoundSrc->componentReferenceSystems();
if (!componentsSrc.empty()) {
std::vector<CoordinateOperationNNPtr> horizTransforms;
- if (componentsSrc[0]->extractGeographicCRS()) {
+ auto srcGeogCRS = componentsSrc[0]->extractGeographicCRS();
+ if (srcGeogCRS) {
horizTransforms =
createOperations(componentsSrc[0], targetCRS, context);
}
@@ -11659,11 +12411,61 @@ CoordinateOperationFactory::Private::createOperations(
for (const auto &horizTransform : horizTransforms) {
for (const auto &verticalTransform : verticalTransforms) {
- auto op = createHorizVerticalPROJBased(
- sourceCRS, targetCRS, horizTransform,
- verticalTransform);
+ crs::GeographicCRSPtr interpolationGeogCRS;
+ auto transformationVerticalTransform =
+ dynamic_cast<const Transformation *>(
+ verticalTransform.get());
+ if (transformationVerticalTransform) {
+ auto interpTransformCRS =
+ transformationVerticalTransform
+ ->interpolationCRS();
+ if (interpTransformCRS) {
+ auto nn_interpTransformCRS =
+ NN_NO_CHECK(interpTransformCRS);
+ if (dynamic_cast<const crs::GeographicCRS *>(
+ nn_interpTransformCRS.get())) {
+ interpolationGeogCRS =
+ util::nn_dynamic_pointer_cast<
+ crs::GeographicCRS>(
+ nn_interpTransformCRS);
+ }
+ }
+ }
+ bool done = false;
+ if (interpolationGeogCRS &&
+ (interpolationGeogCRS->_isEquivalentTo(
+ srcGeogCRS.get(),
+ util::IComparable::Criterion::EQUIVALENT) ||
+ interpolationGeogCRS->is2DPartOf3D(
+ NN_NO_CHECK(srcGeogCRS.get())))) {
+ auto srcToInterp = createOperations(
+ componentsSrc[0],
+ NN_NO_CHECK(interpolationGeogCRS), context);
+ auto interpToCompoundHoriz = createOperations(
+ NN_NO_CHECK(interpolationGeogCRS),
+ componentsSrc[0], context);
+ if (!srcToInterp.empty() &&
+ !interpToCompoundHoriz.empty()) {
+ auto op = createHorizVerticalHorizPROJBased(
+ sourceCRS, componentsSrc[0],
+ srcToInterp.front(), verticalTransform,
+ interpToCompoundHoriz.front(),
+ interpolationGeogCRS);
+ done = true;
+ res.emplace_back(
+ ConcatenatedOperation::
+ createComputeMetadata(
+ {op, horizTransform},
+ !allowEmptyIntersection));
+ }
+ }
+ if (!done) {
+ auto op = createHorizVerticalPROJBased(
+ sourceCRS, targetCRS, horizTransform,
+ verticalTransform);
- res.emplace_back(op);
+ res.emplace_back(op);
+ }
}
}
return res;
@@ -11671,11 +12473,40 @@ CoordinateOperationFactory::Private::createOperations(
return horizTransforms;
}
}
+ } else if (compoundSrc && geodDst) {
+ auto datum = geodDst->datum();
+ if (datum) {
+ auto cs =
+ cs::EllipsoidalCS::createLatitudeLongitudeEllipsoidalHeight(
+ common::UnitOfMeasure::DEGREE,
+ common::UnitOfMeasure::METRE);
+ auto intermGeog3DCRS = util::nn_static_pointer_cast<crs::CRS>(
+ crs::GeographicCRS::create(
+ util::PropertyMap()
+ .set(common::IdentifiedObject::NAME_KEY,
+ geodDst->nameStr())
+ .set(common::ObjectUsage::DOMAIN_OF_VALIDITY_KEY,
+ metadata::Extent::WORLD),
+ NN_NO_CHECK(datum), cs));
+ auto sourceToGeog3DOps =
+ createOperations(sourceCRS, intermGeog3DCRS, context);
+ auto geog3DToTargetOps =
+ createOperations(intermGeog3DCRS, targetCRS, context);
+ if (!geog3DToTargetOps.empty()) {
+ for (const auto &op : sourceToGeog3DOps) {
+ res.emplace_back(
+ ConcatenatedOperation::createComputeMetadata(
+ {op, geog3DToTargetOps.front()},
+ !allowEmptyIntersection));
+ }
+ return res;
+ }
+ }
}
// reverse of previous case
auto compoundDst = dynamic_cast<const crs::CompoundCRS *>(targetCRS.get());
- if (geogSrc && compoundDst) {
+ if (geodSrc && compoundDst) {
return applyInverse(createOperations(targetCRS, sourceCRS, context));
}
@@ -11715,6 +12546,21 @@ CoordinateOperationFactory::Private::createOperations(
nn_interpTransformCRS));
}
}
+ } else {
+ auto compSrc0BoundCrs = dynamic_cast<crs::BoundCRS *>(
+ componentsSrc[0].get());
+ auto compDst0BoundCrs = dynamic_cast<crs::BoundCRS *>(
+ componentsDst[0].get());
+ if (compSrc0BoundCrs && compDst0BoundCrs &&
+ dynamic_cast<crs::GeographicCRS *>(
+ compSrc0BoundCrs->hubCRS().get()) &&
+ compSrc0BoundCrs->hubCRS()->_isEquivalentTo(
+ compDst0BoundCrs->hubCRS().get())) {
+ interpolationGeogCRS =
+ NN_NO_CHECK(util::nn_dynamic_pointer_cast<
+ crs::GeographicCRS>(
+ compSrc0BoundCrs->hubCRS()));
+ }
}
auto opSrcCRSToGeogCRS = createOperations(
componentsSrc[0], interpolationGeogCRS, context);
@@ -11739,12 +12585,157 @@ CoordinateOperationFactory::Private::createOperations(
}
}
+ // '+proj=longlat +ellps=GRS67 +nadgrids=@foo.gsb +type=crs' to
+ // '+proj=longlat +ellps=GRS80 +nadgrids=@bar.gsb +geoidgrids=@bar.gtx
+ // +type=crs'
+ if (boundSrc && compoundDst) {
+ const auto &componentsDst = compoundDst->componentReferenceSystems();
+ if (!componentsDst.empty()) {
+ auto compDst0BoundCrs =
+ dynamic_cast<crs::BoundCRS *>(componentsDst[0].get());
+ if (compDst0BoundCrs) {
+ auto boundSrcHubAsGeogCRS = dynamic_cast<crs::GeographicCRS *>(
+ boundSrc->hubCRS().get());
+ auto compDst0BoundCrsHubAsGeogCRS =
+ dynamic_cast<crs::GeographicCRS *>(
+ compDst0BoundCrs->hubCRS().get());
+ if (boundSrcHubAsGeogCRS && compDst0BoundCrsHubAsGeogCRS) {
+ const auto &boundSrcHubAsGeogCRSDatum =
+ boundSrcHubAsGeogCRS->datum();
+ const auto &compDst0BoundCrsHubAsGeogCRSDatum =
+ compDst0BoundCrsHubAsGeogCRS->datum();
+ if (boundSrcHubAsGeogCRSDatum &&
+ compDst0BoundCrsHubAsGeogCRSDatum &&
+ boundSrcHubAsGeogCRSDatum->_isEquivalentTo(
+ compDst0BoundCrsHubAsGeogCRSDatum.get())) {
+ auto cs = cs::EllipsoidalCS::
+ createLatitudeLongitudeEllipsoidalHeight(
+ common::UnitOfMeasure::DEGREE,
+ common::UnitOfMeasure::METRE);
+ auto intermGeog3DCRS = util::nn_static_pointer_cast<
+ crs::CRS>(crs::GeographicCRS::create(
+ util::PropertyMap()
+ .set(common::IdentifiedObject::NAME_KEY,
+ boundSrcHubAsGeogCRS->nameStr())
+ .set(
+ common::ObjectUsage::DOMAIN_OF_VALIDITY_KEY,
+ metadata::Extent::WORLD),
+ NN_NO_CHECK(boundSrcHubAsGeogCRSDatum), cs));
+ auto sourceToGeog3DOps = createOperations(
+ sourceCRS, intermGeog3DCRS, context);
+ auto geog3DToTargetOps = createOperations(
+ intermGeog3DCRS, targetCRS, context);
+ for (const auto &opSrc : sourceToGeog3DOps) {
+ for (const auto &opDst : geog3DToTargetOps) {
+ if (opSrc->targetCRS() && opDst->sourceCRS() &&
+ !opSrc->targetCRS()->_isEquivalentTo(
+ opDst->sourceCRS().get())) {
+ // Shouldn't happen normally, but typically
+ // one of them can be 2D and the other 3D
+ // due to above createOperations() not
+ // exactly setting the expected source and
+ // target CRS.
+ // So create an adapter operation...
+ auto intermOps = createOperations(
+ NN_NO_CHECK(opSrc->targetCRS()),
+ NN_NO_CHECK(opDst->sourceCRS()),
+ context);
+ if (!intermOps.empty()) {
+ res.emplace_back(
+ ConcatenatedOperation::
+ createComputeMetadata(
+ {opSrc, intermOps.front(),
+ opDst},
+ !allowEmptyIntersection));
+ }
+ } else {
+ res.emplace_back(
+ ConcatenatedOperation::
+ createComputeMetadata(
+ {opSrc, opDst},
+ !allowEmptyIntersection));
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // reverse of previous case
+ if (boundDst && compoundSrc) {
+ return applyInverse(createOperations(targetCRS, sourceCRS, context));
+ }
+
return res;
}
//! @endcond
// ---------------------------------------------------------------------------
+static crs::CRSNNPtr
+getResolvedCRS(const crs::CRSNNPtr &crs,
+ const CoordinateOperationContextNNPtr &context) {
+ const auto &authFactory = context->getAuthorityFactory();
+
+ auto projectedCrs = dynamic_cast<crs::ProjectedCRS *>(crs.get());
+ if (projectedCrs && authFactory) {
+ const auto &ids = projectedCrs->identifiers();
+ if (!ids.empty() && projectedCrs->baseCRS()->identifiers().empty()) {
+ const auto tmpAuthFactory = io::AuthorityFactory::create(
+ authFactory->databaseContext(), *ids.front()->codeSpace());
+ try {
+ auto resolvedCrs(
+ tmpAuthFactory->createProjectedCRS(ids.front()->code()));
+ if (resolvedCrs->isEquivalentTo(
+ crs.get(), util::IComparable::Criterion::EQUIVALENT)) {
+ return util::nn_static_pointer_cast<crs::CRS>(resolvedCrs);
+ }
+ } catch (const std::exception &) {
+ }
+ }
+ }
+
+ auto compoundCrs = dynamic_cast<crs::CompoundCRS *>(crs.get());
+ // If we get a CompoundCRS that has an EPSG code, but whose component CRS
+ // lack one, typically from WKT2, this might be an issue to get proper
+ // results in createOperations(), so import the CompoundCRS from the
+ // registry, and if equivalent to the original one, then use the version
+ // from the registry.
+ if (compoundCrs && authFactory) {
+ const auto &ids = compoundCrs->identifiers();
+ if (!ids.empty()) {
+ const auto &components = compoundCrs->componentReferenceSystems();
+ bool hasMissingId = false;
+ for (const auto &comp : components) {
+ if (comp->identifiers().empty()) {
+ hasMissingId = true;
+ break;
+ }
+ }
+ if (hasMissingId) {
+ const auto tmpAuthFactory = io::AuthorityFactory::create(
+ authFactory->databaseContext(), *ids.front()->codeSpace());
+ try {
+ auto resolvedCrs(
+ tmpAuthFactory->createCompoundCRS(ids.front()->code()));
+ if (resolvedCrs->isEquivalentTo(
+ crs.get(),
+ util::IComparable::Criterion::EQUIVALENT)) {
+ return util::nn_static_pointer_cast<crs::CRS>(
+ resolvedCrs);
+ }
+ } catch (const std::exception &) {
+ }
+ }
+ }
+ }
+ return crs;
+}
+
+// ---------------------------------------------------------------------------
+
/** \brief Find a list of CoordinateOperation from sourceCRS to targetCRS.
*
* The operations are sorted with the most relevant ones first: by
@@ -11773,10 +12764,25 @@ CoordinateOperationFactory::createOperations(
auto l_sourceCRS = srcBoundCRS ? NN_NO_CHECK(srcBoundCRS) : sourceCRS;
auto l_targetCRS = targetBoundCRS ? NN_NO_CHECK(targetBoundCRS) : targetCRS;
- Private::Context contextPrivate(sourceCRS, targetCRS, context);
- return filterAndSort(
- Private::createOperations(l_sourceCRS, l_targetCRS, contextPrivate),
- context, l_sourceCRS, l_targetCRS);
+ auto l_resolvedSourceCRS = getResolvedCRS(l_sourceCRS, context);
+ auto l_resolvedTargetCRS = getResolvedCRS(l_targetCRS, context);
+ Private::Context contextPrivate(l_resolvedSourceCRS, l_resolvedTargetCRS,
+ context);
+
+ if (context->getSourceAndTargetCRSExtentUse() ==
+ CoordinateOperationContext::SourceTargetCRSExtentUse::INTERSECTION) {
+ auto sourceCRSExtent(getExtent(l_resolvedSourceCRS));
+ auto targetCRSExtent(getExtent(l_resolvedTargetCRS));
+ if (sourceCRSExtent && targetCRSExtent &&
+ !sourceCRSExtent->intersects(NN_NO_CHECK(targetCRSExtent))) {
+ return std::vector<CoordinateOperationNNPtr>();
+ }
+ }
+
+ return filterAndSort(Private::createOperations(l_resolvedSourceCRS,
+ l_resolvedTargetCRS,
+ contextPrivate),
+ context, l_resolvedSourceCRS, l_resolvedTargetCRS);
}
// ---------------------------------------------------------------------------
@@ -11797,8 +12803,9 @@ InverseCoordinateOperation::~InverseCoordinateOperation() = default;
// ---------------------------------------------------------------------------
InverseCoordinateOperation::InverseCoordinateOperation(
- const CoordinateOperationNNPtr &forwardOperation, bool wktSupportsInversion)
- : forwardOperation_(forwardOperation),
+ const CoordinateOperationNNPtr &forwardOperationIn,
+ bool wktSupportsInversion)
+ : forwardOperation_(forwardOperationIn),
wktSupportsInversion_(wktSupportsInversion) {}
// ---------------------------------------------------------------------------
@@ -11810,6 +12817,8 @@ void InverseCoordinateOperation::setPropertiesFromForward() {
if (forwardOperation_->sourceCRS() && forwardOperation_->targetCRS()) {
setCRSs(forwardOperation_.get(), true);
}
+ setHasBallparkTransformation(
+ forwardOperation_->hasBallparkTransformation());
}
// ---------------------------------------------------------------------------
@@ -11877,7 +12886,8 @@ PROJBasedOperationNNPtr PROJBasedOperation::create(
const util::PropertyMap &properties,
const io::IPROJStringExportableNNPtr &projExportable, bool inverse,
const crs::CRSNNPtr &sourceCRS, const crs::CRSNNPtr &targetCRS,
- const std::vector<metadata::PositionalAccuracyNNPtr> &accuracies) {
+ const std::vector<metadata::PositionalAccuracyNNPtr> &accuracies,
+ bool hasBallparkTransformation) {
auto formatter = io::PROJStringFormatter::create();
if (inverse) {
@@ -11891,7 +12901,7 @@ PROJBasedOperationNNPtr PROJBasedOperation::create(
auto method = OperationMethod::create(
util::PropertyMap().set(common::IdentifiedObject::NAME_KEY,
- "PROJ-based operation method (approximate) : " +
+ "PROJ-based operation method (approximate): " +
projString),
std::vector<GeneralOperationParameterNNPtr>{});
auto op = PROJBasedOperation::nn_make_shared<PROJBasedOperation>(method);
@@ -11903,6 +12913,7 @@ PROJBasedOperationNNPtr PROJBasedOperation::create(
op->setAccuracies(accuracies);
op->projStringExportable_ = projExportable.as_nullable();
op->inverse_ = inverse;
+ op->setHasBallparkTransformation(hasBallparkTransformation);
return op;
}
@@ -11916,7 +12927,7 @@ CoordinateOperationNNPtr PROJBasedOperation::inverse() const {
createPropertiesForInverse(this, false, false),
NN_NO_CHECK(projStringExportable_), !inverse_,
NN_NO_CHECK(targetCRS()), NN_NO_CHECK(sourceCRS()),
- coordinateOperationAccuracies()));
+ coordinateOperationAccuracies(), hasBallparkTransformation()));
}
auto formatter = io::PROJStringFormatter::create();
@@ -11929,11 +12940,11 @@ CoordinateOperationNNPtr PROJBasedOperation::inverse() const {
}
formatter->stopInversion();
- return util::nn_static_pointer_cast<CoordinateOperation>(
- PROJBasedOperation::create(
- createPropertiesForInverse(this, false, false),
- formatter->toString(), targetCRS(), sourceCRS(),
- coordinateOperationAccuracies()));
+ auto op = PROJBasedOperation::create(
+ createPropertiesForInverse(this, false, false), formatter->toString(),
+ targetCRS(), sourceCRS(), coordinateOperationAccuracies());
+ op->setHasBallparkTransformation(hasBallparkTransformation());
+ return util::nn_static_pointer_cast<CoordinateOperation>(op);
}
// ---------------------------------------------------------------------------
@@ -11987,6 +12998,15 @@ void PROJBasedOperation::_exportToPROJString(
// ---------------------------------------------------------------------------
+CoordinateOperationNNPtr PROJBasedOperation::_shallowClone() const {
+ auto op = PROJBasedOperation::nn_make_shared<PROJBasedOperation>(*this);
+ op->assignSelf(op);
+ op->setCRSs(this, false);
+ return util::nn_static_pointer_cast<CoordinateOperation>(op);
+}
+
+// ---------------------------------------------------------------------------
+
std::set<GridDescription> PROJBasedOperation::gridsNeeded(
const io::DatabaseContextPtr &databaseContext) const {
std::set<GridDescription> res;
diff --git a/src/iso19111/coordinatesystem.cpp b/src/iso19111/coordinatesystem.cpp
index efba8c05..ef9cac93 100644
--- a/src/iso19111/coordinatesystem.cpp
+++ b/src/iso19111/coordinatesystem.cpp
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Project: PROJ
- * Purpose: ISO19111:2018 implementation
+ * Purpose: ISO19111:2019 implementation
* Author: Even Rouault <even dot rouault at spatialys dot com>
*
******************************************************************************
@@ -483,7 +483,7 @@ void CoordinateSystem::_exportToWKT(
const auto &l_axisList = axisList();
if (isWKT2) {
- formatter->startNode(io::WKTConstants::CS, !identifiers().empty());
+ formatter->startNode(io::WKTConstants::CS_, !identifiers().empty());
formatter->add(getWKT2Type(formatter->use2018Keywords()));
formatter->add(static_cast<int>(l_axisList.size()));
formatter->endNode();
diff --git a/src/iso19111/crs.cpp b/src/iso19111/crs.cpp
index 01a588e3..476bc72b 100644
--- a/src/iso19111/crs.cpp
+++ b/src/iso19111/crs.cpp
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Project: PROJ
- * Purpose: ISO19111:2018 implementation
+ * Purpose: ISO19111:2019 implementation
* Author: Even Rouault <even dot rouault at spatialys dot com>
*
******************************************************************************
@@ -453,7 +453,7 @@ CRSNNPtr CRS::createBoundCRSToWGS84IfPossible(
auto transf =
util::nn_dynamic_pointer_cast<operation::Transformation>(
op);
- if (transf && !starts_with(transf->nameStr(), "Null geo")) {
+ if (transf && !starts_with(transf->nameStr(), "Ballpark geo")) {
try {
transf->getTOWGS84Parameters();
} catch (const std::exception &) {
@@ -486,7 +486,7 @@ CRSNNPtr CRS::createBoundCRSToWGS84IfPossible(
operation::Transformation>(subops[1]);
if (transf &&
!starts_with(transf->nameStr(),
- "Null geo")) {
+ "Ballpark geo")) {
try {
transf->getTOWGS84Parameters();
} catch (const std::exception &) {
@@ -591,6 +591,104 @@ CRSNNPtr CRS::alterId(const std::string &authName,
// ---------------------------------------------------------------------------
+//! @cond Doxygen_Suppress
+
+static bool isAxisListNorthEast(
+ const std::vector<cs::CoordinateSystemAxisNNPtr> &axisList) {
+ const auto &dir0 = axisList[0]->direction();
+ const auto &dir1 = axisList[1]->direction();
+ return (&dir0 == &cs::AxisDirection::NORTH &&
+ &dir1 == &cs::AxisDirection::EAST);
+}
+// ---------------------------------------------------------------------------
+
+bool CRS::mustAxisOrderBeSwitchedForVisualization() const {
+
+ const CompoundCRS *compoundCRS = dynamic_cast<const CompoundCRS *>(this);
+ if (compoundCRS) {
+ const auto &comps = compoundCRS->componentReferenceSystems();
+ if (!comps.empty()) {
+ return comps[0]->mustAxisOrderBeSwitchedForVisualization();
+ }
+ }
+
+ const GeographicCRS *geogCRS = dynamic_cast<const GeographicCRS *>(this);
+ if (geogCRS) {
+ return isAxisListNorthEast(geogCRS->coordinateSystem()->axisList());
+ }
+
+ const ProjectedCRS *projCRS = dynamic_cast<const ProjectedCRS *>(this);
+ if (projCRS) {
+ return isAxisListNorthEast(projCRS->coordinateSystem()->axisList());
+ }
+
+ return false;
+}
+
+//! @endcond
+
+// ---------------------------------------------------------------------------
+
+//! @cond Doxygen_Suppress
+
+CRSNNPtr CRS::normalizeForVisualization() const {
+ auto props = util::PropertyMap().set(
+ common::IdentifiedObject::NAME_KEY,
+ nameStr() + " (with axis order normalized for visualization)");
+
+ const CompoundCRS *compoundCRS = dynamic_cast<const CompoundCRS *>(this);
+ if (compoundCRS) {
+ const auto &comps = compoundCRS->componentReferenceSystems();
+ if (!comps.empty()) {
+ std::vector<CRSNNPtr> newComps;
+ newComps.emplace_back(comps[0]->normalizeForVisualization());
+ for (size_t i = 1; i < comps.size(); i++) {
+ newComps.emplace_back(comps[i]);
+ }
+ return util::nn_static_pointer_cast<CRS>(
+ CompoundCRS::create(props, newComps));
+ }
+ }
+
+ const GeographicCRS *geogCRS = dynamic_cast<const GeographicCRS *>(this);
+ if (geogCRS) {
+ const auto &axisList = geogCRS->coordinateSystem()->axisList();
+ if (isAxisListNorthEast(axisList)) {
+ auto cs = axisList.size() == 2
+ ? cs::EllipsoidalCS::create(util::PropertyMap(),
+ axisList[1], axisList[0])
+ : cs::EllipsoidalCS::create(util::PropertyMap(),
+ axisList[1], axisList[0],
+ axisList[2]);
+ return util::nn_static_pointer_cast<CRS>(GeographicCRS::create(
+ props, geogCRS->datum(), geogCRS->datumEnsemble(), cs));
+ }
+ }
+
+ const ProjectedCRS *projCRS = dynamic_cast<const ProjectedCRS *>(this);
+ if (projCRS) {
+ const auto &axisList = projCRS->coordinateSystem()->axisList();
+ if (isAxisListNorthEast(axisList)) {
+ auto cs =
+ axisList.size() == 2
+ ? cs::CartesianCS::create(util::PropertyMap(), axisList[1],
+ axisList[0])
+ : cs::CartesianCS::create(util::PropertyMap(), axisList[1],
+ axisList[0], axisList[2]);
+ return util::nn_static_pointer_cast<CRS>(
+ ProjectedCRS::create(props, projCRS->baseCRS(),
+ projCRS->derivingConversionRef(), cs));
+ }
+ }
+
+ return NN_NO_CHECK(
+ std::static_pointer_cast<CRS>(shared_from_this().as_nullable()));
+}
+
+//! @endcond
+
+// ---------------------------------------------------------------------------
+
/** \brief Identify the CRS with reference CRSs.
*
* The candidate CRSs are either hard-coded, or looked in the database when
@@ -1289,6 +1387,36 @@ GeodeticCRSNNPtr GeodeticCRS::createEPSG_4978() {
// ---------------------------------------------------------------------------
+//! @cond Doxygen_Suppress
+
+static bool hasCodeCompatibleOfAuthorityFactory(
+ const common::IdentifiedObject *obj,
+ const io::AuthorityFactoryPtr &authorityFactory) {
+ const auto &ids = obj->identifiers();
+ if (!ids.empty() && authorityFactory->getAuthority().empty()) {
+ return true;
+ }
+ for (const auto &id : ids) {
+ if (*(id->codeSpace()) == authorityFactory->getAuthority()) {
+ return true;
+ }
+ }
+ return false;
+}
+
+static bool hasCodeCompatibleOfAuthorityFactory(
+ const metadata::IdentifierNNPtr &id,
+ const io::AuthorityFactoryPtr &authorityFactory) {
+ if (authorityFactory->getAuthority().empty()) {
+ return true;
+ }
+ return *(id->codeSpace()) == authorityFactory->getAuthority();
+}
+
+//! @endcond
+
+// ---------------------------------------------------------------------------
+
/** \brief Identify the CRS with reference CRSs.
*
* The candidate CRSs are either hard-coded, or looked in the database when
@@ -1432,19 +1560,22 @@ GeodeticCRS::identify(const io::AuthorityFactoryPtr &authorityFactory) const {
searchByEllipsoid();
}
}
- } else if (!identifiers().empty()) {
+ } else if (hasCodeCompatibleOfAuthorityFactory(this,
+ authorityFactory)) {
// If the CRS has already an id, check in the database for the
// official object, and verify that they are equivalent.
for (const auto &id : identifiers()) {
- try {
- auto crs = io::AuthorityFactory::create(
- authorityFactory->databaseContext(),
- *id->codeSpace())
- ->createGeodeticCRS(id->code());
- bool match = _isEquivalentTo(crs.get(), crsCriterion);
- res.emplace_back(crs, match ? 100 : 25);
- return res;
- } catch (const std::exception &) {
+ if (hasCodeCompatibleOfAuthorityFactory(id, authorityFactory)) {
+ try {
+ auto crs = io::AuthorityFactory::create(
+ authorityFactory->databaseContext(),
+ *id->codeSpace())
+ ->createGeodeticCRS(id->code());
+ bool match = _isEquivalentTo(crs.get(), crsCriterion);
+ res.emplace_back(crs, match ? 100 : 25);
+ return res;
+ } catch (const std::exception &) {
+ }
}
}
} else {
@@ -1892,9 +2023,7 @@ void GeographicCRS::addAngularUnitConvertAndAxisSwap(
if (order[0] && order[1] && (order[0] != one || order[1] != two)) {
formatter->addStep("axisswap");
char orderStr[10];
- strcpy(orderStr, order[0]);
- strcat(orderStr, ",");
- strcat(orderStr, order[1]);
+ sprintf(orderStr, "%.2s,%.2s", order[0], order[1]);
formatter->addParam("order", orderStr);
}
}
@@ -2096,7 +2225,6 @@ void VerticalCRS::addLinearUnitConvert(
auto &axisList = coordinateSystem()->axisList();
if (!axisList.empty()) {
- auto projUnit = axisList[0]->unit().exportToPROJString();
if (axisList[0]->unit().conversionToSI() != 1.0) {
formatter->addStep("unitconvert");
formatter->addParam("z_in", "m");
@@ -2204,20 +2332,23 @@ VerticalCRS::identify(const io::AuthorityFactoryPtr &authorityFactory) const {
const bool unsignificantName = thisName.empty() ||
ci_equal(thisName, "unknown") ||
ci_equal(thisName, "unnamed");
- if (!identifiers().empty()) {
+ if (hasCodeCompatibleOfAuthorityFactory(this, authorityFactory)) {
// If the CRS has already an id, check in the database for the
// official object, and verify that they are equivalent.
for (const auto &id : identifiers()) {
- try {
- auto crs = io::AuthorityFactory::create(
- authorityFactory->databaseContext(),
- *id->codeSpace())
- ->createVerticalCRS(id->code());
- bool match = _isEquivalentTo(
- crs.get(), util::IComparable::Criterion::EQUIVALENT);
- res.emplace_back(crs, match ? 100 : 25);
- return res;
- } catch (const std::exception &) {
+ if (hasCodeCompatibleOfAuthorityFactory(id, authorityFactory)) {
+ try {
+ auto crs = io::AuthorityFactory::create(
+ authorityFactory->databaseContext(),
+ *id->codeSpace())
+ ->createVerticalCRS(id->code());
+ bool match = _isEquivalentTo(
+ crs.get(),
+ util::IComparable::Criterion::EQUIVALENT);
+ res.emplace_back(crs, match ? 100 : 25);
+ return res;
+ } catch (const std::exception &) {
+ }
}
}
} else if (!unsignificantName) {
@@ -2422,16 +2553,21 @@ void DerivedCRS::setDerivingConversionCRS() {
// ---------------------------------------------------------------------------
-void DerivedCRS::baseExportToWKT(io::WKTFormatter *&formatter,
+void DerivedCRS::baseExportToWKT(io::WKTFormatter *formatter,
const std::string &keyword,
const std::string &baseKeyword) const {
formatter->startNode(keyword, !identifiers().empty());
formatter->addQuotedString(nameStr());
const auto &l_baseCRS = d->baseCRS_;
- formatter->startNode(baseKeyword, !l_baseCRS->identifiers().empty());
+ formatter->startNode(baseKeyword, formatter->use2018Keywords() &&
+ !l_baseCRS->identifiers().empty());
formatter->addQuotedString(l_baseCRS->nameStr());
l_baseCRS->exportDatumOrDatumEnsembleToWkt(formatter);
+ if (formatter->use2018Keywords() &&
+ !(formatter->idOnTopLevelOnly() && formatter->topLevelHasId())) {
+ l_baseCRS->formatID(formatter);
+ }
formatter->endNode();
formatter->setUseDerivingConversion(true);
@@ -2659,7 +2795,7 @@ void ProjectedCRS::_exportToWKT(io::WKTFormatter *formatter) const {
dynamic_cast<const GeographicCRS *>(l_baseCRS.get()))
? io::WKTConstants::BASEGEOGCRS
: io::WKTConstants::BASEGEODCRS,
- !l_baseCRS->identifiers().empty());
+ formatter->use2018Keywords() && !l_baseCRS->identifiers().empty());
formatter->addQuotedString(l_baseCRS->nameStr());
l_baseCRS->exportDatumOrDatumEnsembleToWkt(formatter);
// insert ellipsoidal cs unit when the units of the map
@@ -2670,6 +2806,10 @@ void ProjectedCRS::_exportToWKT(io::WKTFormatter *formatter) const {
geodeticCRSAxisList[0]->unit()._exportToWKT(formatter);
}
l_baseCRS->primeMeridian()->_exportToWKT(formatter);
+ if (formatter->use2018Keywords() &&
+ !(formatter->idOnTopLevelOnly() && formatter->topLevelHasId())) {
+ l_baseCRS->formatID(formatter);
+ }
formatter->endNode();
} else {
const auto oldAxisOutputRule = formatter->outputAxis();
@@ -2843,9 +2983,7 @@ void ProjectedCRS::addUnitConvertAndAxisSwap(io::PROJStringFormatter *formatter,
if (order[0] && order[1]) {
formatter->addStep("axisswap");
char orderStr[10];
- strcpy(orderStr, order[0]);
- strcat(orderStr, ",");
- strcat(orderStr, order[1]);
+ sprintf(orderStr, "%.2s,%.2s", order[0], order[1]);
formatter->addParam("order", orderStr);
}
} else {
@@ -2998,21 +3136,24 @@ ProjectedCRS::identify(const io::AuthorityFactoryPtr &authorityFactory) const {
ci_equal(thisName, "unnamed");
bool foundEquivalentName = false;
- if (!identifiers().empty()) {
+ if (hasCodeCompatibleOfAuthorityFactory(this, authorityFactory)) {
// If the CRS has already an id, check in the database for the
// official object, and verify that they are equivalent.
for (const auto &id : identifiers()) {
- try {
- auto crs = io::AuthorityFactory::create(
- authorityFactory->databaseContext(),
- *id->codeSpace())
- ->createProjectedCRS(id->code());
- bool match = _isEquivalentTo(
- crs.get(), util::IComparable::Criterion::
- EQUIVALENT_EXCEPT_AXIS_ORDER_GEOGCRS);
- res.emplace_back(crs, match ? 100 : 25);
- return res;
- } catch (const std::exception &) {
+ if (hasCodeCompatibleOfAuthorityFactory(id, authorityFactory)) {
+ try {
+ auto crs = io::AuthorityFactory::create(
+ authorityFactory->databaseContext(),
+ *id->codeSpace())
+ ->createProjectedCRS(id->code());
+ bool match = _isEquivalentTo(
+ crs.get(),
+ util::IComparable::Criterion::
+ EQUIVALENT_EXCEPT_AXIS_ORDER_GEOGCRS);
+ res.emplace_back(crs, match ? 100 : 25);
+ return res;
+ } catch (const std::exception &) {
+ }
}
}
} else if (!unsignificantName) {
@@ -3087,8 +3228,8 @@ ProjectedCRS::identify(const io::AuthorityFactoryPtr &authorityFactory) const {
// Sort results
res.sort(lambdaSort);
- if (identifiers().empty() && !foundEquivalentName &&
- (res.empty() || res.front().second < 50)) {
+ if (!hasCodeCompatibleOfAuthorityFactory(this, authorityFactory) &&
+ !foundEquivalentName && (res.empty() || res.front().second < 50)) {
std::set<std::pair<std::string, std::string>> alreadyKnown;
for (const auto &pair : res) {
const auto &ids = pair.first->identifiers();
@@ -3346,20 +3487,23 @@ CompoundCRS::identify(const io::AuthorityFactoryPtr &authorityFactory) const {
ci_equal(thisName, "unnamed");
bool foundEquivalentName = false;
- if (!identifiers().empty()) {
+ if (hasCodeCompatibleOfAuthorityFactory(this, authorityFactory)) {
// If the CRS has already an id, check in the database for the
// official object, and verify that they are equivalent.
for (const auto &id : identifiers()) {
- try {
- auto crs = io::AuthorityFactory::create(
- authorityFactory->databaseContext(),
- *id->codeSpace())
- ->createCompoundCRS(id->code());
- bool match = _isEquivalentTo(
- crs.get(), util::IComparable::Criterion::EQUIVALENT);
- res.emplace_back(crs, match ? 100 : 25);
- return res;
- } catch (const std::exception &) {
+ if (hasCodeCompatibleOfAuthorityFactory(id, authorityFactory)) {
+ try {
+ auto crs = io::AuthorityFactory::create(
+ authorityFactory->databaseContext(),
+ *id->codeSpace())
+ ->createCompoundCRS(id->code());
+ bool match = _isEquivalentTo(
+ crs.get(),
+ util::IComparable::Criterion::EQUIVALENT);
+ res.emplace_back(crs, match ? 100 : 25);
+ return res;
+ } catch (const std::exception &) {
+ }
}
}
} else if (!unsignificantName) {
@@ -3855,7 +3999,7 @@ BoundCRS::_identify(const io::AuthorityFactoryPtr &authorityFactory) const {
for (const auto &op : ops) {
std::string opTransfPROJString;
bool opTransfPROJStringValid = false;
- if (op->nameStr().find("Null geographic") == 0) {
+ if (op->nameStr().find("Ballpark geographic") == 0) {
if (isTOWGS84Compatible()) {
auto params =
transformation()->getTOWGS84Parameters();
@@ -4849,7 +4993,7 @@ DerivedCRSTemplate<DerivedCRSTraits>::create(
// ---------------------------------------------------------------------------
-static void DerivedCRSTemplateCheckExportToWKT(io::WKTFormatter *&formatter,
+static void DerivedCRSTemplateCheckExportToWKT(io::WKTFormatter *formatter,
const std::string &crsName,
bool wkt2_2018_only) {
const bool isWKT2 = formatter->version() == io::WKTFormatter::Version::WKT2;
diff --git a/src/iso19111/datum.cpp b/src/iso19111/datum.cpp
index 66717f70..bf3092c1 100644
--- a/src/iso19111/datum.cpp
+++ b/src/iso19111/datum.cpp
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Project: PROJ
- * Purpose: ISO19111:2018 implementation
+ * Purpose: ISO19111:2019 implementation
* Author: Even Rouault <even dot rouault at spatialys dot com>
*
******************************************************************************
@@ -154,7 +154,7 @@ const util::optional<std::string> &Datum::anchorDefinition() const {
/** \brief Return the date on which the datum definition was published.
*
- * \note Departure from \ref ISO_19111_2018 : we return a DateTime instead of
+ * \note Departure from \ref ISO_19111_2019 : we return a DateTime instead of
* a Citation::Date.
*
* @return the publication date, or empty.
@@ -783,7 +783,7 @@ bool Ellipsoid::lookForProjWellKnownEllps(std::string &projEllpsName,
if (::fabs(b - b_iter) < 1e-10 * b_iter) {
projEllpsName = proj_ellps[i].id;
ellpsName = proj_ellps[i].name;
- if (ellpsName.find("GRS 1980") == 0) {
+ if (starts_with(ellpsName, "GRS 1980")) {
ellpsName = "GRS 1980";
}
return true;
@@ -794,7 +794,7 @@ bool Ellipsoid::lookForProjWellKnownEllps(std::string &projEllpsName,
if (::fabs(rf - rf_iter) < 1e-10 * rf_iter) {
projEllpsName = proj_ellps[i].id;
ellpsName = proj_ellps[i].name;
- if (ellpsName.find("GRS 1980") == 0) {
+ if (starts_with(ellpsName, "GRS 1980")) {
ellpsName = "GRS 1980";
}
return true;
@@ -1010,7 +1010,7 @@ GeodeticReferenceFrame::primeMeridian() PROJ_PURE_DEFN {
/** \brief Return the Ellipsoid associated with a GeodeticReferenceFrame.
*
- * \note The \ref ISO_19111_2018 modelling allows (but discourages) a
+ * \note The \ref ISO_19111_2019 modelling allows (but discourages) a
* GeodeticReferenceFrame
* to not be associated with a Ellipsoid in the case where it is used by a
* geocentric crs::GeodeticCRS. We have made the choice of making the ellipsoid
@@ -1223,7 +1223,7 @@ DynamicGeodeticReferenceFrame::frameReferenceEpoch() const {
/** \brief Return the name of the deformation model.
*
- * @note This is an extension to the \ref ISO_19111_2018 modeling, to
+ * @note This is an extension to the \ref ISO_19111_2019 modeling, to
* hold the content of the DYNAMIC.MODEL WKT2 node.
*
* @return the name of the deformation model.
@@ -1660,7 +1660,7 @@ DynamicVerticalReferenceFrame::frameReferenceEpoch() const {
/** \brief Return the name of the deformation model.
*
- * @note This is an extension to the \ref ISO_19111_2018 modeling, to
+ * @note This is an extension to the \ref ISO_19111_2019 modeling, to
* hold the content of the DYNAMIC.MODEL WKT2 node.
*
* @return the name of the deformation model.
diff --git a/src/iso19111/factory.cpp b/src/iso19111/factory.cpp
index 81abcdf1..4515188a 100644
--- a/src/iso19111/factory.cpp
+++ b/src/iso19111/factory.cpp
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Project: PROJ
- * Purpose: ISO19111:2018 implementation
+ * Purpose: ISO19111:2019 implementation
* Author: Even Rouault <even dot rouault at spatialys dot com>
*
******************************************************************************
@@ -259,7 +259,7 @@ struct DatabaseContext::Private {
static void getFromCache(LRUCacheOfObjects &cache, const std::string &code,
util::BaseObjectPtr &obj);
- void closeDB();
+ void closeDB() noexcept;
// cppcheck-suppress functionStatic
void registerFunctions();
@@ -295,7 +295,7 @@ DatabaseContext::Private::~Private() {
// ---------------------------------------------------------------------------
-void DatabaseContext::Private::closeDB() {
+void DatabaseContext::Private::closeDB() noexcept {
if (detach_) {
// Workaround a bug visible in SQLite 3.8.1 and 3.8.2 that causes
@@ -309,7 +309,10 @@ void DatabaseContext::Private::closeDB() {
// https://github.com/mackyle/sqlite/commit/ccf328c4318eacedab9ed08c404bc4f402dcad19
// also seemed to hide the issue.
// Detaching a database hides the issue, not sure if it is by chance...
- run("DETACH DATABASE db_0");
+ try {
+ run("DETACH DATABASE db_0");
+ } catch (...) {
+ }
detach_ = false;
}
@@ -611,11 +614,16 @@ void DatabaseContext::Private::setHandle(sqlite3 *sqlite_handle) {
// ---------------------------------------------------------------------------
std::vector<std::string> DatabaseContext::Private::getDatabaseStructure() {
- auto sqlRes = run("SELECT sql FROM sqlite_master WHERE type "
- "IN ('table', 'trigger', 'view') ORDER BY type");
+ const char *sqls[] = {
+ "SELECT sql FROM sqlite_master WHERE type = 'table'",
+ "SELECT sql FROM sqlite_master WHERE type = 'view'",
+ "SELECT sql FROM sqlite_master WHERE type = 'trigger'"};
std::vector<std::string> res;
- for (const auto &row : sqlRes) {
- res.emplace_back(row[0]);
+ for (const auto &sql : sqls) {
+ auto sqlRes = run(sql);
+ for (const auto &row : sqlRes) {
+ res.emplace_back(row[0]);
+ }
}
return res;
}
@@ -1024,8 +1032,8 @@ bool DatabaseContext::lookForGridInfo(const std::string &projFilename,
info.url = url;
info.directDownload = directDownload;
info.openLicense = openLicense;
- info.gridAvailable = gridAvailable;
}
+ info.gridAvailable = gridAvailable;
info.found = ret;
d->cache(projFilename, info);
return ret;
@@ -1359,6 +1367,15 @@ const DatabaseContextNNPtr &AuthorityFactory::databaseContext() const {
// ---------------------------------------------------------------------------
+//! @cond Doxygen_Suppress
+AuthorityFactory::CRSInfo::CRSInfo()
+ : authName{}, code{}, name{}, type{ObjectType::CRS}, deprecated{},
+ bbox_valid{}, west_lon_degree{}, south_lat_degree{}, east_lon_degree{},
+ north_lat_degree{}, areaName{}, projectionMethodName{} {}
+//! @endcond
+
+// ---------------------------------------------------------------------------
+
/** \brief Returns an arbitrary object from a code.
*
* The returned object will typically be an instance of Datum,
@@ -1606,10 +1623,12 @@ static double normalizeMeasure(const std::string &uom_code,
assert(seconds.size() == precision - 2);
normalized_value =
(normalized_value < 0 ? -1.0 : 1.0) *
- (int(std::fabs(normalized_value)) + c_locale_stod(minutes) / 60. +
+ (std::floor(std::fabs(normalized_value)) +
+ c_locale_stod(minutes) / 60. +
(c_locale_stod(seconds) / std::pow(10, seconds.size() - 2)) /
3600.);
normalized_uom_code = common::UnitOfMeasure::DEGREE.code();
+ /* coverity[overflow_sink] */
return normalized_value;
} else {
normalized_uom_code = uom_code;
@@ -2394,6 +2413,11 @@ AuthorityFactory::createProjectedCRS(const std::string &code) const {
auto conv = d->createFactory(conversion_auth_name)
->createConversion(conversion_code);
+ if (conv->nameStr() == "unnamed") {
+ conv = conv->shallowClone();
+ conv->setProperties(util::PropertyMap().set(
+ common::IdentifiedObject::NAME_KEY, name));
+ }
auto cartesianCS = util::nn_dynamic_pointer_cast<cs::CartesianCS>(cs);
if (cartesianCS) {
@@ -2470,6 +2494,8 @@ crs::CRSNNPtr AuthorityFactory::createCoordinateReferenceSystem(
return createCoordinateReferenceSystem(code, true);
}
+//! @cond Doxygen_Suppress
+
crs::CRSNNPtr
AuthorityFactory::createCoordinateReferenceSystem(const std::string &code,
bool allowCompound) const {
@@ -2499,6 +2525,9 @@ AuthorityFactory::createCoordinateReferenceSystem(const std::string &code,
}
throw FactoryException("unhandled CRS type: " + type);
}
+
+//! @endcond
+
// ---------------------------------------------------------------------------
//! @cond Doxygen_Suppress
@@ -2588,7 +2617,7 @@ operation::CoordinateOperationNNPtr AuthorityFactory::createCoordinateOperation(
"rate_scale_difference, rate_scale_difference_uom_auth_name, "
"rate_scale_difference_uom_code, epoch, epoch_uom_auth_name, "
"epoch_uom_code, px, py, pz, pivot_uom_auth_name, pivot_uom_code, "
- "deprecated FROM "
+ "operation_version, deprecated FROM "
"helmert_transformation WHERE auth_name = ? AND code = ?",
code);
if (res.empty()) {
@@ -2649,6 +2678,7 @@ operation::CoordinateOperationNNPtr AuthorityFactory::createCoordinateOperation(
const auto &pivot_uom_auth_name = row[idx++];
const auto &pivot_uom_code = row[idx++];
+ const auto &operation_version = row[idx++];
const auto &deprecated_str = row[idx++];
const bool deprecated = deprecated_str == "1";
assert(idx == row.size());
@@ -2789,6 +2819,10 @@ operation::CoordinateOperationNNPtr AuthorityFactory::createCoordinateOperation(
auto props =
d->createProperties(code, name, deprecated,
area_of_use_auth_name, area_of_use_code);
+ if (!operation_version.empty()) {
+ props.set(operation::CoordinateOperation::OPERATION_VERSION_KEY,
+ operation_version);
+ }
auto propsMethod =
util::PropertyMap()
@@ -2819,8 +2853,8 @@ operation::CoordinateOperationNNPtr AuthorityFactory::createCoordinateOperation(
"grid_name, "
"grid2_param_auth_name, grid2_param_code, grid2_param_name, "
"grid2_name, "
- "interpolation_crs_auth_name, interpolation_crs_code, deprecated "
- "FROM "
+ "interpolation_crs_auth_name, interpolation_crs_code, "
+ "operation_version, deprecated FROM "
"grid_transformation WHERE auth_name = ? AND code = ?",
code);
if (res.empty()) {
@@ -2852,7 +2886,7 @@ operation::CoordinateOperationNNPtr AuthorityFactory::createCoordinateOperation(
const auto &grid2_name = row[idx++];
const auto &interpolation_crs_auth_name = row[idx++];
const auto &interpolation_crs_code = row[idx++];
-
+ const auto &operation_version = row[idx++];
const auto &deprecated_str = row[idx++];
const bool deprecated = deprecated_str == "1";
assert(idx == row.size());
@@ -2898,6 +2932,10 @@ operation::CoordinateOperationNNPtr AuthorityFactory::createCoordinateOperation(
auto props =
d->createProperties(code, name, deprecated,
area_of_use_auth_name, area_of_use_code);
+ if (!operation_version.empty()) {
+ props.set(operation::CoordinateOperation::OPERATION_VERSION_KEY,
+ operation_version);
+ }
auto propsMethod =
util::PropertyMap()
.set(metadata::Identifier::CODESPACE_KEY, method_auth_name)
@@ -2939,8 +2977,8 @@ operation::CoordinateOperationNNPtr AuthorityFactory::createCoordinateOperation(
buffer << ", param" << i << "_uom_auth_name";
buffer << ", param" << i << "_uom_code";
}
- buffer << ", deprecated FROM other_transformation WHERE auth_name = ? "
- "AND code = ?";
+ buffer << ", operation_version, deprecated FROM other_transformation "
+ "WHERE auth_name = ? AND code = ?";
auto res = d->runWithCodeParam(buffer.str(), code);
if (res.empty()) {
@@ -2993,6 +3031,7 @@ operation::CoordinateOperationNNPtr AuthorityFactory::createCoordinateOperation(
}
idx = base_param_idx + 6 * N_MAX_PARAMS;
+ const auto &operation_version = row[idx++];
const auto &deprecated_str = row[idx++];
const bool deprecated = deprecated_str == "1";
assert(idx == row.size());
@@ -3007,6 +3046,10 @@ operation::CoordinateOperationNNPtr AuthorityFactory::createCoordinateOperation(
auto props =
d->createProperties(code, name, deprecated,
area_of_use_auth_name, area_of_use_code);
+ if (!operation_version.empty()) {
+ props.set(operation::CoordinateOperation::OPERATION_VERSION_KEY,
+ operation_version);
+ }
std::vector<metadata::PositionalAccuracyNNPtr> accuracies;
if (!accuracy.empty()) {
@@ -3060,7 +3103,7 @@ operation::CoordinateOperationNNPtr AuthorityFactory::createCoordinateOperation(
"target_crs_auth_name, target_crs_code, "
"area_of_use_auth_name, area_of_use_code, accuracy, "
"step1_auth_name, step1_code, step2_auth_name, step2_code, "
- "step3_auth_name, step3_code, deprecated FROM "
+ "step3_auth_name, step3_code, operation_version, deprecated FROM "
"concatenated_operation WHERE auth_name = ? AND code = ?",
code);
if (res.empty()) {
@@ -3085,6 +3128,7 @@ operation::CoordinateOperationNNPtr AuthorityFactory::createCoordinateOperation(
const auto &step2_code = row[idx++];
const auto &step3_auth_name = row[idx++];
const auto &step3_code = row[idx++];
+ const auto &operation_version = row[idx++];
const auto &deprecated_str = row[idx++];
const bool deprecated = deprecated_str == "1";
@@ -3118,6 +3162,10 @@ operation::CoordinateOperationNNPtr AuthorityFactory::createCoordinateOperation(
auto props =
d->createProperties(code, name, deprecated,
area_of_use_auth_name, area_of_use_code);
+ if (!operation_version.empty()) {
+ props.set(operation::CoordinateOperation::OPERATION_VERSION_KEY,
+ operation_version);
+ }
std::vector<metadata::PositionalAccuracyNNPtr> accuracies;
if (!accuracy.empty()) {
@@ -3873,7 +3921,7 @@ AuthorityFactory::getDescriptionText(const std::string &code) const {
/** \brief Return a list of information on CRS objects
*
* This is functionnaly equivalent of listing the codes from an authority,
- * instanciating
+ * instantiating
* a CRS object for each of them and getting the information from this CRS
* object, but this implementation has much less overhead.
*
@@ -3896,13 +3944,16 @@ std::list<AuthorityFactory::CRSInfo> AuthorityFactory::getCRSInfoList() const {
sql += "SELECT c.auth_name, c.code, c.name, 'projected', "
"c.deprecated, "
"a.west_lon, a.south_lat, a.east_lon, a.north_lat, "
- "a.name, conv.method_name FROM projected_crs c "
+ "a.name, cm.name AS conversion_method_name FROM projected_crs c "
"JOIN area a ON "
"c.area_of_use_auth_name = a.auth_name AND "
"c.area_of_use_code = a.code "
- "LEFT JOIN conversion conv ON "
+ "LEFT JOIN conversion_table conv ON "
"c.conversion_auth_name = conv.auth_name AND "
- "c.conversion_code = conv.code";
+ "c.conversion_code = conv.code "
+ "LEFT JOIN conversion_method cm ON "
+ "conv.method_auth_name = cm.auth_name AND "
+ "conv.method_code = cm.code";
if (d->hasAuthorityRestriction()) {
sql += " WHERE c.auth_name = ?";
params.emplace_back(d->authority());
@@ -4625,9 +4676,9 @@ AuthorityFactory::createProjectedCRSFromExisting(
std::string sql(
"SELECT projected_crs.auth_name, projected_crs.code FROM projected_crs "
- "JOIN conversion ON "
- "projected_crs.conversion_auth_name = conversion.auth_name AND "
- "projected_crs.conversion_code = conversion.code WHERE "
+ "JOIN conversion_table conv ON "
+ "projected_crs.conversion_auth_name = conv.auth_name AND "
+ "projected_crs.conversion_code = conv.code WHERE "
"projected_crs.deprecated = 0 AND ");
ListOfParams params;
if (!candidatesGeodCRS.empty()) {
@@ -4635,8 +4686,8 @@ AuthorityFactory::createProjectedCRSFromExisting(
"projected_crs.geodetic_crs_");
sql += " AND ";
}
- sql += "conversion.method_auth_name = 'EPSG' AND "
- "conversion.method_code = ?";
+ sql += "conv.method_auth_name = 'EPSG' AND "
+ "conv.method_code = ?";
params.emplace_back(toString(methodEPSGCode));
if (d->hasAuthorityRestriction()) {
sql += " AND projected_crs.auth_name = ?";
@@ -4663,11 +4714,11 @@ AuthorityFactory::createProjectedCRSFromExisting(
if (unit == common::UnitOfMeasure::DEGREE &&
geogCRS->coordinateSystem()->axisList()[0]->unit() == unit) {
const auto iParamAsStr(toString(iParam));
- sql += " AND conversion.param";
+ sql += " AND conv.param";
sql += iParamAsStr;
- sql += "_code = ? AND conversion.param";
+ sql += "_code = ? AND conv.param";
sql += iParamAsStr;
- sql += "_auth_name = 'EPSG' AND conversion.param";
+ sql += "_auth_name = 'EPSG' AND conv.param";
sql += iParamAsStr;
sql += "_value BETWEEN ? AND ?";
// As angles might be expressed with the odd unit EPSG:9110
diff --git a/src/iso19111/internal.cpp b/src/iso19111/internal.cpp
index 0c330d30..4810202d 100644
--- a/src/iso19111/internal.cpp
+++ b/src/iso19111/internal.cpp
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Project: PROJ
- * Purpose: ISO19111:2018 implementation
+ * Purpose: ISO19111:2019 implementation
* Author: Even Rouault <even dot rouault at spatialys dot com>
*
******************************************************************************
@@ -298,6 +298,21 @@ std::vector<std::string> split(const std::string &str, char separator) {
// ---------------------------------------------------------------------------
+std::vector<std::string> split(const std::string &str,
+ const std::string &separator) {
+ std::vector<std::string> res;
+ size_t lastPos = 0;
+ size_t newPos = 0;
+ while ((newPos = str.find(separator, lastPos)) != std::string::npos) {
+ res.push_back(str.substr(lastPos, newPos - lastPos));
+ lastPos = newPos + separator.size();
+ }
+ res.push_back(str.substr(lastPos));
+ return res;
+}
+
+// ---------------------------------------------------------------------------
+
#ifdef _WIN32
// For some reason, sqlite3_snprintf() in the sqlite3 builds used on AppVeyor
diff --git a/src/iso19111/io.cpp b/src/iso19111/io.cpp
index e14239b0..7329758a 100644
--- a/src/iso19111/io.cpp
+++ b/src/iso19111/io.cpp
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Project: PROJ
- * Purpose: ISO19111:2018 implementation
+ * Purpose: ISO19111:2019 implementation
* Author: Even Rouault <even dot rouault at spatialys dot com>
*
******************************************************************************
@@ -141,6 +141,7 @@ struct WKTFormatter::Private {
std::vector<bool> stackHasChild_{};
std::vector<bool> stackHasId_{false};
std::vector<bool> stackEmptyKeyword_{};
+ std::vector<bool> stackDisableUsage_{};
std::vector<bool> outputUnitStack_{true};
std::vector<bool> outputIdStack_{true};
std::vector<UnitOfMeasureNNPtr> axisLinearUnitStack_{
@@ -272,6 +273,11 @@ const std::string &WKTFormatter::toString() const {
if (d->outputUnitStack_.size() != 1)
throw FormattingException(
"Unbalanced pushOutputUnit() / popOutputUnit()");
+ if (d->stackHasId_.size() != 1)
+ throw FormattingException("Unbalanced pushHasId() / popHasId()");
+ if (!d->stackDisableUsage_.empty())
+ throw FormattingException(
+ "Unbalanced pushDisableUsage() / popDisableUsage()");
return d->result_;
}
@@ -556,6 +562,28 @@ bool WKTFormatter::outputId() const {
// ---------------------------------------------------------------------------
+void WKTFormatter::pushHasId(bool hasId) { d->stackHasId_.push_back(hasId); }
+
+// ---------------------------------------------------------------------------
+
+void WKTFormatter::popHasId() { d->stackHasId_.pop_back(); }
+
+// ---------------------------------------------------------------------------
+
+void WKTFormatter::pushDisableUsage() { d->stackDisableUsage_.push_back(true); }
+
+// ---------------------------------------------------------------------------
+
+void WKTFormatter::popDisableUsage() { d->stackDisableUsage_.pop_back(); }
+
+// ---------------------------------------------------------------------------
+
+bool WKTFormatter::outputUsage() const {
+ return outputId() && d->stackDisableUsage_.empty();
+}
+
+// ---------------------------------------------------------------------------
+
void WKTFormatter::pushAxisLinearUnit(const UnitOfMeasureNNPtr &unit) {
d->axisLinearUnitStack_.push_back(unit);
}
@@ -634,6 +662,18 @@ bool WKTFormatter::primeMeridianInDegree() const {
// ---------------------------------------------------------------------------
+bool WKTFormatter::idOnTopLevelOnly() const {
+ return d->params_.idOnTopLevelOnly_;
+}
+
+// ---------------------------------------------------------------------------
+
+bool WKTFormatter::topLevelHasId() const {
+ return d->stackHasId_.size() >= 2 && d->stackHasId_[1];
+}
+
+// ---------------------------------------------------------------------------
+
WKTFormatter::Version WKTFormatter::version() const {
return d->params_.version_;
}
@@ -717,13 +757,22 @@ const std::string &WKTFormatter::getHDatumExtension() const {
// ---------------------------------------------------------------------------
std::string WKTFormatter::morphNameToESRI(const std::string &name) {
+
+ for (const auto *suffix : {"(m)", "(ftUS)", "(E-N)", "(N-E)"}) {
+ if (ends_with(name, suffix)) {
+ return morphNameToESRI(
+ name.substr(0, name.size() - strlen(suffix))) +
+ suffix;
+ }
+ }
+
std::string ret;
bool insertUnderscore = false;
// Replace any special character by underscore, except at the beginning
// and of the name where those characters are removed.
for (char ch : name) {
- if (ch == '+' || (ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'z') ||
- (ch >= 'A' && ch <= 'Z')) {
+ if (ch == '+' || ch == '-' || (ch >= '0' && ch <= '9') ||
+ (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) {
if (insertUnderscore && !ret.empty()) {
ret += '_';
}
@@ -973,7 +1022,7 @@ const std::vector<WKTNodeNNPtr> &WKTNode::children() const {
//! @cond Doxygen_Suppress
static size_t skipSpace(const std::string &str, size_t start) {
size_t i = start;
- while (i < str.size() && ::isspace(str[i])) {
+ while (i < str.size() && ::isspace(static_cast<unsigned char>(str[i]))) {
++i;
}
return i;
@@ -1002,8 +1051,9 @@ WKTNodeNNPtr WKTNode::createFrom(const std::string &wkt, size_t indexStart,
bool inString = false;
for (; i < wkt.size() &&
- (inString || (wkt[i] != '[' && wkt[i] != '(' && wkt[i] != ',' &&
- wkt[i] != ']' && wkt[i] != ')' && !::isspace(wkt[i])));
+ (inString ||
+ (wkt[i] != '[' && wkt[i] != '(' && wkt[i] != ',' && wkt[i] != ']' &&
+ wkt[i] != ')' && !::isspace(static_cast<unsigned char>(wkt[i]))));
++i) {
if (wkt[i] == '"') {
if (!inString) {
@@ -1185,7 +1235,7 @@ struct WKTParser::Private {
buildPrimeMeridian(const WKTNodeNNPtr &node,
const UnitOfMeasure &defaultAngularUnit);
- optional<std::string> getAnchor(const WKTNodeNNPtr &node);
+ static optional<std::string> getAnchor(const WKTNodeNNPtr &node);
static void parseDynamic(const WKTNodeNNPtr &dynamicNode,
double &frameReferenceEpoch,
@@ -1301,7 +1351,7 @@ struct WKTParser::Private {
CRSPtr buildCRS(const WKTNodeNNPtr &node);
- CoordinateOperationNNPtr buildCoordinateOperation(const WKTNodeNNPtr &node);
+ TransformationNNPtr buildCoordinateOperation(const WKTNodeNNPtr &node);
ConcatenatedOperationNNPtr
buildConcatenatedOperation(const WKTNodeNNPtr &node);
@@ -1580,6 +1630,17 @@ PropertyMap &WKTParser::Private::buildProperties(const WKTNodeNNPtr &node,
}
}
+ auto &versionNode = nodeP->lookForChild(WKTConstants::VERSION);
+ if (!isNull(versionNode)) {
+ const auto &versionChildren = versionNode->GP()->children();
+ if (versionChildren.size() == 1) {
+ properties->set(CoordinateOperation::OPERATION_VERSION_KEY,
+ stripQuotes(versionChildren[0]));
+ } else {
+ ThrowNotRequiredNumberOfChildren(versionNode->GP()->value());
+ }
+ }
+
return *properties;
}
@@ -2556,13 +2617,13 @@ WKTParser::Private::buildGeodeticCRS(const WKTNodeNNPtr &node) {
auto &dynamicNode = nodeP->lookForChild(WKTConstants::DYNAMIC);
- auto &csNode = nodeP->lookForChild(WKTConstants::CS);
+ auto &csNode = nodeP->lookForChild(WKTConstants::CS_);
const auto &nodeName = nodeP->value();
if (isNull(csNode) && !ci_equal(nodeName, WKTConstants::GEOGCS) &&
!ci_equal(nodeName, WKTConstants::GEOCCS) &&
!ci_equal(nodeName, WKTConstants::BASEGEODCRS) &&
!ci_equal(nodeName, WKTConstants::BASEGEOGCRS)) {
- ThrowMissing(WKTConstants::CS);
+ ThrowMissing(WKTConstants::CS_);
}
auto &primeMeridianNode =
@@ -2712,9 +2773,9 @@ CRSNNPtr WKTParser::Private::buildDerivedGeodeticCRS(const WKTNodeNNPtr &node) {
auto derivingConversion = buildConversion(
derivingConversionNode, UnitOfMeasure::NONE, UnitOfMeasure::NONE);
- auto &csNode = nodeP->lookForChild(WKTConstants::CS);
+ auto &csNode = nodeP->lookForChild(WKTConstants::CS_);
if (isNull(csNode)) {
- ThrowMissing(WKTConstants::CS);
+ ThrowMissing(WKTConstants::CS_);
}
auto cs = buildCS(csNode, node, UnitOfMeasure::NONE);
@@ -2888,7 +2949,7 @@ WKTParser::Private::buildConversion(const WKTNodeNNPtr &node,
// ---------------------------------------------------------------------------
-CoordinateOperationNNPtr
+TransformationNNPtr
WKTParser::Private::buildCoordinateOperation(const WKTNodeNNPtr &node) {
const auto *nodeP = node->GP();
auto &methodNode = nodeP->lookForChild(WKTConstants::METHOD);
@@ -2939,11 +3000,10 @@ WKTParser::Private::buildCoordinateOperation(const WKTNodeNNPtr &node) {
stripQuotes(accuracyNode->GP()->children()[0])));
}
- return util::nn_static_pointer_cast<CoordinateOperation>(
- Transformation::create(buildProperties(node), NN_NO_CHECK(sourceCRS),
- NN_NO_CHECK(targetCRS), interpolationCRS,
- buildProperties(methodNode), parameters, values,
- accuracies));
+ return Transformation::create(buildProperties(node), NN_NO_CHECK(sourceCRS),
+ NN_NO_CHECK(targetCRS), interpolationCRS,
+ buildProperties(methodNode), parameters,
+ values, accuracies);
}
// ---------------------------------------------------------------------------
@@ -3116,7 +3176,6 @@ ConversionNNPtr WKTParser::Private::buildProjectionFromESRI(
}
const auto *wkt2_mapping = getMapping(esriMapping->wkt2_name);
- assert(wkt2_mapping);
if (ci_equal(esriProjectionName, "Stereographic")) {
try {
if (std::fabs(io::asDouble(
@@ -3127,6 +3186,7 @@ ConversionNNPtr WKTParser::Private::buildProjectionFromESRI(
} catch (const std::exception &) {
}
}
+ assert(wkt2_mapping);
PropertyMap propertiesMethod;
propertiesMethod.set(IdentifiedObject::NAME_KEY, wkt2_mapping->wkt2_name);
@@ -3205,7 +3265,10 @@ ConversionNNPtr WKTParser::Private::buildProjectionFromESRI(
}
return Conversion::create(
- PropertyMap().set(IdentifiedObject::NAME_KEY, "unnamed"),
+ PropertyMap().set(IdentifiedObject::NAME_KEY,
+ esriProjectionName == "Gauss_Kruger"
+ ? "unnnamed (Gauss Kruger)"
+ : "unnamed"),
propertiesMethod, parameters, values)
->identify();
}
@@ -3539,11 +3602,11 @@ WKTParser::Private::buildProjectedCRS(const WKTNodeNNPtr &node) {
? buildConversion(conversionNode, linearUnit, angularUnit)
: buildProjection(node, projectionNode, linearUnit, angularUnit);
- auto &csNode = nodeP->lookForChild(WKTConstants::CS);
+ auto &csNode = nodeP->lookForChild(WKTConstants::CS_);
const auto &nodeValue = nodeP->value();
if (isNull(csNode) && !ci_equal(nodeValue, WKTConstants::PROJCS) &&
!ci_equal(nodeValue, WKTConstants::BASEPROJCRS)) {
- ThrowMissing(WKTConstants::CS);
+ ThrowMissing(WKTConstants::CS_);
}
auto cs = buildCS(csNode, node, UnitOfMeasure::NONE);
auto cartesianCS = nn_dynamic_pointer_cast<CartesianCS>(cs);
@@ -3726,11 +3789,11 @@ CRSNNPtr WKTParser::Private::buildVerticalCRS(const WKTNodeNNPtr &node) {
? buildDatumEnsemble(ensembleNode, nullptr, false).as_nullable()
: nullptr;
- auto &csNode = nodeP->lookForChild(WKTConstants::CS);
+ auto &csNode = nodeP->lookForChild(WKTConstants::CS_);
const auto &nodeValue = nodeP->value();
if (isNull(csNode) && !ci_equal(nodeValue, WKTConstants::VERT_CS) &&
!ci_equal(nodeValue, WKTConstants::BASEVERTCRS)) {
- ThrowMissing(WKTConstants::CS);
+ ThrowMissing(WKTConstants::CS_);
}
auto cs = buildCS(csNode, node, UnitOfMeasure::NONE);
auto verticalCS = nn_dynamic_pointer_cast<VerticalCS>(cs);
@@ -3755,7 +3818,7 @@ CRSNNPtr WKTParser::Private::buildVerticalCRS(const WKTNodeNNPtr &node) {
Transformation::createGravityRelatedHeightToGeographic3D(
PropertyMap().set(IdentifiedObject::NAME_KEY,
transformationName),
- crs, GeographicCRS::EPSG_4979,
+ crs, GeographicCRS::EPSG_4979, nullptr,
stripQuotes(extensionChildren[1]),
std::vector<PositionalAccuracyNNPtr>());
return nn_static_pointer_cast<CRS>(BoundCRS::create(
@@ -3787,9 +3850,9 @@ WKTParser::Private::buildDerivedVerticalCRS(const WKTNodeNNPtr &node) {
auto derivingConversion = buildConversion(
derivingConversionNode, UnitOfMeasure::NONE, UnitOfMeasure::NONE);
- auto &csNode = nodeP->lookForChild(WKTConstants::CS);
+ auto &csNode = nodeP->lookForChild(WKTConstants::CS_);
if (isNull(csNode)) {
- ThrowMissing(WKTConstants::CS);
+ ThrowMissing(WKTConstants::CS_);
}
auto cs = buildCS(csNode, node, UnitOfMeasure::NONE);
@@ -3892,10 +3955,10 @@ BoundCRSNNPtr WKTParser::Private::buildBoundCRS(const WKTNodeNNPtr &node) {
TemporalCSNNPtr
WKTParser::Private::buildTemporalCS(const WKTNodeNNPtr &parentNode) {
- auto &csNode = parentNode->GP()->lookForChild(WKTConstants::CS);
+ auto &csNode = parentNode->GP()->lookForChild(WKTConstants::CS_);
if (isNull(csNode) &&
!ci_equal(parentNode->GP()->value(), WKTConstants::BASETIMECRS)) {
- ThrowMissing(WKTConstants::CS);
+ ThrowMissing(WKTConstants::CS_);
}
auto cs = buildCS(csNode, parentNode, UnitOfMeasure::NONE);
auto temporalCS = nn_dynamic_pointer_cast<TemporalCS>(cs);
@@ -3953,9 +4016,9 @@ WKTParser::Private::buildEngineeringCRS(const WKTNodeNNPtr &node) {
throw ParsingException("Missing EDATUM / ENGINEERINGDATUM node");
}
- auto &csNode = nodeP->lookForChild(WKTConstants::CS);
+ auto &csNode = nodeP->lookForChild(WKTConstants::CS_);
if (isNull(csNode) && !ci_equal(nodeP->value(), WKTConstants::BASEENGCRS)) {
- ThrowMissing(WKTConstants::CS);
+ ThrowMissing(WKTConstants::CS_);
}
auto cs = buildCS(csNode, node, UnitOfMeasure::NONE);
@@ -3998,9 +4061,9 @@ WKTParser::Private::buildDerivedEngineeringCRS(const WKTNodeNNPtr &node) {
auto derivingConversion = buildConversion(
derivingConversionNode, UnitOfMeasure::NONE, UnitOfMeasure::NONE);
- auto &csNode = nodeP->lookForChild(WKTConstants::CS);
+ auto &csNode = nodeP->lookForChild(WKTConstants::CS_);
if (isNull(csNode)) {
- ThrowMissing(WKTConstants::CS);
+ ThrowMissing(WKTConstants::CS_);
}
auto cs = buildCS(csNode, node, UnitOfMeasure::NONE);
@@ -4013,10 +4076,10 @@ WKTParser::Private::buildDerivedEngineeringCRS(const WKTNodeNNPtr &node) {
ParametricCSNNPtr
WKTParser::Private::buildParametricCS(const WKTNodeNNPtr &parentNode) {
- auto &csNode = parentNode->GP()->lookForChild(WKTConstants::CS);
+ auto &csNode = parentNode->GP()->lookForChild(WKTConstants::CS_);
if (isNull(csNode) &&
!ci_equal(parentNode->GP()->value(), WKTConstants::BASEPARAMCRS)) {
- ThrowMissing(WKTConstants::CS);
+ ThrowMissing(WKTConstants::CS_);
}
auto cs = buildCS(csNode, parentNode, UnitOfMeasure::NONE);
auto parametricCS = nn_dynamic_pointer_cast<ParametricCS>(cs);
@@ -4086,9 +4149,9 @@ WKTParser::Private::buildDerivedProjectedCRS(const WKTNodeNNPtr &node) {
auto conversion = buildConversion(conversionNode, linearUnit, angularUnit);
- auto &csNode = nodeP->lookForChild(WKTConstants::CS);
+ auto &csNode = nodeP->lookForChild(WKTConstants::CS_);
if (isNull(csNode) && !ci_equal(nodeP->value(), WKTConstants::PROJCS)) {
- ThrowMissing(WKTConstants::CS);
+ ThrowMissing(WKTConstants::CS_);
}
auto cs = buildCS(csNode, node, UnitOfMeasure::NONE);
return DerivedProjectedCRS::create(buildProperties(node), baseProjCRS,
@@ -4255,16 +4318,31 @@ BaseObjectNNPtr WKTParser::Private::build(const WKTNodeNNPtr &node) {
}
if (ci_equal(name, WKTConstants::COORDINATEOPERATION)) {
- return util::nn_static_pointer_cast<BaseObject>(
- buildCoordinateOperation(node));
+ auto transf = buildCoordinateOperation(node);
+
+ const char *prefixes[] = {
+ "PROJ-based operation method: ",
+ "PROJ-based operation method (approximate): "};
+ for (const char *prefix : prefixes) {
+ if (starts_with(transf->method()->nameStr(), prefix)) {
+ auto projString =
+ transf->method()->nameStr().substr(strlen(prefix));
+ return util::nn_static_pointer_cast<BaseObject>(
+ PROJBasedOperation::create(
+ PropertyMap(), projString, transf->sourceCRS(),
+ transf->targetCRS(),
+ transf->coordinateOperationAccuracies()));
+ }
+ }
+
+ return util::nn_static_pointer_cast<BaseObject>(transf);
}
if (ci_equal(name, WKTConstants::CONVERSION)) {
auto conv =
buildConversion(node, UnitOfMeasure::METRE, UnitOfMeasure::DEGREE);
- if (conv->nameStr() == "PROJ-based coordinate operation" &&
- starts_with(conv->method()->nameStr(),
+ if (starts_with(conv->method()->nameStr(),
"PROJ-based operation method: ")) {
auto projString = conv->method()->nameStr().substr(
strlen("PROJ-based operation method: "));
@@ -4345,15 +4423,97 @@ static BaseObjectNNPtr createFromUserInput(const std::string &text,
const auto authorities = dbContextNNPtr->getAuthorities();
for (const auto &authCandidate : authorities) {
if (ci_equal(authCandidate, authName)) {
- return AuthorityFactory::create(dbContextNNPtr,
- authCandidate)
- ->createCoordinateReferenceSystem(code);
+ factory =
+ AuthorityFactory::create(dbContextNNPtr, authCandidate);
+ try {
+ return factory->createCoordinateReferenceSystem(code);
+ } catch (...) {
+ // EPSG:4326+3855
+ auto tokensCode = split(code, '+');
+ if (tokensCode.size() == 2) {
+ auto crs1(factory->createCoordinateReferenceSystem(
+ tokensCode[0], false));
+ auto crs2(factory->createCoordinateReferenceSystem(
+ tokensCode[1], false));
+ return CompoundCRS::create(
+ util::PropertyMap().set(
+ IdentifiedObject::NAME_KEY,
+ crs1->nameStr() + " + " + crs2->nameStr()),
+ {crs1, crs2});
+ }
+ throw;
+ }
}
}
throw;
}
}
+ // OGC 07-092r2: para 7.5.2
+ // URN combined references for compound coordinate reference systems
+ if (starts_with(text, "urn:ogc:def:crs,")) {
+ if (!dbContext) {
+ throw ParsingException("no database context specified");
+ }
+ auto tokensComma = split(text, ',');
+ std::vector<CRSNNPtr> components;
+ std::string name;
+ for (size_t i = 1; i < tokensComma.size(); i++) {
+ tokens = split(tokensComma[i], ':');
+ if (tokens.size() != 4) {
+ throw ParsingException(
+ concat("invalid crs component: ", tokensComma[i]));
+ }
+ const auto &type = tokens[0];
+ auto factory =
+ AuthorityFactory::create(NN_NO_CHECK(dbContext), tokens[1]);
+ const auto &code = tokens[3];
+ if (type == "crs") {
+ auto crs(factory->createCoordinateReferenceSystem(code, false));
+ components.emplace_back(crs);
+ if (!name.empty()) {
+ name += " + ";
+ }
+ name += crs->nameStr();
+ } else {
+ throw ParsingException(
+ concat("unexpected object type: ", type));
+ }
+ }
+ return CompoundCRS::create(
+ util::PropertyMap().set(IdentifiedObject::NAME_KEY, name),
+ components);
+ }
+
+ // OGC 07-092r2: para 7.5.3
+ // 7.5.3 URN combined references for concatenated operations
+ if (starts_with(text, "urn:ogc:def:coordinateOperation,")) {
+ if (!dbContext) {
+ throw ParsingException("no database context specified");
+ }
+ auto tokensComma = split(text, ',');
+ std::vector<CoordinateOperationNNPtr> components;
+ for (size_t i = 1; i < tokensComma.size(); i++) {
+ tokens = split(tokensComma[i], ':');
+ if (tokens.size() != 4) {
+ throw ParsingException(concat(
+ "invalid coordinateOperation component: ", tokensComma[i]));
+ }
+ const auto &type = tokens[0];
+ auto factory =
+ AuthorityFactory::create(NN_NO_CHECK(dbContext), tokens[1]);
+ const auto &code = tokens[3];
+ if (type == "coordinateOperation") {
+ auto op(factory->createCoordinateOperation(code, false));
+ components.emplace_back(op);
+ } else {
+ throw ParsingException(
+ concat("unexpected object type: ", type));
+ }
+ }
+ return ConcatenatedOperation::createComputeMetadata(components, true);
+ }
+
// urn:ogc:def:crs:EPSG::4326
if (tokens.size() == 7) {
if (!dbContext) {
@@ -4454,9 +4614,18 @@ static BaseObjectNNPtr createFromUserInput(const std::string &text,
* <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
+ * <li>OGC URN. e.g. "urn:ogc:def:crs:EPSG::4326",
+ * "urn:ogc:def:coordinateOperation:EPSG::1671",
+ * "urn:ogc:def:ellipsoid:EPSG::7001"
+ * or "urn:ogc:def:datum:EPSG::6326"</li>
+ * <li> OGC URN combining references for compound coordinate reference systems
+ * e.g. "urn:ogc:def:crs,crs:EPSG::2393,crs:EPSG::5717"
+ * We also accept a custom abbreviated syntax EPSG:2393+5717
+ * </li>
+ * <li> OGC URN combining references for concatenated operations
+ * e.g.
+ * "urn:ogc:def:coordinateOperation,coordinateOperation:EPSG::3895,coordinateOperation:EPSG::1618"</li>
+ * <li>an Object 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>
@@ -4488,9 +4657,18 @@ BaseObjectNNPtr createFromUserInput(const std::string &text,
* <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
+ * <li>OGC URN. e.g. "urn:ogc:def:crs:EPSG::4326",
+ * "urn:ogc:def:coordinateOperation:EPSG::1671",
+ * "urn:ogc:def:ellipsoid:EPSG::7001"
+ * or "urn:ogc:def:datum:EPSG::6326"</li>
+ * <li> OGC URN combining references for compound coordinate reference systems
+ * e.g. "urn:ogc:def:crs,crs:EPSG::2393,crs:EPSG::5717"
+ * We also accept a custom abbreviated syntax EPSG:2393+5717
+ * </li>
+ * <li> OGC URN combining references for concatenated operations
+ * e.g.
+ * "urn:ogc:def:coordinateOperation,coordinateOperation:EPSG::3895,coordinateOperation:EPSG::1618"</li>
+ * <li>an Object 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>
@@ -4744,7 +4922,7 @@ struct PROJStringFormatter::Private {
};
std::vector<InversionStackElt> inversionStack_{InversionStackElt()};
bool omitProjLongLatIfPossible_ = false;
- bool omitZUnitConversion_ = false;
+ std::vector<bool> omitZUnitConversion_{false};
DatabaseContextPtr dbContext_{};
bool useApproxTMerc_ = false;
bool addNoDefs_ = true;
@@ -5048,7 +5226,7 @@ const std::string &PROJStringFormatter::toString() const {
first.paramValues[1].keyEquals("z_in") &&
first.paramValues[2].keyEquals("xy_out") &&
first.paramValues[3].keyEquals("z_out") &&
- second.paramValues[0].keyEquals("xy_in=") &&
+ second.paramValues[0].keyEquals("xy_in") &&
second.paramValues[1].keyEquals("xy_out") &&
first.paramValues[0].value == second.paramValues[1].value &&
first.paramValues[2].value == second.paramValues[0].value) {
@@ -5073,6 +5251,22 @@ const std::string &PROJStringFormatter::toString() const {
break;
}
+ // unitconvert (1), axisswap order=2,1, unitconvert(2) ==>
+ // axisswap order=2,1, unitconvert (1), unitconvert(2) which
+ // will get further optimized by previous case
+ if (i + 1 < d->steps_.size() && prevStep.name == "unitconvert" &&
+ curStep.name == "axisswap" && curStepParamCount == 1 &&
+ curStep.paramValues[0].equals("order", "2,1")) {
+ auto iterNext = iterCur;
+ ++iterNext;
+ auto &nextStep = *iterNext;
+ if (nextStep.name == "unitconvert") {
+ std::swap(*iterPrev, *iterCur);
+ changeDone = true;
+ break;
+ }
+ }
+
// axisswap order=2,1 followed by itself is a no-op
if (curStep.name == "axisswap" && prevStep.name == "axisswap" &&
curStepParamCount == 1 && prevStepParamCount == 1 &&
@@ -5102,71 +5296,6 @@ const std::string &PROJStringFormatter::toString() const {
}
}
- // axisswap order=2,1, pop/push v_3, axisswap order=2,1 -> can
- // suppress axisswap
- if (i + 1 < d->steps_.size() && prevStep.name == "axisswap" &&
- (curStep.name == "push" || curStep.name == "pop") &&
- prevStepParamCount == 1 &&
- prevStep.paramValues[0].equals("order", "2,1") &&
- curStepParamCount == 1 && curStep.paramValues[0].key == "v_3") {
- auto iterNext = iterCur;
- ++iterNext;
- auto &nextStep = *iterNext;
- if (nextStep.name == "axisswap" &&
- nextStep.paramValues.size() == 1 &&
- nextStep.paramValues[0].equals("order", "2,1")) {
- d->steps_.erase(iterPrev);
- d->steps_.erase(iterNext);
- changeDone = true;
- break;
- }
- }
-
- // push v_3, axisswap order=2,1, pop v_3 -> can suppress push/pop
- if (i + 1 < d->steps_.size() && prevStep.name == "push" &&
- prevStepParamCount == 1 &&
- prevStep.paramValues[0].key == "v_3" &&
- curStep.name == "axisswap" && curStepParamCount == 1 &&
- curStep.paramValues[0].equals("order", "2,1")) {
- auto iterNext = iterCur;
- ++iterNext;
- auto &nextStep = *iterNext;
- if (nextStep.name == "pop" &&
- nextStep.paramValues.size() == 1 &&
- nextStep.paramValues[0].key == "v_3") {
- d->steps_.erase(iterPrev);
- d->steps_.erase(iterNext);
- changeDone = true;
- break;
- }
- }
-
- // unitconvert xy_in=A xy_out=B, pop/push v_3, unitconvert xy_in=B
- // xy_out=A -> can suppress unitconvert
- if (i + 1 < d->steps_.size() && prevStep.name == "unitconvert" &&
- (curStep.name == "push" || curStep.name == "pop") &&
- prevStepParamCount == 2 &&
- prevStep.paramValues[0].key == "xy_in" &&
- prevStep.paramValues[1].key == "xy_out" &&
- curStepParamCount == 1 && curStep.paramValues[0].key == "v_3") {
- auto iterNext = iterCur;
- ++iterNext;
- auto &nextStep = *iterNext;
- if (nextStep.name == "unitconvert" &&
- nextStep.paramValues.size() == 2 &&
- nextStep.paramValues[0].key == "xy_in" &&
- nextStep.paramValues[1].key == "xy_out" &&
- nextStep.paramValues[0].value ==
- prevStep.paramValues[1].value &&
- nextStep.paramValues[1].value ==
- prevStep.paramValues[0].value) {
- d->steps_.erase(iterPrev);
- d->steps_.erase(iterNext);
- changeDone = true;
- break;
- }
- }
-
// for practical purposes WGS84 and GRS80 ellipsoids are
// equivalents (cartesian transform between both lead to differences
// of the order of 1e-14 deg..).
@@ -5335,6 +5464,11 @@ const std::string &PROJStringFormatter::toString() const {
}
}
}
+
+ if (d->result_.empty()) {
+ d->appendToResult("+proj=noop");
+ }
+
return d->result_;
}
@@ -5382,7 +5516,7 @@ PROJStringSyntaxParser(const std::string &projString, std::vector<Step> &steps,
{
size_t i = 0;
while (true) {
- for (; isspace(c_str[i]); i++) {
+ for (; isspace(static_cast<unsigned char>(c_str[i])); i++) {
}
std::string token;
bool in_string = false;
@@ -5399,7 +5533,7 @@ PROJStringSyntaxParser(const std::string &projString, std::vector<Step> &steps,
token += c_str[i];
i++;
continue;
- } else if (isspace(c_str[i])) {
+ } else if (isspace(static_cast<unsigned char>(c_str[i]))) {
break;
}
token += c_str[i];
@@ -5805,15 +5939,21 @@ bool PROJStringFormatter::omitProjLongLatIfPossible() const {
// ---------------------------------------------------------------------------
-void PROJStringFormatter::setOmitZUnitConversion(bool omit) {
- assert(d->omitZUnitConversion_ ^ omit);
- d->omitZUnitConversion_ = omit;
+void PROJStringFormatter::pushOmitZUnitConversion() {
+ d->omitZUnitConversion_.push_back(true);
+}
+
+// ---------------------------------------------------------------------------
+
+void PROJStringFormatter::popOmitZUnitConversion() {
+ assert(d->omitZUnitConversion_.size() > 1);
+ d->omitZUnitConversion_.pop_back();
}
// ---------------------------------------------------------------------------
bool PROJStringFormatter::omitZUnitConversion() const {
- return d->omitZUnitConversion_;
+ return d->omitZUnitConversion_.back();
}
// ---------------------------------------------------------------------------
@@ -6079,6 +6219,9 @@ static UnitOfMeasure _buildUnit(const LinearUnitDesc *unitsMatch) {
static UnitOfMeasure _buildUnit(double to_meter_value) {
// TODO: look-up in EPSG catalog
+ if (to_meter_value == 0) {
+ throw ParsingException("invalid unit value");
+ }
return UnitOfMeasure("unknown", to_meter_value,
UnitOfMeasure::Type::LINEAR);
}
@@ -6593,9 +6736,9 @@ PROJStringParser::Private::processAxisSwap(Step &step,
? AxisDirection::NORTH
: (axisType == AxisType::NORTH_POLE)
? AxisDirection::SOUTH
- : (axisType == AxisType::SOUTH_POLE)
- ? AxisDirection::NORTH
- : AxisDirection::NORTH;
+ /*: (axisType == AxisType::SOUTH_POLE)
+ ? AxisDirection::NORTH*/
+ : AxisDirection::NORTH;
CoordinateSystemAxisNNPtr north = createAxis(
northName, northAbbev, northDir, unit,
(!isGeographic && axisType == AxisType::NORTH_POLE)
@@ -6727,6 +6870,9 @@ static double getNumericValue(const std::string &paramValue,
}
// ---------------------------------------------------------------------------
+namespace {
+template <class T> inline void ignoreRetVal(T) {}
+}
GeographicCRSNNPtr
PROJStringParser::Private::buildGeographicCRS(int iStep, int iUnitConvert,
@@ -6739,7 +6885,7 @@ PROJStringParser::Private::buildGeographicCRS(int iStep, int iUnitConvert,
// units=m is often found in the wild.
// No need to create a extension string for this
- hasParamValue(step, "units");
+ ignoreRetVal(hasParamValue(step, "units"));
auto datum = buildDatum(step, title);
@@ -6753,6 +6899,7 @@ PROJStringParser::Private::buildGeographicCRS(int iStep, int iUnitConvert,
getNumericValue(getParamValue(step, "lon_0")) != 0.0)) {
props.set("EXTENSION_PROJ4", projString_);
}
+ props.set("IMPLICIT_CS", true);
return GeographicCRS::create(props, datum, cs);
}
@@ -6771,7 +6918,7 @@ PROJStringParser::Private::buildGeocentricCRS(int iStep, int iUnitConvert) {
auto datum = buildDatum(step, title);
- UnitOfMeasure unit = UnitOfMeasure::METRE;
+ UnitOfMeasure unit = buildUnit(step, "units", "");
if (iUnitConvert >= 0) {
auto &stepUnitConvert = steps_[iUnitConvert];
const std::string *xy_in = &getParamValue(stepUnitConvert, "xy_in");
@@ -6855,7 +7002,7 @@ PROJStringParser::Private::buildBoundOrCompoundCRSIfNeeded(int iStep,
Transformation::createGravityRelatedHeightToGeographic3D(
PropertyMap().set(IdentifiedObject::NAME_KEY,
"unknown to WGS84 ellipsoidal height"),
- crs, GeographicCRS::EPSG_4979, geoidgrids,
+ crs, GeographicCRS::EPSG_4979, nullptr, geoidgrids,
std::vector<PositionalAccuracyNNPtr>());
auto boundvcrs =
BoundCRS::create(vcrs, GeographicCRS::EPSG_4979, transformation);
@@ -7243,6 +7390,8 @@ CRSNNPtr PROJStringParser::Private::buildProjectedCRS(
props.set("EXTENSION_PROJ4", projString_);
}
+ props.set("IMPLICIT_CS", true);
+
CRSNNPtr crs = ProjectedCRS::create(props, geogCRS, NN_NO_CHECK(conv), cs);
if (!hasParamValue(step, "geoidgrids") &&
diff --git a/src/iso19111/metadata.cpp b/src/iso19111/metadata.cpp
index 6bf9d600..3725b072 100644
--- a/src/iso19111/metadata.cpp
+++ b/src/iso19111/metadata.cpp
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Project: PROJ
- * Purpose: ISO19111:2018 implementation
+ * Purpose: ISO19111:2019 implementation
* Author: Even Rouault <even dot rouault at spatialys dot com>
*
******************************************************************************
diff --git a/src/iso19111/static.cpp b/src/iso19111/static.cpp
index 5de046f1..824047f0 100644
--- a/src/iso19111/static.cpp
+++ b/src/iso19111/static.cpp
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Project: PROJ
- * Purpose: ISO19111:2018 implementation
+ * Purpose: ISO19111:2019 implementation
* Author: Even Rouault <even dot rouault at spatialys dot com>
*
******************************************************************************
@@ -31,6 +31,7 @@
#endif
#include "proj/common.hpp"
+#include "proj/coordinateoperation.hpp"
#include "proj/coordinatesystem.hpp"
#include "proj/crs.hpp"
#include "proj/datum.hpp"
@@ -57,6 +58,7 @@ using namespace NS_PROJ::crs;
using namespace NS_PROJ::datum;
using namespace NS_PROJ::io;
using namespace NS_PROJ::metadata;
+using namespace NS_PROJ::operation;
using namespace NS_PROJ::util;
NS_PROJ_START
@@ -215,7 +217,7 @@ DEFINE_WKT_CONSTANT(ANGLEUNIT);
DEFINE_WKT_CONSTANT(SCALEUNIT);
DEFINE_WKT_CONSTANT(TIMEUNIT);
DEFINE_WKT_CONSTANT(ELLIPSOID);
-DEFINE_WKT_CONSTANT(CS);
+const std::string WKTConstants::CS_(createAndAddToConstantList("CS"));
DEFINE_WKT_CONSTANT(ID);
DEFINE_WKT_CONSTANT(PROJCRS);
DEFINE_WKT_CONSTANT(BASEGEODCRS);
@@ -271,6 +273,7 @@ DEFINE_WKT_CONSTANT(BASEVERTCRS);
DEFINE_WKT_CONSTANT(BASEENGCRS);
DEFINE_WKT_CONSTANT(BASEPARAMCRS);
DEFINE_WKT_CONSTANT(BASETIMECRS);
+DEFINE_WKT_CONSTANT(VERSION);
DEFINE_WKT_CONSTANT(GEODETICCRS);
DEFINE_WKT_CONSTANT(GEODETICDATUM);
@@ -641,4 +644,13 @@ const GeographicCRSNNPtr
// ---------------------------------------------------------------------------
+/** \brief Key to set the operation version of a operation::CoordinateOperation
+ *
+ * The value is to be provided as a string.
+ */
+const std::string
+ operation::CoordinateOperation::OPERATION_VERSION_KEY("operationVersion");
+
+// ---------------------------------------------------------------------------
+
NS_PROJ_END
diff --git a/src/iso19111/util.cpp b/src/iso19111/util.cpp
index d6cfa9f4..25207d5c 100644
--- a/src/iso19111/util.cpp
+++ b/src/iso19111/util.cpp
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Project: PROJ
- * Purpose: ISO19111:2018 implementation
+ * Purpose: ISO19111:2019 implementation
* Author: Even Rouault <even dot rouault at spatialys dot com>
*
******************************************************************************
diff --git a/src/jniproj.cpp b/src/jniproj.cpp
index 59b5b2a0..6f441529 100644
--- a/src/jniproj.cpp
+++ b/src/jniproj.cpp
@@ -279,7 +279,7 @@ JNIEXPORT jcharArray JNICALL Java_org_proj4_PJ_getAxisDirections
{
PJ *pj = getPJ(env, object);
if (pj) {
- int length = strlen(pj->axis);
+ int length = static_cast<int>(strlen(pj->axis));
jcharArray array = env->NewCharArray(length);
if (array) {
jchar* axis = env->GetCharArrayElements(array, nullptr);
diff --git a/src/lib_proj.cmake b/src/lib_proj.cmake
index f28a1d68..5a0a8070 100644
--- a/src/lib_proj.cmake
+++ b/src/lib_proj.cmake
@@ -6,245 +6,313 @@ message(STATUS "")
# default config, shared on unix and static on Windows
if(UNIX)
- set(BUILD_LIBPROJ_SHARED_DEFAULT ON )
-endif(UNIX)
-if( WIN32)
- set(BUILD_LIBPROJ_SHARED_DEFAULT OFF)
-endif(WIN32)
-option(BUILD_LIBPROJ_SHARED "Build libproj library shared." ${BUILD_LIBPROJ_SHARED_DEFAULT})
+ set(BUILD_LIBPROJ_SHARED_DEFAULT ON)
+endif()
+if(WIN32)
+ set(BUILD_LIBPROJ_SHARED_DEFAULT OFF)
+endif()
+option(BUILD_LIBPROJ_SHARED
+ "Build libproj library shared." ${BUILD_LIBPROJ_SHARED_DEFAULT})
if(BUILD_LIBPROJ_SHARED)
set(PROJ_LIBRARY_TYPE SHARED)
-else(BUILD_LIBPROJ_SHARED)
+else()
set(PROJ_LIBRARY_TYPE STATIC)
-endif(BUILD_LIBPROJ_SHARED)
+endif()
option(USE_THREAD "Build libproj with thread/mutex support " ON)
if(NOT USE_THREAD)
- add_definitions( -DMUTEX_stub)
-endif(NOT USE_THREAD)
+ add_definitions(-DMUTEX_stub)
+endif()
find_package(Threads QUIET)
-if(USE_THREAD AND Threads_FOUND AND CMAKE_USE_WIN32_THREADS_INIT )
- add_definitions( -DMUTEX_win32)
-elseif(USE_THREAD AND Threads_FOUND AND CMAKE_USE_PTHREADS_INIT )
- add_definitions( -DMUTEX_pthread)
+if(USE_THREAD AND Threads_FOUND AND CMAKE_USE_WIN32_THREADS_INIT)
+ add_definitions(-DMUTEX_win32)
+elseif(USE_THREAD AND Threads_FOUND AND CMAKE_USE_PTHREADS_INIT)
+ add_definitions(-DMUTEX_pthread)
elseif(USE_THREAD AND NOT Threads_FOUND)
- message(FATAL_ERROR "No thread library found and thread/mutex support is required by USE_THREAD option")
+ message(FATAL_ERROR
+ "No thread library found and thread/mutex support is "
+ "required by USE_THREAD option")
endif()
-option(ENABLE_LTO "Build library with LTO optimization (if available)." OFF)
+option(ENABLE_LTO
+ "Build library with LTO/IPO optimization (if available)." OFF)
if(ENABLE_LTO)
- if("${CMAKE_C_COMPILER_ID}" MATCHES "Clang")
- include (CheckCXXSourceCompiles)
- SET(CMAKE_REQUIRED_FLAGS "-Wl,-flto")
- check_cxx_source_compiles("int main(){ return 0; }" COMPILER_SUPPORTS_FLTO_FLAG)
- IF(COMPILER_SUPPORTS_FLTO_FLAG)
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -flto")
- ENDIF()
+ # Determine ENABLE_LTO_METHOD to either "flag" or "property"
+ if(CMAKE_C_COMPILER_ID STREQUAL "Intel"
+ AND CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ set(ENABLE_LTO_METHOD "property")
+ elseif(CMAKE_VERSION VERSION_LESS 3.9)
+ # Maual checks required
+ if(CMAKE_C_COMPILER_ID STREQUAL "Clang")
+ include(CheckCXXSourceCompiles)
+ set(CMAKE_REQUIRED_FLAGS "-Wl,-flto")
+ check_cxx_source_compiles("int main(){ return 0; }"
+ COMPILER_SUPPORTS_FLTO_FLAG)
else()
- include(CheckCXXCompilerFlag)
- CHECK_CXX_COMPILER_FLAG("-flto" COMPILER_SUPPORTS_FLTO_FLAG)
- if(COMPILER_SUPPORTS_FLTO_FLAG)
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -flto")
- endif()
+ include(CheckCXXCompilerFlag)
+ check_cxx_compiler_flag("-flto" COMPILER_SUPPORTS_FLTO_FLAG)
endif()
+ set(ENABLE_LTO_METHOD "flag")
+ if(NOT COMPILER_SUPPORTS_FLTO_FLAG)
+ set(ENABLE_LTO OFF)
+ endif()
+ else() # CMake v3.9
+ cmake_policy(SET CMP0069 NEW)
+ include(CheckIPOSupported)
+ check_ipo_supported(RESULT ENABLE_LTO)
+ set(ENABLE_LTO_METHOD "property")
+ endif()
endif()
+boost_report_value(ENABLE_LTO)
##############################################
### library source list and include_list ###
##############################################
-SET(SRC_LIBPROJ_PROJECTIONS
- projections/aeqd.cpp
- projections/gnom.cpp
- projections/laea.cpp
- projections/mod_ster.cpp
- projections/nsper.cpp
- projections/nzmg.cpp
- projections/ortho.cpp
- projections/stere.cpp
- projections/sterea.cpp
- projections/aea.cpp
- projections/bipc.cpp
- projections/bonne.cpp
- projections/eqdc.cpp
- projections/isea.cpp
- projections/ccon.cpp
- projections/imw_p.cpp
- projections/krovak.cpp
- projections/lcc.cpp
- projections/poly.cpp
- projections/rpoly.cpp
- projections/sconics.cpp
- projections/rouss.cpp
- projections/cass.cpp
- projections/cc.cpp
- projections/cea.cpp
- projections/eqc.cpp
- projections/gall.cpp
- projections/labrd.cpp
- projections/lsat.cpp
- projections/misrsom.cpp
- projections/merc.cpp
- projections/mill.cpp
- projections/ocea.cpp
- projections/omerc.cpp
- projections/somerc.cpp
- projections/tcc.cpp
- projections/tcea.cpp
- projections/times.cpp
- projections/tmerc.cpp
- projections/tobmerc.cpp
- projections/airy.cpp
- projections/aitoff.cpp
- projections/august.cpp
- projections/bacon.cpp
- projections/bertin1953.cpp
- projections/chamb.cpp
- projections/hammer.cpp
- projections/lagrng.cpp
- projections/larr.cpp
- projections/lask.cpp
- projections/latlong.cpp
- projections/nicol.cpp
- projections/ob_tran.cpp
- projections/oea.cpp
- projections/tpeqd.cpp
- projections/vandg.cpp
- projections/vandg2.cpp
- projections/vandg4.cpp
- projections/wag7.cpp
- projections/lcca.cpp
- projections/geos.cpp
- projections/boggs.cpp
- projections/collg.cpp
- projections/comill.cpp
- projections/crast.cpp
- projections/denoy.cpp
- projections/eck1.cpp
- projections/eck2.cpp
- projections/eck3.cpp
- projections/eck4.cpp
- projections/eck5.cpp
- projections/fahey.cpp
- projections/fouc_s.cpp
- projections/gins8.cpp
- projections/gstmerc.cpp
- projections/gn_sinu.cpp
- projections/goode.cpp
- projections/igh.cpp
- projections/hatano.cpp
- projections/loxim.cpp
- projections/mbt_fps.cpp
- projections/mbtfpp.cpp
- projections/mbtfpq.cpp
- projections/moll.cpp
- projections/nell.cpp
- projections/nell_h.cpp
- projections/patterson.cpp
- projections/putp2.cpp
- projections/putp3.cpp
- projections/putp4p.cpp
- projections/putp5.cpp
- projections/putp6.cpp
- projections/qsc.cpp
- projections/robin.cpp
- projections/sch.cpp
- projections/sts.cpp
- projections/urm5.cpp
- projections/urmfps.cpp
- projections/wag2.cpp
- projections/wag3.cpp
- projections/wink1.cpp
- projections/wink2.cpp
- projections/healpix.cpp
- projections/natearth.cpp
- projections/natearth2.cpp
- projections/calcofi.cpp
- projections/eqearth.cpp
+set(SRC_LIBPROJ_PROJECTIONS
+ projections/aeqd.cpp
+ projections/gnom.cpp
+ projections/laea.cpp
+ projections/mod_ster.cpp
+ projections/nsper.cpp
+ projections/nzmg.cpp
+ projections/ortho.cpp
+ projections/stere.cpp
+ projections/sterea.cpp
+ projections/aea.cpp
+ projections/bipc.cpp
+ projections/bonne.cpp
+ projections/eqdc.cpp
+ projections/isea.cpp
+ projections/ccon.cpp
+ projections/imw_p.cpp
+ projections/krovak.cpp
+ projections/lcc.cpp
+ projections/poly.cpp
+ projections/rpoly.cpp
+ projections/sconics.cpp
+ projections/rouss.cpp
+ projections/cass.cpp
+ projections/cc.cpp
+ projections/cea.cpp
+ projections/eqc.cpp
+ projections/gall.cpp
+ projections/labrd.cpp
+ projections/lsat.cpp
+ projections/misrsom.cpp
+ projections/merc.cpp
+ projections/mill.cpp
+ projections/ocea.cpp
+ projections/omerc.cpp
+ projections/somerc.cpp
+ projections/tcc.cpp
+ projections/tcea.cpp
+ projections/times.cpp
+ projections/tmerc.cpp
+ projections/tobmerc.cpp
+ projections/airy.cpp
+ projections/aitoff.cpp
+ projections/august.cpp
+ projections/bacon.cpp
+ projections/bertin1953.cpp
+ projections/chamb.cpp
+ projections/hammer.cpp
+ projections/lagrng.cpp
+ projections/larr.cpp
+ projections/lask.cpp
+ projections/latlong.cpp
+ projections/nicol.cpp
+ projections/ob_tran.cpp
+ projections/oea.cpp
+ projections/tpeqd.cpp
+ projections/vandg.cpp
+ projections/vandg2.cpp
+ projections/vandg4.cpp
+ projections/wag7.cpp
+ projections/lcca.cpp
+ projections/geos.cpp
+ projections/boggs.cpp
+ projections/collg.cpp
+ projections/comill.cpp
+ projections/crast.cpp
+ projections/denoy.cpp
+ projections/eck1.cpp
+ projections/eck2.cpp
+ projections/eck3.cpp
+ projections/eck4.cpp
+ projections/eck5.cpp
+ projections/fahey.cpp
+ projections/fouc_s.cpp
+ projections/gins8.cpp
+ projections/gstmerc.cpp
+ projections/gn_sinu.cpp
+ projections/goode.cpp
+ projections/igh.cpp
+ projections/hatano.cpp
+ projections/loxim.cpp
+ projections/mbt_fps.cpp
+ projections/mbtfpp.cpp
+ projections/mbtfpq.cpp
+ projections/moll.cpp
+ projections/nell.cpp
+ projections/nell_h.cpp
+ projections/patterson.cpp
+ projections/putp2.cpp
+ projections/putp3.cpp
+ projections/putp4p.cpp
+ projections/putp5.cpp
+ projections/putp6.cpp
+ projections/qsc.cpp
+ projections/robin.cpp
+ projections/sch.cpp
+ projections/sts.cpp
+ projections/urm5.cpp
+ projections/urmfps.cpp
+ projections/wag2.cpp
+ projections/wag3.cpp
+ projections/wink1.cpp
+ projections/wink2.cpp
+ projections/healpix.cpp
+ projections/natearth.cpp
+ projections/natearth2.cpp
+ projections/calcofi.cpp
+ projections/eqearth.cpp
)
-SET(SRC_LIBPROJ_CONVERSIONS
- conversions/axisswap.cpp
- conversions/cart.cpp
- conversions/geoc.cpp
- conversions/geocent.cpp
- conversions/unitconvert.cpp
+set(SRC_LIBPROJ_CONVERSIONS
+ conversions/axisswap.cpp
+ conversions/cart.cpp
+ conversions/geoc.cpp
+ conversions/geocent.cpp
+ conversions/noop.cpp
+ conversions/unitconvert.cpp
)
-SET(SRC_LIBPROJ_TRANSFORMATIONS
- transformations/affine.cpp
- transformations/deformation.cpp
- transformations/helmert.cpp
- transformations/hgridshift.cpp
- transformations/horner.cpp
- transformations/molodensky.cpp
- transformations/vgridshift.cpp
+set(SRC_LIBPROJ_TRANSFORMATIONS
+ transformations/affine.cpp
+ transformations/deformation.cpp
+ transformations/helmert.cpp
+ transformations/hgridshift.cpp
+ transformations/horner.cpp
+ transformations/molodensky.cpp
+ transformations/vgridshift.cpp
)
-SET(SRC_LIBPROJ_ISO19111
- iso19111/static.cpp
- iso19111/util.cpp
- iso19111/metadata.cpp
- iso19111/common.cpp
- iso19111/crs.cpp
- iso19111/datum.cpp
- iso19111/coordinatesystem.cpp
- iso19111/coordinateoperation.cpp
- iso19111/io.cpp
- iso19111/internal.cpp
- iso19111/factory.cpp
- iso19111/c_api.cpp
+set(SRC_LIBPROJ_ISO19111
+ iso19111/static.cpp
+ iso19111/util.cpp
+ iso19111/metadata.cpp
+ iso19111/common.cpp
+ iso19111/crs.cpp
+ iso19111/datum.cpp
+ iso19111/coordinatesystem.cpp
+ iso19111/coordinateoperation.cpp
+ iso19111/io.cpp
+ iso19111/internal.cpp
+ iso19111/factory.cpp
+ iso19111/c_api.cpp
)
-SET(SRC_LIBPROJ_CORE
- pj_list.h proj_internal.h proj_math.h
- aasincos.cpp adjlon.cpp
- dmstor.cpp auth.cpp
- deriv.cpp ell_set.cpp ellps.cpp errno.cpp
- factors.cpp fwd.cpp init.cpp inv.cpp
- list.cpp malloc.cpp mlfn.cpp msfn.cpp proj_mdist.cpp
- open_lib.cpp param.cpp phi2.cpp pr_list.cpp
- qsfn.cpp strerrno.cpp
- tsfn.cpp units.cpp ctx.cpp log.cpp zpoly1.cpp rtodms.cpp
- release.cpp gauss.cpp
- fileapi.cpp
- gc_reader.cpp gridcatalog.cpp
- nad_cvt.cpp nad_init.cpp nad_intr.cpp
- apply_gridshift.cpp datums.cpp datum_set.cpp transform.cpp
- geocent.cpp geocent.h utils.cpp gridinfo.cpp gridlist.cpp
- jniproj.cpp mutex.cpp initcache.cpp apply_vgridshift.cpp geodesic.c
- strtod.cpp math.cpp
- 4D_api.cpp pipeline.cpp
- internal.cpp
- wkt_parser.hpp wkt_parser.cpp
- wkt1_parser.h wkt1_parser.cpp
- wkt1_generated_parser.h wkt1_generated_parser.c
- wkt2_parser.h wkt2_parser.cpp
- wkt2_generated_parser.h wkt2_generated_parser.c
- ${CMAKE_CURRENT_BINARY_DIR}/proj_config.h
+set(SRC_LIBPROJ_CORE
+ 4D_api.cpp
+ aasincos.cpp
+ adjlon.cpp
+ apply_gridshift.cpp
+ apply_vgridshift.cpp
+ auth.cpp
+ ctx.cpp
+ datum_set.cpp
+ datums.cpp
+ deriv.cpp
+ dmstor.cpp
+ ell_set.cpp
+ ellps.cpp
+ errno.cpp
+ factors.cpp
+ fileapi.cpp
+ fwd.cpp
+ gauss.cpp
+ gc_reader.cpp
+ geocent.cpp
+ geocent.h
+ geodesic.c
+ gridcatalog.cpp
+ gridinfo.cpp
+ gridlist.cpp
+ init.cpp
+ initcache.cpp
+ internal.cpp
+ inv.cpp
+ jniproj.cpp
+ list.cpp
+ log.cpp
+ malloc.cpp
+ math.cpp
+ mlfn.cpp
+ msfn.cpp
+ mutex.cpp
+ nad_cvt.cpp
+ nad_init.cpp
+ nad_intr.cpp
+ open_lib.cpp
+ param.cpp
+ phi2.cpp
+ pipeline.cpp
+ pj_list.h
+ pr_list.cpp
+ proj_internal.h
+ proj_math.h
+ proj_mdist.cpp
+ qsfn.cpp
+ release.cpp
+ rtodms.cpp
+ strerrno.cpp
+ strtod.cpp
+ transform.cpp
+ tsfn.cpp
+ units.cpp
+ utils.cpp
+ wkt1_generated_parser.c
+ wkt1_generated_parser.h
+ wkt1_parser.cpp
+ wkt1_parser.h
+ wkt2_generated_parser.c
+ wkt2_generated_parser.h
+ wkt2_parser.cpp
+ wkt2_parser.h
+ wkt_parser.cpp
+ wkt_parser.hpp
+ zpoly1.cpp
+ ${CMAKE_CURRENT_BINARY_DIR}/proj_config.h
)
set(HEADERS_LIBPROJ
- proj_api.h
- proj.h
- proj_experimental.h
- proj_constants.h
- geodesic.h
+ proj_api.h
+ proj.h
+ proj_experimental.h
+ proj_constants.h
+ geodesic.h
)
# Group source files for IDE source explorers (e.g. Visual Studio)
-source_group("Header Files" FILES ${HEADERS_LIBPROJ})
-source_group("Source Files\\Core" FILES ${SRC_LIBPROJ_CORE})
-source_group("Source Files\\Conversions" FILES ${SRC_LIBPROJ_CONVERSIONS})
-source_group("Source Files\\Projections" FILES ${SRC_LIBPROJ_PROJECTIONS})
-source_group("Source Files\\Transformations" FILES ${SRC_LIBPROJ_TRANSFORMATIONS})
-source_group("Source Files\\ISO19111" FILES ${SRC_LIBPROJ_ISO19111})
+source_group("Header Files"
+ FILES ${HEADERS_LIBPROJ})
+source_group("Source Files\\Core"
+ FILES ${SRC_LIBPROJ_CORE})
+source_group("Source Files\\Conversions"
+ FILES ${SRC_LIBPROJ_CONVERSIONS})
+source_group("Source Files\\Projections"
+ FILES ${SRC_LIBPROJ_PROJECTIONS})
+source_group("Source Files\\Transformations"
+ FILES ${SRC_LIBPROJ_TRANSFORMATIONS})
+source_group("Source Files\\ISO19111"
+ FILES ${SRC_LIBPROJ_ISO19111})
include_directories(${CMAKE_SOURCE_DIR}/include)
-include_directories( ${CMAKE_CURRENT_BINARY_DIR})
+include_directories(${CMAKE_CURRENT_BINARY_DIR})
source_group("CMake Files" FILES CMakeLists.txt)
@@ -258,45 +326,77 @@ option(JNI_SUPPORT "Build support of java/jni wrapping for proj library" OFF)
find_package(JNI QUIET)
if(JNI_SUPPORT AND NOT JNI_FOUND)
message(FATAL_ERROR "jni support is required but jni is not found")
-endif(JNI_SUPPORT AND NOT JNI_FOUND)
+endif()
boost_report_value(JNI_SUPPORT)
if(JNI_SUPPORT)
- set(SRC_LIBPROJ_CORE ${SRC_LIBPROJ_CORE}
- jniproj.cpp )
- set(HEADERS_LIBPROJ ${HEADERS_LIBPROJ}
- org_proj4_PJ.h)
+ set(SRC_LIBPROJ_CORE
+ ${SRC_LIBPROJ_CORE} jniproj.cpp)
+ set(HEADERS_LIBPROJ
+ ${HEADERS_LIBPROJ} org_proj4_PJ.h)
source_group("Source Files\\JNI" FILES ${SRC_LIBPROJ_JNI})
add_definitions(-DJNI_ENABLED)
- include_directories( ${JNI_INCLUDE_DIRS})
+ include_directories(${JNI_INCLUDE_DIRS})
boost_report_value(JNI_INCLUDE_DIRS)
-endif(JNI_SUPPORT)
+endif()
#################################################
## targets: libproj and proj_config.h
#################################################
-set(ALL_LIBPROJ_SOURCES ${SRC_LIBPROJ_CORE}
- ${SRC_LIBPROJ_CONVERSIONS}
- ${SRC_LIBPROJ_PROJECTIONS}
- ${SRC_LIBPROJ_TRANSFORMATIONS}
- ${SRC_LIBPROJ_ISO19111}
+set(ALL_LIBPROJ_SOURCES
+ ${SRC_LIBPROJ_CORE}
+ ${SRC_LIBPROJ_CONVERSIONS}
+ ${SRC_LIBPROJ_PROJECTIONS}
+ ${SRC_LIBPROJ_TRANSFORMATIONS}
+ ${SRC_LIBPROJ_ISO19111}
)
-set(ALL_LIBPROJ_HEADERS ${HEADERS_LIBPROJ} )
+set(ALL_LIBPROJ_HEADERS ${HEADERS_LIBPROJ})
# Core targets configuration
string(TOLOWER "${PROJECT_INTERN_NAME}" PROJECTNAMEL)
set(PROJ_CORE_TARGET ${PROJECTNAMEL})
proj_target_output_name(${PROJ_CORE_TARGET} PROJ_CORE_TARGET_OUTPUT_NAME)
-add_library( ${PROJ_CORE_TARGET}
- ${PROJ_LIBRARY_TYPE}
- ${ALL_LIBPROJ_SOURCES}
- ${ALL_LIBPROJ_HEADERS}
- ${PROJ_RESOURCES} )
+add_library(
+ ${PROJ_CORE_TARGET}
+ ${PROJ_LIBRARY_TYPE}
+ ${ALL_LIBPROJ_SOURCES}
+ ${ALL_LIBPROJ_HEADERS}
+ ${PROJ_RESOURCES}
+)
+target_compile_options(${PROJ_CORE_TARGET}
+ PRIVATE $<$<COMPILE_LANGUAGE:C>:${PROJ_C_WARN_FLAGS}>
+ PRIVATE $<$<COMPILE_LANGUAGE:CXX>:${PROJ_CXX_WARN_FLAGS}>
+)
+
+# Tell Intel compiler to do arithmetic accurately. This is needed to stop the
+# compiler from ignoring parentheses in expressions like (a + b) + c and from
+# simplifying 0.0 + x to x (which is wrong if x = -0.0).
+if("${CMAKE_C_COMPILER_ID}" STREQUAL "Intel")
+ if(MSVC)
+ set(FP_PRECISE "/fp:precise")
+ else()
+ set(FP_PRECISE "-fp-model precise")
+ endif()
+ # Apply to source files that require this option
+ set_source_files_properties(
+ geodesic.c
+ PROPERTIES COMPILE_FLAGS ${FP_PRECISE})
+endif()
+
+if(ENABLE_LTO)
+ if(ENABLE_LTO_METHOD STREQUAL "property")
+ set_property(TARGET ${PROJ_CORE_TARGET}
+ PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
+ elseif(ENABLE_LTO_METHOD STREQUAL "flag")
+ # pre-CMake 3.9 workaround
+ target_compile_options(${PROJ_CORE_TARGET} PRIVATE -flto)
+ endif()
+endif()
-if (NOT CMAKE_VERSION VERSION_LESS 2.8.11)
- target_include_directories (${PROJ_CORE_TARGET} INTERFACE
+if(NOT CMAKE_VERSION VERSION_LESS 2.8.11)
+ target_include_directories(${PROJ_CORE_TARGET} INTERFACE
$<INSTALL_INTERFACE:${INCLUDEDIR}>)
-endif ()
+endif()
if(WIN32)
set_target_properties(${PROJ_CORE_TARGET}
@@ -319,45 +419,47 @@ else()
endif()
set_target_properties(${PROJ_CORE_TARGET}
- PROPERTIES
- LINKER_LANGUAGE CXX)
+ PROPERTIES
+ LINKER_LANGUAGE CXX)
##############################################
# Link properties
##############################################
set(PROJ_LIBRARIES ${PROJ_CORE_TARGET})
-set(PROJ_LIBRARIES ${PROJ_LIBRARIES} PARENT_SCOPE) # hack, required for test/unit
+# hack, required for test/unit
+set(PROJ_LIBRARIES ${PROJ_LIBRARIES} PARENT_SCOPE)
if(UNIX)
- find_library(M_LIB m)
- if(M_LIB)
- TARGET_LINK_LIBRARIES(${PROJ_CORE_TARGET} -lm)
- endif()
-endif(UNIX)
+ find_library(M_LIB m)
+ if(M_LIB)
+ target_link_libraries(${PROJ_CORE_TARGET} -lm)
+ endif()
+endif()
if(USE_THREAD AND Threads_FOUND AND CMAKE_USE_PTHREADS_INIT)
- TARGET_LINK_LIBRARIES(${PROJ_CORE_TARGET} ${CMAKE_THREAD_LIBS_INIT})
-endif(USE_THREAD AND Threads_FOUND AND CMAKE_USE_PTHREADS_INIT)
+ target_link_libraries(${PROJ_CORE_TARGET} ${CMAKE_THREAD_LIBS_INIT})
+endif()
include_directories(${SQLITE3_INCLUDE_DIR})
-TARGET_LINK_LIBRARIES(${PROJ_CORE_TARGET} ${SQLITE3_LIBRARY})
+target_link_libraries(${PROJ_CORE_TARGET} ${SQLITE3_LIBRARY})
if(MSVC)
- target_compile_definitions(${PROJ_CORE_TARGET} PRIVATE PROJ_MSVC_DLL_EXPORT=1)
+ target_compile_definitions(${PROJ_CORE_TARGET}
+ PRIVATE PROJ_MSVC_DLL_EXPORT=1)
endif()
##############################################
# install
##############################################
install(TARGETS ${PROJ_CORE_TARGET}
- EXPORT targets
- RUNTIME DESTINATION ${BINDIR}
- LIBRARY DESTINATION ${LIBDIR}
- ARCHIVE DESTINATION ${LIBDIR}
- FRAMEWORK DESTINATION ${FRAMEWORKDIR})
+ EXPORT targets
+ RUNTIME DESTINATION ${BINDIR}
+ LIBRARY DESTINATION ${LIBDIR}
+ ARCHIVE DESTINATION ${LIBDIR}
+ FRAMEWORK DESTINATION ${FRAMEWORKDIR})
if(NOT BUILD_FRAMEWORKS_AND_BUNDLE)
install(FILES ${ALL_LIBPROJ_HEADERS}
- DESTINATION ${INCLUDEDIR})
-endif(NOT BUILD_FRAMEWORKS_AND_BUNDLE)
+ DESTINATION ${INCLUDEDIR})
+endif()
##############################################
# Core configuration summary
diff --git a/src/mutex.cpp b/src/mutex.cpp
index 12251f0f..da415e55 100644
--- a/src/mutex.cpp
+++ b/src/mutex.cpp
@@ -25,14 +25,6 @@
* DEALINGS IN THE SOFTWARE.
*****************************************************************************/
-
-/* projects.h and windows.h conflict - avoid this! */
-
-#if defined(MUTEX_pthread) && !defined(_XOPEN_SOURCE) && !defined(__sun)
-/* For pthread_mutexattr_settype */
-#define _XOPEN_SOURCE 500
-#endif
-
/* For PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP */
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
diff --git a/src/nad_init.cpp b/src/nad_init.cpp
index d9701e70..315318be 100644
--- a/src/nad_init.cpp
+++ b/src/nad_init.cpp
@@ -265,7 +265,6 @@ struct CTABLE *nad_ctable2_init( projCtx ctx, struct projFileAPI_t* fileapi )
struct CTABLE *nad_init(projCtx ctx, char *name)
{
- char fname[MAX_PATH_FILENAME+1];
struct CTABLE *ct;
PAFile fid;
@@ -274,8 +273,7 @@ struct CTABLE *nad_init(projCtx ctx, char *name)
/* -------------------------------------------------------------------- */
/* Open the file using the usual search rules. */
/* -------------------------------------------------------------------- */
- strcpy(fname, name);
- if (!(fid = pj_open_lib(ctx, fname, "rb"))) {
+ if (!(fid = pj_open_lib(ctx, name, "rb"))) {
return nullptr;
}
diff --git a/src/nad_intr.cpp b/src/nad_intr.cpp
index 2c301ef8..8dc2f652 100644
--- a/src/nad_intr.cpp
+++ b/src/nad_intr.cpp
@@ -1,9 +1,8 @@
/* Determine nad table correction value */
#define PJ_LIB__
-#include "proj_internal.h"
-#include "proj_math.h"
#include "proj.h"
#include "proj_internal.h"
+#include "proj_math.h"
PJ_LP nad_intr(PJ_LP t, struct CTABLE *ct) {
PJ_LP val, frct;
diff --git a/src/open_lib.cpp b/src/open_lib.cpp
index 510704e9..01f626e8 100644
--- a/src/open_lib.cpp
+++ b/src/open_lib.cpp
@@ -34,6 +34,7 @@
#define FROM_PROJ_CPP
#endif
+#include <assert.h>
#include <errno.h>
#include <stddef.h>
#include <stdio.h>
@@ -194,15 +195,30 @@ pj_open_lib_ex(projCtx ctx, const char *name, const char *mode,
sysname = name;
/* or try to use application provided file finder */
- else if( ctx && ctx->file_finder != nullptr && (sysname = ctx->file_finder( ctx, name, ctx->file_finder_user_data )) != nullptr )
+ else if( ctx->file_finder != nullptr && (sysname = ctx->file_finder( ctx, name, ctx->file_finder_user_data )) != nullptr )
;
- else if( ctx && ctx->file_finder_legacy != nullptr && (sysname = ctx->file_finder_legacy( name )) != nullptr )
+ else if( ctx->file_finder_legacy != nullptr && (sysname = ctx->file_finder_legacy( name )) != nullptr )
;
- /* or is environment PROJ_LIB defined */
+ /* The user has search paths set */
+ else if( !ctx->search_paths.empty() ) {
+ for( const auto& path: ctx->search_paths ) {
+ try {
+ fname = path;
+ fname += DIR_CHAR;
+ fname += name;
+ sysname = fname.c_str();
+ fid = pj_ctx_fopen(ctx, sysname, mode);
+ } catch( const std::exception& )
+ {
+ }
+ if( fid )
+ break;
+ }
+ }
+ /* if is environment PROJ_LIB defined */
else if ((sysname = getenv("PROJ_LIB")) != nullptr) {
-
auto paths = NS_PROJ::internal::split(std::string(sysname), dirSeparator);
for( const auto& path: paths ) {
fname = path;
@@ -213,16 +229,18 @@ pj_open_lib_ex(projCtx ctx, const char *name, const char *mode,
if( fid )
break;
}
-
/* or hardcoded path */
} else if ((sysname = proj_lib_name) != nullptr) {
fname = sysname;
fname += DIR_CHAR;
fname += name;
sysname = fname.c_str();
- } else /* just try it bare bones */
+ /* just try it bare bones */
+ } else {
sysname = name;
+ }
+ assert(sysname); // to make Coverity Scan happy
if ( fid != nullptr || (fid = pj_ctx_fopen(ctx, sysname, mode)) != nullptr)
{
if( out_full_filename != nullptr && out_full_filename_size > 0 )
@@ -233,33 +251,6 @@ pj_open_lib_ex(projCtx ctx, const char *name, const char *mode,
errno = 0;
}
- /* If none of those work and we have a search path, try it */
- if (!fid && ctx && !ctx->search_paths.empty() )
- {
- for( const auto& path: ctx->search_paths ) {
- try {
- fname = path;
- fname += DIR_CHAR;
- fname += name;
- sysname = fname.c_str();
- fid = pj_ctx_fopen(ctx, sysname, mode);
- } catch( const std::exception& )
- {
- }
- if( fid )
- break;
- }
- if (fid)
- {
- if( out_full_filename != nullptr && out_full_filename_size > 0 )
- {
- strncpy(out_full_filename, sysname, out_full_filename_size);
- out_full_filename[out_full_filename_size-1] = '\0';
- }
- errno = 0;
- }
- }
-
if( ctx->last_errno == 0 && errno != 0 )
pj_ctx_set_errno( ctx, errno );
diff --git a/src/pipeline.cpp b/src/pipeline.cpp
index 39563c65..afa3b19a 100644
--- a/src/pipeline.cpp
+++ b/src/pipeline.cpp
@@ -105,7 +105,6 @@ Thomas Knudsen, thokn@sdfe.dk, 2016-05-20
#include "geodesic.h"
#include "proj.h"
#include "proj_internal.h"
-#include "proj_internal.h"
PROJ_HEAD(pipeline, "Transformation pipeline manager");
PROJ_HEAD(pop, "Retrieve coordinate value from pipeline stack");
diff --git a/src/pj_list.h b/src/pj_list.h
index 8ab4cdc0..0923bba8 100644
--- a/src/pj_list.h
+++ b/src/pj_list.h
@@ -106,6 +106,7 @@ PROJ_HEAD(nell_h, "Nell-Hammer")
PROJ_HEAD(nicol, "Nicolosi Globular")
PROJ_HEAD(nsper, "Near-sided perspective")
PROJ_HEAD(nzmg, "New Zealand Map Grid")
+PROJ_HEAD(noop, "No operation")
PROJ_HEAD(ob_tran, "General Oblique Transformation")
PROJ_HEAD(ocea, "Oblique Cylindrical Equal Area")
PROJ_HEAD(oea, "Oblated Equal Area")
diff --git a/src/proj.h b/src/proj.h
index af22c341..a412f266 100644
--- a/src/proj.h
+++ b/src/proj.h
@@ -153,7 +153,7 @@ extern "C" {
/* The version numbers should be updated with every release! **/
#define PROJ_VERSION_MAJOR 6
-#define PROJ_VERSION_MINOR 0
+#define PROJ_VERSION_MINOR 1
#define PROJ_VERSION_PATCH 0
extern char const PROJ_DLL pj_release[]; /* global release id string */
@@ -356,6 +356,7 @@ int PROJ_DLL proj_context_get_use_proj4_init_rules(PJ_CONTEXT *ctx, int from_leg
PJ PROJ_DLL *proj_create (PJ_CONTEXT *ctx, const char *definition);
PJ PROJ_DLL *proj_create_argv (PJ_CONTEXT *ctx, int argc, char **argv);
PJ PROJ_DLL *proj_create_crs_to_crs(PJ_CONTEXT *ctx, const char *source_crs, const char *target_crs, PJ_AREA *area);
+PJ PROJ_DLL *proj_normalize_for_visualization(PJ_CONTEXT *ctx, const PJ* obj);
PJ PROJ_DLL *proj_destroy (PJ *P);
@@ -999,7 +1000,10 @@ int PROJ_DLL proj_coordoperation_get_method_info(PJ_CONTEXT *ctx,
const char **out_method_auth_name,
const char **out_method_code);
-int PROJ_DLL proj_coordoperation_is_instanciable(PJ_CONTEXT *ctx,
+int PROJ_DLL proj_coordoperation_is_instantiable(PJ_CONTEXT *ctx,
+ const PJ *coordoperation);
+
+int PROJ_DLL proj_coordoperation_has_ballpark_transformation(PJ_CONTEXT *ctx,
const PJ *coordoperation);
int PROJ_DLL proj_coordoperation_get_param_count(PJ_CONTEXT *ctx,
diff --git a/src/proj_api.h b/src/proj_api.h
index 5c4d5e7a..53b0edfa 100644
--- a/src/proj_api.h
+++ b/src/proj_api.h
@@ -38,7 +38,7 @@
#endif
#ifndef PJ_VERSION
-#define PJ_VERSION 600
+#define PJ_VERSION 610
#endif
#ifdef PROJ_RENAME_SYMBOLS
diff --git a/src/proj_internal.h b/src/proj_internal.h
index 14b69492..8c365793 100644
--- a/src/proj_internal.h
+++ b/src/proj_internal.h
@@ -203,7 +203,7 @@ PJ_COORD PROJ_DLL pj_approx_3D_trans (PJ *P, PJ_DIRECTION direction, PJ_COORD co
/* Grid functionality */
int proj_vgrid_init(PJ *P, const char *grids);
int proj_hgrid_init(PJ *P, const char *grids);
-double proj_vgrid_value(PJ *P, PJ_LP lp);
+double proj_vgrid_value(PJ *P, PJ_LP lp, double vmultiplier);
PJ_LP proj_hgrid_value(PJ *P, PJ_LP lp);
PJ_LP proj_hgrid_apply(PJ *P, PJ_LP lp, PJ_DIRECTION direction);
@@ -624,7 +624,7 @@ struct FACTORS {
#define PJD_ERR_NO_COLON_IN_INIT_STRING -3
#define PJD_ERR_PROJ_NOT_NAMED -4
#define PJD_ERR_UNKNOWN_PROJECTION_ID -5
-#define PJD_ERR_ECCENTRICITY_IS_ONE -6
+#define PJD_ERR_INVALID_ECCENTRICITY -6
#define PJD_ERR_UNKNOWN_UNIT_ID -7
#define PJD_ERR_INVALID_BOOLEAN_PARAM -8
#define PJD_ERR_UNKNOWN_ELLP_PARAM -9
@@ -648,7 +648,7 @@ struct FACTORS {
#define PJD_ERR_W_OR_M_ZERO_OR_LESS -27
#define PJD_ERR_LSAT_NOT_IN_RANGE -28
#define PJD_ERR_PATH_NOT_IN_RANGE -29
-#define PJD_ERR_H_LESS_THAN_ZERO -30
+#define PJD_ERR_INVALID_H -30
#define PJD_ERR_K_LESS_THAN_ZERO -31
#define PJD_ERR_LAT_1_OR_2_ZERO_OR_90 -32
#define PJD_ERR_LAT_0_OR_ALPHA_EQ_90 -33
@@ -679,6 +679,7 @@ struct FACTORS {
#define PJD_ERR_INVALID_ARG -58
#define PJD_ERR_INCONSISTENT_UNIT -59
#define PJD_ERR_MUTUALLY_EXCLUSIVE_ARGS -60
+#define PJD_ERR_GENERIC_ERROR -61
/* NOTE: Remember to update src/strerrno.cpp, src/apps/gie.cpp and transient_error in */
/* src/transform.cpp when adding new value */
@@ -898,12 +899,6 @@ int pj_gc_apply_gridshift( PJ *defn, int inverse,
long point_count, int point_offset,
double *x, double *y, double *z );
-PJ_GRIDINFO *pj_gc_findgrid( projCtx_t *ctx,
- PJ_GridCatalog *catalog, int after,
- PJ_LP location, double date,
- PJ_Region *optional_region,
- double *grid_date );
-
double pj_gc_parsedate( projCtx_t *, const char * );
void *proj_mdist_ini(double);
diff --git a/src/proj_symbol_rename.h b/src/proj_symbol_rename.h
index 0ce342fd..b6e887ca 100644
--- a/src/proj_symbol_rename.h
+++ b/src/proj_symbol_rename.h
@@ -115,7 +115,7 @@
#define proj_coordoperation_get_param_count internal_proj_coordoperation_get_param_count
#define proj_coordoperation_get_param_index internal_proj_coordoperation_get_param_index
#define proj_coordoperation_get_towgs84_values internal_proj_coordoperation_get_towgs84_values
-#define proj_coordoperation_is_instanciable internal_proj_coordoperation_is_instanciable
+#define proj_coordoperation_is_instantiable internal_proj_coordoperation_is_instantiable
#define proj_create internal_proj_create
#define proj_create_argv internal_proj_create_argv
#define proj_create_cartesian_2D_cs internal_proj_create_cartesian_2D_cs
diff --git a/src/projections/aea.cpp b/src/projections/aea.cpp
index 9a0c4656..721ea3c9 100644
--- a/src/projections/aea.cpp
+++ b/src/projections/aea.cpp
@@ -99,7 +99,7 @@ static PJ *destructor (PJ *P, int errlev) { /* Destructor
-static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoid/spheroid, forward */
+static PJ_XY aea_e_forward (PJ_LP lp, PJ *P) { /* Ellipsoid/spheroid, forward */
PJ_XY xy = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
Q->rho = Q->c - (Q->ellips ? Q->n * pj_qsfn(sin(lp.phi), P->e, P->one_es) : Q->n2 * sin(lp.phi));;
@@ -114,7 +114,7 @@ static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoid/spheroid, forward */
}
-static PJ_LP e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoid/spheroid, inverse */
+static PJ_LP aea_e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoid/spheroid, inverse */
PJ_LP lp = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
if( (Q->rho = hypot(xy.x, xy.y = Q->rho0 - xy.y)) != 0.0 ) {
@@ -152,9 +152,11 @@ static PJ *setup(PJ *P) {
int secant;
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
- P->inv = e_inverse;
- P->fwd = e_forward;
+ P->inv = aea_e_inverse;
+ P->fwd = aea_e_forward;
+ if (fabs(Q->phi1) > M_HALFPI || fabs(Q->phi2) > M_HALFPI)
+ return destructor(P, PJD_ERR_LAT_LARGER_THAN_90);
if (fabs(Q->phi1 + Q->phi2) < EPS10)
return destructor(P, PJD_ERR_CONIC_LAT_EQUAL);
Q->n = sinphi = sin(Q->phi1);
@@ -178,6 +180,10 @@ static PJ *setup(PJ *P) {
return destructor(P, 0);
Q->n = (m1 * m1 - m2 * m2) / (ml2 - ml1);
+ if (Q->n == 0) {
+ // Not quite, but es is very close to 1...
+ return destructor(P, PJD_ERR_INVALID_ECCENTRICITY);
+ }
}
Q->ec = 1. - .5 * P->one_es * log((1. - P->e) /
(1. + P->e)) / P->e;
diff --git a/src/projections/aeqd.cpp b/src/projections/aeqd.cpp
index 8566062d..04c3662e 100644
--- a/src/projections/aeqd.cpp
+++ b/src/projections/aeqd.cpp
@@ -91,7 +91,7 @@ static PJ_XY e_guam_fwd(PJ_LP lp, PJ *P) { /* Guam elliptical */
}
-static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
+static PJ_XY aeqd_e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
PJ_XY xy = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double coslam, cosphi, sinphi, rho;
@@ -130,7 +130,7 @@ static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
}
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY aeqd_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double coslam, cosphi, sinphi;
@@ -195,7 +195,7 @@ static PJ_LP e_guam_inv(PJ_XY xy, PJ *P) { /* Guam elliptical */
}
-static PJ_LP e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
+static PJ_LP aeqd_e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
PJ_LP lp = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double c;
@@ -227,7 +227,7 @@ static PJ_LP e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP aeqd_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double cosc, c_rh, sinc;
@@ -291,8 +291,8 @@ PJ *PROJECTION(aeqd) {
Q->cosph0 = cos(P->phi0);
}
if (P->es == 0.0) {
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = aeqd_s_inverse;
+ P->fwd = aeqd_s_forward;
} else {
if (!(Q->en = pj_enfn(P->es)))
return pj_default_destructor (P, 0);
@@ -310,14 +310,13 @@ PJ *PROJECTION(aeqd) {
break;
case EQUIT:
case OBLIQ:
- P->inv = e_inverse; P->fwd = e_forward;
Q->N1 = 1. / sqrt(1. - P->es * Q->sinph0 * Q->sinph0);
Q->G = Q->sinph0 * (Q->He = P->e / sqrt(P->one_es));
Q->He *= Q->cosph0;
break;
}
- P->inv = e_inverse;
- P->fwd = e_forward;
+ P->inv = aeqd_e_inverse;
+ P->fwd = aeqd_e_forward;
}
}
diff --git a/src/projections/airy.cpp b/src/projections/airy.cpp
index f7068061..91b4b7a2 100644
--- a/src/projections/airy.cpp
+++ b/src/projections/airy.cpp
@@ -58,7 +58,7 @@ struct pj_opaque {
# define EPS 1.e-10
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY airy_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double sinlam, coslam, cosphi, sinphi, t, s, Krho, cosz;
@@ -79,6 +79,10 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
if (fabs(s = 1. - cosz) > EPS) {
t = 0.5 * (1. + cosz);
+ if(t == 0) {
+ proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION);
+ return xy;
+ }
Krho = -log(t)/s - Q->Cb / t;
} else
Krho = 0.5 - Q->Cb;
@@ -147,7 +151,7 @@ PJ *PROJECTION(airy) {
Q->cosph0 = cos(P->phi0);
}
}
- P->fwd = s_forward;
+ P->fwd = airy_s_forward;
P->es = 0.;
return P;
}
diff --git a/src/projections/aitoff.cpp b/src/projections/aitoff.cpp
index 127841ff..dadae12d 100644
--- a/src/projections/aitoff.cpp
+++ b/src/projections/aitoff.cpp
@@ -58,11 +58,11 @@ PROJ_HEAD(wintri, "Winkel Tripel") "\n\tMisc Sph\n\tlat_1";
#if 0
-FORWARD(s_forward); /* spheroid */
+FORWARD(aitoff_s_forward); /* spheroid */
#endif
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY aitoff_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double c, d;
@@ -100,7 +100,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
*
************************************************************************************/
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP aitoff_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
int iter, MAXITER = 10, round = 0, MAXROUND = 20;
@@ -116,15 +116,20 @@ static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
sl = sin(lp.lam * 0.5); cl = cos(lp.lam * 0.5);
sp = sin(lp.phi); cp = cos(lp.phi);
D = cp * cl;
- C = 1. - D * D;
- D = acos(D) / pow(C, 1.5);
- f1 = 2. * D * C * cp * sl;
- f2 = D * C * sp;
- f1p = 2.* (sl * cl * sp * cp / C - D * sp * sl);
- f1l = cp * cp * sl * sl / C + D * cp * cl * sp * sp;
- f2p = sp * sp * cl / C + D * sl * sl * cp;
- f2l = 0.5 * (sp * cp * sl / C - D * sp * cp * cp * sl * cl);
- if (Q->mode == WINKEL_TRIPEL) {
+ C = 1. - D * D;
+ const double denom = pow(C, 1.5);
+ if( denom == 0 ) {
+ proj_errno_set(P, PJD_ERR_NON_CONVERGENT);
+ return lp;
+ }
+ D = acos(D) / denom;
+ f1 = 2. * D * C * cp * sl;
+ f2 = D * C * sp;
+ f1p = 2.* (sl * cl * sp * cp / C - D * sp * sl);
+ f1l = cp * cp * sl * sl / C + D * cp * cl * sp * sp;
+ f2p = sp * sp * cl / C + D * sl * sl * cp;
+ f2l = 0.5 * (sp * cp * sl / C - D * sp * cp * cp * sl * cl);
+ if (Q->mode == WINKEL_TRIPEL) {
f1 = 0.5 * (f1 + lp.lam * Q->cosphi1);
f2 = 0.5 * (f2 + lp.phi);
f1p *= 0.5;
@@ -156,18 +161,18 @@ static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
} while (((fabs(xy.x-x) > EPSILON) || (fabs(xy.y-y) > EPSILON)) && (round++ < MAXROUND));
if (iter == MAXITER && round == MAXROUND)
- {
- pj_ctx_set_errno( P->ctx, PJD_ERR_NON_CONVERGENT );
- /* fprintf(stderr, "Warning: Accuracy of 1e-12 not reached. Last increments: dlat=%e and dlon=%e\n", dp, dl); */
- }
+ {
+ pj_ctx_set_errno( P->ctx, PJD_ERR_NON_CONVERGENT );
+ /* fprintf(stderr, "Warning: Accuracy of 1e-12 not reached. Last increments: dlat=%e and dlon=%e\n", dp, dl); */
+ }
return lp;
}
static PJ *setup(PJ *P) {
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = aitoff_s_inverse;
+ P->fwd = aitoff_s_forward;
P->es = 0.;
return P;
}
diff --git a/src/projections/august.cpp b/src/projections/august.cpp
index 3523034e..2104c3cc 100644
--- a/src/projections/august.cpp
+++ b/src/projections/august.cpp
@@ -9,7 +9,7 @@ PROJ_HEAD(august, "August Epicycloidal") "\n\tMisc Sph, no inv";
#define M 1.333333333333333
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY august_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
double t, c1, c, x1, x12, y1, y12;
(void) P;
@@ -29,7 +29,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ *PROJECTION(august) {
P->inv = nullptr;
- P->fwd = s_forward;
+ P->fwd = august_s_forward;
P->es = 0.;
return P;
}
diff --git a/src/projections/bacon.cpp b/src/projections/bacon.cpp
index c713a989..5db2d854 100644
--- a/src/projections/bacon.cpp
+++ b/src/projections/bacon.cpp
@@ -20,7 +20,7 @@ PROJ_HEAD(ortel, "Ortelius Oval") "\n\tMisc Sph, no inv";
PROJ_HEAD(bacon, "Bacon Globular") "\n\tMisc Sph, no inv";
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY bacon_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double ax, f;
@@ -50,7 +50,7 @@ PJ *PROJECTION(bacon) {
Q->bacn = 1;
Q->ortl = 0;
P->es = 0.;
- P->fwd = s_forward;
+ P->fwd = bacon_s_forward;
return P;
}
@@ -63,7 +63,7 @@ PJ *PROJECTION(apian) {
Q->bacn = Q->ortl = 0;
P->es = 0.;
- P->fwd = s_forward;
+ P->fwd = bacon_s_forward;
return P;
}
@@ -77,6 +77,6 @@ PJ *PROJECTION(ortel) {
Q->bacn = 0;
Q->ortl = 1;
P->es = 0.;
- P->fwd = s_forward;
+ P->fwd = bacon_s_forward;
return P;
}
diff --git a/src/projections/bertin1953.cpp b/src/projections/bertin1953.cpp
index 96de6d4b..63154084 100644
--- a/src/projections/bertin1953.cpp
+++ b/src/projections/bertin1953.cpp
@@ -14,7 +14,6 @@
#include <errno.h>
#include <math.h>
-#include "proj_internal.h"
#include "proj.h"
#include "proj_internal.h"
@@ -28,7 +27,7 @@ struct pj_opaque {
} // anonymous namespace
-static PJ_XY s_forward (PJ_LP lp, PJ *P) {
+static PJ_XY bertin1953_s_forward (PJ_LP lp, PJ *P) {
PJ_XY xy = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
@@ -90,7 +89,7 @@ PJ *PROJECTION(bertin1953) {
Q->sin_delta_gamma = 0.;
P->es = 0.;
- P->fwd = s_forward;
+ P->fwd = bertin1953_s_forward;
return P;
}
diff --git a/src/projections/bipc.cpp b/src/projections/bipc.cpp
index 5cfef11f..9fd2fc6f 100644
--- a/src/projections/bipc.cpp
+++ b/src/projections/bipc.cpp
@@ -36,7 +36,7 @@ struct pj_opaque {
} // anonymous namespace
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY bipc_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double cphi, sphi, tphi, t, al, Az, z, Av, cdlam, sdlam, r;
@@ -113,7 +113,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP bipc_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double t, r, rp, rl, al, z = 0.0, fAz, Az, s, c, Av;
@@ -169,8 +169,8 @@ PJ *PROJECTION(bipc) {
P->opaque = Q;
Q->noskew = pj_param(P->ctx, P->params, "bns").i;
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = bipc_s_inverse;
+ P->fwd = bipc_s_forward;
P->es = 0.;
return P;
}
diff --git a/src/projections/boggs.cpp b/src/projections/boggs.cpp
index 5502d493..e7278904 100644
--- a/src/projections/boggs.cpp
+++ b/src/projections/boggs.cpp
@@ -12,7 +12,7 @@ PROJ_HEAD(boggs, "Boggs Eumorphic") "\n\tPCyl, no inv, Sph";
# define FYC 0.49931
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY boggs_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
double theta, th1, c;
int i;
@@ -39,6 +39,6 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ *PROJECTION(boggs) {
P->es = 0.;
- P->fwd = s_forward;
+ P->fwd = boggs_s_forward;
return P;
}
diff --git a/src/projections/bonne.cpp b/src/projections/bonne.cpp
index 0e9bae79..31f90907 100644
--- a/src/projections/bonne.cpp
+++ b/src/projections/bonne.cpp
@@ -20,20 +20,25 @@ struct pj_opaque {
} // anonymous namespace
-static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
+static PJ_XY bonne_e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
PJ_XY xy = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double rh, E, c;
rh = Q->am1 + Q->m1 - pj_mlfn(lp.phi, E = sin(lp.phi), c = cos(lp.phi), Q->en);
- E = c * lp.lam / (rh * sqrt(1. - P->es * E * E));
- xy.x = rh * sin(E);
- xy.y = Q->am1 - rh * cos(E);
+ if (fabs(rh) > EPS10) {
+ E = c * lp.lam / (rh * sqrt(1. - P->es * E * E));
+ xy.x = rh * sin(E);
+ xy.y = Q->am1 - rh * cos(E);
+ } else {
+ xy.x = 0.;
+ xy.y = 0.;
+ }
return xy;
}
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY bonne_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double E, rh;
@@ -48,7 +53,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP bonne_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double rh;
@@ -67,7 +72,7 @@ static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static PJ_LP e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
+static PJ_LP bonne_e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
PJ_LP lp = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double s, rh;
@@ -120,15 +125,15 @@ PJ *PROJECTION(bonne) {
Q->m1 = pj_mlfn(Q->phi1, Q->am1 = sin(Q->phi1),
c = cos(Q->phi1), Q->en);
Q->am1 = c / (sqrt(1. - P->es * Q->am1 * Q->am1) * Q->am1);
- P->inv = e_inverse;
- P->fwd = e_forward;
+ P->inv = bonne_e_inverse;
+ P->fwd = bonne_e_forward;
} else {
if (fabs(Q->phi1) + EPS10 >= M_HALFPI)
Q->cphi1 = 0.;
else
Q->cphi1 = 1. / tan(Q->phi1);
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = bonne_s_inverse;
+ P->fwd = bonne_s_forward;
}
return P;
}
diff --git a/src/projections/calcofi.cpp b/src/projections/calcofi.cpp
index e81843b4..57c12dde 100644
--- a/src/projections/calcofi.cpp
+++ b/src/projections/calcofi.cpp
@@ -35,7 +35,7 @@ whatever ellipsoid is provided. */
#define ROTATION_ANGLE 0.52359877559829882 /*CalCOFI angle of 30 deg in rad */
-static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
+static PJ_XY calcofi_e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
PJ_XY xy = {0.0,0.0};
double oy; /* pt O y value in Mercator */
double l1; /* l1 and l2 are distances calculated using trig that sum
@@ -67,7 +67,7 @@ static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
}
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY calcofi_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
double oy;
double l1;
@@ -93,7 +93,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
+static PJ_LP calcofi_e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
PJ_LP lp = {0.0,0.0};
double ry; /* y value of point r */
double oymctr; /* Mercator-transformed y value of point O */
@@ -116,7 +116,7 @@ static PJ_LP e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP calcofi_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
double ry;
double oymctr;
@@ -153,11 +153,11 @@ PJ *PROJECTION(calcofi) {
P->over = 1;
if (P->es != 0.0) { /* ellipsoid */
- P->inv = e_inverse;
- P->fwd = e_forward;
+ P->inv = calcofi_e_inverse;
+ P->fwd = calcofi_e_forward;
} else { /* sphere */
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = calcofi_s_inverse;
+ P->fwd = calcofi_s_forward;
}
return P;
}
diff --git a/src/projections/cass.cpp b/src/projections/cass.cpp
index ee050548..9eea10c5 100644
--- a/src/projections/cass.cpp
+++ b/src/projections/cass.cpp
@@ -25,7 +25,7 @@ struct pj_opaque {
-static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
+static PJ_XY cass_e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
double n, t, a1, c, a2, tn;
PJ_XY xy = {0.0, 0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
@@ -47,7 +47,7 @@ static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
}
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY cass_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0, 0.0};
xy.x = asin (cos (lp.phi) * sin (lp.lam));
xy.y = atan2 (tan (lp.phi), cos (lp.lam)) - P->phi0;
@@ -55,7 +55,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
+static PJ_LP cass_e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
double n, t, r, dd, d2, tn, ph1;
PJ_LP lp = {0.0, 0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
@@ -76,7 +76,7 @@ static PJ_LP e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP cass_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
double dd;
lp.phi = asin(sin(dd = xy.y + P->phi0) * cos(xy.x));
@@ -101,8 +101,8 @@ PJ *PROJECTION(cass) {
/* Spheroidal? */
if (0==P->es) {
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = cass_s_inverse;
+ P->fwd = cass_s_forward;
return P;
}
@@ -117,8 +117,8 @@ PJ *PROJECTION(cass) {
return pj_default_destructor (P, ENOMEM);
static_cast<struct pj_opaque*>(P->opaque)->m0 = pj_mlfn (P->phi0, sin (P->phi0), cos (P->phi0), static_cast<struct pj_opaque*>(P->opaque)->en);
- P->inv = e_inverse;
- P->fwd = e_forward;
+ P->inv = cass_e_inverse;
+ P->fwd = cass_e_forward;
return P;
}
diff --git a/src/projections/cc.cpp b/src/projections/cc.cpp
index 559a4f1a..244e185d 100644
--- a/src/projections/cc.cpp
+++ b/src/projections/cc.cpp
@@ -9,7 +9,7 @@ PROJ_HEAD(cc, "Central Cylindrical") "\n\tCyl, Sph";
#define EPS10 1.e-10
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY cc_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
if (fabs (fabs(lp.phi) - M_HALFPI) <= EPS10) {
proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION);
@@ -21,7 +21,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP cc_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
(void) P;
lp.phi = atan(xy.y);
@@ -34,8 +34,8 @@ static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ *PROJECTION(cc) {
P->es = 0.;
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = cc_s_inverse;
+ P->fwd = cc_s_forward;
return P;
}
diff --git a/src/projections/ccon.cpp b/src/projections/ccon.cpp
index 5f5128cf..e2312c0d 100644
--- a/src/projections/ccon.cpp
+++ b/src/projections/ccon.cpp
@@ -43,7 +43,7 @@ PROJ_HEAD(ccon, "Central Conic")
-static PJ_XY forward (PJ_LP lp, PJ *P) {
+static PJ_XY ccon_forward (PJ_LP lp, PJ *P) {
PJ_XY xy = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double r;
@@ -56,7 +56,7 @@ static PJ_XY forward (PJ_LP lp, PJ *P) {
}
-static PJ_LP inverse (PJ_XY xy, PJ *P) {
+static PJ_LP ccon_inverse (PJ_XY xy, PJ *P) {
PJ_LP lp = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
@@ -100,8 +100,8 @@ PJ *PROJECTION(ccon) {
Q->ctgphi1 = Q->cosphi1/Q->sinphi1;
- P->inv = inverse;
- P->fwd = forward;
+ P->inv = ccon_inverse;
+ P->fwd = ccon_forward;
return P;
}
diff --git a/src/projections/cea.cpp b/src/projections/cea.cpp
index a1c9c8b5..a7e5fd04 100644
--- a/src/projections/cea.cpp
+++ b/src/projections/cea.cpp
@@ -17,7 +17,7 @@ PROJ_HEAD(cea, "Equal Area Cylindrical") "\n\tCyl, Sph&Ell\n\tlat_ts=";
# define EPS 1e-10
-static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
+static PJ_XY cea_e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
PJ_XY xy = {0.0,0.0};
xy.x = P->k0 * lp.lam;
xy.y = 0.5 * pj_qsfn (sin (lp.phi), P->e, P->one_es) / P->k0;
@@ -25,7 +25,7 @@ static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
}
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY cea_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
xy.x = P->k0 * lp.lam;
xy.y = sin(lp.phi) / P->k0;
@@ -33,7 +33,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
+static PJ_LP cea_e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
PJ_LP lp = {0.0,0.0};
lp.phi = pj_authlat(asin( 2. * xy.y * P->k0 / static_cast<struct pj_opaque*>(P->opaque)->qp), static_cast<struct pj_opaque*>(P->opaque)->apa);
lp.lam = xy.x / P->k0;
@@ -41,7 +41,7 @@ static PJ_LP e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP cea_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
double t;
@@ -92,11 +92,11 @@ PJ *PROJECTION(cea) {
return pj_default_destructor(P, ENOMEM);
Q->qp = pj_qsfn(1., P->e, P->one_es);
- P->inv = e_inverse;
- P->fwd = e_forward;
+ P->inv = cea_e_inverse;
+ P->fwd = cea_e_forward;
} else {
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = cea_s_inverse;
+ P->fwd = cea_s_forward;
}
return P;
diff --git a/src/projections/chamb.cpp b/src/projections/chamb.cpp
index 33a38781..e6bac22c 100644
--- a/src/projections/chamb.cpp
+++ b/src/projections/chamb.cpp
@@ -54,7 +54,7 @@ static double lc(projCtx ctx, double b,double c,double a) {
}
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY chamb_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy;
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double sinphi, cosphi, a;
@@ -135,7 +135,7 @@ PJ *PROJECTION(chamb) {
Q->p.x = Q->c[2].p.x = Q->c[0].p.x + Q->c[2].v.r * cos(Q->beta_0);
P->es = 0.;
- P->fwd = s_forward;
+ P->fwd = chamb_s_forward;
return P;
}
diff --git a/src/projections/collg.cpp b/src/projections/collg.cpp
index b22e1bf2..40319a51 100644
--- a/src/projections/collg.cpp
+++ b/src/projections/collg.cpp
@@ -11,7 +11,7 @@ PROJ_HEAD(collg, "Collignon") "\n\tPCyl, Sph";
#define ONEEPS 1.0000001
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY collg_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
(void) P;
if ((xy.y = 1. - sin(lp.phi)) <= 0.)
@@ -24,7 +24,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP collg_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
lp.phi = xy.y / FYC - 1.;
if (fabs(lp.phi = 1. - lp.phi * lp.phi) < 1.)
@@ -46,8 +46,8 @@ static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ *PROJECTION(collg) {
P->es = 0.0;
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = collg_s_inverse;
+ P->fwd = collg_s_forward;
return P;
}
diff --git a/src/projections/comill.cpp b/src/projections/comill.cpp
index 3af19b42..afcfbf7f 100644
--- a/src/projections/comill.cpp
+++ b/src/projections/comill.cpp
@@ -26,7 +26,7 @@ PROJ_HEAD(comill, "Compact Miller") "\n\tCyl, Sph";
/* Not sure at all of the appropriate number for MAX_ITER... */
#define MAX_ITER 100
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY comill_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
double lat_sq;
@@ -39,7 +39,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP comill_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
double yc, tol, y2, f, fder;
int i;
@@ -78,8 +78,8 @@ static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ *PROJECTION(comill) {
P->es = 0;
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = comill_s_inverse;
+ P->fwd = comill_s_forward;
return P;
}
diff --git a/src/projections/crast.cpp b/src/projections/crast.cpp
index 35272058..cff35472 100644
--- a/src/projections/crast.cpp
+++ b/src/projections/crast.cpp
@@ -13,7 +13,7 @@ PROJ_HEAD(crast, "Craster Parabolic (Putnins P4)") "\n\tPCyl, Sph";
#define THIRD 0.333333333333333333
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY crast_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
(void) P;
lp.phi *= THIRD;
@@ -23,7 +23,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP crast_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
(void) P;
lp.phi = 3. * asin(xy.y * RYM);
@@ -34,8 +34,8 @@ static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ *PROJECTION(crast) {
P->es = 0.0;
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = crast_s_inverse;
+ P->fwd = crast_s_forward;
return P;
}
diff --git a/src/projections/denoy.cpp b/src/projections/denoy.cpp
index 1560ad6b..5f736a40 100644
--- a/src/projections/denoy.cpp
+++ b/src/projections/denoy.cpp
@@ -13,7 +13,7 @@ PROJ_HEAD(denoy, "Denoyer Semi-Elliptical") "\n\tPCyl, no inv, Sph";
#define D5 0.03
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY denoy_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0, 0.0};
(void) P;
xy.y = lp.phi;
@@ -27,7 +27,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ *PROJECTION(denoy) {
P->es = 0.0;
- P->fwd = s_forward;
+ P->fwd = denoy_s_forward;
return P;
}
diff --git a/src/projections/eck1.cpp b/src/projections/eck1.cpp
index 3a19796e..55944952 100644
--- a/src/projections/eck1.cpp
+++ b/src/projections/eck1.cpp
@@ -9,7 +9,7 @@ PROJ_HEAD(eck1, "Eckert I") "\n\tPCyl, Sph";
#define RP 0.31830988618379067154
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY eck1_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
(void) P;
@@ -20,7 +20,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP eck1_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
(void) P;
@@ -34,8 +34,8 @@ static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ *PROJECTION(eck1) {
P->es = 0.0;
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = eck1_s_inverse;
+ P->fwd = eck1_s_forward;
return P
;
diff --git a/src/projections/eck2.cpp b/src/projections/eck2.cpp
index f019fdab..27b94aed 100644
--- a/src/projections/eck2.cpp
+++ b/src/projections/eck2.cpp
@@ -13,7 +13,7 @@ PROJ_HEAD(eck2, "Eckert II") "\n\tPCyl, Sph";
#define ONEEPS 1.0000001
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY eck2_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
(void) P;
@@ -25,7 +25,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP eck2_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
(void) P;
@@ -49,8 +49,8 @@ static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ *PROJECTION(eck2) {
P->es = 0.;
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = eck2_s_inverse;
+ P->fwd = eck2_s_forward;
return P;
}
diff --git a/src/projections/eck3.cpp b/src/projections/eck3.cpp
index 6777c765..dd04fb39 100644
--- a/src/projections/eck3.cpp
+++ b/src/projections/eck3.cpp
@@ -18,7 +18,7 @@ struct pj_opaque {
} // anonymous namespace
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY eck3_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
@@ -28,7 +28,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP eck3_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double denominator;
@@ -45,8 +45,8 @@ static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
static PJ *setup(PJ *P) {
P->es = 0.;
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = eck3_s_inverse;
+ P->fwd = eck3_s_forward;
return P;
}
diff --git a/src/projections/eck4.cpp b/src/projections/eck4.cpp
index 7f8203b2..df2caf42 100644
--- a/src/projections/eck4.cpp
+++ b/src/projections/eck4.cpp
@@ -16,7 +16,7 @@ PROJ_HEAD(eck4, "Eckert IV") "\n\tPCyl, Sph";
#define NITER 6
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY eck4_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
double p, V, s, c;
int i;
@@ -44,7 +44,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP eck4_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
double c;
@@ -57,8 +57,8 @@ static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ *PROJECTION(eck4) {
P->es = 0.0;
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = eck4_s_inverse;
+ P->fwd = eck4_s_forward;
return P;
}
diff --git a/src/projections/eck5.cpp b/src/projections/eck5.cpp
index 40e9d3bb..bf0e6a42 100644
--- a/src/projections/eck5.cpp
+++ b/src/projections/eck5.cpp
@@ -13,7 +13,7 @@ PROJ_HEAD(eck5, "Eckert V") "\n\tPCyl, Sph";
#define RYF 1.13375401361911319568
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY eck5_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
(void) P;
xy.x = XF * (1. + cos(lp.phi)) * lp.lam;
@@ -23,7 +23,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP eck5_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
(void) P;
lp.lam = RXF * xy.x / (1. + cos( lp.phi = RYF * xy.y));
@@ -34,8 +34,8 @@ static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ *PROJECTION(eck5) {
P->es = 0.0;
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = eck5_s_inverse;
+ P->fwd = eck5_s_forward;
return P;
}
diff --git a/src/projections/eqc.cpp b/src/projections/eqc.cpp
index eb021eac..194625ef 100644
--- a/src/projections/eqc.cpp
+++ b/src/projections/eqc.cpp
@@ -16,7 +16,7 @@ PROJ_HEAD(eqc, "Equidistant Cylindrical (Plate Carree)")
"\n\tCyl, Sph\n\tlat_ts=[, lat_0=0]";
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY eqc_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
@@ -27,7 +27,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP eqc_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
@@ -46,8 +46,8 @@ PJ *PROJECTION(eqc) {
if ((Q->rc = cos(pj_param(P->ctx, P->params, "rlat_ts").f)) <= 0.)
return pj_default_destructor (P, PJD_ERR_LAT_TS_LARGER_THAN_90);
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = eqc_s_inverse;
+ P->fwd = eqc_s_forward;
P->es = 0.;
return P;
diff --git a/src/projections/eqdc.cpp b/src/projections/eqdc.cpp
index d175d4a1..e050a593 100644
--- a/src/projections/eqdc.cpp
+++ b/src/projections/eqdc.cpp
@@ -25,7 +25,7 @@ PROJ_HEAD(eqdc, "Equidistant Conic")
# define EPS10 1.e-10
-static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
+static PJ_XY eqdc_e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
PJ_XY xy = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
@@ -38,7 +38,7 @@ static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
}
-static PJ_LP e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
+static PJ_LP eqdc_e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
PJ_LP lp = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
@@ -84,12 +84,14 @@ PJ *PROJECTION(eqdc) {
Q->phi1 = pj_param(P->ctx, P->params, "rlat_1").f;
Q->phi2 = pj_param(P->ctx, P->params, "rlat_2").f;
+ if (fabs(Q->phi1) > M_HALFPI || fabs(Q->phi2) > M_HALFPI)
+ return destructor(P, PJD_ERR_LAT_LARGER_THAN_90);
if (fabs(Q->phi1 + Q->phi2) < EPS10)
- return pj_default_destructor (P, PJD_ERR_CONIC_LAT_EQUAL);
+ return destructor (P, PJD_ERR_CONIC_LAT_EQUAL);
if (!(Q->en = pj_enfn(P->es)))
- return pj_default_destructor(P, ENOMEM);
+ return destructor(P, ENOMEM);
Q->n = sinphi = sin(Q->phi1);
cosphi = cos(Q->phi1);
@@ -104,6 +106,10 @@ PJ *PROJECTION(eqdc) {
cosphi = cos(Q->phi2);
Q->n = (m1 - pj_msfn(sinphi, cosphi, P->es)) /
(pj_mlfn(Q->phi2, sinphi, cosphi, Q->en) - ml1);
+ if (Q->n == 0) {
+ // Not quite, but es is very close to 1...
+ return destructor(P, PJD_ERR_INVALID_ECCENTRICITY);
+ }
}
Q->c = ml1 + m1 / Q->n;
Q->rho0 = Q->c - pj_mlfn(P->phi0, sin(P->phi0),
@@ -115,8 +121,8 @@ PJ *PROJECTION(eqdc) {
Q->rho0 = Q->c - P->phi0;
}
- P->inv = e_inverse;
- P->fwd = e_forward;
+ P->inv = eqdc_e_inverse;
+ P->fwd = eqdc_e_forward;
return P;
}
diff --git a/src/projections/eqearth.cpp b/src/projections/eqearth.cpp
index dc58eed9..832c9444 100644
--- a/src/projections/eqearth.cpp
+++ b/src/projections/eqearth.cpp
@@ -26,7 +26,7 @@ PROJ_HEAD(eqearth, "Equal Earth") "\n\tPCyl, Sph&Ell";
#define A2 -0.081106
#define A3 0.000893
#define A4 0.003796
-#define M (sqrt(3) / 2.0)
+#define M (sqrt(3.0) / 2.0)
#define MAX_Y 1.3173627591574 /* 90° latitude on a sphere with radius 1 */
#define EPS 1e-11
@@ -40,7 +40,7 @@ struct pj_opaque {
};
} // anonymous namespace
-static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal/spheroidal, forward */
+static PJ_XY eqearth_e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal/spheroidal, forward */
PJ_XY xy = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double sbeta;
@@ -74,7 +74,7 @@ static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal/spheroidal,
}
-static PJ_LP e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal/spheroidal, inverse */
+static PJ_LP eqearth_e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal/spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double yc, y2, y6;
@@ -148,8 +148,8 @@ PJ *PROJECTION(eqearth) {
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
P->destructor = destructor;
- P->fwd = e_forward;
- P->inv = e_inverse;
+ P->fwd = eqearth_e_forward;
+ P->inv = eqearth_e_inverse;
Q->rqda = 1.0;
/* Ellipsoidal case */
diff --git a/src/projections/fahey.cpp b/src/projections/fahey.cpp
index ba8cb8f9..9561217a 100644
--- a/src/projections/fahey.cpp
+++ b/src/projections/fahey.cpp
@@ -10,7 +10,7 @@ PROJ_HEAD(fahey, "Fahey") "\n\tPcyl, Sph";
#define TOL 1e-6
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY fahey_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
(void) P;
@@ -21,7 +21,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP fahey_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
(void) P;
@@ -35,8 +35,8 @@ static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ *PROJECTION(fahey) {
P->es = 0.;
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = fahey_s_inverse;
+ P->fwd = fahey_s_forward;
return P;
}
diff --git a/src/projections/fouc_s.cpp b/src/projections/fouc_s.cpp
index e91f41c3..29d6437d 100644
--- a/src/projections/fouc_s.cpp
+++ b/src/projections/fouc_s.cpp
@@ -18,7 +18,7 @@ struct pj_opaque {
} // anonymous namespace
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY fouc_s_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double t;
@@ -30,7 +30,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP fouc_s_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double V;
@@ -66,7 +66,7 @@ PJ *PROJECTION(fouc_s) {
Q->n1 = 1. - Q->n;
P->es = 0;
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = fouc_s_s_inverse;
+ P->fwd = fouc_s_s_forward;
return P;
}
diff --git a/src/projections/gall.cpp b/src/projections/gall.cpp
index 8f1ca1f8..091c75d7 100644
--- a/src/projections/gall.cpp
+++ b/src/projections/gall.cpp
@@ -13,7 +13,7 @@ PROJ_HEAD(gall, "Gall (Gall Stereographic)") "\n\tCyl, Sph";
#define RXF 1.41421356237309504880
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY gall_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
(void) P;
@@ -24,7 +24,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP gall_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
(void) P;
@@ -38,8 +38,8 @@ static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ *PROJECTION(gall) {
P->es = 0.0;
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = gall_s_inverse;
+ P->fwd = gall_s_forward;
return P;
}
diff --git a/src/projections/geos.cpp b/src/projections/geos.cpp
index cdb0244a..5b3e594c 100644
--- a/src/projections/geos.cpp
+++ b/src/projections/geos.cpp
@@ -52,7 +52,7 @@ struct pj_opaque {
PROJ_HEAD(geos, "Geostationary Satellite View") "\n\tAzi, Sph&Ell\n\th=";
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY geos_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double Vx, Vy, Vz, tmp;
@@ -82,7 +82,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
+static PJ_XY geos_e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
PJ_XY xy = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double r, Vx, Vy, Vz, tmp;
@@ -118,7 +118,7 @@ static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP geos_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double Vx, Vy, Vz, a, b, det, k;
@@ -155,7 +155,7 @@ static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static PJ_LP e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
+static PJ_LP geos_e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
PJ_LP lp = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double Vx, Vy, Vz, a, b, det, k;
@@ -202,8 +202,7 @@ PJ *PROJECTION(geos) {
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
- if ((Q->h = pj_param(P->ctx, P->params, "dh").f) <= 0.)
- return pj_default_destructor (P, PJD_ERR_H_LESS_THAN_ZERO);
+ Q->h = pj_param(P->ctx, P->params, "dh").f;
sweep_axis = pj_param(P->ctx, P->params, "ssweep").s;
if (sweep_axis == nullptr)
@@ -220,18 +219,20 @@ PJ *PROJECTION(geos) {
}
Q->radius_g_1 = Q->h / P->a;
+ if ( Q->radius_g_1 <= 0 || Q->radius_g_1 > 1e10 )
+ return pj_default_destructor (P, PJD_ERR_INVALID_H);
Q->radius_g = 1. + Q->radius_g_1;
Q->C = Q->radius_g * Q->radius_g - 1.0;
if (P->es != 0.0) {
Q->radius_p = sqrt (P->one_es);
Q->radius_p2 = P->one_es;
Q->radius_p_inv2 = P->rone_es;
- P->inv = e_inverse;
- P->fwd = e_forward;
+ P->inv = geos_e_inverse;
+ P->fwd = geos_e_forward;
} else {
Q->radius_p = Q->radius_p2 = Q->radius_p_inv2 = 1.0;
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = geos_s_inverse;
+ P->fwd = geos_s_forward;
}
return P;
diff --git a/src/projections/gins8.cpp b/src/projections/gins8.cpp
index 6f499889..73f00d6f 100644
--- a/src/projections/gins8.cpp
+++ b/src/projections/gins8.cpp
@@ -10,7 +10,7 @@ PROJ_HEAD(gins8, "Ginsburg VIII (TsNIIGAiK)") "\n\tPCyl, Sph, no inv";
#define C12 0.08333333333333333
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY gins8_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
double t = lp.phi * lp.phi;
(void) P;
@@ -27,7 +27,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ *PROJECTION(gins8) {
P->es = 0.0;
P->inv = nullptr;
- P->fwd = s_forward;
+ P->fwd = gins8_s_forward;
return P;
}
diff --git a/src/projections/gn_sinu.cpp b/src/projections/gn_sinu.cpp
index 3a591669..84883cbc 100644
--- a/src/projections/gn_sinu.cpp
+++ b/src/projections/gn_sinu.cpp
@@ -23,7 +23,7 @@ struct pj_opaque {
} // anonymous namespace
-static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
+static PJ_XY gn_sinu_e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
PJ_XY xy = {0.0,0.0};
double s, c;
@@ -33,7 +33,7 @@ static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
}
-static PJ_LP e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
+static PJ_LP gn_sinu_e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
PJ_LP lp = {0.0,0.0};
double s;
@@ -50,7 +50,7 @@ static PJ_LP e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
}
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY gn_sinu_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
@@ -80,7 +80,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP gn_sinu_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
@@ -109,8 +109,8 @@ static PJ *destructor (PJ *P, int errlev) { /* Destructor
static void setup(PJ *P) {
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
P->es = 0;
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = gn_sinu_s_inverse;
+ P->fwd = gn_sinu_s_forward;
Q->C_x = (Q->C_y = sqrt((Q->m + 1.) / Q->n))/(Q->m + 1.);
}
@@ -127,8 +127,8 @@ PJ *PROJECTION(sinu) {
return pj_default_destructor (P, ENOMEM);
if (P->es != 0.0) {
- P->inv = e_inverse;
- P->fwd = e_forward;
+ P->inv = gn_sinu_e_inverse;
+ P->fwd = gn_sinu_e_forward;
} else {
Q->n = 1.;
Q->m = 0.;
diff --git a/src/projections/gnom.cpp b/src/projections/gnom.cpp
index bf454ba9..f7cb2635 100644
--- a/src/projections/gnom.cpp
+++ b/src/projections/gnom.cpp
@@ -29,7 +29,7 @@ struct pj_opaque {
} // anonymous namespace
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY gnom_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double coslam, cosphi, sinphi;
@@ -77,7 +77,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP gnom_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double rh, cosz, sinz;
@@ -139,8 +139,8 @@ PJ *PROJECTION(gnom) {
Q->cosph0 = cos(P->phi0);
}
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = gnom_s_inverse;
+ P->fwd = gnom_s_forward;
P->es = 0.;
return P;
diff --git a/src/projections/goode.cpp b/src/projections/goode.cpp
index 802df90c..c716649d 100644
--- a/src/projections/goode.cpp
+++ b/src/projections/goode.cpp
@@ -21,7 +21,7 @@ struct pj_opaque {
} // anonymous namespace
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY goode_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy;
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
@@ -35,7 +35,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP goode_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp;
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
@@ -77,8 +77,8 @@ PJ *PROJECTION(goode) {
if (!(Q->sinu = pj_sinu(Q->sinu)) || !(Q->moll = pj_moll(Q->moll)))
return destructor (P, ENOMEM);
- P->fwd = s_forward;
- P->inv = s_inverse;
+ P->fwd = goode_s_forward;
+ P->inv = goode_s_inverse;
return P;
}
diff --git a/src/projections/gstmerc.cpp b/src/projections/gstmerc.cpp
index 735d39e5..808d9ef7 100644
--- a/src/projections/gstmerc.cpp
+++ b/src/projections/gstmerc.cpp
@@ -22,7 +22,7 @@ struct pj_opaque {
} // anonymous namespace
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY gstmerc_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double L, Ls, sinLs1, Ls1;
@@ -38,7 +38,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP gstmerc_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double L, LC, sinC;
@@ -68,8 +68,8 @@ PJ *PROJECTION(gstmerc) {
Q->XS = 0;
Q->YS = -1.0 * Q->n2 * Q->phic;
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = gstmerc_s_inverse;
+ P->fwd = gstmerc_s_forward;
return P;
}
diff --git a/src/projections/hammer.cpp b/src/projections/hammer.cpp
index aa7d1ba9..56bdf74e 100644
--- a/src/projections/hammer.cpp
+++ b/src/projections/hammer.cpp
@@ -19,19 +19,26 @@ struct pj_opaque {
} // anonymous namespace
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY hammer_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double cosphi, d;
- d = sqrt(2./(1. + (cosphi = cos(lp.phi)) * cos(lp.lam *= Q->w)));
+ cosphi = cos(lp.phi);
+ lp.lam *= Q->w;
+ double denom = 1. + cosphi * cos(lp.lam);
+ if( denom == 0.0 ) {
+ proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION);
+ return proj_coord_error().xy;
+ }
+ d = sqrt(2./denom);
xy.x = Q->m * d * cosphi * sin(lp.lam);
xy.y = Q->rm * d * sin(lp.phi);
return xy;
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP hammer_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double z;
@@ -70,8 +77,8 @@ PJ *PROJECTION(hammer) {
Q->m /= Q->w;
P->es = 0.;
- P->fwd = s_forward;
- P->inv = s_inverse;
+ P->fwd = hammer_s_forward;
+ P->inv = hammer_s_inverse;
return P;
}
diff --git a/src/projections/hatano.cpp b/src/projections/hatano.cpp
index b2ef6c6f..6c125d2e 100644
--- a/src/projections/hatano.cpp
+++ b/src/projections/hatano.cpp
@@ -22,7 +22,7 @@ PROJ_HEAD(hatano, "Hatano Asymmetrical Equal Area") "\n\tPCyl, Sph";
#define RXC 1.17647058823529411764
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY hatano_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
double th1, c;
int i;
@@ -40,7 +40,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP hatano_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
double th;
@@ -76,8 +76,8 @@ static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ *PROJECTION(hatano) {
P->es = 0.;
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = hatano_s_inverse;
+ P->fwd = hatano_s_forward;
return P;
}
diff --git a/src/projections/healpix.cpp b/src/projections/healpix.cpp
index 8e4846ed..515f4f6f 100644
--- a/src/projections/healpix.cpp
+++ b/src/projections/healpix.cpp
@@ -33,7 +33,6 @@
#include <errno.h>
#include <math.h>
-#include "proj_internal.h"
#include "proj.h"
#include "proj_internal.h"
@@ -282,7 +281,7 @@ static PJ_XY healpix_sphere(PJ_LP lp) {
/**
* Return the inverse of healpix_sphere().
**/
-static PJ_LP healpix_sphere_inverse(PJ_XY xy) {
+static PJ_LP healpix_spherhealpix_e_inverse(PJ_XY xy) {
PJ_LP lp;
double x = xy.x;
double y = xy.y;
@@ -533,7 +532,7 @@ static PJ_LP s_healpix_inverse(PJ_XY xy, PJ *P) { /* sphere */
pj_ctx_set_errno(P->ctx, PJD_ERR_INVALID_X_OR_Y);
return lp;
}
- return healpix_sphere_inverse(xy);
+ return healpix_spherhealpix_e_inverse(xy);
}
@@ -547,7 +546,7 @@ static PJ_LP e_healpix_inverse(PJ_XY xy, PJ *P) { /* ellipsoid */
pj_ctx_set_errno(P->ctx, PJD_ERR_INVALID_X_OR_Y);
return lp;
}
- lp = healpix_sphere_inverse(xy);
+ lp = healpix_spherhealpix_e_inverse(xy);
lp.phi = auth_lat(P, lp.phi, 1);
return lp;
}
@@ -582,7 +581,7 @@ static PJ_LP s_rhealpix_inverse(PJ_XY xy, PJ *P) { /* sphere */
return lp;
}
xy = combine_caps(xy.x, xy.y, Q->north_square, Q->south_square, 1);
- return healpix_sphere_inverse(xy);
+ return healpix_spherhealpix_e_inverse(xy);
}
@@ -598,7 +597,7 @@ static PJ_LP e_rhealpix_inverse(PJ_XY xy, PJ *P) { /* ellipsoid */
return lp;
}
xy = combine_caps(xy.x, xy.y, Q->north_square, Q->south_square, 1);
- lp = healpix_sphere_inverse(xy);
+ lp = healpix_spherhealpix_e_inverse(xy);
lp.phi = auth_lat(P, lp.phi, 1);
return lp;
}
diff --git a/src/projections/igh.cpp b/src/projections/igh.cpp
index a8efbb9d..8a41cea3 100644
--- a/src/projections/igh.cpp
+++ b/src/projections/igh.cpp
@@ -41,7 +41,7 @@ struct pj_opaque {
} // anonymous namespace
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY igh_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy;
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
int z;
@@ -74,10 +74,10 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP igh_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
- const double y90 = Q->dy0 + sqrt(2); /* lt=90 corresponds to y=y0+sqrt(2) */
+ const double y90 = Q->dy0 + sqrt(2.0); /* lt=90 corresponds to y=y0+sqrt(2) */
int z = 0;
if (xy.y > y90+EPSLN || xy.y < -y90+EPSLN) /* 0 */
@@ -219,8 +219,8 @@ PJ *PROJECTION(igh) {
SETUP(11, moll, d20, -Q->dy0, d20);
SETUP(12, moll, d140, -Q->dy0, d140);
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = igh_s_inverse;
+ P->fwd = igh_s_forward;
P->destructor = destructor;
P->es = 0.;
diff --git a/src/projections/imw_p.cpp b/src/projections/imw_p.cpp
index 723fcc48..ee206091 100644
--- a/src/projections/imw_p.cpp
+++ b/src/projections/imw_p.cpp
@@ -97,14 +97,14 @@ static PJ_XY loc_for(PJ_LP lp, PJ *P, double *yc) {
}
-static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
+static PJ_XY imw_p_e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
double yc;
PJ_XY xy = loc_for(lp, P, &yc);
return (xy);
}
-static PJ_LP e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
+static PJ_LP imw_p_e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
PJ_LP lp = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
PJ_XY t;
@@ -116,15 +116,25 @@ static PJ_LP e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
lp.lam = xy.x / cos(lp.phi);
do {
t = loc_for(lp, P, &yc);
- lp.phi = ((lp.phi - Q->phi_1) * (xy.y - yc) / (t.y - yc)) + Q->phi_1;
- lp.lam = lp.lam * xy.x / t.x;
+ const double denom = t.y - yc;
+ if( denom != 0 || fabs(t.y - xy.y) > TOL )
+ {
+ if( denom == 0 ) {
+ proj_errno_set(P, PJD_ERR_NON_CONVERGENT);
+ return proj_coord_error().lp;
+ }
+ lp.phi = ((lp.phi - Q->phi_1) * (xy.y - yc) / denom) + Q->phi_1;
+ }
+ if( t.x != 0 && fabs(t.x - xy.x) > TOL )
+ lp.lam = lp.lam * xy.x / t.x;
i ++;
} while (i < N_MAX_ITER &&
(fabs(t.x - xy.x) > TOL || fabs(t.y - xy.y) > TOL));
if( i == N_MAX_ITER )
{
- lp.lam = lp.phi = HUGE_VAL;
+ proj_errno_set(P, PJD_ERR_NON_CONVERGENT);
+ return proj_coord_error().lp;
}
return lp;
@@ -209,8 +219,8 @@ PJ *PROJECTION(imw_p) {
Q->Pp = (m2 * x1 - m1 * x2) * t;
Q->Qp = (x2 - x1) * t;
- P->fwd = e_forward;
- P->inv = e_inverse;
+ P->fwd = imw_p_e_forward;
+ P->inv = imw_p_e_inverse;
P->destructor = destructor;
return P;
diff --git a/src/projections/isea.cpp b/src/projections/isea.cpp
index 3a0a0a48..c22e143d 100644
--- a/src/projections/isea.cpp
+++ b/src/projections/isea.cpp
@@ -10,11 +10,12 @@
#include <stdlib.h>
#include <string.h>
+#include <limits>
+
#define PJ_LIB__
-#include "proj_internal.h"
-#include "proj_math.h"
#include "proj.h"
#include "proj_internal.h"
+#include "proj_math.h"
#define DEG36 0.62831853071795864768
#define DEG72 1.25663706143591729537
@@ -89,6 +90,9 @@ static void hexbin2(double width, double x, double y, long *i, long *j) {
y = y - x / 2.0; /* adjustment for rotated X */
/* adjust for actual hexwidth */
+ if( width == 0 ) {
+ throw "Division by zero";
+ }
x /= width;
y /= width;
@@ -100,6 +104,10 @@ static void hexbin2(double width, double x, double y, long *i, long *j) {
iy = lround(ry);
rz = floor(z + 0.5);
iz = lround(rz);
+ if( fabs((double)ix + iy) > std::numeric_limits<int>::max() ||
+ fabs((double)ix + iy + iz) > std::numeric_limits<int>::max() ) {
+ throw "Integer overflow";
+ }
s = ix + iy + iz;
@@ -764,11 +772,18 @@ static int isea_dddi(struct isea_dgg *g, int quad, struct isea_pt *pt,
}
/* todo might want to do this as an iterated loop */
if (g->aperture >0) {
- sidelength = lround(pow(g->aperture, g->resolution / 2.0));
+ double sidelengthDouble = pow(g->aperture, g->resolution / 2.0);
+ if( fabs(sidelengthDouble) > std::numeric_limits<int>::max() ) {
+ throw "Integer overflow";
+ }
+ sidelength = lround(sidelengthDouble);
} else {
sidelength = g->resolution;
}
+ if( sidelength == 0 ) {
+ throw "Division by zero";
+ }
hexwidth = 1.0 / sidelength;
v = *pt;
@@ -847,7 +862,7 @@ static long isea_disn(struct isea_dgg *g, int quad, struct isea_pt *di) {
return g->serial;
}
/* hexes in a quad */
- hexes = lround(pow(g->aperture, g->resolution));
+ hexes = lround(pow(static_cast<double>(g->aperture), static_cast<double>(g->resolution)));
if (quad == 11) {
g->serial = 1 + 10 * hexes + 1;
return g->serial;
@@ -883,6 +898,10 @@ static int isea_hex(struct isea_dgg *g, int tri,
quad = isea_ptdi(g, tri, pt, &v);
+ if( v.x < (INT_MIN >> 4) || v.x > (INT_MAX >> 4) )
+ {
+ throw "Invalid shift";
+ }
hex->x = ((int)v.x << 4) + quad;
hex->y = v.y;
@@ -995,7 +1014,7 @@ struct pj_opaque {
} // anonymous namespace
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY isea_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
struct isea_pt out;
@@ -1004,7 +1023,12 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
in.lon = lp.lam;
in.lat = lp.phi;
- out = isea_forward(&Q->dgg, &in);
+ try {
+ out = isea_forward(&Q->dgg, &in);
+ } catch( const char* ) {
+ proj_errno_set(P, PJD_ERR_NON_CONVERGENT);
+ return proj_coord_error().xy;
+ }
xy.x = out.x;
xy.y = out.y;
@@ -1021,7 +1045,7 @@ PJ *PROJECTION(isea) {
P->opaque = Q;
- P->fwd = s_forward;
+ P->fwd = isea_s_forward;
isea_grid_init(&Q->dgg);
Q->dgg.output = ISEA_PLANE;
@@ -1051,14 +1075,6 @@ PJ *PROJECTION(isea) {
Q->dgg.o_lat = pj_param(P->ctx,P->params, "rlat_0").f;
}
- if (pj_param(P->ctx,P->params, "taperture").i) {
- Q->dgg.aperture = pj_param(P->ctx,P->params, "iaperture").i;
- }
-
- if (pj_param(P->ctx,P->params, "tresolution").i) {
- Q->dgg.resolution = pj_param(P->ctx,P->params, "iresolution").i;
- }
-
opt = pj_param(P->ctx,P->params, "smode").s;
if (opt) {
if (!strcmp(opt, "plane")) {
diff --git a/src/projections/krovak.cpp b/src/projections/krovak.cpp
index 591f8dcc..98f09199 100644
--- a/src/projections/krovak.cpp
+++ b/src/projections/krovak.cpp
@@ -103,7 +103,7 @@ struct pj_opaque {
} // anonymous namespace
-static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
+static PJ_XY krovak_e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
PJ_XY xy = {0.0,0.0};
@@ -115,7 +115,14 @@ static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forwar
deltav = -lp.lam * Q->alpha;
s = asin(cos(Q->ad) * sin(u) + sin(Q->ad) * cos(u) * cos(deltav));
- d = asin(cos(u) * sin(deltav) / cos(s));
+ const double cos_s = cos(s);
+ if( cos_s < 1e-12 )
+ {
+ xy.x = 0;
+ xy.y = 0;
+ return xy;
+ }
+ d = asin(cos(u) * sin(deltav) / cos_s);
eps = Q->n * d;
rho = Q->rho0 * pow(tan(S0 / 2. + M_PI_4) , Q->n) / pow(tan(s / 2. + M_PI_4) , Q->n);
@@ -130,7 +137,7 @@ static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forwar
}
-static PJ_LP e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
+static PJ_LP krovak_e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
PJ_LP lp = {0.0,0.0};
@@ -148,7 +155,12 @@ static PJ_LP e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, invers
eps = atan2(xy.y, xy.x);
d = eps / sin(S0);
- s = 2. * (atan( pow(Q->rho0 / rho, 1. / Q->n) * tan(S0 / 2. + M_PI_4)) - M_PI_4);
+ if( rho == 0.0 ) {
+ s = M_PI_2;
+ }
+ else {
+ s = 2. * (atan( pow(Q->rho0 / rho, 1. / Q->n) * tan(S0 / 2. + M_PI_4)) - M_PI_4);
+ }
u = asin(cos(Q->ad) * sin(s) - sin(Q->ad) * cos(s) * cos(d));
deltav = asin(cos(s) * sin(d) / cos(u));
@@ -210,14 +222,18 @@ PJ *PROJECTION(krovak) {
Q->alpha = sqrt(1. + (P->es * pow(cos(P->phi0), 4)) / (1. - P->es));
u0 = asin(sin(P->phi0) / Q->alpha);
g = pow( (1. + P->e * sin(P->phi0)) / (1. - P->e * sin(P->phi0)) , Q->alpha * P->e / 2. );
- Q->k = tan( u0 / 2. + M_PI_4) / pow (tan(P->phi0 / 2. + M_PI_4) , Q->alpha) * g;
+ double tan_half_phi0_plus_pi_4 = tan(P->phi0 / 2. + M_PI_4);
+ if( tan_half_phi0_plus_pi_4 == 0.0 ) {
+ return pj_default_destructor(P, PJD_ERR_INVALID_ARG);
+ }
+ Q->k = tan( u0 / 2. + M_PI_4) / pow (tan_half_phi0_plus_pi_4 , Q->alpha) * g;
n0 = sqrt(1. - P->es) / (1. - P->es * pow(sin(P->phi0), 2));
Q->n = sin(S0);
Q->rho0 = P->k0 * n0 / tan(S0);
Q->ad = M_PI_2 - UQ;
- P->inv = e_inverse;
- P->fwd = e_forward;
+ P->inv = krovak_e_inverse;
+ P->fwd = krovak_e_forward;
return P;
}
diff --git a/src/projections/labrd.cpp b/src/projections/labrd.cpp
index 85ab3ddd..21d9099f 100644
--- a/src/projections/labrd.cpp
+++ b/src/projections/labrd.cpp
@@ -16,7 +16,7 @@ struct pj_opaque {
} // anonymous namespace
-static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
+static PJ_XY labrd_e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
PJ_XY xy = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double V1, V2, ps, sinps, cosps, sinps2, cosps2;
@@ -49,7 +49,7 @@ static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
}
-static PJ_LP e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
+static PJ_LP labrd_e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
PJ_LP lp = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
/* t = 0.0 optimization is to avoid a false positive cppcheck warning */
@@ -130,8 +130,8 @@ PJ *PROJECTION(labrd) {
Q->Cc = 3. * (Q->Ca * Q->Ca - Q->Cb * Q->Cb);
Q->Cd = 6. * Q->Ca * Q->Cb;
- P->inv = e_inverse;
- P->fwd = e_forward;
+ P->inv = labrd_e_inverse;
+ P->fwd = labrd_e_forward;
return P;
}
diff --git a/src/projections/laea.cpp b/src/projections/laea.cpp
index 22fb1691..8a23c504 100644
--- a/src/projections/laea.cpp
+++ b/src/projections/laea.cpp
@@ -32,7 +32,7 @@ struct pj_opaque {
#define EPS10 1.e-10
-static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
+static PJ_XY laea_e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
PJ_XY xy = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double coslam, sinlam, sinphi, q, sinb=0.0, cosb=0.0, b=0.0;
@@ -94,7 +94,7 @@ eqcon:
}
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY laea_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double coslam, cosphi, sinphi;
@@ -136,7 +136,7 @@ oblcon:
}
-static PJ_LP e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
+static PJ_LP laea_e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
PJ_LP lp = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double cCe, sCe, q, rho, ab=0.0;
@@ -185,7 +185,7 @@ static PJ_LP e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP laea_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double cosz=0.0, rh, sinz=0.0;
@@ -248,6 +248,9 @@ PJ *PROJECTION(laea) {
P->destructor = destructor;
t = fabs(P->phi0);
+ if (t > M_HALFPI + EPS10 ) {
+ return destructor(P, PJD_ERR_LAT_LARGER_THAN_90);
+ }
if (fabs(t - M_HALFPI) < EPS10)
Q->mode = P->phi0 < 0. ? S_POLE : N_POLE;
else if (fabs(t) < EPS10)
@@ -284,15 +287,15 @@ PJ *PROJECTION(laea) {
Q->xmf *= Q->dd;
break;
}
- P->inv = e_inverse;
- P->fwd = e_forward;
+ P->inv = laea_e_inverse;
+ P->fwd = laea_e_forward;
} else {
if (Q->mode == OBLIQ) {
Q->sinb1 = sin(P->phi0);
Q->cosb1 = cos(P->phi0);
}
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = laea_s_inverse;
+ P->fwd = laea_s_forward;
}
return P;
diff --git a/src/projections/lagrng.cpp b/src/projections/lagrng.cpp
index 65686584..d37a00e6 100644
--- a/src/projections/lagrng.cpp
+++ b/src/projections/lagrng.cpp
@@ -21,17 +21,17 @@ struct pj_opaque {
} // anonymous namespace
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY lagrng_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double v, c;
- if (fabs(fabs(lp.phi) - M_HALFPI) < TOL) {
+ const double sin_phi = sin(lp.phi);
+ if (fabs(fabs(sin_phi) - 1) < TOL) {
xy.x = 0;
xy.y = lp.phi < 0 ? -2. : 2.;
} else {
- lp.phi = sin(lp.phi);
- v = Q->a1 * pow((1. + lp.phi)/(1. - lp.phi), Q->hrw);
+ v = Q->a1 * pow((1. + sin_phi)/(1. - sin_phi), Q->hrw);
lp.lam *= Q->rw;
c = 0.5 * (v + 1./v) + cos(lp.lam);
if (c < TOL) {
@@ -45,7 +45,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP lagrng_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double c, x2, y2p, y2m;
@@ -70,7 +70,7 @@ static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ *PROJECTION(lagrng) {
- double phi1;
+ double sin_phi1;
struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
@@ -85,16 +85,16 @@ PJ *PROJECTION(lagrng) {
Q->hw = 0.5 * Q->w;
Q->rw = 1. / Q->w;
Q->hrw = 0.5 * Q->rw;
- phi1 = sin(pj_param(P->ctx, P->params, "rlat_1").f);
- if (fabs(fabs(phi1) - 1.) < TOL)
+ sin_phi1 = sin(pj_param(P->ctx, P->params, "rlat_1").f);
+ if (fabs(fabs(sin_phi1) - 1.) < TOL)
return pj_default_destructor(P, PJD_ERR_LAT_LARGER_THAN_90);
- Q->a1 = pow((1. - phi1)/(1. + phi1), Q->hrw);
+ Q->a1 = pow((1. - sin_phi1)/(1. + sin_phi1), Q->hrw);
Q->a2 = Q->a1 * Q->a1;
P->es = 0.;
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = lagrng_s_inverse;
+ P->fwd = lagrng_s_forward;
return P;
}
diff --git a/src/projections/larr.cpp b/src/projections/larr.cpp
index bab1dbf4..33fbd94c 100644
--- a/src/projections/larr.cpp
+++ b/src/projections/larr.cpp
@@ -10,7 +10,7 @@ PROJ_HEAD(larr, "Larrivee") "\n\tMisc Sph, no inv";
#define SIXTH .16666666666666666
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY larr_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
(void) P;
@@ -23,7 +23,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ *PROJECTION(larr) {
P->es = 0;
- P->fwd = s_forward;
+ P->fwd = larr_s_forward;
return P;
}
diff --git a/src/projections/lask.cpp b/src/projections/lask.cpp
index c4c6734d..80e50522 100644
--- a/src/projections/lask.cpp
+++ b/src/projections/lask.cpp
@@ -17,7 +17,7 @@ PROJ_HEAD(lask, "Laskowski") "\n\tMisc Sph, no inv";
#define b05 -0.0491032
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY lask_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
double l2, p2;
(void) P;
@@ -33,7 +33,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ *PROJECTION(lask) {
- P->fwd = s_forward;
+ P->fwd = lask_s_forward;
P->es = 0.;
return P;
diff --git a/src/projections/latlong.cpp b/src/projections/latlong.cpp
index 970c4893..2c98a4cd 100644
--- a/src/projections/latlong.cpp
+++ b/src/projections/latlong.cpp
@@ -30,7 +30,6 @@
/* very loosely based upon DMA code by Bradford W. Drew */
#define PJ_LIB__
#include "proj_internal.h"
-#include "proj_internal.h"
PROJ_HEAD(lonlat, "Lat/long (Geodetic)") "\n\t";
PROJ_HEAD(latlon, "Lat/long (Geodetic alias)") "\n\t";
diff --git a/src/projections/lcc.cpp b/src/projections/lcc.cpp
index a1fe79a9..beb2efd1 100644
--- a/src/projections/lcc.cpp
+++ b/src/projections/lcc.cpp
@@ -20,7 +20,7 @@ struct pj_opaque {
} // anonymous namespace
-static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
+static PJ_XY lcc_e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
PJ_XY xy = {0., 0.};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double rho;
@@ -43,7 +43,7 @@ static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
}
-static PJ_LP e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
+static PJ_LP lcc_e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
PJ_LP lp = {0., 0.};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double rho;
@@ -94,6 +94,8 @@ PJ *PROJECTION(lcc) {
if (!pj_param(P->ctx, P->params, "tlat_0").i)
P->phi0 = Q->phi1;
}
+ if (fabs(Q->phi1) > M_HALFPI || fabs(Q->phi2) > M_HALFPI)
+ return pj_default_destructor(P, PJD_ERR_LAT_LARGER_THAN_90);
if (fabs(Q->phi1 + Q->phi2) < EPS10)
return pj_default_destructor(P, PJD_ERR_CONIC_LAT_EQUAL);
@@ -105,15 +107,34 @@ PJ *PROJECTION(lcc) {
m1 = pj_msfn(sinphi, cosphi, P->es);
ml1 = pj_tsfn(Q->phi1, sinphi, P->e);
+ if( ml1 == 0 ) {
+ return pj_default_destructor(P, PJD_ERR_LAT_1_OR_2_ZERO_OR_90);
+ }
if (secant) { /* secant cone */
sinphi = sin(Q->phi2);
Q->n = log(m1 / pj_msfn(sinphi, cos(Q->phi2), P->es));
- Q->n /= log(ml1 / pj_tsfn(Q->phi2, sinphi, P->e));
+ if (Q->n == 0) {
+ // Not quite, but es is very close to 1...
+ return pj_default_destructor(P, PJD_ERR_INVALID_ECCENTRICITY);
+ }
+ const double ml2 = pj_tsfn(Q->phi2, sinphi, P->e);
+ if( ml2 == 0 ) {
+ return pj_default_destructor(P, PJD_ERR_LAT_1_OR_2_ZERO_OR_90);
+ }
+ const double denom = log(ml1 / ml2);
+ if( denom == 0 ) {
+ // Not quite, but es is very close to 1...
+ return pj_default_destructor(P, PJD_ERR_INVALID_ECCENTRICITY);
+ }
+ Q->n /= denom;
}
Q->c = (Q->rho0 = m1 * pow(ml1, -Q->n) / Q->n);
Q->rho0 *= (fabs(fabs(P->phi0) - M_HALFPI) < EPS10) ? 0. :
pow(pj_tsfn(P->phi0, sin(P->phi0), P->e), Q->n);
} else {
+ if( fabs(cosphi) < EPS10 || fabs(cos(Q->phi2)) < EPS10 ) {
+ return pj_default_destructor(P, PJD_ERR_LAT_1_OR_2_ZERO_OR_90);
+ }
if (secant)
Q->n = log(cosphi / cos(Q->phi2)) /
log(tan(M_FORTPI + .5 * Q->phi2) /
@@ -123,8 +144,8 @@ PJ *PROJECTION(lcc) {
Q->c * pow(tan(M_FORTPI + .5 * P->phi0), -Q->n);
}
- P->inv = e_inverse;
- P->fwd = e_forward;
+ P->inv = lcc_e_inverse;
+ P->fwd = lcc_e_forward;
return P;
}
diff --git a/src/projections/lcca.cpp b/src/projections/lcca.cpp
index d4dc8641..11ecb29c 100644
--- a/src/projections/lcca.cpp
+++ b/src/projections/lcca.cpp
@@ -80,7 +80,7 @@ static double fSp(double S, double C) { /* deriv of fs */
}
-static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
+static PJ_XY lcca_e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
PJ_XY xy = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double S, r, dr;
@@ -94,7 +94,7 @@ static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
}
-static PJ_LP e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
+static PJ_LP lcca_e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
PJ_LP lp = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double theta, dr, S, dif;
@@ -156,8 +156,8 @@ PJ *PROJECTION(lcca) {
Q->r0 = N0 / tan0;
Q->C = 1. / (6. * R0 * N0);
- P->inv = e_inverse;
- P->fwd = e_forward;
+ P->inv = lcca_e_inverse;
+ P->fwd = lcca_e_forward;
P->destructor = destructor;
return P;
diff --git a/src/projections/loxim.cpp b/src/projections/loxim.cpp
index 2a780a9e..2ee88037 100644
--- a/src/projections/loxim.cpp
+++ b/src/projections/loxim.cpp
@@ -19,7 +19,7 @@ struct pj_opaque {
} // anonymous namespace
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY loxim_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
@@ -37,7 +37,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP loxim_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
@@ -69,8 +69,8 @@ PJ *PROJECTION(loxim) {
Q->tanphi1 = tan(M_FORTPI + 0.5 * Q->phi1);
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = loxim_s_inverse;
+ P->fwd = loxim_s_forward;
P->es = 0.;
return P;
diff --git a/src/projections/lsat.cpp b/src/projections/lsat.cpp
index 5b7520d3..f6114485 100644
--- a/src/projections/lsat.cpp
+++ b/src/projections/lsat.cpp
@@ -44,7 +44,7 @@ static void seraz0(double lam, double mult, PJ *P) {
}
-static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
+static PJ_XY lsat_e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
PJ_XY xy = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
int l, nn;
@@ -107,12 +107,11 @@ static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
}
-static PJ_LP e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
+static PJ_LP lsat_e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
PJ_LP lp = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
int nn;
double lamt, sdsq, s, lamdp, phidp, sppsq, dd, sd, sl, fac, scl, sav, spp;
-
lamdp = xy.x / Q->b;
nn = 50;
do {
@@ -135,10 +134,14 @@ static PJ_LP e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
lamdp -= TOL;
spp = sin(phidp);
sppsq = spp * spp;
+ const double denom = 1. - sppsq * (1. + Q->u);
+ if( denom == 0.0 ) {
+ proj_errno_set(P, PJD_ERR_INVALID_X_OR_Y);
+ return proj_coord_error().lp;
+ }
lamt = atan(((1. - sppsq * P->rone_es) * tan(lamdp) *
Q->ca - spp * Q->sa * sqrt((1. + Q->q * dd) * (
- 1. - sppsq) - sppsq * Q->u) / cos(lamdp)) / (1. - sppsq
- * (1. + Q->u)));
+ 1. - sppsq) - sppsq * Q->u) / cos(lamdp)) / denom);
sl = lamt >= 0. ? 1. : -1.;
scl = cos(lamdp) >= 0. ? 1. : -1;
lamt -= M_HALFPI * (1. - scl) * sl;
@@ -205,8 +208,8 @@ PJ *PROJECTION(lsat) {
Q->c1 /= 15.;
Q->c3 /= 45.;
- P->inv = e_inverse;
- P->fwd = e_forward;
+ P->inv = lsat_e_inverse;
+ P->fwd = lsat_e_forward;
return P;
}
diff --git a/src/projections/mbt_fps.cpp b/src/projections/mbt_fps.cpp
index beff3314..9ce2aa36 100644
--- a/src/projections/mbt_fps.cpp
+++ b/src/projections/mbt_fps.cpp
@@ -16,7 +16,7 @@ PROJ_HEAD(mbt_fps, "McBryde-Thomas Flat-Pole Sine (No. 2)") "\n\tCyl, Sph";
#define C_y 1.44492
#define C1_2 0.33333333333333333333333333
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY mbt_fps_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
double k, V, t;
int i;
@@ -37,7 +37,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP mbt_fps_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
double t;
@@ -51,8 +51,8 @@ static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ *PROJECTION(mbt_fps) {
P->es = 0;
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = mbt_fps_s_inverse;
+ P->fwd = mbt_fps_s_forward;
return P;
}
diff --git a/src/projections/mbtfpp.cpp b/src/projections/mbtfpp.cpp
index ebd860ee..a4ab60b9 100644
--- a/src/projections/mbtfpp.cpp
+++ b/src/projections/mbtfpp.cpp
@@ -15,7 +15,7 @@ PROJ_HEAD(mbtfpp, "McBride-Thomas Flat-Polar Parabolic") "\n\tCyl, Sph";
#define ONEEPS 1.0000001
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY mbtfpp_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
(void) P;
@@ -26,7 +26,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP mbtfpp_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
lp.phi = xy.y / FYC;
@@ -58,8 +58,8 @@ static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ *PROJECTION(mbtfpp) {
P->es = 0.;
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = mbtfpp_s_inverse;
+ P->fwd = mbtfpp_s_forward;
return P;
}
diff --git a/src/projections/mbtfpq.cpp b/src/projections/mbtfpq.cpp
index ec49f9ce..9a419790 100644
--- a/src/projections/mbtfpq.cpp
+++ b/src/projections/mbtfpq.cpp
@@ -18,7 +18,7 @@ PROJ_HEAD(mbtfpq, "McBryde-Thomas Flat-Polar Quartic") "\n\tCyl, Sph";
#define RXC 3.20041258076506210122
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY mbtfpq_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
double th1, c;
int i;
@@ -36,7 +36,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP mbtfpq_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
double t;
@@ -67,8 +67,8 @@ static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ *PROJECTION(mbtfpq) {
P->es = 0.;
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = mbtfpq_s_inverse;
+ P->fwd = mbtfpq_s_forward;
return P;
}
diff --git a/src/projections/merc.cpp b/src/projections/merc.cpp
index 5b65de90..10b8bb90 100644
--- a/src/projections/merc.cpp
+++ b/src/projections/merc.cpp
@@ -3,10 +3,9 @@
#include <float.h>
#include <math.h>
-#include "proj_internal.h"
#include "proj.h"
-#include "proj_math.h"
#include "proj_internal.h"
+#include "proj_math.h"
PROJ_HEAD(merc, "Mercator") "\n\tCyl, Sph&Ell\n\tlat_ts=";
PROJ_HEAD(webmerc, "Web Mercator / Pseudo Mercator") "\n\tCyl, Ell\n\t";
@@ -20,7 +19,7 @@ static double logtanpfpim1(double x) { /* log(tan(x/2 + M_FORTPI)) */
return log(tan(M_FORTPI + .5 * x));
}
-static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
+static PJ_XY merc_e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
PJ_XY xy = {0.0,0.0};
if (fabs(fabs(lp.phi) - M_HALFPI) <= EPS10) {
proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION);
@@ -32,7 +31,7 @@ static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
}
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY merc_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
if (fabs(fabs(lp.phi) - M_HALFPI) <= EPS10) {
proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION);
@@ -44,7 +43,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
+static PJ_LP merc_e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
PJ_LP lp = {0.0,0.0};
if ((lp.phi = pj_phi2(P->ctx, exp(- xy.y / P->k0), P->e)) == HUGE_VAL) {
proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION);
@@ -55,7 +54,7 @@ static PJ_LP e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP merc_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
lp.phi = atan(sinh(xy.y / P->k0));
lp.lam = xy.x / P->k0;
@@ -76,15 +75,15 @@ PJ *PROJECTION(merc) {
if (P->es != 0.0) { /* ellipsoid */
if (is_phits)
P->k0 = pj_msfn(sin(phits), cos(phits), P->es);
- P->inv = e_inverse;
- P->fwd = e_forward;
+ P->inv = merc_e_inverse;
+ P->fwd = merc_e_forward;
}
else { /* sphere */
if (is_phits)
P->k0 = cos(phits);
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = merc_s_inverse;
+ P->fwd = merc_s_forward;
}
return P;
@@ -95,7 +94,7 @@ PJ *PROJECTION(webmerc) {
/* Overriding k_0 with fixed parameter */
P->k0 = 1.0;
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = merc_s_inverse;
+ P->fwd = merc_s_forward;
return P;
}
diff --git a/src/projections/mill.cpp b/src/projections/mill.cpp
index 5d4acd89..e6a97057 100644
--- a/src/projections/mill.cpp
+++ b/src/projections/mill.cpp
@@ -7,7 +7,7 @@
PROJ_HEAD(mill, "Miller Cylindrical") "\n\tCyl, Sph";
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY mill_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
(void) P;
@@ -18,7 +18,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP mill_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
(void) P;
@@ -31,8 +31,8 @@ static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ *PROJECTION(mill) {
P->es = 0.;
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = mill_s_inverse;
+ P->fwd = mill_s_forward;
return P;
}
diff --git a/src/projections/misrsom.cpp b/src/projections/misrsom.cpp
index c53f22a1..09e2d8f3 100644
--- a/src/projections/misrsom.cpp
+++ b/src/projections/misrsom.cpp
@@ -62,7 +62,7 @@ static void seraz0(double lam, double mult, PJ *P) {
}
-static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
+static PJ_XY misrsom_e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
PJ_XY xy = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
int l, nn;
@@ -123,7 +123,7 @@ static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
}
-static PJ_LP e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
+static PJ_LP misrsom_e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
PJ_LP lp = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
int nn;
@@ -151,10 +151,14 @@ static PJ_LP e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
lamdp -= TOL;
spp = sin(phidp);
sppsq = spp * spp;
+ const double denom = 1. - sppsq * (1. + Q->u);
+ if( denom == 0.0 ) {
+ proj_errno_set(P, PJD_ERR_NON_CONVERGENT);
+ return proj_coord_error().lp;
+ }
lamt = atan(((1. - sppsq * P->rone_es) * tan(lamdp) *
Q->ca - spp * Q->sa * sqrt((1. + Q->q * dd) * (
- 1. - sppsq) - sppsq * Q->u) / cos(lamdp)) / (1. - sppsq
- * (1. + Q->u)));
+ 1. - sppsq) - sppsq * Q->u) / cos(lamdp)) / denom);
sl = lamt >= 0. ? 1. : -1.;
scl = cos(lamdp) >= 0. ? 1. : -1;
lamt -= M_HALFPI * (1. - scl) * sl;
@@ -212,8 +216,8 @@ PJ *PROJECTION(misrsom) {
Q->c1 /= 15.;
Q->c3 /= 45.;
- P->inv = e_inverse;
- P->fwd = e_forward;
+ P->inv = misrsom_e_inverse;
+ P->fwd = misrsom_e_forward;
return P;
}
diff --git a/src/projections/mod_ster.cpp b/src/projections/mod_ster.cpp
index 83390178..8e02ea72 100644
--- a/src/projections/mod_ster.cpp
+++ b/src/projections/mod_ster.cpp
@@ -22,7 +22,7 @@ struct pj_opaque {
} // anonymous namespace
-static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
+static PJ_XY mod_ster_e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
PJ_XY xy = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double sinlon, coslon, esphi, chi, schi, cchi, s;
@@ -35,7 +35,12 @@ static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
pow((1. - esphi) / (1. + esphi), P->e * .5)) - M_HALFPI;
schi = sin(chi);
cchi = cos(chi);
- s = 2. / (1. + Q->schio * schi + Q->cchio * cchi * coslon);
+ const double denom = 1. + Q->schio * schi + Q->cchio * cchi * coslon;
+ if( denom == 0 ) {
+ proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION);
+ return xy;
+ }
+ s = 2. / denom;
p.r = s * cchi * sinlon;
p.i = s * (Q->cchio * schi - Q->schio * cchi * coslon);
p = pj_zpoly1(p, Q->zcoeff, Q->n);
@@ -46,7 +51,7 @@ static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
}
-static PJ_LP e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
+static PJ_LP mod_ster_e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
PJ_LP lp = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
int nn;
@@ -72,7 +77,6 @@ static PJ_LP e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
z = 2. * atan(.5 * rh);
sinz = sin(z);
cosz = cos(z);
- lp.lam = P->lam0;
if (fabs(rh) <= EPSLN) {
/* if we end up here input coordinates were (0,0).
* pj_inv() adds P->lam0 to lp.lam, this way we are
@@ -115,8 +119,8 @@ static PJ *setup(PJ *P) { /* general initialization */
chio = P->phi0;
Q->schio = sin(chio);
Q->cchio = cos(chio);
- P->inv = e_inverse;
- P->fwd = e_forward;
+ P->inv = mod_ster_e_inverse;
+ P->fwd = mod_ster_e_forward;
return P;
}
diff --git a/src/projections/moll.cpp b/src/projections/moll.cpp
index 03393b01..d511c6e0 100644
--- a/src/projections/moll.cpp
+++ b/src/projections/moll.cpp
@@ -20,7 +20,7 @@ struct pj_opaque {
} // anonymous namespace
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY moll_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double k, V;
@@ -43,7 +43,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP moll_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
lp.phi = aasin(P->ctx, xy.y / Q->C_y);
@@ -70,8 +70,8 @@ static PJ * setup(PJ *P, double p) {
Q->C_y = r / sp;
Q->C_p = p2 + sin(p2);
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = moll_s_inverse;
+ P->fwd = moll_s_forward;
return P;
}
@@ -106,8 +106,8 @@ PJ *PROJECTION(wag5) {
Q->C_y = 1.65014;
Q->C_p = 3.00896;
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = moll_s_inverse;
+ P->fwd = moll_s_forward;
return P;
}
diff --git a/src/projections/natearth.cpp b/src/projections/natearth.cpp
index d8e52c37..ff8aef6a 100644
--- a/src/projections/natearth.cpp
+++ b/src/projections/natearth.cpp
@@ -42,7 +42,7 @@ PROJ_HEAD(natearth, "Natural Earth") "\n\tPCyl, Sph";
#define MAX_ITER 100
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY natearth_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
double phi2, phi4;
(void) P;
@@ -55,7 +55,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP natearth_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
double yc, tol, y2, y4, f, fder;
int i;
@@ -94,8 +94,8 @@ static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ *PROJECTION(natearth) {
P->es = 0;
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = natearth_s_inverse;
+ P->fwd = natearth_s_forward;
return P;
}
diff --git a/src/projections/natearth2.cpp b/src/projections/natearth2.cpp
index 9849a723..95d73c36 100644
--- a/src/projections/natearth2.cpp
+++ b/src/projections/natearth2.cpp
@@ -34,7 +34,7 @@ PROJ_HEAD(natearth2, "Natural Earth 2") "\n\tPCyl, Sph";
#define MAX_ITER 100
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY natearth2_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
double phi2, phi4, phi6;
(void) P;
@@ -49,7 +49,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP natearth2_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
double yc, tol, y2, y4, y6, f, fder;
int i;
@@ -91,8 +91,8 @@ static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ *PROJECTION(natearth2) {
P->es = 0;
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = natearth2_s_inverse;
+ P->fwd = natearth2_s_forward;
return P;
}
diff --git a/src/projections/nell.cpp b/src/projections/nell.cpp
index b6e69dd6..63a0eec1 100644
--- a/src/projections/nell.cpp
+++ b/src/projections/nell.cpp
@@ -11,7 +11,7 @@ PROJ_HEAD(nell, "Nell") "\n\tPCyl, Sph";
#define LOOP_TOL 1e-7
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY nell_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
double k, V;
int i;
@@ -33,7 +33,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP nell_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
lp.lam = 2. * xy.x / (1. + cos(xy.y));
lp.phi = aasin(P->ctx,0.5 * (xy.y + sin(xy.y)));
@@ -45,8 +45,8 @@ static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ *PROJECTION(nell) {
P->es = 0;
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = nell_s_inverse;
+ P->fwd = nell_s_forward;
return P;
}
diff --git a/src/projections/nell_h.cpp b/src/projections/nell_h.cpp
index be28b917..63d12391 100644
--- a/src/projections/nell_h.cpp
+++ b/src/projections/nell_h.cpp
@@ -11,7 +11,7 @@ PROJ_HEAD(nell_h, "Nell-Hammer") "\n\tPCyl, Sph";
#define EPS 1e-7
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY nell_h_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
(void) P;
@@ -22,7 +22,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP nell_h_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
double V, c, p;
int i;
@@ -47,8 +47,8 @@ static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ *PROJECTION(nell_h) {
P->es = 0.;
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = nell_h_s_inverse;
+ P->fwd = nell_h_s_forward;
return P;
}
diff --git a/src/projections/nicol.cpp b/src/projections/nicol.cpp
index c4bee261..fb1b93ea 100644
--- a/src/projections/nicol.cpp
+++ b/src/projections/nicol.cpp
@@ -10,7 +10,7 @@ PROJ_HEAD(nicol, "Nicolosi Globular") "\n\tMisc Sph, no inv";
#define EPS 1e-10
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY nicol_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
(void) P;
@@ -49,7 +49,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ *PROJECTION(nicol) {
P->es = 0.;
- P->fwd = s_forward;
+ P->fwd = nicol_s_forward;
return P;
}
diff --git a/src/projections/nsper.cpp b/src/projections/nsper.cpp
index a0bb5686..d641e1b6 100644
--- a/src/projections/nsper.cpp
+++ b/src/projections/nsper.cpp
@@ -38,7 +38,7 @@ PROJ_HEAD(tpers, "Tilted perspective") "\n\tAzi, Sph\n\ttilt= azi= h=";
# define EPS10 1.e-10
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY nsper_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double coslam, cosphi, sinphi;
@@ -93,10 +93,10 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP nsper_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
- double rh, cosz, sinz;
+ double rh;
if (Q->tilt) {
double bm, bq, yt;
@@ -108,16 +108,18 @@ static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
xy.y = bq * Q->cg - bm * Q->sg;
}
rh = hypot(xy.x, xy.y);
- if ((sinz = 1. - rh * rh * Q->pfact) < 0.) {
- proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION);
- return lp;
- }
- sinz = (Q->p - sqrt(sinz)) / (Q->pn1 / rh + rh / Q->pn1);
- cosz = sqrt(1. - sinz * sinz);
if (fabs(rh) <= EPS10) {
lp.lam = 0.;
lp.phi = P->phi0;
} else {
+ double cosz, sinz;
+ sinz = 1. - rh * rh * Q->pfact;
+ if (sinz < 0.) {
+ proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION);
+ return lp;
+ }
+ sinz = (Q->p - sqrt(sinz)) / (Q->pn1 / rh + rh / Q->pn1);
+ cosz = sqrt(1. - sinz * sinz);
switch (Q->mode) {
case OBLIQ:
lp.phi = asin(cosz * Q->sinph0 + xy.y * sinz * Q->cosph0 / rh);
@@ -146,8 +148,7 @@ static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
static PJ *setup(PJ *P) {
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
- if ((Q->height = pj_param(P->ctx, P->params, "dh").f) <= 0.)
- return pj_default_destructor(P, PJD_ERR_H_LESS_THAN_ZERO);
+ Q->height = pj_param(P->ctx, P->params, "dh").f;
if (fabs(fabs(P->phi0) - M_HALFPI) < EPS10)
Q->mode = P->phi0 < 0. ? S_POLE : N_POLE;
@@ -159,12 +160,14 @@ static PJ *setup(PJ *P) {
Q->cosph0 = cos(P->phi0);
}
Q->pn1 = Q->height / P->a; /* normalize by radius */
+ if ( Q->pn1 <= 0 || Q->pn1 > 1e10 )
+ return pj_default_destructor (P, PJD_ERR_INVALID_H);
Q->p = 1. + Q->pn1;
Q->rp = 1. / Q->p;
Q->h = 1. / Q->pn1;
Q->pfact = (Q->p + 1.) * Q->h;
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = nsper_s_inverse;
+ P->fwd = nsper_s_forward;
P->es = 0.;
return P;
diff --git a/src/projections/nzmg.cpp b/src/projections/nzmg.cpp
index 1c2d9fb7..2f1a897e 100644
--- a/src/projections/nzmg.cpp
+++ b/src/projections/nzmg.cpp
@@ -58,7 +58,7 @@ static const double tpsi[] = { .6399175073, -.1358797613, .063294409, -.02526853
#define Ntphi 8
-static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
+static PJ_XY nzmg_e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
PJ_XY xy = {0.0,0.0};
COMPLEX p;
const double *C;
@@ -77,7 +77,7 @@ static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
}
-static PJ_LP e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
+static PJ_LP nzmg_e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
PJ_LP lp = {0.0,0.0};
int nn, i;
COMPLEX p, f, fp, dp;
@@ -116,8 +116,8 @@ PJ *PROJECTION(nzmg) {
P->x0 = 2510000.;
P->y0 = 6023150.;
- P->inv = e_inverse;
- P->fwd = e_forward;
+ P->inv = nzmg_e_inverse;
+ P->fwd = nzmg_e_forward;
return P;
diff --git a/src/projections/ob_tran.cpp b/src/projections/ob_tran.cpp
index 6daae394..f9eaa6f0 100644
--- a/src/projections/ob_tran.cpp
+++ b/src/projections/ob_tran.cpp
@@ -154,6 +154,11 @@ static ARGS ob_tran_target_params (paralist *params) {
if (0!=strncmp (args.argv[i], "o_proj=", 7))
continue;
args.argv[i] += 2;
+ if (strcmp(args.argv[i], "proj=ob_tran") == 0 ) {
+ pj_dealloc (args.argv);
+ args.argc = 0;
+ args.argv = nullptr;
+ }
break;
}
@@ -164,7 +169,6 @@ static ARGS ob_tran_target_params (paralist *params) {
PJ *PROJECTION(ob_tran) {
double phip;
- char *name;
ARGS args;
PJ *R; /* projection to rotate */
@@ -176,15 +180,15 @@ PJ *PROJECTION(ob_tran) {
P->destructor = destructor;
/* get name of projection to be translated */
- if (!(name = pj_param(P->ctx, P->params, "so_proj").s))
+ if (pj_param(P->ctx, P->params, "so_proj").s == nullptr)
return destructor(P, PJD_ERR_NO_ROTATION_PROJ);
- /* avoid endless recursion */
- if( strcmp(name, "ob_tran") == 0 )
- return destructor(P, PJD_ERR_FAILED_TO_FIND_PROJ);
-
/* Create the target projection object to rotate */
args = ob_tran_target_params (P->params);
+ /* avoid endless recursion */
+ if (args.argv == nullptr ) {
+ return destructor(P, PJD_ERR_FAILED_TO_FIND_PROJ);
+ }
R = pj_init_ctx (pj_get_ctx(P), args.argc, args.argv);
pj_dealloc (args.argv);
diff --git a/src/projections/ocea.cpp b/src/projections/ocea.cpp
index 75aa6666..646b8638 100644
--- a/src/projections/ocea.cpp
+++ b/src/projections/ocea.cpp
@@ -15,13 +15,11 @@ struct pj_opaque {
double rtk;
double sinphi;
double cosphi;
- double singam;
- double cosgam;
};
} // anonymous namespace
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY ocea_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double t;
@@ -36,7 +34,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP ocea_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double t, s;
@@ -52,7 +50,7 @@ static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ *PROJECTION(ocea) {
- double phi_0=0.0, phi_1, phi_2, lam_1, lam_2, lonz, alpha;
+ double phi_1, phi_2, lam_1, lam_2, lonz, alpha;
struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
@@ -61,15 +59,21 @@ PJ *PROJECTION(ocea) {
Q->rok = 1. / P->k0;
Q->rtk = P->k0;
+ double lam_p, phi_p;
/*If the keyword "alpha" is found in the sentence then use 1point+1azimuth*/
if ( pj_param(P->ctx, P->params, "talpha").i) {
/*Define Pole of oblique transformation from 1 point & 1 azimuth*/
- alpha = pj_param(P->ctx, P->params, "ralpha").f;
+ // ERO: I've added M_PI so that the alpha is the angle from point 1 to point 2
+ // from the North in a clockwise direction
+ // (to be consistent with omerc behaviour)
+ alpha = M_PI + pj_param(P->ctx, P->params, "ralpha").f;
lonz = pj_param(P->ctx, P->params, "rlonc").f;
/*Equation 9-8 page 80 (http://pubs.usgs.gov/pp/1395/report.pdf)*/
- Q->singam = atan(-cos(alpha)/(-sin(phi_0) * sin(alpha))) + lonz;
+ // Actually slightliy modified to use atan2(), as it is suggested by
+ // Snyder for equation 9-1, but this is not mentionned here
+ lam_p = atan2(-cos(alpha) , -sin(P->phi0) * sin(alpha)) + lonz;
/*Equation 9-7 page 80 (http://pubs.usgs.gov/pp/1395/report.pdf)*/
- Q->sinphi = asin(cos(phi_0) * sin(alpha));
+ phi_p = asin(cos(P->phi0) * sin(alpha));
/*If the keyword "alpha" is NOT found in the sentence then use 2points*/
} else {
/*Define Pole of oblique transformation from 2 points*/
@@ -78,25 +82,32 @@ PJ *PROJECTION(ocea) {
lam_1 = pj_param(P->ctx, P->params, "rlon_1").f;
lam_2 = pj_param(P->ctx, P->params, "rlon_2").f;
/*Equation 9-1 page 80 (http://pubs.usgs.gov/pp/1395/report.pdf)*/
- Q->singam = atan2(cos(phi_1) * sin(phi_2) * cos(lam_1) -
+ lam_p = atan2(cos(phi_1) * sin(phi_2) * cos(lam_1) -
sin(phi_1) * cos(phi_2) * cos(lam_2),
sin(phi_1) * cos(phi_2) * sin(lam_2) -
cos(phi_1) * sin(phi_2) * sin(lam_1) );
/* take care of P->lam0 wrap-around when +lam_1=-90*/
if (lam_1 == -M_HALFPI)
- Q->singam = -Q->singam;
+ lam_p = -lam_p;
/*Equation 9-2 page 80 (http://pubs.usgs.gov/pp/1395/report.pdf)*/
- Q->sinphi = atan(-cos(Q->singam - lam_1) / tan(phi_1));
+ double cos_lamp_m_minus_lam_1 = cos(lam_p - lam_1);
+ double tan_phi_1 = tan(phi_1);
+ if( tan_phi_1 == 0.0 ) {
+ // Not sure if we want to support this case, but at least this avoids
+ // a division by zero, and gives the same result as the below atan()
+ phi_p = (cos_lamp_m_minus_lam_1 >= 0.0 ) ? -M_HALFPI : M_HALFPI;
+ }
+ else {
+ phi_p = atan(- cos_lamp_m_minus_lam_1 / tan_phi_1);
+ }
}
- P->lam0 = Q->singam + M_HALFPI;
- Q->cosphi = cos(Q->sinphi);
- Q->sinphi = sin(Q->sinphi);
- Q->cosgam = cos(Q->singam);
- Q->singam = sin(Q->singam);
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->lam0 = lam_p + M_HALFPI;
+ Q->cosphi = cos(phi_p);
+ Q->sinphi = sin(phi_p);
+ P->inv = ocea_s_inverse;
+ P->fwd = ocea_s_forward;
P->es = 0.;
return P;
diff --git a/src/projections/oea.cpp b/src/projections/oea.cpp
index f2fc1053..ac0f643f 100644
--- a/src/projections/oea.cpp
+++ b/src/projections/oea.cpp
@@ -16,7 +16,7 @@ struct pj_opaque {
} // anonymous namespace
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY oea_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double Az, M, N, cp, sp, cl, shz;
@@ -35,7 +35,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP oea_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double N, M, xp, yp, z, Az, cz, sz, cAz;
@@ -77,8 +77,8 @@ PJ *PROJECTION(oea) {
Q->two_r_m = 2. * Q->rm;
Q->hm = 0.5 * Q->m;
Q->hn = 0.5 * Q->n;
- P->fwd = s_forward;
- P->inv = s_inverse;
+ P->fwd = oea_s_forward;
+ P->inv = oea_s_inverse;
P->es = 0.;
}
diff --git a/src/projections/omerc.cpp b/src/projections/omerc.cpp
index e9b7b4a0..954023df 100644
--- a/src/projections/omerc.cpp
+++ b/src/projections/omerc.cpp
@@ -45,7 +45,7 @@ struct pj_opaque {
#define EPS 1.e-10
-static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
+static PJ_XY omerc_e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
PJ_XY xy = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double S, T, U, V, W, temp, u, v;
@@ -84,7 +84,7 @@ static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
}
-static PJ_LP e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
+static PJ_LP omerc_e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
PJ_LP lp = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double u, v, Qp, Sp, Tp, Vp, Up;
@@ -97,6 +97,10 @@ static PJ_LP e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
u = xy.y * Q->cosrot + xy.x * Q->sinrot + Q->u_0;
}
Qp = exp(- Q->BrA * v);
+ if( Qp == 0 ) {
+ proj_errno_set(P, PJD_ERR_INVALID_X_OR_Y);
+ return proj_coord_error().lp;
+ }
Sp = .5 * (Qp - 1. / Qp);
Tp = .5 * (Qp + 1. / Qp);
Vp = sin(Q->BrA * u);
@@ -150,6 +154,8 @@ PJ *PROJECTION(omerc) {
phi1 = pj_param(P->ctx, P->params, "rlat_1").f;
lam2 = pj_param(P->ctx, P->params, "rlon_2").f;
phi2 = pj_param(P->ctx, P->params, "rlat_2").f;
+ if (fabs(phi1) > M_HALFPI || fabs(phi2) > M_HALFPI)
+ return pj_default_destructor(P, PJD_ERR_LAT_LARGER_THAN_90);
if (fabs(phi1 - phi2) <= TOL ||
(con = fabs(phi1)) <= TOL ||
fabs(con - M_HALFPI) <= TOL ||
@@ -187,6 +193,9 @@ PJ *PROJECTION(omerc) {
gamma = alpha_c;
} else
alpha_c = aasin(P->ctx, D*sin(gamma0 = gamma));
+ if( fabs(fabs(P->phi0) - M_HALFPI) <= TOL ) {
+ return pj_default_destructor(P, PJD_ERR_LAT_0_OR_ALPHA_EQ_90);
+ }
P->lam0 = lamc - aasin(P->ctx, .5 * (F - 1. / F) *
tan(gamma0)) / Q->B;
} else {
@@ -194,6 +203,10 @@ PJ *PROJECTION(omerc) {
L = pow(pj_tsfn(phi2, sin(phi2), P->e), Q->B);
F = Q->E / H;
p = (L - H) / (L + H);
+ if( p == 0 ) {
+ // Not quite, but es is very close to 1...
+ return pj_default_destructor(P, PJD_ERR_INVALID_ECCENTRICITY);
+ }
J = Q->E * Q->E;
J = (J - L * H) / (J + L * H);
if ((con = lam1 - lam2) < -M_PI)
@@ -202,8 +215,11 @@ PJ *PROJECTION(omerc) {
lam2 += M_TWOPI;
P->lam0 = adjlon(.5 * (lam1 + lam2) - atan(
J * tan(.5 * Q->B * (lam1 - lam2)) / p) / Q->B);
- gamma0 = atan(2. * sin(Q->B * adjlon(lam1 - P->lam0)) /
- (F - 1. / F));
+ const double denom = F - 1. / F;
+ if( denom == 0 ) {
+ return pj_default_destructor(P, PJD_ERR_INVALID_ECCENTRICITY);
+ }
+ gamma0 = atan(2. * sin(Q->B * adjlon(lam1 - P->lam0)) / denom);
gamma = alpha_c = aasin(P->ctx, D * sin(gamma0));
}
Q->singam = sin(gamma0);
@@ -222,8 +238,8 @@ PJ *PROJECTION(omerc) {
F = 0.5 * gamma0;
Q->v_pole_n = Q->ArB * log(tan(M_FORTPI - F));
Q->v_pole_s = Q->ArB * log(tan(M_FORTPI + F));
- P->inv = e_inverse;
- P->fwd = e_forward;
+ P->inv = omerc_e_inverse;
+ P->fwd = omerc_e_forward;
return P;
}
diff --git a/src/projections/ortho.cpp b/src/projections/ortho.cpp
index d4300bd5..94764756 100644
--- a/src/projections/ortho.cpp
+++ b/src/projections/ortho.cpp
@@ -3,7 +3,6 @@
#include "proj.h"
#include "proj_internal.h"
#include "proj_math.h"
-#include "proj_internal.h"
PROJ_HEAD(ortho, "Orthographic") "\n\tAzi, Sph";
@@ -33,7 +32,7 @@ static PJ_XY forward_error(PJ *P, PJ_LP lp, PJ_XY xy) {
return xy;
}
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY ortho_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy;
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double coslam, cosphi, sinphi;
@@ -67,7 +66,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP ortho_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp;
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double rh, cosc, sinc;
@@ -134,8 +133,8 @@ PJ *PROJECTION(ortho) {
Q->cosph0 = cos(P->phi0);
} else
Q->mode = EQUIT;
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = ortho_s_inverse;
+ P->fwd = ortho_s_forward;
P->es = 0.;
return P;
diff --git a/src/projections/patterson.cpp b/src/projections/patterson.cpp
index 7f0ea3a9..16e7b746 100644
--- a/src/projections/patterson.cpp
+++ b/src/projections/patterson.cpp
@@ -61,7 +61,7 @@ PROJ_HEAD(patterson, "Patterson Cylindrical") "\n\tCyl";
#define MAX_ITER 100
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY patterson_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
double phi2;
(void) P;
@@ -74,7 +74,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP patterson_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
double yc, tol, y2, f, fder;
int i;
@@ -111,8 +111,8 @@ static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ *PROJECTION(patterson) {
P->es = 0.;
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = patterson_s_inverse;
+ P->fwd = patterson_s_forward;
return P;
}
diff --git a/src/projections/poly.cpp b/src/projections/poly.cpp
index b4b61b00..08a4aaad 100644
--- a/src/projections/poly.cpp
+++ b/src/projections/poly.cpp
@@ -23,7 +23,7 @@ struct pj_opaque {
#define ITOL 1.e-12
-static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
+static PJ_XY poly_e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
PJ_XY xy = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double ms, sp, cp;
@@ -42,7 +42,7 @@ static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
}
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY poly_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double cot, E;
@@ -60,7 +60,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
+static PJ_LP poly_e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
PJ_LP lp = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
@@ -104,7 +104,7 @@ static PJ_LP e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP poly_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
double B, dphi, tp;
int i;
@@ -159,12 +159,12 @@ PJ *PROJECTION(poly) {
if (!(Q->en = pj_enfn(P->es)))
return pj_default_destructor (P, ENOMEM);
Q->ml0 = pj_mlfn(P->phi0, sin(P->phi0), cos(P->phi0), Q->en);
- P->inv = e_inverse;
- P->fwd = e_forward;
+ P->inv = poly_e_inverse;
+ P->fwd = poly_e_forward;
} else {
Q->ml0 = -P->phi0;
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = poly_s_inverse;
+ P->fwd = poly_s_forward;
}
return P;
diff --git a/src/projections/putp2.cpp b/src/projections/putp2.cpp
index d5b3b9f5..a11e479e 100644
--- a/src/projections/putp2.cpp
+++ b/src/projections/putp2.cpp
@@ -15,7 +15,7 @@ PROJ_HEAD(putp2, "Putnins P2") "\n\tPCyl, Sph";
#define PI_DIV_3 1.0471975511965977
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY putp2_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
double p, c, s, V;
int i;
@@ -41,7 +41,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP putp2_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
double c;
@@ -55,8 +55,8 @@ static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ *PROJECTION(putp2) {
P->es = 0.;
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = putp2_s_inverse;
+ P->fwd = putp2_s_forward;
return P;
}
diff --git a/src/projections/putp3.cpp b/src/projections/putp3.cpp
index bc4a02e4..c2df20e8 100644
--- a/src/projections/putp3.cpp
+++ b/src/projections/putp3.cpp
@@ -17,7 +17,7 @@ PROJ_HEAD(putp3p, "Putnins P3'") "\n\tPCyl, Sph";
#define RPISQ 0.1013211836
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY putp3_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
xy.x = C * lp.lam * (1. - static_cast<struct pj_opaque*>(P->opaque)->A * lp.phi * lp.phi);
@@ -27,7 +27,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP putp3_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
lp.phi = xy.y / C;
@@ -46,8 +46,8 @@ PJ *PROJECTION(putp3) {
Q->A = 4. * RPISQ;
P->es = 0.;
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = putp3_s_inverse;
+ P->fwd = putp3_s_forward;
return P;
}
@@ -61,8 +61,8 @@ PJ *PROJECTION(putp3p) {
Q->A = 2. * RPISQ;
P->es = 0.;
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = putp3_s_inverse;
+ P->fwd = putp3_s_forward;
return P;
}
diff --git a/src/projections/putp4p.cpp b/src/projections/putp4p.cpp
index 462dae81..a5728b74 100644
--- a/src/projections/putp4p.cpp
+++ b/src/projections/putp4p.cpp
@@ -16,7 +16,7 @@ PROJ_HEAD(putp4p, "Putnins P4'") "\n\tPCyl, Sph";
PROJ_HEAD(weren, "Werenskiold I") "\n\tPCyl, Sph";
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY putp4p_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
@@ -29,7 +29,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP putp4p_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
@@ -53,8 +53,8 @@ PJ *PROJECTION(putp4p) {
Q->C_y = 3.883251825;
P->es = 0.;
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = putp4p_s_inverse;
+ P->fwd = putp4p_s_forward;
return P;
}
@@ -70,8 +70,8 @@ PJ *PROJECTION(weren) {
Q->C_y = 4.442882938;
P->es = 0.;
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = putp4p_s_inverse;
+ P->fwd = putp4p_s_forward;
return P;
}
diff --git a/src/projections/putp5.cpp b/src/projections/putp5.cpp
index 62cb2ea9..1847e7a9 100644
--- a/src/projections/putp5.cpp
+++ b/src/projections/putp5.cpp
@@ -19,7 +19,7 @@ PROJ_HEAD(putp5p, "Putnins P5'") "\n\tPCyl, Sph";
#define D 1.2158542
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY putp5_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
@@ -30,7 +30,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP putp5_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
@@ -52,8 +52,8 @@ PJ *PROJECTION(putp5) {
Q->B = 1.;
P->es = 0.;
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = putp5_s_inverse;
+ P->fwd = putp5_s_forward;
return P;
}
@@ -69,8 +69,8 @@ PJ *PROJECTION(putp5p) {
Q->B = 0.5;
P->es = 0.;
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = putp5_s_inverse;
+ P->fwd = putp5_s_forward;
return P;
}
diff --git a/src/projections/putp6.cpp b/src/projections/putp6.cpp
index 4bae7ae6..bcf9ad8e 100644
--- a/src/projections/putp6.cpp
+++ b/src/projections/putp6.cpp
@@ -20,7 +20,7 @@ PROJ_HEAD(putp6p, "Putnins P6'") "\n\tPCyl, Sph";
#define CON_POLE 1.732050807568877
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY putp6_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double p, r, V;
@@ -44,7 +44,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP putp6_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double r;
@@ -71,8 +71,8 @@ PJ *PROJECTION(putp6) {
Q->D = 2.;
P->es = 0.;
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = putp6_s_inverse;
+ P->fwd = putp6_s_forward;
return P;
}
@@ -91,8 +91,8 @@ PJ *PROJECTION(putp6p) {
Q->D = 3.;
P->es = 0.;
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = putp6_s_inverse;
+ P->fwd = putp6_s_forward;
return P;
}
diff --git a/src/projections/qsc.cpp b/src/projections/qsc.cpp
index 409afb38..98e3755e 100644
--- a/src/projections/qsc.cpp
+++ b/src/projections/qsc.cpp
@@ -119,7 +119,7 @@ static double qsc_shift_lon_origin(double lon, double offset) {
}
-static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
+static PJ_XY qsc_e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
PJ_XY xy = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double lat, lon;
@@ -235,7 +235,7 @@ static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
}
-static PJ_LP e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
+static PJ_LP qsc_e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
PJ_LP lp = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double mu, nu, cosmu, tannu;
@@ -382,8 +382,8 @@ PJ *PROJECTION(qsc) {
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
- P->inv = e_inverse;
- P->fwd = e_forward;
+ P->inv = qsc_e_inverse;
+ P->fwd = qsc_e_forward;
/* Determine the cube face from the center of projection. */
if (P->phi0 >= M_HALFPI - M_FORTPI / 2.0) {
Q->face = FACE_TOP;
diff --git a/src/projections/robin.cpp b/src/projections/robin.cpp
index 8f142aad..c08ac0e2 100644
--- a/src/projections/robin.cpp
+++ b/src/projections/robin.cpp
@@ -1,13 +1,12 @@
#define PJ_LIB__
-#include "proj_math.h"
-#include "proj_internal.h"
#include "proj.h"
#include "proj_internal.h"
+#include "proj_math.h"
PROJ_HEAD(robin, "Robinson") "\n\tPCyl, Sph";
#define V(C,z) (C.c0 + z * (C.c1 + z * (C.c2 + z * C.c3)))
-#define DV(C,z) (C.c1 + z * (C.c2 + C.c2 + z * 3. * C.c3))
+#define DV(C,z) (C.c1 + 2 * z * C.c2 + z * z * 3. * C.c3)
/*
note: following terms based upon 5 deg. intervals in degrees.
@@ -74,11 +73,11 @@ static const struct COEFS Y[] = {
#define RC1 0.08726646259971647884
#define NODES 18
#define ONEEPS 1.000001
-#define EPS 1e-8
+#define EPS 1e-10
/* Not sure at all of the appropriate number for MAX_ITER... */
#define MAX_ITER 100
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY robin_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
long i;
double dphi;
@@ -90,7 +89,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION);
return xy;
}
- if (i >= NODES) i = NODES - 1;
+ if (i >= NODES) i = NODES;
dphi = RAD_TO_DEG * (dphi - RC1 * i);
xy.x = V(X[i], dphi) * FXC * lp.lam;
xy.y = V(Y[i], dphi) * FYC;
@@ -100,7 +99,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP robin_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
long i;
double t, t1;
@@ -133,10 +132,8 @@ static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
T = Y[i];
/* first guess, linear interp */
t = 5. * (lp.phi - T.c0)/(Y[i+1].c0 - T.c0);
- /* make into root */
- T.c0 = (float)(T.c0 - lp.phi);
for (iters = MAX_ITER; iters ; --iters) { /* Newton-Raphson */
- t -= t1 = V(T,t) / DV(T,t);
+ t -= t1 = (V(T,t) - lp.phi) / DV(T,t);
if (fabs(t1) < EPS)
break;
}
@@ -152,8 +149,8 @@ static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ *PROJECTION(robin) {
P->es = 0.;
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = robin_s_inverse;
+ P->fwd = robin_s_forward;
return P;
}
diff --git a/src/projections/rouss.cpp b/src/projections/rouss.cpp
index f58277b8..f5a8f12f 100644
--- a/src/projections/rouss.cpp
+++ b/src/projections/rouss.cpp
@@ -44,7 +44,7 @@ struct pj_opaque {
PROJ_HEAD(rouss, "Roussilhe Stereographic") "\n\tAzi, Ell";
-static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
+static PJ_XY rouss_e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
PJ_XY xy = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double s, al, cp, sp, al2, s2;
@@ -65,7 +65,7 @@ static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
}
-static PJ_LP e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
+static PJ_LP rouss_e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
PJ_LP lp = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double s, al, x = xy.x / P->k0, y = xy.y / P->k0, x2, y2;;
@@ -150,8 +150,8 @@ PJ *PROJECTION(rouss) {
Q->D10 = R_R0_4 * t * (29. + t2 * (86. + t2 * 48.))/(96. * N0);
Q->D11 = R_R0_4 * t * (37. + t2 * 44.)/(96. * N0);
- P->fwd = e_forward;
- P->inv = e_inverse;
+ P->fwd = rouss_e_forward;
+ P->inv = rouss_e_inverse;
P->destructor = destructor;
return P;
diff --git a/src/projections/rpoly.cpp b/src/projections/rpoly.cpp
index 6e883ab2..58decf66 100644
--- a/src/projections/rpoly.cpp
+++ b/src/projections/rpoly.cpp
@@ -20,7 +20,7 @@ PROJ_HEAD(rpoly, "Rectangular Polyconic")
#define EPS 1e-9
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY rpoly_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double fa;
@@ -53,7 +53,7 @@ PJ *PROJECTION(rpoly) {
Q->fxa = 0.5 / Q->fxb;
}
P->es = 0.;
- P->fwd = s_forward;
+ P->fwd = rpoly_s_forward;
return P;
}
diff --git a/src/projections/sch.cpp b/src/projections/sch.cpp
index f4c66688..e302c1da 100644
--- a/src/projections/sch.cpp
+++ b/src/projections/sch.cpp
@@ -55,7 +55,7 @@ struct pj_opaque {
PROJ_HEAD(sch, "Spherical Cross-track Height") "\n\tMisc\n\tplat_0= plon_0= phdg_0= [h_0=]";
-static PJ_LPZ inverse3d(PJ_XYZ xyz, PJ *P) {
+static PJ_LPZ sch_inverse3d(PJ_XYZ xyz, PJ *P) {
PJ_LPZ lpz = {0.0, 0.0, 0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double temp[3];
@@ -93,7 +93,7 @@ static PJ_LPZ inverse3d(PJ_XYZ xyz, PJ *P) {
return lpz;
}
-static PJ_XYZ forward3d(PJ_LPZ lpz, PJ *P) {
+static PJ_XYZ sch_forward3d(PJ_LPZ lpz, PJ *P) {
PJ_XYZ xyz = {0.0, 0.0, 0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double temp[3];
@@ -187,8 +187,8 @@ static PJ *setup(PJ *P) { /* general initialization */
Q->xyzoff[1] = pxyz[1] - (Q->rcurv) * clt * slo;
Q->xyzoff[2] = pxyz[2] - (Q->rcurv) * slt;
- P->fwd3d = forward3d;
- P->inv3d = inverse3d;
+ P->fwd3d = sch_forward3d;
+ P->inv3d = sch_inverse3d;
return P;
}
@@ -215,7 +215,7 @@ PJ *PROJECTION(sch) {
return pj_default_destructor(P, PJD_ERR_FAILED_TO_FIND_PROJ);
}
- /* Check if peg latitude is defined */
+ /* Check if peg heading is defined */
if (pj_param(P->ctx, P->params, "tphdg_0").i)
Q->phdg = pj_param(P->ctx, P->params, "rphdg_0").f;
else {
diff --git a/src/projections/sconics.cpp b/src/projections/sconics.cpp
index 7bdd2603..1a16fe24 100644
--- a/src/projections/sconics.cpp
+++ b/src/projections/sconics.cpp
@@ -62,7 +62,7 @@ static int phi12(PJ *P, double *del) {
}
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY sconics_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0, 0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double rho;
@@ -85,7 +85,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, (and ellipsoidal?) inverse */
+static PJ_LP sconics_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, (and ellipsoidal?) inverse */
PJ_LP lp = {0.0, 0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double rho;
@@ -177,8 +177,8 @@ static PJ *setup(PJ *P, enum Type type) {
break;
}
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = sconics_s_inverse;
+ P->fwd = sconics_s_forward;
P->es = 0;
return (P);
}
diff --git a/src/projections/somerc.cpp b/src/projections/somerc.cpp
index ead9090f..be1f660d 100644
--- a/src/projections/somerc.cpp
+++ b/src/projections/somerc.cpp
@@ -18,7 +18,7 @@ struct pj_opaque {
#define NITER 6
-static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
+static PJ_XY somerc_e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
PJ_XY xy = {0.0, 0.0};
double phip, lamp, phipp, lampp, sp, cp;
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
@@ -37,7 +37,7 @@ static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
}
-static PJ_LP e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
+static PJ_LP somerc_e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
PJ_LP lp = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double phip, lamp, phipp, lampp, cp, esp, con, delp;
@@ -88,7 +88,7 @@ PJ *PROJECTION(somerc) {
log (tan (M_FORTPI + 0.5 * P->phi0)) - Q->hlf_e *
log ((1. + sp) / (1. - sp)));
Q->kR = P->k0 * sqrt(P->one_es) / (1. - sp * sp);
- P->inv = e_inverse;
- P->fwd = e_forward;
+ P->inv = somerc_e_inverse;
+ P->fwd = somerc_e_forward;
return P;
}
diff --git a/src/projections/stere.cpp b/src/projections/stere.cpp
index 9b24a596..683d484c 100644
--- a/src/projections/stere.cpp
+++ b/src/projections/stere.cpp
@@ -41,7 +41,7 @@ static double ssfn_ (double phit, double sinphi, double eccen) {
}
-static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
+static PJ_XY stere_e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
PJ_XY xy = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double coslam, sinlam, sinX = 0.0, cosX = 0.0, X, A = 0.0, sinphi;
@@ -55,11 +55,18 @@ static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
}
switch (Q->mode) {
- case OBLIQ:
- A = Q->akm1 / (Q->cosX1 * (1. + Q->sinX1 * sinX +
- Q->cosX1 * cosX * coslam));
+ case OBLIQ: {
+ const double denom = Q->cosX1 * (1. + Q->sinX1 * sinX +
+ Q->cosX1 * cosX * coslam);
+ if( denom == 0 ) {
+ proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION);
+ return proj_coord_error().xy;
+ }
+ A = Q->akm1 / denom;
xy.y = A * (Q->cosX1 * sinX - Q->sinX1 * cosX * coslam);
- goto xmul; /* but why not just xy.x = A * cosX; break; ? */
+ xy.x = A * cosX;
+ break;
+ }
case EQUIT:
/* avoid zero division */
@@ -69,7 +76,6 @@ static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
A = Q->akm1 / (1. + cosX * coslam);
xy.y = A * sinX;
}
-xmul:
xy.x = A * cosX;
break;
@@ -89,7 +95,7 @@ xmul:
}
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY stere_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double sinphi, cosphi, coslam, sinlam;
@@ -131,7 +137,7 @@ oblcon:
}
-static PJ_LP e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
+static PJ_LP stere_e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
PJ_LP lp = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double cosphi, sinphi, tp=0.0, phi_l=0.0, rho, halfe=0.0, halfpi=0.0;
@@ -165,7 +171,7 @@ static PJ_LP e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
break;
}
- for (i = NITER; i--; phi_l = lp.phi) {
+ for (i = NITER; i--; ) {
sinphi = P->e * sin(phi_l);
lp.phi = 2. * atan (tp * pow ((1.+sinphi)/(1.-sinphi), halfe)) - halfpi;
if (fabs (phi_l - lp.phi) < CONV) {
@@ -174,6 +180,7 @@ static PJ_LP e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
lp.lam = (xy.x == 0. && xy.y == 0.) ? 0. : atan2 (xy.x, xy.y);
return lp;
}
+ phi_l = lp.phi;
}
proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION);
@@ -181,7 +188,7 @@ static PJ_LP e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP stere_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double c, rh, sinc, cosc;
@@ -258,8 +265,8 @@ static PJ *setup(PJ *P) { /* general initialization */
Q->cosX1 = cos (X);
break;
}
- P->inv = e_inverse;
- P->fwd = e_forward;
+ P->inv = stere_e_inverse;
+ P->fwd = stere_e_forward;
} else {
switch (Q->mode) {
case OBLIQ:
@@ -277,8 +284,8 @@ static PJ *setup(PJ *P) { /* general initialization */
break;
}
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = stere_s_inverse;
+ P->fwd = stere_s_forward;
}
return P;
}
diff --git a/src/projections/sterea.cpp b/src/projections/sterea.cpp
index b6ebc7b4..ca3bfd06 100644
--- a/src/projections/sterea.cpp
+++ b/src/projections/sterea.cpp
@@ -44,7 +44,7 @@ PROJ_HEAD(sterea, "Oblique Stereographic Alternative") "\n\tAzimuthal, Sph&Ell";
-static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
+static PJ_XY sterea_e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
PJ_XY xy = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double cosc, sinc, cosl, k;
@@ -53,14 +53,19 @@ static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
sinc = sin(lp.phi);
cosc = cos(lp.phi);
cosl = cos(lp.lam);
- k = P->k0 * Q->R2 / (1. + Q->sinc0 * sinc + Q->cosc0 * cosc * cosl);
+ const double denom = 1. + Q->sinc0 * sinc + Q->cosc0 * cosc * cosl;
+ if( denom == 0.0 ) {
+ proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION);
+ return proj_coord_error().xy;
+ }
+ k = P->k0 * Q->R2 / denom;
xy.x = k * cosc * sin(lp.lam);
xy.y = k * (Q->cosc0 * sinc - Q->sinc0 * cosc * cosl);
return xy;
}
-static PJ_LP e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
+static PJ_LP sterea_e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
PJ_LP lp = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double rho, c, sinc, cosc;
@@ -109,8 +114,8 @@ PJ *PROJECTION(sterea) {
Q->cosc0 = cos (Q->phic0);
Q->R2 = 2. * R;
- P->inv = e_inverse;
- P->fwd = e_forward;
+ P->inv = sterea_e_inverse;
+ P->fwd = sterea_e_forward;
P->destructor = destructor;
return P;
diff --git a/src/projections/sts.cpp b/src/projections/sts.cpp
index 27dc3eb8..4d682a53 100644
--- a/src/projections/sts.cpp
+++ b/src/projections/sts.cpp
@@ -20,7 +20,7 @@ struct pj_opaque {
} // anonymous namespace
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY sts_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double c;
@@ -40,7 +40,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP sts_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double c;
@@ -59,8 +59,8 @@ static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
static PJ *setup(PJ *P, double p, double q, int mode) {
P->es = 0.;
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = sts_s_inverse;
+ P->fwd = sts_s_forward;
static_cast<struct pj_opaque*>(P->opaque)->C_x = q / p;
static_cast<struct pj_opaque*>(P->opaque)->C_y = p;
static_cast<struct pj_opaque*>(P->opaque)->C_p = 1/ q;
diff --git a/src/projections/tcc.cpp b/src/projections/tcc.cpp
index cfac9974..3dd47940 100644
--- a/src/projections/tcc.cpp
+++ b/src/projections/tcc.cpp
@@ -10,7 +10,7 @@ PROJ_HEAD(tcc, "Transverse Central Cylindrical") "\n\tCyl, Sph, no inv";
#define EPS10 1.e-10
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY tcc_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0, 0.0};
double b, bt;
@@ -27,7 +27,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ *PROJECTION(tcc) {
P->es = 0.;
- P->fwd = s_forward;
+ P->fwd = tcc_s_forward;
P->inv = nullptr;
return P;
diff --git a/src/projections/tcea.cpp b/src/projections/tcea.cpp
index d780718d..a3c771ff 100644
--- a/src/projections/tcea.cpp
+++ b/src/projections/tcea.cpp
@@ -8,7 +8,7 @@
PROJ_HEAD(tcea, "Transverse Cylindrical Equal Area") "\n\tCyl, Sph";
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY tcea_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
xy.x = cos (lp.phi) * sin (lp.lam) / P->k0;
xy.y = P->k0 * (atan2 (tan (lp.phi), cos (lp.lam)) - P->phi0);
@@ -16,7 +16,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP tcea_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0, 0.0};
double t;
@@ -30,8 +30,8 @@ static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ *PROJECTION(tcea) {
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = tcea_s_inverse;
+ P->fwd = tcea_s_forward;
P->es = 0.;
return P;
}
diff --git a/src/projections/times.cpp b/src/projections/times.cpp
index 4a0d0f59..21c6c19a 100644
--- a/src/projections/times.cpp
+++ b/src/projections/times.cpp
@@ -38,7 +38,7 @@
PROJ_HEAD(times, "Times") "\n\tCyl, Sph";
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY times_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
double T, S, S2;
PJ_XY xy = {0.0,0.0};
(void) P;
@@ -54,7 +54,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP times_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
double T, S, S2;
PJ_LP lp = {0.0,0.0};
(void) P;
@@ -73,8 +73,8 @@ static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ *PROJECTION(times) {
P->es = 0.0;
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = times_s_inverse;
+ P->fwd = times_s_forward;
return P;
}
diff --git a/src/projections/tmerc.cpp b/src/projections/tmerc.cpp
index c91c5174..bb56f8ae 100644
--- a/src/projections/tmerc.cpp
+++ b/src/projections/tmerc.cpp
@@ -188,6 +188,10 @@ static PJ_LP approx_s_inv (PJ_XY xy, PJ *P) {
double h, g;
h = exp(xy.x / static_cast<struct pj_opaque_approx*>(P->opaque)->esp);
+ if( h == 0 ) {
+ proj_errno_set(P, PJD_ERR_INVALID_X_OR_Y);
+ return proj_coord_error().lp;
+ }
g = .5 * (h - 1. / h);
h = cos (P->phi0 + xy.y / static_cast<struct pj_opaque_approx*>(P->opaque)->esp);
lp.phi = asin(sqrt((1. - h * h) / (1. + g * g)));
diff --git a/src/projections/tobmerc.cpp b/src/projections/tobmerc.cpp
index 95960097..7215f0db 100644
--- a/src/projections/tobmerc.cpp
+++ b/src/projections/tobmerc.cpp
@@ -3,10 +3,9 @@
#include <float.h>
#include <math.h>
-#include "proj_internal.h"
#include "proj.h"
-#include "proj_math.h"
#include "proj_internal.h"
+#include "proj_math.h"
PROJ_HEAD(tobmerc, "Tobler-Mercator") "\n\tCyl, Sph";
@@ -19,7 +18,7 @@ static double logtanpfpim1(double x) { /* log(tan(x/2 + M_FORTPI)) */
return log(tan(M_FORTPI + .5 * x));
}
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY tobmerc_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0, 0.0};
double cosphi;
@@ -34,7 +33,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
return xy;
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP tobmerc_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0, 0.0};
double cosphi;
@@ -45,7 +44,7 @@ static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
}
PJ *PROJECTION(tobmerc) {
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = tobmerc_s_inverse;
+ P->fwd = tobmerc_s_forward;
return P;
}
diff --git a/src/projections/tpeqd.cpp b/src/projections/tpeqd.cpp
index 20921de4..b306968c 100644
--- a/src/projections/tpeqd.cpp
+++ b/src/projections/tpeqd.cpp
@@ -16,7 +16,7 @@ struct pj_opaque {
} // anonymous namespace
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY tpeqd_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0, 0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double t, z1, z2, dl1, dl2, sp, cp;
@@ -37,7 +37,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP tpeqd_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double cz1, cz2, s, d, cp, sp;
@@ -87,6 +87,10 @@ PJ *PROJECTION(tpeqd) {
Q->sc = Q->sp1 * Q->cp2;
Q->ccs = Q->cp1 * Q->cp2 * sin(Q->dlam2);
Q->z02 = aacos(P->ctx, Q->sp1 * Q->sp2 + Q->cp1 * Q->cp2 * cos (Q->dlam2));
+ if( Q->z02 == 0.0 ) {
+ // Actually happens when both lat_1 = lat_2 and |lat_1| = 90
+ return pj_default_destructor(P, PJD_ERR_LAT_1_OR_2_ZERO_OR_90);
+ }
Q->hz0 = .5 * Q->z02;
A12 = atan2(Q->cp2 * sin (Q->dlam2),
Q->cp1 * Q->sp2 - Q->sp1 * Q->cp2 * cos (Q->dlam2));
@@ -100,8 +104,8 @@ PJ *PROJECTION(tpeqd) {
Q->r2z0 = 0.5 / Q->z02;
Q->z02 *= Q->z02;
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = tpeqd_s_inverse;
+ P->fwd = tpeqd_s_forward;
P->es = 0.;
return P;
diff --git a/src/projections/urm5.cpp b/src/projections/urm5.cpp
index a93293c0..499644d2 100644
--- a/src/projections/urm5.cpp
+++ b/src/projections/urm5.cpp
@@ -15,7 +15,7 @@ struct pj_opaque {
} // anonymous namespace
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY urm5_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0, 0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double t;
@@ -45,12 +45,16 @@ PJ *PROJECTION(urm5) {
Q->q3 = pj_param(P->ctx, P->params, "dq").f / 3.;
alpha = pj_param(P->ctx, P->params, "ralpha").f;
t = Q->n * sin (alpha);
- Q->m = cos (alpha) / sqrt (1. - t * t);
+ const double denom = sqrt (1. - t * t);
+ if( denom == 0 ) {
+ return pj_default_destructor(P, PJD_ERR_LAT_0_OR_ALPHA_EQ_90);
+ }
+ Q->m = cos (alpha) / denom;
Q->rmn = 1. / (Q->m * Q->n);
P->es = 0.;
P->inv = nullptr;
- P->fwd = s_forward;
+ P->fwd = urm5_s_forward;
return P;
}
diff --git a/src/projections/urmfps.cpp b/src/projections/urmfps.cpp
index 3a51798b..3f9fdf23 100644
--- a/src/projections/urmfps.cpp
+++ b/src/projections/urmfps.cpp
@@ -19,7 +19,7 @@ struct pj_opaque {
#define Cy 1.139753528477
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY urmfps_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0, 0.0};
lp.phi = aasin (P->ctx,static_cast<struct pj_opaque*>(P->opaque)->n * sin (lp.phi));
xy.x = C_x * lp.lam * cos (lp.phi);
@@ -28,7 +28,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP urmfps_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0, 0.0};
xy.y /= static_cast<struct pj_opaque*>(P->opaque)->C_y;
lp.phi = aasin(P->ctx, sin (xy.y) / static_cast<struct pj_opaque*>(P->opaque)->n);
@@ -40,8 +40,8 @@ static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
static PJ *setup(PJ *P) {
static_cast<struct pj_opaque*>(P->opaque)->C_y = Cy / static_cast<struct pj_opaque*>(P->opaque)->n;
P->es = 0.;
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = urmfps_s_inverse;
+ P->fwd = urmfps_s_forward;
return P;
}
diff --git a/src/projections/vandg.cpp b/src/projections/vandg.cpp
index 89620356..7d485aff 100644
--- a/src/projections/vandg.cpp
+++ b/src/projections/vandg.cpp
@@ -13,7 +13,7 @@ PROJ_HEAD(vandg, "van der Grinten (I)") "\n\tMisc Sph";
# define HPISQ 4.93480220054467930934
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY vandg_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
double al, al2, g, g2, p2;
@@ -58,7 +58,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP vandg_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
double t, c0, c1, c2, c3, al, r2, r, m, d, ay, x2, y2;
@@ -80,7 +80,14 @@ static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
al = c1 / c3 - THIRD * c2 * c2;
m = 2. * sqrt(-THIRD * al);
d = C2_27 * c2 * c2 * c2 + (c0 * c0 - THIRD * c2 * c1) / c3;
- if (((t = fabs(d = 3. * d / (al * m))) - TOL) <= 1.) {
+ const double al_mul_m = al * m;
+ if( al_mul_m == 0 ) {
+ proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION);
+ return proj_coord_error().lp;
+ }
+ d = 3. * d /al_mul_m;
+ t = fabs(d);
+ if ((t - TOL) <= 1.) {
d = t > 1. ? (d > 0. ? 0. : M_PI) : acos(d);
lp.phi = M_PI * (m * cos(d * THIRD + PI4_3) - THIRD * c2);
if (xy.y < 0.) lp.phi = -lp.phi;
@@ -98,8 +105,8 @@ static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ *PROJECTION(vandg) {
P->es = 0.;
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = vandg_s_inverse;
+ P->fwd = vandg_s_forward;
return P;
}
diff --git a/src/projections/vandg2.cpp b/src/projections/vandg2.cpp
index de63b085..05314833 100644
--- a/src/projections/vandg2.cpp
+++ b/src/projections/vandg2.cpp
@@ -18,7 +18,7 @@ PROJ_HEAD(vandg3, "van der Grinten III") "\n\tMisc Sph, no inv";
#define TOL 1e-10
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY vandg2_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
double x1, at, bt, ct;
@@ -58,7 +58,7 @@ PJ *PROJECTION(vandg2) {
P->opaque = Q;
Q->vdg3 = 0;
- P->fwd = s_forward;
+ P->fwd = vandg2_s_forward;
return P;
}
@@ -71,7 +71,7 @@ PJ *PROJECTION(vandg3) {
Q->vdg3 = 1;
P->es = 0.;
- P->fwd = s_forward;
+ P->fwd = vandg2_s_forward;
return P;
}
diff --git a/src/projections/vandg4.cpp b/src/projections/vandg4.cpp
index 8511431d..a5cfd8e6 100644
--- a/src/projections/vandg4.cpp
+++ b/src/projections/vandg4.cpp
@@ -10,7 +10,7 @@ PROJ_HEAD(vandg4, "van der Grinten IV") "\n\tMisc Sph, no inv";
#define TOL 1e-10
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY vandg4_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
double x1, t, bt, ct, ft, bt2, ct2, dt, dt2;
(void) P;
@@ -50,7 +50,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ *PROJECTION(vandg4) {
P->es = 0.;
- P->fwd = s_forward;
+ P->fwd = vandg4_s_forward;
return P;
}
diff --git a/src/projections/wag2.cpp b/src/projections/wag2.cpp
index e04cc648..4e7c28ac 100644
--- a/src/projections/wag2.cpp
+++ b/src/projections/wag2.cpp
@@ -13,7 +13,7 @@ PROJ_HEAD(wag2, "Wagner II") "\n\tPCyl, Sph";
#define C_p2 0.88550
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY wag2_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
lp.phi = aasin (P->ctx,C_p1 * sin (C_p2 * lp.phi));
xy.x = C_x * lp.lam * cos (lp.phi);
@@ -22,7 +22,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP wag2_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
lp.phi = xy.y / C_y;
lp.lam = xy.x / (C_x * cos(lp.phi));
@@ -33,7 +33,7 @@ static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ *PROJECTION(wag2) {
P->es = 0.;
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = wag2_s_inverse;
+ P->fwd = wag2_s_forward;
return P;
}
diff --git a/src/projections/wag3.cpp b/src/projections/wag3.cpp
index ed695ffd..33313cdb 100644
--- a/src/projections/wag3.cpp
+++ b/src/projections/wag3.cpp
@@ -17,7 +17,7 @@ struct pj_opaque {
} // anonymous namespace
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY wag3_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
xy.x = static_cast<struct pj_opaque*>(P->opaque)->C_x * lp.lam * cos(TWOTHIRD * lp.phi);
xy.y = lp.phi;
@@ -25,7 +25,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP wag3_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
lp.phi = xy.y;
lp.lam = xy.x / (static_cast<struct pj_opaque*>(P->opaque)->C_x * cos(TWOTHIRD * lp.phi));
@@ -44,8 +44,8 @@ PJ *PROJECTION(wag3) {
ts = pj_param (P->ctx, P->params, "rlat_ts").f;
static_cast<struct pj_opaque*>(P->opaque)->C_x = cos (ts) / cos (2.*ts/3.);
P->es = 0.;
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = wag3_s_inverse;
+ P->fwd = wag3_s_forward;
return P;
}
diff --git a/src/projections/wag7.cpp b/src/projections/wag7.cpp
index 45b70ee2..3afb5a03 100644
--- a/src/projections/wag7.cpp
+++ b/src/projections/wag7.cpp
@@ -9,7 +9,7 @@ PROJ_HEAD(wag7, "Wagner VII") "\n\tMisc Sph, no inv";
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY wag7_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0, 0.0};
double theta, ct, D;
@@ -24,7 +24,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ *PROJECTION(wag7) {
- P->fwd = s_forward;
+ P->fwd = wag7_s_forward;
P->inv = nullptr;
P->es = 0.;
return P;
diff --git a/src/projections/wink1.cpp b/src/projections/wink1.cpp
index 75abbffc..d097978f 100644
--- a/src/projections/wink1.cpp
+++ b/src/projections/wink1.cpp
@@ -16,7 +16,7 @@ struct pj_opaque {
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY wink1_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
xy.x = .5 * lp.lam * (static_cast<struct pj_opaque*>(P->opaque)->cosphi1 + cos(lp.phi));
xy.y = lp.phi;
@@ -24,7 +24,7 @@ static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
}
-static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
+static PJ_LP wink1_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */
PJ_LP lp = {0.0,0.0};
lp.phi = xy.y;
lp.lam = 2. * xy.x / (static_cast<struct pj_opaque*>(P->opaque)->cosphi1 + cos(lp.phi));
@@ -40,8 +40,8 @@ PJ *PROJECTION(wink1) {
static_cast<struct pj_opaque*>(P->opaque)->cosphi1 = cos (pj_param(P->ctx, P->params, "rlat_ts").f);
P->es = 0.;
- P->inv = s_inverse;
- P->fwd = s_forward;
+ P->inv = wink1_s_inverse;
+ P->fwd = wink1_s_forward;
return P;
}
diff --git a/src/projections/wink2.cpp b/src/projections/wink2.cpp
index 6957bde1..4aaf1972 100644
--- a/src/projections/wink2.cpp
+++ b/src/projections/wink2.cpp
@@ -18,7 +18,7 @@ struct pj_opaque {
#define LOOP_TOL 1e-7
-static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
+static PJ_XY wink2_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0, 0.0};
double k, V;
int i;
@@ -51,7 +51,7 @@ PJ *PROJECTION(wink2) {
static_cast<struct pj_opaque*>(P->opaque)->cosphi1 = cos(pj_param(P->ctx, P->params, "rlat_1").f);
P->es = 0.;
P->inv = nullptr;
- P->fwd = s_forward;
+ P->fwd = wink2_s_forward;
return P;
}
diff --git a/src/release.cpp b/src/release.cpp
index ddc768c6..822ea4a9 100644
--- a/src/release.cpp
+++ b/src/release.cpp
@@ -11,7 +11,7 @@ char const pj_release[] =
STR(PROJ_VERSION_MAJOR)"."
STR(PROJ_VERSION_MINOR)"."
STR(PROJ_VERSION_PATCH)", "
- "March 1st, 2019";
+ "May 15th, 2019";
const char *pj_get_release() {
return pj_release;
diff --git a/src/strerrno.cpp b/src/strerrno.cpp
index 01097a42..9bf5f45a 100644
--- a/src/strerrno.cpp
+++ b/src/strerrno.cpp
@@ -5,6 +5,7 @@
#include <string.h>
#include "proj.h"
+#include "proj_config.h"
#include "proj_internal.h"
static const char * const
@@ -14,7 +15,7 @@ pj_err_list[] = {
"no colon in init= string", /* -3 */
"projection not named", /* -4 */
"unknown projection id", /* -5 */
- "effective eccentricity = 1.", /* -6 */
+ "effective eccentricity < 0 or >= 1.", /* -6 */
"unknown unit conversion id", /* -7 */
"invalid boolean param argument", /* -8 */
"unknown elliptical parameter name", /* -9 */
@@ -30,7 +31,7 @@ pj_err_list[] = {
"acos/asin: |arg| >1.+1e-14", /* -19 */
"tolerance condition error", /* -20 */
"conic lat_1 = -lat_2", /* -21 */
- "lat_1 >= 90", /* -22 */
+ "lat_0, lat_1 or lat_2 >= 90", /* -22 */
"lat_1 = 0", /* -23 */
"lat_ts >= 90", /* -24 */
"no distance between control points", /* -25 */
@@ -38,10 +39,10 @@ pj_err_list[] = {
"W <= 0 or M <= 0", /* -27 */
"lsat not in 1-5 range", /* -28 */
"path not in range", /* -29 */
- "h <= 0", /* -30 */
+ "h <= 0 or h > 1e10 * a", /* -30 */
"k <= 0", /* -31 */
- "lat_0 = 0 or 90 or alpha = 90", /* -32 */
- "lat_1=lat_2 or lat_1=0 or lat_2=90", /* -33 */
+ "lat_1=lat_2 or lat_1=0 or lat_2=90", /* -32 */
+ "lat_0 = 0 or 90 or alpha = 90", /* -33 */
"elliptical usage required", /* -34 */
"invalid UTM zone number", /* -35 */
"", /* no longer used */ /* -36 */
@@ -69,6 +70,7 @@ pj_err_list[] = {
"argument not numerical or out of range", /* -58 */
"inconsistent unit type between input and output", /* -59 */
"arguments are mutually exclusive", /* -60 */
+ "generic error of unknown origin", /* -61 */
/* When adding error messages, remember to update ID defines in
projects.h, and transient_error array in pj_transform */
diff --git a/src/strtod.cpp b/src/strtod.cpp
index 7ab271c5..d45e62db 100644
--- a/src/strtod.cpp
+++ b/src/strtod.cpp
@@ -33,13 +33,8 @@
#include <string.h>
#include "proj.h"
-#include "proj_internal.h"
-
-/* Windows nmake build doesn't have a proj_config.h, but HAVE_LOCALECONV */
-/* is defined in the compilation line */
-#ifndef HAVE_LOCALECONV
#include "proj_config.h"
-#endif
+#include "proj_internal.h"
#define PJ_STRTOD_WORK_BUFFER_SIZE 64
diff --git a/src/transformations/affine.cpp b/src/transformations/affine.cpp
index bda54f1e..28f73b9a 100644
--- a/src/transformations/affine.cpp
+++ b/src/transformations/affine.cpp
@@ -25,7 +25,6 @@
#include <errno.h>
#include <math.h>
-#include "proj_internal.h"
#include "proj.h"
#include "proj_internal.h"
diff --git a/src/transformations/deformation.cpp b/src/transformations/deformation.cpp
index c28e1489..5bb86909 100644
--- a/src/transformations/deformation.cpp
+++ b/src/transformations/deformation.cpp
@@ -56,7 +56,6 @@ grid-values in units of mm/year in ENU-space.
#include "proj.h"
#include "proj_internal.h"
#include "proj_math.h"
-#include "proj_internal.h"
PROJ_HEAD(deformation, "Kinematic grid shift");
@@ -92,7 +91,7 @@ static PJ_XYZ get_grid_shift(PJ* P, PJ_XYZ cartesian) {
/* look up correction values in grids */
shift.lp = proj_hgrid_value(P, geodetic.lp);
- shift.enu.u = proj_vgrid_value(P, geodetic.lp);
+ shift.enu.u = proj_vgrid_value(P, geodetic.lp, 1.0);
if (proj_errno(P) == PJD_ERR_GRID_AREA)
proj_log_debug(P, "deformation: coordinate (%.3f, %.3f) outside deformation model",
diff --git a/src/transformations/helmert.cpp b/src/transformations/helmert.cpp
index 034f76f4..63785ea5 100644
--- a/src/transformations/helmert.cpp
+++ b/src/transformations/helmert.cpp
@@ -53,7 +53,6 @@ Last update: 2018-10-26
#include <math.h>
#include "proj_internal.h"
-#include "proj_internal.h"
#include "geocent.h"
PROJ_HEAD(helmert, "3(6)-, 4(8)- and 7(14)-parameter Helmert shift");
@@ -567,14 +566,14 @@ PJ *TRANSFORMATION(helmert, 0) {
if (pj_param_exists (P->params, "theta")) {
P->left = PJ_IO_UNITS_PROJECTED;
P->right = PJ_IO_UNITS_PROJECTED;
+ P->fwd = helmert_forward;
+ P->inv = helmert_reverse;
}
P->fwd4d = helmert_forward_4d;
P->inv4d = helmert_reverse_4d;
P->fwd3d = helmert_forward_3d;
P->inv3d = helmert_reverse_3d;
- P->fwd = helmert_forward;
- P->inv = helmert_reverse;
Q = (struct pj_opaque_helmert *)P->opaque;
diff --git a/src/transformations/hgridshift.cpp b/src/transformations/hgridshift.cpp
index 2e2294cb..90633939 100644
--- a/src/transformations/hgridshift.cpp
+++ b/src/transformations/hgridshift.cpp
@@ -6,7 +6,6 @@
#include <time.h>
#include "proj_internal.h"
-#include "proj_internal.h"
PROJ_HEAD(hgridshift, "Horizontal grid shift");
diff --git a/src/transformations/horner.cpp b/src/transformations/horner.cpp
index f5d749c4..a6638773 100644
--- a/src/transformations/horner.cpp
+++ b/src/transformations/horner.cpp
@@ -85,7 +85,6 @@
#include "proj.h"
#include "proj_internal.h"
-#include "proj_internal.h"
PROJ_HEAD(horner, "Horner polynomial evaluation");
diff --git a/src/transformations/molodensky.cpp b/src/transformations/molodensky.cpp
index c389fd32..7d17f64c 100644
--- a/src/transformations/molodensky.cpp
+++ b/src/transformations/molodensky.cpp
@@ -49,7 +49,6 @@
#include "proj.h"
#include "proj_internal.h"
-#include "proj_internal.h"
PROJ_HEAD(molodensky, "Molodensky transform");
@@ -140,16 +139,26 @@ static PJ_LPZ calc_standard_params(PJ_LPZ lpz, PJ *P) {
/* ellipsoid radii of curvature */
double rho = RM(a, P->es, lpz.phi);
- double nu = RN(a, P->e2s, lpz.phi);
+ double nu = RN(a, P->es, lpz.phi);
/* delta phi */
dphi = (-dx*sphi*clam) - (dy*sphi*slam) + (dz*cphi)
+ ((nu * P->es * sphi * cphi * da) / a)
+ (sphi*cphi * ( rho/(1-f) + nu*(1-f))*df);
- dphi /= (rho + lpz.z);
+ const double dphi_denom = rho + lpz.z;
+ if( dphi_denom == 0.0 ) {
+ lpz.lam = HUGE_VAL;
+ return lpz;
+ }
+ dphi /= dphi_denom;
/* delta lambda */
- dlam = (-dx*slam + dy*clam) / ((nu+lpz.z)*cphi);
+ const double dlam_denom = (nu+lpz.z)*cphi;
+ if( dlam_denom == 0.0 ) {
+ lpz.lam = HUGE_VAL;
+ return lpz;
+ }
+ dlam = (-dx*slam + dy*clam) / dlam_denom;
/* delta h */
dh = dx*cphi*clam + dy*cphi*slam + dz*sphi - (a/nu)*da + nu*(1-f)*sphi*sphi*df;
@@ -183,7 +192,12 @@ static PJ_LPZ calc_abridged_params(PJ_LPZ lpz, PJ *P) {
/* delta lambda */
dlam = -dx*slam + dy*clam;
- dlam /= RN(P->a, P->e2s, lpz.phi)*cphi;
+ const double dlam_denom = RN(P->a, P->es, lpz.phi)*cphi;
+ if( dlam_denom == 0.0 ) {
+ lpz.lam = HUGE_VAL;
+ return lpz;
+ }
+ dlam /= dlam_denom;
/* delta h */
dh = dx*cphi*clam + dy*cphi*slam + dz*sphi - da + adffda*sphi*sphi;
@@ -230,6 +244,10 @@ static PJ_XYZ forward_3d(PJ_LPZ lpz, PJ *P) {
} else {
lpz = calc_standard_params(lpz, P);
}
+ if( lpz.lam == HUGE_VAL ) {
+ proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION);
+ return proj_coord_error().xyz;
+ }
/* offset coordinate */
point.lpz.phi += lpz.phi;
@@ -258,6 +276,11 @@ static PJ_LPZ reverse_3d(PJ_XYZ xyz, PJ *P) {
else
lpz = calc_standard_params(point.lpz, P);
+ if( lpz.lam == HUGE_VAL ) {
+ proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION);
+ return proj_coord_error().lpz;
+ }
+
/* offset coordinate */
point.lpz.phi -= lpz.phi;
point.lpz.lam -= lpz.lam;
diff --git a/src/transformations/vgridshift.cpp b/src/transformations/vgridshift.cpp
index fda38ec3..de0cdd8c 100644
--- a/src/transformations/vgridshift.cpp
+++ b/src/transformations/vgridshift.cpp
@@ -6,7 +6,6 @@
#include <time.h>
#include "proj_internal.h"
-#include "proj_internal.h"
PROJ_HEAD(vgridshift, "Vertical grid shift");
@@ -26,7 +25,7 @@ static PJ_XYZ forward_3d(PJ_LPZ lpz, PJ *P) {
if (P->vgridlist_geoid != nullptr) {
/* Only try the gridshift if at least one grid is loaded,
* otherwise just pass the coordinate through unchanged. */
- point.xyz.z += Q->forward_multiplier * proj_vgrid_value(P, point.lp);
+ point.xyz.z += proj_vgrid_value(P, point.lp, Q->forward_multiplier);
}
return point.xyz;
@@ -41,7 +40,7 @@ static PJ_LPZ reverse_3d(PJ_XYZ xyz, PJ *P) {
if (P->vgridlist_geoid != nullptr) {
/* Only try the gridshift if at least one grid is loaded,
* otherwise just pass the coordinate through unchanged. */
- point.xyz.z -= Q->forward_multiplier * proj_vgrid_value(P, point.lp);
+ point.xyz.z -= proj_vgrid_value(P, point.lp, Q->forward_multiplier);
}
return point.lpz;
diff --git a/src/wkt2_generated_parser.c b/src/wkt2_generated_parser.c
index f6b1f6b1..b3a9eb24 100644
--- a/src/wkt2_generated_parser.c
+++ b/src/wkt2_generated_parser.c
@@ -211,76 +211,77 @@ extern int pj_wkt2_debug;
T_COORDEPOCH = 330,
T_COORDINATEMETADATA = 331,
T_POINTMOTIONOPERATION = 332,
- T_GEODETICCRS = 333,
- T_GEODETICDATUM = 334,
- T_PROJECTEDCRS = 335,
- T_PRIMEMERIDIAN = 336,
- T_GEOGRAPHICCRS = 337,
- T_TRF = 338,
- T_VERTICALCRS = 339,
- T_VERTICALDATUM = 340,
- T_VRF = 341,
- T_TIMEDATUM = 342,
- T_TEMPORALQUANTITY = 343,
- T_ENGINEERINGDATUM = 344,
- T_ENGINEERINGCRS = 345,
- T_PARAMETRICDATUM = 346,
- T_AFFINE = 347,
- T_CARTESIAN = 348,
- T_CYLINDRICAL = 349,
- T_ELLIPSOIDAL = 350,
- T_LINEAR = 351,
- T_PARAMETRIC = 352,
- T_POLAR = 353,
- T_SPHERICAL = 354,
- T_VERTICAL = 355,
- T_TEMPORAL = 356,
- T_TEMPORALCOUNT = 357,
- T_TEMPORALMEASURE = 358,
- T_ORDINAL = 359,
- T_TEMPORALDATETIME = 360,
- T_NORTH = 361,
- T_NORTHNORTHEAST = 362,
- T_NORTHEAST = 363,
- T_EASTNORTHEAST = 364,
- T_EAST = 365,
- T_EASTSOUTHEAST = 366,
- T_SOUTHEAST = 367,
- T_SOUTHSOUTHEAST = 368,
- T_SOUTH = 369,
- T_SOUTHSOUTHWEST = 370,
- T_SOUTHWEST = 371,
- T_WESTSOUTHWEST = 372,
- T_WEST = 373,
- T_WESTNORTHWEST = 374,
- T_NORTHWEST = 375,
- T_NORTHNORTHWEST = 376,
- T_UP = 377,
- T_DOWN = 378,
- T_GEOCENTRICX = 379,
- T_GEOCENTRICY = 380,
- T_GEOCENTRICZ = 381,
- T_COLUMNPOSITIVE = 382,
- T_COLUMNNEGATIVE = 383,
- T_ROWPOSITIVE = 384,
- T_ROWNEGATIVE = 385,
- T_DISPLAYRIGHT = 386,
- T_DISPLAYLEFT = 387,
- T_DISPLAYUP = 388,
- T_DISPLAYDOWN = 389,
- T_FORWARD = 390,
- T_AFT = 391,
- T_PORT = 392,
- T_STARBOARD = 393,
- T_CLOCKWISE = 394,
- T_COUNTERCLOCKWISE = 395,
- T_TOWARDS = 396,
- T_AWAYFROM = 397,
- T_FUTURE = 398,
- T_PAST = 399,
- T_UNSPECIFIED = 400,
- T_STRING = 401,
- T_UNSIGNED_INTEGER_DIFFERENT_ONE_TWO_THREE = 402
+ T_VERSION = 333,
+ T_GEODETICCRS = 334,
+ T_GEODETICDATUM = 335,
+ T_PROJECTEDCRS = 336,
+ T_PRIMEMERIDIAN = 337,
+ T_GEOGRAPHICCRS = 338,
+ T_TRF = 339,
+ T_VERTICALCRS = 340,
+ T_VERTICALDATUM = 341,
+ T_VRF = 342,
+ T_TIMEDATUM = 343,
+ T_TEMPORALQUANTITY = 344,
+ T_ENGINEERINGDATUM = 345,
+ T_ENGINEERINGCRS = 346,
+ T_PARAMETRICDATUM = 347,
+ T_AFFINE = 348,
+ T_CARTESIAN = 349,
+ T_CYLINDRICAL = 350,
+ T_ELLIPSOIDAL = 351,
+ T_LINEAR = 352,
+ T_PARAMETRIC = 353,
+ T_POLAR = 354,
+ T_SPHERICAL = 355,
+ T_VERTICAL = 356,
+ T_TEMPORAL = 357,
+ T_TEMPORALCOUNT = 358,
+ T_TEMPORALMEASURE = 359,
+ T_ORDINAL = 360,
+ T_TEMPORALDATETIME = 361,
+ T_NORTH = 362,
+ T_NORTHNORTHEAST = 363,
+ T_NORTHEAST = 364,
+ T_EASTNORTHEAST = 365,
+ T_EAST = 366,
+ T_EASTSOUTHEAST = 367,
+ T_SOUTHEAST = 368,
+ T_SOUTHSOUTHEAST = 369,
+ T_SOUTH = 370,
+ T_SOUTHSOUTHWEST = 371,
+ T_SOUTHWEST = 372,
+ T_WESTSOUTHWEST = 373,
+ T_WEST = 374,
+ T_WESTNORTHWEST = 375,
+ T_NORTHWEST = 376,
+ T_NORTHNORTHWEST = 377,
+ T_UP = 378,
+ T_DOWN = 379,
+ T_GEOCENTRICX = 380,
+ T_GEOCENTRICY = 381,
+ T_GEOCENTRICZ = 382,
+ T_COLUMNPOSITIVE = 383,
+ T_COLUMNNEGATIVE = 384,
+ T_ROWPOSITIVE = 385,
+ T_ROWNEGATIVE = 386,
+ T_DISPLAYRIGHT = 387,
+ T_DISPLAYLEFT = 388,
+ T_DISPLAYUP = 389,
+ T_DISPLAYDOWN = 390,
+ T_FORWARD = 391,
+ T_AFT = 392,
+ T_PORT = 393,
+ T_STARBOARD = 394,
+ T_CLOCKWISE = 395,
+ T_COUNTERCLOCKWISE = 396,
+ T_TOWARDS = 397,
+ T_AWAYFROM = 398,
+ T_FUTURE = 399,
+ T_PAST = 400,
+ T_UNSPECIFIED = 401,
+ T_STRING = 402,
+ T_UNSIGNED_INTEGER_DIFFERENT_ONE_TWO_THREE = 403
};
#endif
@@ -541,21 +542,21 @@ union yyalloc
/* YYFINAL -- State number of the termination state. */
#define YYFINAL 105
/* YYLAST -- Last index in YYTABLE. */
-#define YYLAST 3221
+#define YYLAST 3309
/* YYNTOKENS -- Number of terminals. */
-#define YYNTOKENS 163
+#define YYNTOKENS 164
/* YYNNTS -- Number of nonterminals. */
-#define YYNNTS 339
+#define YYNNTS 350
/* YYNRULES -- Number of rules. */
-#define YYNRULES 670
+#define YYNRULES 687
/* YYNSTATES -- Number of states. */
-#define YYNSTATES 1371
+#define YYNSTATES 1411
/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
by yylex, with out-of-bounds checking. */
#define YYUNDEFTOK 2
-#define YYMAXUTOK 402
+#define YYMAXUTOK 403
#define YYTRANSLATE(YYX) \
((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
@@ -568,12 +569,12 @@ static const yytype_uint8 yytranslate[] =
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 159, 161, 2, 153, 162, 154, 148, 2, 2, 150,
- 151, 152, 2, 2, 2, 2, 2, 2, 155, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 149,
+ 160, 162, 2, 154, 163, 155, 149, 2, 2, 151,
+ 152, 153, 2, 2, 2, 2, 2, 2, 156, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 150,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 156, 2, 2, 2, 2, 2,
- 157, 158, 2, 160, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 157, 2, 2, 2, 2, 2,
+ 158, 159, 2, 161, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
@@ -604,81 +605,82 @@ static const yytype_uint8 yytranslate[] =
115, 116, 117, 118, 119, 120, 121, 122, 123, 124,
125, 126, 127, 128, 129, 130, 131, 132, 133, 134,
135, 136, 137, 138, 139, 140, 141, 142, 143, 144,
- 145, 146, 147
+ 145, 146, 147, 148
};
#if YYDEBUG
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
static const yytype_uint16 yyrline[] =
{
- 0, 206, 206, 206, 206, 206, 206, 206, 207, 207,
- 207, 208, 211, 211, 212, 212, 212, 213, 215, 215,
- 219, 223, 223, 225, 227, 229, 229, 231, 231, 233,
- 235, 237, 239, 241, 241, 243, 243, 245, 245, 245,
- 245, 247, 247, 251, 253, 257, 258, 259, 261, 261,
- 263, 265, 267, 269, 273, 274, 277, 278, 280, 282,
- 284, 287, 288, 289, 291, 293, 295, 295, 297, 300,
- 301, 303, 303, 308, 308, 310, 310, 312, 314, 316,
- 320, 321, 324, 325, 326, 328, 328, 329, 332, 333,
- 337, 338, 339, 343, 344, 345, 346, 348, 352, 354,
- 357, 359, 362, 363, 364, 365, 366, 367, 368, 369,
- 370, 371, 372, 373, 374, 375, 376, 379, 380, 381,
- 382, 383, 384, 385, 386, 387, 388, 389, 390, 391,
- 392, 393, 397, 399, 401, 405, 410, 412, 414, 416,
- 418, 422, 427, 428, 430, 432, 434, 438, 442, 444,
- 444, 446, 446, 451, 456, 457, 458, 459, 460, 461,
- 462, 464, 466, 468, 468, 470, 470, 472, 474, 476,
- 478, 480, 482, 486, 488, 492, 492, 495, 498, 503,
- 503, 503, 503, 503, 506, 511, 511, 511, 511, 514,
- 518, 519, 521, 537, 541, 542, 544, 544, 546, 546,
- 552, 552, 554, 556, 563, 563, 563, 565, 572, 573,
- 574, 575, 577, 584, 591, 592, 593, 595, 597, 597,
- 597, 597, 597, 597, 597, 597, 597, 600, 600, 600,
- 602, 602, 604, 604, 604, 606, 611, 617, 622, 625,
- 628, 629, 630, 631, 632, 633, 634, 635, 636, 639,
- 640, 641, 642, 643, 644, 645, 646, 649, 650, 651,
- 652, 653, 654, 655, 656, 659, 660, 663, 664, 665,
- 666, 671, 672, 673, 674, 675, 676, 677, 678, 679,
- 682, 683, 684, 685, 688, 689, 690, 691, 694, 695,
- 698, 699, 704, 705, 708, 709, 710, 711, 714, 715,
- 716, 717, 718, 719, 720, 721, 722, 723, 724, 725,
- 726, 727, 728, 729, 730, 731, 732, 733, 734, 735,
- 736, 737, 738, 739, 740, 741, 742, 743, 744, 745,
- 746, 747, 748, 749, 751, 754, 756, 758, 760, 762,
- 764, 780, 780, 782, 790, 791, 793, 794, 796, 804,
- 805, 807, 809, 811, 816, 817, 819, 821, 823, 825,
- 827, 829, 831, 836, 840, 842, 845, 848, 849, 850,
- 852, 853, 855, 860, 861, 863, 863, 865, 869, 869,
- 869, 871, 871, 873, 881, 890, 898, 908, 909, 911,
- 913, 913, 915, 915, 918, 919, 923, 929, 930, 931,
- 933, 933, 935, 937, 939, 943, 948, 948, 950, 953,
- 954, 958, 963, 963, 963, 965, 967, 968, 969, 970,
- 972, 975, 977, 981, 987, 987, 991, 991, 992, 992,
- 994, 999, 1000, 1001, 1002, 1004, 1010, 1015, 1021, 1023,
- 1025, 1027, 1031, 1037, 1038, 1039, 1041, 1043, 1045, 1049,
- 1049, 1051, 1053, 1058, 1059, 1061, 1063, 1065, 1067, 1071,
- 1071, 1073, 1079, 1086, 1086, 1089, 1096, 1097, 1098, 1099,
- 1100, 1102, 1106, 1108, 1110, 1110, 1114, 1119, 1119, 1119,
- 1123, 1128, 1128, 1130, 1134, 1134, 1138, 1143, 1145, 1149,
- 1149, 1153, 1158, 1160, 1164, 1165, 1166, 1167, 1168, 1170,
- 1170, 1172, 1175, 1177, 1177, 1179, 1181, 1183, 1187, 1193,
- 1194, 1195, 1196, 1198, 1200, 1204, 1209, 1211, 1214, 1219,
- 1223, 1229, 1229, 1229, 1229, 1229, 1229, 1233, 1238, 1240,
- 1245, 1245, 1246, 1248, 1248, 1250, 1257, 1257, 1259, 1266,
- 1266, 1268, 1275, 1282, 1287, 1288, 1290, 1296, 1301, 1309,
- 1315, 1317, 1319, 1324, 1326, 1326, 1327, 1327, 1331, 1337,
- 1337, 1339, 1342, 1346, 1351, 1357, 1360, 1365, 1371, 1374,
- 1379, 1385, 1388, 1393, 1399, 1399, 1400, 1400, 1401, 1401,
- 1402, 1402, 1403, 1403, 1404, 1404, 1407, 1407, 1409, 1410,
- 1411, 1413, 1415, 1419, 1422, 1422, 1425, 1426, 1427, 1429,
- 1433, 1434, 1436, 1438, 1438, 1439, 1439, 1440, 1440, 1440,
- 1441, 1442, 1442, 1443, 1443, 1444, 1444, 1446, 1446, 1447,
- 1447, 1448, 1449, 1449, 1453, 1459, 1460, 1461, 1462, 1463,
- 1464, 1465, 1467, 1469, 1471, 1473, 1475, 1477, 1479, 1481,
- 1483, 1485, 1490, 1496, 1497, 1498, 1499, 1500, 1502, 1507,
- 1515, 1515, 1515, 1515, 1517, 1518, 1519, 1520, 1522, 1524,
- 1529, 1535, 1537, 1544, 1544, 1546, 1547, 1548, 1549, 1551,
- 1553
+ 0, 207, 207, 207, 207, 207, 207, 207, 208, 208,
+ 208, 209, 212, 212, 213, 213, 213, 214, 216, 216,
+ 220, 224, 224, 226, 228, 230, 230, 232, 232, 234,
+ 236, 238, 240, 242, 242, 244, 244, 246, 246, 246,
+ 246, 248, 248, 252, 254, 258, 259, 260, 262, 262,
+ 264, 266, 268, 270, 274, 275, 278, 279, 281, 283,
+ 285, 288, 289, 290, 292, 294, 296, 296, 298, 301,
+ 302, 304, 304, 309, 309, 311, 311, 313, 315, 317,
+ 321, 322, 325, 326, 327, 329, 329, 330, 333, 334,
+ 338, 339, 340, 344, 345, 346, 347, 349, 353, 355,
+ 358, 360, 363, 364, 365, 366, 367, 368, 369, 370,
+ 371, 372, 373, 374, 375, 376, 377, 380, 381, 382,
+ 383, 384, 385, 386, 387, 388, 389, 390, 391, 392,
+ 393, 394, 398, 400, 402, 406, 411, 413, 415, 417,
+ 419, 423, 428, 429, 431, 433, 435, 439, 443, 445,
+ 445, 447, 447, 452, 457, 458, 459, 460, 461, 462,
+ 463, 465, 467, 469, 469, 471, 471, 473, 475, 477,
+ 479, 481, 483, 487, 489, 493, 493, 496, 499, 504,
+ 504, 504, 504, 504, 507, 512, 512, 512, 512, 515,
+ 519, 520, 522, 538, 542, 543, 545, 545, 547, 547,
+ 553, 553, 555, 557, 564, 564, 564, 566, 573, 574,
+ 575, 576, 578, 585, 592, 593, 594, 596, 598, 598,
+ 598, 598, 598, 598, 598, 598, 598, 601, 601, 601,
+ 603, 603, 605, 605, 605, 607, 612, 618, 623, 626,
+ 629, 630, 631, 632, 633, 634, 635, 636, 637, 640,
+ 641, 642, 643, 644, 645, 646, 647, 650, 651, 652,
+ 653, 654, 655, 656, 657, 660, 661, 664, 665, 666,
+ 667, 672, 673, 674, 675, 676, 677, 678, 679, 680,
+ 683, 684, 685, 686, 689, 690, 691, 692, 695, 696,
+ 699, 700, 705, 706, 709, 710, 711, 712, 715, 716,
+ 717, 718, 719, 720, 721, 722, 723, 724, 725, 726,
+ 727, 728, 729, 730, 731, 732, 733, 734, 735, 736,
+ 737, 738, 739, 740, 741, 742, 743, 744, 745, 746,
+ 747, 748, 749, 750, 752, 755, 757, 759, 761, 763,
+ 765, 781, 781, 783, 791, 792, 794, 795, 797, 805,
+ 806, 808, 810, 812, 817, 818, 820, 822, 824, 826,
+ 828, 830, 832, 837, 841, 843, 846, 849, 850, 851,
+ 853, 854, 856, 861, 862, 864, 864, 866, 870, 870,
+ 870, 872, 872, 874, 882, 891, 899, 909, 910, 912,
+ 914, 914, 916, 916, 919, 920, 924, 930, 931, 932,
+ 934, 934, 936, 938, 940, 944, 949, 949, 951, 954,
+ 955, 959, 964, 964, 964, 966, 968, 969, 970, 971,
+ 973, 976, 978, 982, 988, 988, 992, 992, 993, 993,
+ 995, 1000, 1001, 1002, 1003, 1004, 1006, 1012, 1017, 1023,
+ 1025, 1027, 1029, 1033, 1039, 1040, 1041, 1043, 1045, 1047,
+ 1051, 1051, 1053, 1055, 1060, 1061, 1063, 1065, 1067, 1069,
+ 1073, 1073, 1075, 1081, 1088, 1088, 1091, 1098, 1099, 1100,
+ 1101, 1102, 1104, 1108, 1110, 1112, 1112, 1116, 1121, 1121,
+ 1121, 1125, 1130, 1130, 1132, 1136, 1136, 1140, 1145, 1147,
+ 1151, 1151, 1155, 1160, 1162, 1166, 1167, 1168, 1169, 1170,
+ 1172, 1172, 1174, 1177, 1179, 1179, 1181, 1183, 1185, 1189,
+ 1195, 1196, 1197, 1198, 1200, 1202, 1206, 1211, 1213, 1216,
+ 1221, 1225, 1231, 1231, 1231, 1231, 1231, 1231, 1235, 1240,
+ 1242, 1247, 1247, 1248, 1250, 1250, 1252, 1259, 1259, 1261,
+ 1268, 1268, 1270, 1277, 1284, 1289, 1290, 1291, 1293, 1299,
+ 1304, 1312, 1318, 1320, 1322, 1328, 1330, 1330, 1331, 1331,
+ 1335, 1341, 1341, 1343, 1348, 1354, 1359, 1365, 1370, 1375,
+ 1381, 1386, 1391, 1397, 1402, 1407, 1413, 1413, 1414, 1414,
+ 1415, 1415, 1416, 1416, 1417, 1417, 1418, 1418, 1421, 1421,
+ 1423, 1424, 1425, 1427, 1429, 1433, 1436, 1436, 1439, 1440,
+ 1441, 1443, 1447, 1448, 1450, 1452, 1452, 1453, 1453, 1454,
+ 1454, 1454, 1455, 1456, 1456, 1457, 1457, 1458, 1458, 1460,
+ 1460, 1461, 1461, 1462, 1463, 1463, 1467, 1471, 1472, 1475,
+ 1480, 1481, 1482, 1483, 1484, 1485, 1486, 1488, 1490, 1492,
+ 1495, 1497, 1499, 1501, 1503, 1505, 1507, 1509, 1511, 1513,
+ 1518, 1522, 1523, 1526, 1531, 1532, 1533, 1534, 1535, 1537,
+ 1542, 1547, 1548, 1551, 1557, 1557, 1557, 1557, 1559, 1560,
+ 1561, 1562, 1564, 1566, 1571, 1577, 1579, 1584, 1585, 1588,
+ 1594, 1594, 1596, 1597, 1598, 1599, 1601, 1603
};
#endif
@@ -707,13 +709,13 @@ static const char *const yytname[] =
"\"PARAMETRICCRS\"", "\"PARAMETRICUNIT\"", "\"BASEVERTCRS\"",
"\"BASEENGCRS\"", "\"BASEPARAMCRS\"", "\"BASETIMECRS\"", "\"EPOCH\"",
"\"COORDEPOCH\"", "\"COORDINATEMETADATA\"", "\"POINTMOTIONOPERATION\"",
- "\"GEODETICCRS\"", "\"GEODETICDATUM\"", "\"PROJECTEDCRS\"",
- "\"PRIMEMERIDIAN\"", "\"GEOGRAPHICCRS\"", "\"TRF\"", "\"VERTICALCRS\"",
- "\"VERTICALDATUM\"", "\"VRF\"", "\"TIMEDATUM\"", "\"TEMPORALQUANTITY\"",
- "\"ENGINEERINGDATUM\"", "\"ENGINEERINGCRS\"", "\"PARAMETRICDATUM\"",
- "\"affine\"", "\"Cartesian\"", "\"cylindrical\"", "\"ellipsoidal\"",
- "\"linear\"", "\"parametric\"", "\"polar\"", "\"spherical\"",
- "\"vertical\"", "\"temporal\"", "\"temporalCount\"",
+ "\"VERSION\"", "\"GEODETICCRS\"", "\"GEODETICDATUM\"",
+ "\"PROJECTEDCRS\"", "\"PRIMEMERIDIAN\"", "\"GEOGRAPHICCRS\"", "\"TRF\"",
+ "\"VERTICALCRS\"", "\"VERTICALDATUM\"", "\"VRF\"", "\"TIMEDATUM\"",
+ "\"TEMPORALQUANTITY\"", "\"ENGINEERINGDATUM\"", "\"ENGINEERINGCRS\"",
+ "\"PARAMETRICDATUM\"", "\"affine\"", "\"Cartesian\"", "\"cylindrical\"",
+ "\"ellipsoidal\"", "\"linear\"", "\"parametric\"", "\"polar\"",
+ "\"spherical\"", "\"vertical\"", "\"temporal\"", "\"temporalCount\"",
"\"temporalMeasure\"", "\"ordinal\"", "\"temporalDateTime\"",
"\"north\"", "\"northNorthEast\"", "\"northEast\"", "\"eastNorthEast\"",
"\"east\"", "\"eastSouthEast\"", "\"southEast\"", "\"southSouthEast\"",
@@ -819,12 +821,12 @@ static const char *const yytname[] =
"opt_separator_datum_anchor_identifier_list", "datum_anchor",
"datum_anchor_keyword", "datum_anchor_description", "projected_crs",
"projected_crs_keyword", "base_geodetic_crs", "base_static_geodetic_crs",
- "opt_separator_pm_ellipsoidal_cs_unit", "base_dynamic_geodetic_crs",
- "base_static_geographic_crs", "base_dynamic_geographic_crs",
- "base_geodetic_crs_keyword", "base_geographic_crs_keyword",
- "base_crs_name", "ellipsoidal_cs_unit", "map_projection",
- "opt_separator_parameter_list_identifier_list", "map_projection_keyword",
- "map_projection_name", "map_projection_method",
+ "opt_separator_pm_ellipsoidal_cs_unit_opt_separator_identifier_list",
+ "base_dynamic_geodetic_crs", "base_static_geographic_crs",
+ "base_dynamic_geographic_crs", "base_geodetic_crs_keyword",
+ "base_geographic_crs_keyword", "base_crs_name", "ellipsoidal_cs_unit",
+ "map_projection", "opt_separator_parameter_list_identifier_list",
+ "map_projection_keyword", "map_projection_name", "map_projection_method",
"map_projection_method_keyword", "map_projection_method_name",
"map_projection_parameter", "opt_separator_param_unit_identifier_list",
"parameter_keyword", "parameter_name", "parameter_value",
@@ -857,10 +859,10 @@ static const char *const yytname[] =
"derived_dynamic_geod_crs",
"base_dynamic_geod_crs_or_base_dynamic_geog_crs",
"derived_static_geog_crs", "derived_dynamic_geog_crs",
- "base_static_geod_crs", "opt_separator_pm", "base_dynamic_geod_crs",
- "base_static_geog_crs", "base_dynamic_geog_crs", "derived_projected_crs",
- "derived_projected_crs_keyword", "derived_crs_name",
- "base_projected_crs", "base_projected_crs_keyword",
+ "base_static_geod_crs", "opt_separator_pm_opt_separator_identifier_list",
+ "base_dynamic_geod_crs", "base_static_geog_crs", "base_dynamic_geog_crs",
+ "derived_projected_crs", "derived_projected_crs_keyword",
+ "derived_crs_name", "base_projected_crs", "base_projected_crs_keyword",
"base_geodetic_geographic_crs", "derived_vertical_crs",
"base_vertical_crs", "base_static_vertical_crs",
"base_dynamic_vertical_crs", "base_vertical_crs_keyword",
@@ -874,17 +876,23 @@ static const char *const yytname[] =
"coordinate_epoch_keyword", "coordinate_epoch", "coordinate_metadata",
"coordinate_metadata_crs", "coordinate_metadata_keyword",
"static_crs_coordinate_metadata", "dynamic_crs_coordinate_metadata",
- "coordinate_operation",
+ "coordinate_operation", "coordinate_operation_next",
+ "coordinate_operation_end",
"opt_parameter_or_parameter_file_list_opt_interpolation_crs_opt_operation_accuracy_opt_separator_scope_extent_identifier_remark",
- "operation_keyword", "operation_name", "source_crs",
+ "operation_keyword", "operation_name", "operation_version",
+ "operation_version_keyword", "operation_version_text", "source_crs",
"source_crs_keyword", "target_crs", "target_crs_keyword",
"interpolation_crs", "interpolation_crs_keyword", "operation_accuracy",
"operation_accuracy_keyword", "point_motion_operation",
+ "point_motion_operation_next", "point_motion_operation_end",
"opt_parameter_or_parameter_file_list_opt_operation_accuracy_opt_separator_scope_extent_identifier_remark",
- "point_motion_keyword", "concatenated_operation", "step",
+ "point_motion_keyword", "concatenated_operation",
+ "concatenated_operation_next", "concatenated_operation_end", "step",
"opt_concatenated_operation_end", "concatenated_operation_keyword",
"step_keyword", "bound_crs", "bound_crs_keyword",
"abridged_coordinate_transformation",
+ "abridged_coordinate_transformation_next",
+ "abridged_coordinate_transformation_end",
"abridged_parameter_or_parameter_file",
"opt_end_abridged_coordinate_transformation",
"abridged_transformation_keyword", "abridged_transformation_parameter", YY_NULLPTR
@@ -910,18 +918,18 @@ static const yytype_uint16 yytoknum[] =
365, 366, 367, 368, 369, 370, 371, 372, 373, 374,
375, 376, 377, 378, 379, 380, 381, 382, 383, 384,
385, 386, 387, 388, 389, 390, 391, 392, 393, 394,
- 395, 396, 397, 398, 399, 400, 401, 402, 46, 69,
- 49, 50, 51, 43, 45, 58, 84, 90, 91, 40,
- 93, 41, 44
+ 395, 396, 397, 398, 399, 400, 401, 402, 403, 46,
+ 69, 49, 50, 51, 43, 45, 58, 84, 90, 91,
+ 40, 93, 41, 44
};
# endif
-#define YYPACT_NINF -1145
+#define YYPACT_NINF -1187
#define yypact_value_is_default(Yystate) \
- (!!((Yystate) == (-1145)))
+ (!!((Yystate) == (-1187)))
-#define YYTABLE_NINF -624
+#define YYTABLE_NINF -626
#define yytable_value_is_error(Yytable_value) \
0
@@ -930,144 +938,148 @@ static const yytype_uint16 yytoknum[] =
STATE-NUM. */
static const yytype_int16 yypact[] =
{
- 799, -1145, -1145, -1145, -1145, -1145, -1145, -1145, -1145, -1145,
- -1145, -1145, -1145, -1145, -1145, -1145, -1145, -1145, -1145, -1145,
- -1145, -1145, -1145, -1145, -1145, -1145, -1145, -1145, -1145, -1145,
- -1145, -1145, -1145, -1145, -1145, -1145, -1145, 132, -1145, -1145,
- -1145, 304, -1145, -1145, -1145, 304, -1145, -1145, -1145, -1145,
- -1145, -1145, 304, 304, -1145, 304, -1145, 304, -1145, 304,
- -1145, 304, -1145, -1145, -1145, 304, -1145, 304, -1145, 304,
- -1145, 304, -1145, 304, -1145, 304, -1145, 304, -1145, 304,
- -1145, -1145, -1145, -1145, -1145, -1145, -1145, 304, -1145, -1145,
- -1145, -1145, -1145, -1145, 304, -1145, 304, -1145, 304, -1145,
- 304, -1145, 304, -1145, 304, -1145, -1145, -1145, 30, 30,
- 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
- 30, 30, 30, 30, 30, 30, 1044, 30, 30, 30,
- 170, -1145, -1145, 61, -1145, 61, -1145, 61, 61, -1145,
- 61, -1145, 61, 61, -1145, 61, 61, 61, 61, 61,
- 61, 61, 61, 61, -1145, 61, -1145, 61, -1145, -1145,
- -1145, -1145, 78, -1145, -1145, -1145, -1145, -1145, 148, 229,
- 241, -1145, -1145, -1145, -1145, 315, -1145, 61, -1145, 61,
- 61, 61, -1145, 61, 304, -1145, 922, 284, 445, 445,
- 577, 345, 279, 321, 412, 342, 315, 250, 315, 393,
- 315, 67, 280, 315, 351, 1285, -1145, -1145, -1145, 446,
- 170, 170, 170, 381, 1044, -1145, -1145, -1145, -1145, -1145,
- -1145, -1145, 624, -1145, -1145, -1145, -1145, 299, 302, 307,
- 577, -1145, 61, -1145, 61, 304, -1145, -1145, -1145, -1145,
- 304, 61, 304, 61, -1145, 304, 304, 61, 61, -1145,
- -1145, -1145, -1145, 61, 61, 61, 61, -1145, 61, 61,
- 61, -1145, -1145, -1145, -1145, 304, 304, -1145, -1145, 61,
- 304, -1145, -1145, 304, 61, 61, -1145, 61, -1145, -1145,
- 304, -1145, 61, 61, 304, -1145, -1145, 61, 61, 304,
- -1145, -1145, 61, 61, 304, -1145, -1145, 61, 61, 304,
- -1145, -1145, 61, 61, 304, 61, 304, -1145, -1145, 61,
- 304, -1145, 61, -1145, -1145, -1145, -1145, 304, 61, 61,
- 61, -1145, 61, 304, 315, -1145, 400, 624, -1145, -1145,
- 365, 315, 122, 315, 315, 30, 30, 115, 402, 127,
- 30, 30, 419, 419, 115, 127, 419, 419, 577, 315,
- 456, 30, 30, 423, 315, 30, 30, 189, 480, 419,
- 30, 490, -1145, 490, 30, 480, 419, 30, 480, 419,
- 30, 480, 419, 30, -1145, -1145, 506, 146, -1145, 30,
- 419, 30, 1285, 624, 381, 485, 381, 487, 1044, -1145,
- 624, -1145, -1145, -1145, -1145, -1145, -1145, -1145, -1145, 61,
- 61, 304, -1145, 304, -1145, -1145, 61, 61, 304, 61,
- -1145, -1145, -1145, 61, 61, 61, -1145, 61, 304, -1145,
- -1145, -1145, -1145, -1145, -1145, -1145, 304, 315, 61, 304,
- -1145, 61, 61, -1145, 61, 304, 61, 61, 315, 61,
- 61, -1145, 61, -1145, 61, 61, 61, -1145, 61, 61,
- 304, -1145, -1145, 61, 61, 61, 304, 315, 61, 61,
- 61, 61, -1145, 315, 315, 61, 61, 315, 61, 61,
- 315, 61, 61, -1145, -1145, 376, -1145, 315, 61, -1145,
- 315, 61, 61, 61, 307, 315, 61, -1145, 61, 304,
- 61, -1145, 61, 304, 315, -1145, 510, 505, 30, 30,
- -1145, -1145, 490, -1145, 752, 515, 490, 315, 284, 127,
- 532, 315, 624, 1049, -1145, 480, 30, 272, 272, 480,
- 30, 480, 127, -1145, 480, 480, 470, 315, 480, 272,
- 272, -1145, -1145, 30, 315, 284, 480, 1313, -1145, 480,
- 106, -1145, -1145, -1145, -1145, 480, 100, -1145, 480, 152,
- -1145, 480, 74, -1145, -1145, 624, -1145, -1145, 624, -1145,
- -1145, -1145, 480, 279, 953, 315, 624, -1145, 485, 1361,
- 315, 30, 502, 843, 315, 30, -1145, 61, -1145, -1145,
- 315, -1145, 315, -1145, 61, -1145, 315, 61, -1145, 61,
- -1145, 61, 315, -1145, -1145, -1145, 304, -1145, 307, 315,
- -1145, -1145, -1145, -1145, -1145, -1145, -1145, -1145, -1145, -1145,
- -1145, -1145, -1145, -1145, 61, 61, 61, -1145, -1145, 61,
- 61, 61, 61, 61, 315, -1145, 61, 315, 315, 315,
- 315, -1145, -1145, 61, 61, 304, -1145, 315, 61, 61,
- 61, 61, -1145, 61, -1145, 61, 315, 61, 315, 61,
- 315, 315, 315, 315, 315, 315, 315, 428, 418, -1145,
- 534, 315, -1145, -1145, -1145, -1145, 61, -1145, -1145, -1145,
- -1145, -1145, -1145, -1145, -1145, -1145, -1145, -1145, 61, 304,
- 61, 304, -1145, 61, 304, 61, 304, 61, 304, 61,
- 304, 61, -1145, 304, 61, -1145, -1145, 61, -1145, -1145,
- -1145, 304, 61, 61, 304, 61, 304, -1145, -1145, 61,
- -1145, 304, -1145, -1145, 61, 505, -1145, -1145, -1145, -1145,
- -1145, -1145, 110, -1145, 30, 624, -1145, 409, 409, 409,
- 400, 115, 89, 315, 115, 315, -1145, 485, -1145, -1145,
- -1145, -1145, -1145, -1145, 30, -1145, 115, 105, 315, 115,
- 315, 400, 569, -1145, 409, -1145, 189, -1145, -1145, -1145,
- -1145, -1145, -1145, -1145, -1145, 624, -1145, -1145, 624, 624,
- -1145, 431, -1145, -1145, -1145, -1145, 456, 130, 566, 469,
- -1145, 30, 340, -1145, 30, 183, -1145, 752, 282, -1145,
- 752, 335, -1145, 506, -1145, 453, -1145, 1330, 315, 30,
- -1145, -1145, 30, -1145, 752, 490, 315, 90, 485, -1145,
- 61, -1145, 61, -1145, -1145, -1145, -1145, 61, 61, 61,
- 61, 577, 315, 61, -1145, -1145, 61, -1145, 61, -1145,
- 61, 61, -1145, -1145, -1145, 304, 61, -1145, -1145, 61,
- -1145, -1145, 61, 61, 61, 315, -1145, 449, 431, -1145,
- 534, 624, -1145, 315, -1145, 61, -1145, 61, -1145, 61,
- -1145, -1145, 315, 61, 61, 61, -1145, 315, 61, 61,
- -1145, 61, 61, -1145, 61, -1145, -1145, 61, -1145, 315,
- -1145, -1145, 61, 61, 61, 304, 61, -1145, 61, 61,
- 315, -1145, -1145, -1145, -1145, -1145, -1145, 315, 61, 315,
- 315, 315, 315, 497, -1145, -1145, -1145, 315, 315, 339,
- 315, 577, 315, 30, 157, 315, 616, 315, 315, -1145,
- -1145, -1145, 624, -1145, -1145, -1145, -1145, -1145, 273, -1145,
- -1145, 183, -1145, 282, -1145, -1145, -1145, 282, -1145, -1145,
- 752, -1145, 752, 506, -1145, -1145, -1145, 801, -1145, 1044,
- -1145, 400, 30, -1145, 61, 221, -1145, 61, 61, 61,
- 61, -1145, -1145, 61, 61, 61, -1145, -1145, 61, -1145,
- 61, -1145, -1145, -1145, -1145, -1145, -1145, -1145, 304, 61,
- -1145, 61, -1145, -1145, 802, 315, 61, 61, 61, -1145,
- 61, 61, 61, 61, -1145, 61, -1145, 61, -1145, -1145,
- 315, 61, 315, 61, -1145, 61, 502, 304, -1145, 61,
- -1145, 599, 599, 599, -1145, -1145, -1145, -1145, 315, 577,
- 30, -1145, 599, 761, -1145, -1145, 347, 583, 559, 282,
- -1145, -1145, -1145, -1145, 752, 395, 315, -1145, -1145, -1145,
- 305, 315, 304, 30, 1085, 315, -1145, 61, 304, 61,
- 304, 61, 304, -1145, 61, 61, 61, 328, 761, -1145,
- 61, 61, -1145, 61, -1145, -1145, 61, -1145, 61, -1145,
- -1145, -1145, -1145, -1145, -1145, -1145, -1145, 61, -1145, 304,
- -1145, 90, 61, -1145, 61, 61, -1145, 666, -1145, 30,
- -1145, 30, 715, -1145, 30, 315, 577, 912, -1145, -1145,
- 583, 559, 559, -1145, 752, 315, 30, 315, 400, -1145,
- -1145, -1145, -1145, -1145, -1145, -1145, -1145, -1145, -1145, -1145,
- -1145, -1145, 304, -1145, 304, 61, 61, -1145, 61, 61,
- -1145, 61, 61, -1145, 61, -1145, -1145, 61, 61, 304,
- 61, -1145, -1145, -1145, -1145, 315, -1145, 61, 61, 61,
- 30, 30, -1145, -1145, 1410, 1663, -1145, 1450, 315, 1160,
- -1145, -1145, 30, 559, -1145, 577, 315, 943, 315, 315,
- 61, 61, 61, -1145, -1145, -1145, -1145, -1145, -1145, -1145,
- 61, -1145, -1145, -1145, -1145, -1145, -1145, -1145, -1145, -1145,
- -1145, -1145, -1145, -1145, -1145, -1145, -1145, -1145, -1145, -1145,
- -1145, -1145, -1145, -1145, -1145, 61, 61, -1145, -1145, -1145,
- -1145, -1145, 315, -1145, 61, 61, 61, 61, 61, 61,
- 315, -1145, 61, -1145, 61, -1145, 61, -1145, 61, -1145,
- -1145, 61, 304, -1145, -1145, 577, 315, 524, 524, 696,
- 696, -1145, 597, 117, 315, 523, 524, 545, 545, -1145,
- 358, -1145, 315, -1145, -1145, 90, 61, -1145, -1145, -1145,
- 61, 61, -1145, 61, 304, 61, 304, -1145, -1145, 61,
- 61, -1145, 61, 304, 61, -1145, 61, 61, -1145, 61,
- 61, 61, -1145, 61, -1145, 61, -1145, 61, 61, -1145,
- 61, -1145, 61, 61, -1145, 61, -1145, 61, -1145, 315,
- 315, -1145, -1145, 597, -1145, 752, 397, -1145, 624, -1145,
- -1145, 597, -1145, 752, 397, -1145, -1145, -1145, 397, -1145,
- -1145, -1145, 134, -1145, -1145, 358, -1145, -1145, -1145, 358,
- -1145, -1145, -1145, -1145, 61, -1145, 61, 61, 61, 61,
- 315, 61, 61, 315, 61, 61, 61, 61, 61, -1145,
- -1145, 397, -1145, 157, -1145, -1145, -1145, 397, -1145, -1145,
- -1145, -1145, -1145, -1145, -1145, 61, 315, 61, -1145, -1145,
- -1145
+ 820, -1187, -1187, -1187, -1187, -1187, -1187, -1187, -1187, -1187,
+ -1187, -1187, -1187, -1187, -1187, -1187, -1187, -1187, -1187, -1187,
+ -1187, -1187, -1187, -1187, -1187, -1187, -1187, -1187, -1187, -1187,
+ -1187, -1187, -1187, -1187, -1187, -1187, -1187, 147, -1187, -1187,
+ -1187, 213, -1187, -1187, -1187, 213, -1187, -1187, -1187, -1187,
+ -1187, -1187, 213, 213, -1187, 213, -1187, 213, -1187, 213,
+ -1187, 213, -1187, -1187, -1187, 213, -1187, 213, -1187, 213,
+ -1187, 213, -1187, 213, -1187, 213, -1187, 213, -1187, 213,
+ -1187, -1187, -1187, -1187, -1187, -1187, -1187, 213, -1187, -1187,
+ -1187, -1187, -1187, -1187, 213, -1187, 213, -1187, 213, -1187,
+ 213, -1187, 213, -1187, 213, -1187, -1187, -1187, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 928, 19, 19, 19,
+ 164, -1187, -1187, 17, -1187, 17, -1187, 17, 17, -1187,
+ 17, -1187, 17, 17, -1187, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, -1187, 17, -1187, 17, -1187, -1187,
+ -1187, -1187, 78, -1187, -1187, -1187, -1187, -1187, 94, 167,
+ 185, -1187, -1187, -1187, -1187, 345, -1187, 17, -1187, 17,
+ 17, 17, -1187, 17, 213, -1187, 1290, 154, 97, 97,
+ 680, 330, 412, 301, 499, 113, 345, 304, 345, 312,
+ 345, 160, 255, 345, 231, 1501, -1187, -1187, -1187, 487,
+ 100, -1187, -1187, 100, -1187, -1187, 100, -1187, -1187, 382,
+ 928, -1187, -1187, -1187, -1187, -1187, -1187, -1187, 385, -1187,
+ -1187, -1187, -1187, 292, 299, 317, 680, -1187, 17, -1187,
+ 17, 213, -1187, -1187, -1187, -1187, 213, 17, 213, 17,
+ -1187, 213, 213, 17, 17, -1187, -1187, -1187, -1187, 17,
+ 17, 17, 17, -1187, 17, 17, 17, -1187, -1187, -1187,
+ -1187, 213, 213, -1187, -1187, 17, 213, -1187, -1187, 213,
+ 17, 17, -1187, 17, -1187, -1187, 213, -1187, 17, 17,
+ 213, -1187, -1187, 17, 17, 213, -1187, -1187, 17, 17,
+ 213, -1187, -1187, 17, 17, 213, -1187, -1187, 17, 17,
+ 213, 17, 213, -1187, -1187, 17, 213, -1187, 17, -1187,
+ -1187, -1187, -1187, 213, -1187, 17, 213, 17, 17, 17,
+ 17, 17, -1187, 17, 213, 345, -1187, 459, 385, -1187,
+ -1187, 329, 345, 157, 345, 345, 19, 19, 102, 422,
+ 112, 19, 19, 442, 442, 102, 112, 442, 442, 680,
+ 345, 470, 19, 19, 243, 345, 19, 19, 242, 496,
+ 442, 19, 486, -1187, 486, 19, 496, 442, 19, 496,
+ 442, 19, 496, 442, 19, -1187, -1187, 669, 107, -1187,
+ 19, 442, 19, 1501, 385, 164, -1187, 19, 382, 164,
+ -1187, 505, 164, -1187, 382, 493, 928, -1187, 385, -1187,
+ -1187, -1187, -1187, -1187, -1187, -1187, -1187, 17, 17, 213,
+ -1187, 213, -1187, -1187, 17, 17, 213, 17, -1187, -1187,
+ -1187, 17, 17, 17, -1187, 17, 213, -1187, -1187, -1187,
+ -1187, -1187, -1187, -1187, 213, 345, 17, 213, -1187, 17,
+ 17, -1187, 17, 213, 17, 17, 345, 17, 17, -1187,
+ 17, -1187, 17, 17, 17, -1187, 17, 17, 213, -1187,
+ -1187, 17, 17, 17, 213, 345, 17, 17, 17, 17,
+ -1187, 345, 345, 17, 17, 345, 17, 17, 345, 17,
+ 17, -1187, -1187, 363, -1187, 345, 17, -1187, 345, 17,
+ 17, 17, 317, 345, -1187, 345, 17, -1187, 17, 213,
+ 17, -1187, 17, 213, 345, -1187, 489, 514, 19, 19,
+ -1187, -1187, 486, -1187, 1298, 506, 486, 345, 154, 112,
+ 565, 345, 385, 1217, -1187, 496, 19, 90, 90, 496,
+ 19, 496, 112, -1187, 496, 496, 327, 345, 496, 90,
+ 90, -1187, -1187, 19, 345, 154, 496, 1258, -1187, 496,
+ 364, -1187, -1187, -1187, -1187, 496, 108, -1187, 496, 245,
+ -1187, 496, 72, -1187, -1187, 385, -1187, -1187, 385, -1187,
+ -1187, -1187, 496, 412, 1402, 345, 385, -1187, -1187, 505,
+ 694, 345, 19, 534, 1206, 345, 19, -1187, 17, -1187,
+ -1187, 345, -1187, 345, -1187, 17, -1187, 345, 17, -1187,
+ 17, -1187, 17, 345, -1187, -1187, -1187, 213, -1187, 317,
+ 345, -1187, -1187, -1187, -1187, -1187, -1187, -1187, -1187, -1187,
+ -1187, -1187, -1187, -1187, -1187, 17, 17, 17, -1187, -1187,
+ 17, 17, 17, 17, 17, 345, -1187, 17, 345, 345,
+ 345, 345, -1187, -1187, 17, 17, 213, -1187, 345, 17,
+ 17, 17, 17, -1187, 17, -1187, 17, 345, 17, 345,
+ 17, 17, 345, 17, 345, 17, 345, 17, 386, 427,
+ -1187, 635, 345, -1187, -1187, -1187, -1187, 17, -1187, -1187,
+ -1187, -1187, -1187, -1187, -1187, -1187, -1187, -1187, -1187, 17,
+ 213, 17, 213, -1187, 17, 213, 17, 213, 17, 213,
+ 17, 213, 17, -1187, 213, 17, -1187, -1187, 17, -1187,
+ -1187, -1187, 213, 17, 17, 213, 17, 213, -1187, -1187,
+ 17, -1187, 213, -1187, -1187, 17, 514, -1187, -1187, -1187,
+ -1187, -1187, -1187, 140, -1187, 19, 385, -1187, 398, 398,
+ 398, 459, 102, 131, 345, 102, 345, -1187, 505, -1187,
+ -1187, -1187, -1187, -1187, -1187, 19, -1187, 102, 132, 345,
+ 102, 345, 459, 568, -1187, 398, -1187, 242, 345, -1187,
+ 345, -1187, 345, -1187, 345, -1187, 385, -1187, -1187, 385,
+ 385, -1187, 437, -1187, -1187, -1187, -1187, 470, 315, 572,
+ 754, -1187, 19, 527, -1187, 19, 323, -1187, 1298, 115,
+ -1187, 1298, 474, -1187, 669, -1187, 462, -1187, 688, 345,
+ 19, -1187, -1187, 19, -1187, 1298, 486, 345, 151, 101,
+ -1187, -1187, -1187, 17, -1187, 17, -1187, -1187, -1187, -1187,
+ 17, 17, 17, 17, 680, 345, 17, 17, 17, -1187,
+ 17, -1187, 17, -1187, 17, 17, -1187, -1187, 17, -1187,
+ 213, 17, 17, -1187, 17, -1187, -1187, 17, 17, 17,
+ 17, -1187, -1187, -1187, -1187, -1187, 449, 437, -1187, 635,
+ 385, -1187, 17, -1187, 17, -1187, 17, -1187, 17, -1187,
+ -1187, 345, 17, 17, 17, -1187, 345, 17, 17, -1187,
+ 17, 17, -1187, 17, -1187, -1187, 17, -1187, 345, -1187,
+ -1187, 17, 17, 17, 213, 17, -1187, 17, 17, 345,
+ -1187, -1187, -1187, -1187, -1187, -1187, 345, 17, 17, 345,
+ 345, 345, 345, 390, -1187, -1187, -1187, 345, -1187, -1187,
+ 345, 179, 345, 680, 345, -1187, 19, 390, -1187, -1187,
+ 345, 733, 345, 345, 345, -1187, -1187, 385, -1187, -1187,
+ -1187, 345, -1187, 457, -1187, -1187, 323, -1187, 115, -1187,
+ -1187, -1187, 115, -1187, -1187, 1298, -1187, 1298, 669, -1187,
+ -1187, -1187, 991, -1187, 928, -1187, 459, 19, -1187, 17,
+ 114, 505, -1187, -1187, 17, 17, 17, 17, -1187, -1187,
+ 17, 17, 17, -1187, -1187, 17, -1187, 17, 17, -1187,
+ -1187, -1187, -1187, -1187, -1187, 213, 17, -1187, 17, -1187,
+ -1187, -1187, 1034, -1187, 345, 17, 17, 17, -1187, 17,
+ 17, 17, 17, -1187, 17, -1187, 17, -1187, -1187, 345,
+ 17, 345, 17, -1187, 17, 534, 213, -1187, 17, -1187,
+ 596, 596, 596, -1187, -1187, -1187, -1187, 345, 680, -1187,
+ 19, -1187, 596, 1148, -1187, -1187, 190, 591, 557, 115,
+ -1187, -1187, -1187, -1187, 1298, 376, 345, -1187, -1187, -1187,
+ 287, 345, 213, 19, 972, 345, -1187, 17, 213, 17,
+ 213, 17, 213, -1187, 17, 17, 17, 204, 1148, -1187,
+ 17, 17, -1187, 17, -1187, -1187, 17, -1187, 17, -1187,
+ -1187, -1187, -1187, -1187, -1187, -1187, -1187, 17, -1187, 213,
+ -1187, 151, 17, -1187, 17, 17, -1187, 906, -1187, 19,
+ -1187, 19, 566, -1187, 19, 345, 680, 1240, -1187, -1187,
+ 591, 557, 557, -1187, 1298, 345, 19, 345, 459, -1187,
+ -1187, -1187, -1187, -1187, -1187, -1187, -1187, -1187, -1187, -1187,
+ -1187, -1187, 213, -1187, 213, 17, 17, -1187, 17, 17,
+ -1187, 17, 17, -1187, 17, -1187, -1187, 17, 17, 213,
+ 17, -1187, -1187, -1187, -1187, 345, -1187, 17, 17, 17,
+ 19, 19, -1187, -1187, 1544, 1736, -1187, 1584, 345, 1080,
+ -1187, -1187, 19, 557, -1187, 680, 345, 899, 345, 345,
+ 17, 17, 17, -1187, -1187, -1187, -1187, -1187, -1187, -1187,
+ 17, -1187, -1187, -1187, -1187, -1187, -1187, -1187, -1187, -1187,
+ -1187, -1187, -1187, -1187, -1187, -1187, -1187, -1187, -1187, -1187,
+ -1187, -1187, -1187, -1187, -1187, 17, 17, -1187, -1187, -1187,
+ -1187, -1187, 345, -1187, 17, 17, 17, 17, 17, 17,
+ 345, -1187, 17, -1187, 17, -1187, 17, -1187, 17, -1187,
+ -1187, 17, 213, -1187, -1187, 680, 345, 417, 417, 625,
+ 625, -1187, 605, 137, 345, 447, 417, 404, 404, -1187,
+ 476, -1187, 345, -1187, -1187, 151, 17, -1187, -1187, -1187,
+ 17, 17, -1187, 17, 213, 17, 213, -1187, -1187, 17,
+ 17, -1187, 17, 213, 17, -1187, 17, 17, -1187, 17,
+ 17, 17, -1187, 17, -1187, 17, -1187, 17, 17, -1187,
+ 17, -1187, 17, 17, -1187, 17, -1187, 17, -1187, 345,
+ 345, -1187, -1187, 605, -1187, 1298, 379, -1187, 385, -1187,
+ -1187, 605, -1187, 1298, 379, -1187, -1187, -1187, 379, -1187,
+ -1187, -1187, 103, -1187, -1187, 476, -1187, -1187, -1187, 476,
+ -1187, -1187, -1187, -1187, 17, -1187, 17, 17, 17, 17,
+ 345, 17, 17, 345, 17, 17, 17, 17, 17, -1187,
+ -1187, 379, -1187, 490, -1187, -1187, -1187, 379, -1187, -1187,
+ -1187, -1187, -1187, -1187, -1187, 17, 345, 17, -1187, -1187,
+ -1187
};
/* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
@@ -1075,141 +1087,145 @@ static const yytype_int16 yypact[] =
means the default is an error. */
static const yytype_uint16 yydefact[] =
{
- 0, 412, 401, 390, 400, 161, 424, 446, 392, 474,
- 477, 591, 632, 658, 661, 499, 492, 351, 550, 484,
- 481, 489, 487, 602, 648, 391, 414, 425, 393, 413,
- 475, 479, 478, 500, 485, 482, 490, 0, 4, 5,
- 2, 0, 13, 341, 342, 0, 574, 380, 378, 379,
- 381, 382, 0, 0, 3, 0, 12, 0, 576, 0,
- 11, 0, 578, 459, 460, 0, 14, 0, 580, 0,
- 15, 0, 582, 0, 16, 0, 584, 0, 17, 0,
- 575, 532, 530, 531, 533, 534, 577, 0, 579, 581,
- 583, 585, 19, 18, 0, 7, 0, 8, 0, 9,
+ 0, 412, 401, 390, 400, 161, 424, 447, 392, 475,
+ 478, 593, 637, 672, 675, 500, 493, 351, 552, 485,
+ 482, 490, 488, 604, 659, 391, 414, 425, 393, 413,
+ 476, 480, 479, 501, 486, 483, 491, 0, 4, 5,
+ 2, 0, 13, 341, 342, 0, 576, 380, 378, 379,
+ 381, 382, 0, 0, 3, 0, 12, 0, 578, 0,
+ 11, 0, 580, 460, 461, 0, 14, 0, 582, 0,
+ 15, 0, 584, 0, 16, 0, 586, 0, 17, 0,
+ 577, 533, 531, 532, 534, 535, 579, 0, 581, 583,
+ 585, 587, 19, 18, 0, 7, 0, 8, 0, 9,
0, 10, 0, 6, 0, 1, 73, 74, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 78, 162, 0, 352, 0, 389, 0, 0, 402,
- 0, 415, 0, 0, 447, 0, 0, 416, 0, 416,
- 0, 416, 0, 494, 551, 0, 592, 0, 603, 617,
- 604, 618, 605, 606, 620, 607, 608, 609, 610, 611,
- 612, 613, 614, 615, 616, 0, 600, 0, 633, 0,
- 0, 0, 635, 0, 0, 77, 0, 0, 0, 0,
+ 0, 415, 0, 0, 448, 0, 0, 416, 0, 416,
+ 0, 416, 0, 495, 553, 0, 594, 0, 605, 619,
+ 606, 620, 607, 608, 622, 609, 610, 611, 612, 613,
+ 614, 615, 616, 617, 618, 0, 602, 0, 638, 0,
+ 0, 0, 643, 0, 0, 77, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 75, 76, 599, 0,
- 0, 0, 0, 0, 0, 40, 20, 37, 38, 39,
- 41, 42, 0, 163, 21, 22, 26, 0, 25, 35,
- 0, 164, 154, 356, 0, 0, 438, 439, 364, 395,
- 0, 0, 0, 0, 394, 0, 0, 0, 0, 536,
- 539, 537, 540, 0, 0, 0, 0, 403, 0, 416,
- 0, 426, 427, 428, 429, 0, 0, 450, 449, 443,
- 0, 563, 464, 0, 0, 0, 463, 0, 559, 560,
- 0, 421, 190, 417, 0, 476, 566, 0, 0, 0,
- 483, 569, 0, 0, 0, 488, 572, 0, 0, 0,
- 506, 502, 190, 190, 0, 190, 0, 493, 553, 0,
- 0, 586, 0, 587, 594, 595, 601, 0, 0, 0,
- 0, 637, 0, 0, 0, 34, 27, 0, 33, 23,
+ 0, 0, 0, 0, 0, 0, 75, 76, 601, 0,
+ 0, 626, 628, 0, 650, 652, 0, 660, 662, 0,
+ 0, 40, 20, 37, 38, 39, 41, 42, 0, 163,
+ 21, 22, 26, 0, 25, 35, 0, 164, 154, 356,
+ 0, 0, 439, 440, 364, 395, 0, 0, 0, 0,
+ 394, 0, 0, 0, 0, 537, 540, 538, 541, 0,
+ 0, 0, 0, 403, 0, 416, 0, 426, 427, 428,
+ 429, 0, 0, 451, 450, 444, 0, 565, 465, 0,
+ 0, 0, 464, 0, 561, 562, 0, 421, 190, 417,
+ 0, 477, 568, 0, 0, 0, 484, 571, 0, 0,
+ 0, 489, 574, 0, 0, 0, 507, 503, 190, 190,
+ 0, 190, 0, 494, 555, 0, 0, 588, 0, 589,
+ 596, 597, 603, 0, 640, 0, 0, 0, 0, 0,
+ 0, 0, 645, 0, 0, 0, 34, 27, 0, 33,
+ 23, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 418, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 498, 497, 0, 0, 495, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 634,
- 0, 29, 31, 28, 36, 168, 171, 165, 166, 155,
- 158, 0, 160, 0, 153, 360, 0, 346, 0, 0,
- 343, 348, 357, 354, 0, 0, 366, 370, 0, 406,
- 217, 407, 388, 204, 205, 206, 0, 0, 0, 0,
- 440, 0, 0, 513, 0, 0, 0, 0, 0, 0,
- 0, 404, 397, 411, 0, 0, 0, 455, 190, 443,
- 0, 442, 451, 190, 0, 0, 0, 0, 0, 0,
- 190, 190, 422, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 50, 503, 48, 504, 0, 190, 507,
- 0, 0, 0, 588, 596, 0, 0, 516, 643, 0,
- 0, 669, 80, 0, 0, 32, 0, 0, 0, 0,
+ 0, 0, 0, 418, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 499, 498, 0, 0, 496,
+ 0, 0, 0, 0, 0, 0, 627, 0, 0, 0,
+ 651, 0, 0, 661, 0, 0, 0, 642, 0, 29,
+ 31, 28, 36, 168, 171, 165, 166, 155, 158, 0,
+ 160, 0, 153, 360, 0, 346, 0, 0, 343, 348,
+ 357, 354, 0, 0, 366, 370, 0, 406, 217, 407,
+ 388, 204, 205, 206, 0, 0, 0, 0, 441, 0,
+ 0, 514, 0, 0, 0, 0, 0, 0, 0, 404,
+ 397, 411, 0, 0, 0, 456, 190, 444, 0, 443,
+ 452, 190, 0, 0, 0, 0, 0, 0, 190, 190,
+ 422, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 50, 504, 48, 505, 0, 190, 508, 0, 0,
+ 0, 590, 598, 0, 641, 0, 0, 517, 654, 0,
+ 0, 686, 80, 0, 0, 32, 0, 0, 0, 0,
345, 350, 0, 349, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 383, 0, 0, 0, 0, 0,
0, 0, 0, 385, 0, 0, 0, 0, 0, 0,
- 0, 444, 445, 0, 0, 0, 0, 0, 461, 0,
- 0, 191, 419, 420, 480, 0, 0, 486, 0, 0,
- 491, 0, 0, 44, 58, 0, 45, 49, 0, 501,
- 496, 505, 0, 0, 0, 0, 597, 593, 0, 0,
- 0, 0, 0, 0, 0, 0, 636, 156, 159, 169,
- 0, 172, 0, 362, 346, 361, 0, 346, 358, 354,
- 353, 0, 0, 375, 376, 371, 0, 363, 367, 0,
- 218, 219, 220, 221, 222, 223, 224, 225, 226, 227,
- 228, 229, 230, 231, 0, 0, 0, 387, 408, 0,
- 0, 544, 0, 544, 0, 514, 0, 0, 0, 0,
- 0, 199, 198, 190, 190, 0, 396, 0, 0, 431,
- 0, 431, 456, 0, 448, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 48, 0, 59,
- 0, 0, 554, 555, 556, 557, 0, 174, 100, 133,
- 136, 144, 148, 98, 590, 82, 88, 89, 93, 0,
- 85, 0, 92, 85, 0, 85, 0, 85, 0, 85,
- 0, 85, 84, 0, 588, 573, 598, 625, 528, 641,
- 647, 0, 643, 643, 0, 80, 0, 642, 517, 373,
- 659, 0, 81, 660, 0, 0, 167, 170, 347, 359,
- 344, 355, 0, 384, 0, 368, 365, 0, 0, 0,
- 27, 0, 0, 0, 0, 0, 535, 0, 538, 386,
- 541, 542, 399, 398, 0, 423, 0, 0, 0, 0,
- 0, 27, 0, 462, 0, 558, 0, 561, 564, 565,
- 567, 568, 570, 571, 46, 0, 43, 68, 0, 0,
- 53, 71, 55, 66, 67, 549, 0, 0, 0, 0,
- 91, 0, 0, 117, 0, 0, 118, 0, 0, 119,
- 0, 0, 120, 0, 83, 0, 589, 0, 0, 0,
- 644, 645, 0, 646, 0, 0, 0, 0, 0, 157,
- 0, 377, 373, 369, 232, 233, 234, 190, 190, 190,
- 190, 0, 0, 544, 545, 543, 544, 547, 509, 202,
- 0, 431, 197, 196, 441, 0, 432, 434, 430, 431,
- 436, 457, 453, 0, 190, 0, 52, 48, 71, 60,
- 0, 0, 70, 0, 96, 85, 94, 0, 90, 85,
- 87, 101, 0, 85, 85, 85, 134, 0, 85, 85,
- 137, 0, 85, 145, 0, 149, 150, 0, 79, 0,
- 639, 631, 625, 625, 80, 0, 80, 624, 0, 0,
- 0, 374, 515, 652, 653, 650, 651, 0, 0, 0,
- 0, 0, 0, 0, 410, 24, 405, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 562,
- 47, 69, 0, 54, 57, 72, 552, 95, 0, 86,
- 99, 0, 121, 0, 122, 123, 132, 0, 124, 125,
- 0, 126, 0, 0, 173, 626, 627, 0, 628, 0,
- 630, 27, 0, 640, 0, 0, 372, 0, 0, 0,
- 190, 546, 548, 190, 509, 509, 508, 203, 190, 435,
- 0, 433, 437, 188, 186, 185, 187, 458, 0, 190,
- 452, 0, 64, 56, 0, 0, 102, 103, 104, 105,
- 85, 85, 85, 85, 138, 0, 146, 142, 151, 152,
- 0, 80, 0, 0, 529, 373, 0, 0, 664, 665,
- 663, 0, 0, 0, 409, 512, 510, 511, 0, 0,
- 0, 454, 0, 0, 63, 97, 0, 0, 0, 0,
- 127, 128, 129, 130, 0, 0, 0, 147, 629, 638,
+ 0, 445, 446, 0, 0, 0, 0, 0, 462, 0,
+ 0, 191, 419, 420, 481, 0, 0, 487, 0, 0,
+ 492, 0, 0, 44, 58, 0, 45, 49, 0, 502,
+ 497, 506, 0, 0, 0, 0, 599, 595, 639, 0,
+ 0, 0, 0, 0, 0, 0, 0, 644, 156, 159,
+ 169, 0, 172, 0, 362, 346, 361, 0, 346, 358,
+ 354, 353, 0, 0, 375, 376, 371, 0, 363, 367,
+ 0, 218, 219, 220, 221, 222, 223, 224, 225, 226,
+ 227, 228, 229, 230, 231, 0, 0, 0, 387, 408,
+ 0, 0, 545, 0, 545, 0, 515, 0, 0, 0,
+ 0, 0, 199, 198, 190, 190, 0, 396, 0, 0,
+ 431, 0, 431, 457, 0, 449, 0, 0, 0, 0,
+ 0, 190, 0, 190, 0, 190, 0, 190, 48, 0,
+ 59, 0, 0, 556, 557, 558, 559, 0, 174, 100,
+ 133, 136, 144, 148, 98, 592, 82, 88, 89, 93,
+ 0, 85, 0, 92, 85, 0, 85, 0, 85, 0,
+ 85, 0, 85, 84, 0, 590, 575, 600, 630, 529,
+ 649, 658, 0, 654, 654, 0, 80, 0, 653, 518,
+ 373, 673, 0, 81, 674, 0, 0, 167, 170, 347,
+ 359, 344, 355, 0, 384, 0, 368, 365, 0, 0,
+ 0, 27, 0, 0, 0, 0, 0, 536, 0, 539,
+ 386, 542, 543, 399, 398, 0, 423, 0, 0, 0,
+ 0, 0, 27, 0, 463, 0, 560, 0, 0, 566,
+ 0, 569, 0, 572, 0, 46, 0, 43, 68, 0,
+ 0, 53, 71, 55, 66, 67, 551, 0, 0, 0,
+ 0, 91, 0, 0, 117, 0, 0, 118, 0, 0,
+ 119, 0, 0, 120, 0, 83, 0, 591, 0, 0,
+ 0, 655, 656, 0, 657, 0, 0, 0, 0, 0,
+ 676, 678, 157, 0, 377, 373, 369, 232, 233, 234,
+ 190, 190, 190, 190, 0, 0, 545, 190, 190, 544,
+ 545, 549, 510, 202, 0, 431, 197, 196, 190, 442,
+ 0, 190, 190, 430, 431, 437, 458, 454, 0, 190,
+ 190, 563, 567, 570, 573, 52, 48, 71, 60, 0,
+ 0, 70, 190, 96, 85, 94, 0, 90, 85, 87,
+ 101, 0, 85, 85, 85, 134, 0, 85, 85, 137,
+ 0, 85, 145, 0, 149, 150, 0, 79, 0, 647,
+ 636, 630, 630, 80, 0, 80, 629, 0, 0, 0,
+ 374, 516, 666, 667, 664, 665, 0, 0, 0, 0,
+ 0, 0, 0, 0, 410, 24, 405, 0, 547, 546,
+ 0, 0, 0, 0, 0, 435, 0, 0, 432, 434,
+ 0, 0, 0, 0, 0, 47, 69, 0, 54, 57,
+ 72, 0, 95, 0, 86, 99, 0, 121, 0, 122,
+ 123, 132, 0, 124, 125, 0, 126, 0, 0, 173,
+ 631, 632, 0, 633, 0, 635, 27, 0, 648, 0,
+ 0, 0, 677, 372, 0, 0, 0, 190, 548, 550,
+ 190, 510, 510, 509, 203, 190, 436, 0, 190, 438,
+ 188, 186, 185, 187, 459, 0, 190, 453, 0, 564,
+ 64, 56, 0, 554, 0, 102, 103, 104, 105, 85,
+ 85, 85, 85, 138, 0, 146, 142, 151, 152, 0,
+ 80, 0, 0, 530, 373, 0, 0, 681, 682, 680,
+ 0, 0, 0, 409, 513, 511, 512, 0, 0, 433,
+ 0, 455, 0, 0, 63, 97, 0, 0, 0, 0,
+ 127, 128, 129, 130, 0, 0, 0, 147, 634, 646,
0, 0, 0, 0, 0, 0, 238, 208, 0, 80,
- 0, 214, 0, 192, 190, 0, 466, 65, 0, 61,
+ 0, 214, 0, 192, 190, 0, 467, 65, 0, 61,
106, 107, 108, 109, 110, 111, 85, 139, 0, 143,
- 141, 526, 521, 522, 523, 524, 525, 373, 519, 0,
- 527, 0, 0, 668, 665, 665, 662, 0, 207, 0,
- 212, 0, 0, 213, 0, 0, 0, 0, 465, 62,
- 0, 0, 0, 131, 0, 0, 0, 0, 27, 667,
- 666, 183, 180, 179, 182, 200, 181, 201, 211, 340,
+ 141, 527, 522, 523, 524, 525, 526, 373, 520, 0,
+ 528, 0, 0, 685, 682, 682, 679, 0, 207, 0,
+ 212, 0, 0, 213, 0, 0, 0, 0, 466, 62,
+ 0, 0, 0, 131, 0, 0, 0, 0, 27, 684,
+ 683, 183, 180, 179, 182, 200, 181, 201, 211, 340,
175, 177, 0, 176, 0, 208, 80, 239, 0, 0,
- 216, 214, 0, 189, 190, 472, 470, 80, 80, 0,
- 112, 113, 114, 115, 140, 0, 518, 194, 654, 190,
+ 216, 214, 0, 189, 190, 473, 471, 80, 80, 0,
+ 112, 113, 114, 115, 140, 0, 519, 194, 668, 190,
0, 0, 210, 209, 0, 0, 215, 0, 0, 0,
- 467, 469, 0, 0, 135, 0, 0, 0, 0, 0,
+ 468, 470, 0, 0, 135, 0, 0, 0, 0, 0,
0, 194, 241, 298, 299, 300, 301, 302, 303, 304,
243, 305, 306, 307, 308, 309, 310, 311, 312, 313,
314, 315, 316, 317, 318, 319, 320, 321, 322, 323,
324, 325, 326, 327, 328, 245, 247, 329, 330, 331,
332, 333, 0, 240, 265, 292, 272, 274, 276, 278,
- 0, 271, 288, 184, 80, 473, 373, 116, 190, 520,
- 657, 80, 0, 649, 670, 0, 0, 0, 0, 0,
+ 0, 271, 288, 184, 80, 474, 373, 116, 190, 521,
+ 671, 80, 0, 663, 687, 0, 0, 0, 0, 0,
0, 235, 0, 0, 0, 0, 0, 0, 0, 237,
- 0, 468, 0, 195, 656, 0, 190, 193, 335, 339,
+ 0, 469, 0, 195, 670, 0, 190, 193, 335, 339,
190, 190, 242, 190, 0, 190, 0, 244, 337, 190,
190, 246, 190, 0, 190, 248, 190, 190, 266, 190,
190, 190, 293, 190, 236, 190, 273, 190, 190, 275,
- 190, 277, 190, 190, 279, 190, 289, 190, 471, 0,
+ 190, 277, 190, 190, 279, 190, 289, 190, 472, 0,
0, 249, 256, 0, 253, 0, 0, 255, 0, 257,
264, 0, 261, 0, 0, 263, 267, 270, 0, 268,
294, 297, 0, 295, 280, 0, 282, 283, 284, 0,
- 286, 287, 290, 291, 654, 178, 190, 190, 0, 190,
- 0, 190, 190, 0, 190, 190, 190, 190, 190, 655,
+ 286, 287, 290, 291, 668, 178, 190, 190, 0, 190,
+ 0, 190, 190, 0, 190, 190, 190, 190, 190, 669,
252, 0, 250, 0, 254, 338, 260, 0, 258, 336,
262, 269, 296, 281, 285, 190, 0, 190, 251, 334,
259
@@ -1218,79 +1234,81 @@ static const yytype_uint16 yydefact[] =
/* YYPGOTO[NTERM-NUM]. */
static const yytype_int16 yypgoto[] =
{
- -1145, -1145, -1145, -206, -222, -184, -1145, -98, -180, 320,
- -1145, -1145, -1145, -1145, -1145, -1145, -217, -325, -571, -33,
- -675, -564, -1145, -1145, -1145, -1145, -1145, -1145, -1145, -507,
- -203, -1145, -1145, -1145, -794, -1145, -1145, -193, -39, 1855,
- 1023, -42, -1145, -668, -517, -563, -1145, -1145, -107, -1145,
- -1145, -103, -1145, -1145, -1145, -108, -252, -1145, -1145, -741,
- -1145, -1145, -1145, -1145, -1145, -684, -1145, -1145, -1145, -1145,
- -608, -1145, -1145, -1145, 0, -1145, -1145, -1145, -1145, -1145,
- 194, -1145, -1145, -452, -1145, -1145, -685, -1145, -1145, -872,
- -1145, -1145, -1145, -1145, -892, 1299, -342, -1144, -477, -1145,
- -1145, -1145, -878, -966, 73, -1145, -426, -1145, -1145, -430,
- -270, 167, -1145, -1145, -496, -915, -1145, -386, -904, -702,
- -1145, -793, -529, -1145, -1145, -1145, -1145, -533, -1145, -1145,
- -1145, -1145, -555, -523, -1145, -609, -1145, -1090, -1145, -367,
- -1145, 736, -387, -151, 544, -391, 62, -45, -315, 151,
- -1145, -1145, -1145, 242, -1145, -56, -1145, -145, -1145, -1145,
- -1145, -1145, -1145, -1145, -791, -1145, -1145, -1145, -1145, 627,
- 629, 633, 635, -232, 467, -1145, -1145, -105, 58, -1145,
- -1145, -1145, -1145, -1145, -611, -1145, -1145, -1145, 3, -1145,
- 593, -47, -1145, -1145, -1145, 637, -1145, -1145, -1145, -550,
- -1145, -1145, -1145, 558, 572, 198, -148, 4, 323, -1145,
- -1145, -1145, -1145, -1145, -1145, -1145, -344, -756, -855, -1145,
- -1145, 647, 652, -1145, 245, -1145, -375, -1145, -1145, -1145,
- -182, -1145, 660, -1145, -158, -1145, 661, -1145, -166, -1145,
- 663, -1145, -170, -1145, -1145, 413, -1145, -1145, -1145, -1145,
- -1145, 852, -321, -1145, -1145, -526, -1145, -1145, -692, -1145,
- -1145, -1145, -774, -1145, -1145, 667, -1145, -1145, 603, -1145,
- 605, -1145, -1145, 232, -569, 235, 237, 238, 673, -1145,
- -1145, -1145, -1145, -1145, 676, -1145, -1145, -1145, -1145, 681,
- -1145, -1145, 682, -1145, -1145, 684, -1145, -1145, 685, -178,
- -322, 118, -1145, -1145, -1145, -1145, -1145, -1145, -1145, -1145,
- -1145, -1145, 813, -219, -1145, -104, 405, -1145, 236, -1145,
- -1145, -1145, -768, -1145, -1145, -34, 815, -1145, -1017, -515,
- -1145, -916, 820, -1145, -1145, -1145, -424, -1145, -223
+ -1187, -1187, -1187, -219, -226, -180, -1187, -126, -132, 296,
+ -1187, -1187, -1187, -1187, -1187, -1187, -223, -334, -589, -38,
+ -715, -585, -1187, -1187, -1187, -1187, -1187, -1187, -1187, -528,
+ -245, -1187, -1187, -1187, -831, -1187, -1187, -238, -41, 1769,
+ 915, -44, -1187, -707, -567, -577, -1187, -1187, -147, -1187,
+ -1187, -144, -1187, -1187, -1187, -142, -298, -1187, -1187, -741,
+ -1187, -1187, -1187, -1187, -1187, -708, -1187, -1187, -1187, -1187,
+ -553, -1187, -1187, -1187, 0, -1187, -1187, -1187, -1187, -1187,
+ 144, -1187, -1187, -470, -1187, -1187, -698, -1187, -1187, -819,
+ -1187, -1187, -1187, -1187, -908, 1902, -408, -1186, -531, -1187,
+ -1187, -1187, -904, -1002, -40, -1187, -483, -1187, -1187, -484,
+ -278, 133, -1187, -1187, -513, -943, -1187, -440, -939, -726,
+ -1187, -959, -581, -1187, -1187, -1187, -1187, -593, -1187, -1187,
+ -1187, -1187, -641, -572, -1187, -639, -1187, -680, -1187, -427,
+ -1187, 715, -397, -162, 522, -395, 52, -184, -308, 117,
+ -1187, -1187, -1187, 197, -1187, -92, -1187, -149, -1187, -1187,
+ -1187, -1187, -1187, -1187, -804, -1187, -1187, -1187, -1187, 609,
+ 610, 612, 613, -246, 582, -1187, -1187, -93, 88, -1187,
+ -1187, -1187, -1187, -1187, -529, -1187, -1187, -1187, 2, -1187,
+ 454, -42, -1187, -1187, -1187, 624, -1187, -1187, -1187, -575,
+ -1187, -1187, -1187, 559, 560, 291, -191, 7, 293, -1187,
+ -1187, -1187, -1187, -1187, -1187, -1187, -356, -769, -883, -1187,
+ -1187, 633, 636, -1187, 207, -1187, -433, -1187, -1187, -1187,
+ -179, -1187, 641, -1187, -148, -1187, 647, -1187, -160, -1187,
+ 648, -1187, -158, -1187, -1187, 387, -1187, -1187, -1187, -1187,
+ -1187, 488, -325, -1187, -1187, -360, -1187, -1187, -729, -1187,
+ -1187, -1187, -774, -1187, -1187, 651, -1187, -1187, 589, -1187,
+ 592, -1187, -1187, 199, -558, 209, 211, 218, 676, -1187,
+ -1187, -1187, -1187, -1187, 679, -1187, -1187, -1187, -1187, 684,
+ -1187, -1187, 687, -1187, -1187, 689, -1187, -1187, 697, -168,
+ -303, 119, -1187, -1187, -1187, -1187, -1187, -1187, -1187, -1187,
+ -1187, -1187, 827, -1187, 511, -233, -1187, -107, -203, -1187,
+ -1187, -48, -1187, 43, -1187, -1187, -1187, -785, -1187, -1187,
+ -1187, 515, -17, 839, -1187, -1187, 518, -1061, -525, -1187,
+ -923, 850, -1187, -1187, -1187, -77, -1187, -416, -1187, -232
};
/* YYDEFGOTO[NTERM-NUM]. */
static const yytype_int16 yydefgoto[] =
{
- -1, 37, 38, 39, 222, 585, 224, 841, 225, 821,
- 226, 227, 391, 392, 228, 328, 229, 230, 851, 555,
- 474, 556, 475, 658, 847, 557, 770, 923, 558, 771,
- 850, 983, 984, 1058, 772, 773, 774, 852, 108, 208,
- 361, 430, 879, 574, 712, 780, 675, 676, 677, 678,
- 679, 680, 681, 862, 985, 682, 683, 684, 867, 685,
- 686, 871, 995, 1068, 1145, 687, 1036, 688, 874, 997,
- 689, 690, 877, 1000, 460, 331, 41, 133, 232, 399,
- 400, 401, 580, 402, 403, 582, 692, 693, 1119, 1261,
- 1121, 1122, 977, 978, 834, 362, 634, 1123, 1166, 835,
- 635, 1124, 830, 968, 422, 423, 1088, 424, 425, 1093,
- 426, 614, 615, 616, 817, 1047, 1049, 1051, 1048, 1128,
- 1212, 1262, 1271, 1213, 1278, 1220, 1286, 1291, 1221, 1296,
- 1244, 1282, 1214, 1263, 1264, 1272, 1273, 1265, 1266, 1126,
- 42, 239, 333, 503, 44, 334, 240, 135, 234, 507,
- 235, 413, 589, 407, 408, 586, 584, 241, 242, 417,
- 418, 599, 511, 595, 806, 596, 812, 46, 47, 48,
- 49, 50, 51, 427, 137, 52, 53, 243, 409, 527,
- 55, 140, 258, 442, 428, 429, 619, 822, 244, 57,
- 142, 196, 283, 284, 463, 58, 59, 260, 261, 748,
- 262, 263, 264, 245, 246, 431, 837, 893, 354, 61,
- 145, 269, 270, 453, 449, 917, 701, 643, 842, 979,
- 62, 63, 64, 275, 457, 1098, 1138, 1139, 1226, 65,
+ -1, 37, 38, 39, 228, 606, 230, 866, 231, 844,
+ 232, 233, 409, 410, 234, 339, 235, 236, 880, 575,
+ 492, 576, 493, 679, 876, 577, 791, 958, 578, 792,
+ 879, 1021, 1022, 1098, 793, 794, 795, 881, 108, 208,
+ 372, 448, 908, 595, 733, 801, 696, 697, 698, 699,
+ 700, 701, 702, 891, 1024, 703, 704, 705, 896, 706,
+ 707, 900, 1034, 1108, 1185, 708, 1076, 709, 903, 1036,
+ 710, 711, 906, 1039, 478, 342, 41, 133, 238, 417,
+ 418, 419, 601, 420, 421, 603, 713, 714, 1159, 1301,
+ 1161, 1162, 1014, 1015, 859, 373, 655, 1163, 1206, 860,
+ 656, 1164, 854, 1005, 440, 441, 1128, 442, 443, 1133,
+ 444, 635, 636, 637, 840, 1087, 1089, 1091, 1088, 1168,
+ 1252, 1302, 1311, 1253, 1318, 1260, 1326, 1331, 1261, 1336,
+ 1284, 1322, 1254, 1303, 1304, 1312, 1313, 1305, 1306, 1166,
+ 42, 245, 344, 523, 44, 345, 246, 135, 240, 527,
+ 241, 431, 610, 425, 426, 607, 605, 247, 248, 435,
+ 436, 620, 531, 616, 827, 617, 835, 46, 47, 48,
+ 49, 50, 51, 445, 137, 52, 53, 249, 427, 547,
+ 55, 140, 264, 460, 446, 447, 640, 845, 250, 57,
+ 142, 196, 289, 290, 481, 58, 59, 266, 267, 769,
+ 268, 269, 270, 251, 252, 449, 862, 922, 365, 61,
+ 145, 275, 276, 471, 467, 952, 722, 664, 867, 1016,
+ 62, 63, 64, 281, 475, 1138, 1178, 1179, 1266, 65,
66, 67, 68, 69, 70, 71, 72, 73, 74, 75,
- 76, 77, 78, 203, 79, 303, 304, 477, 305, 306,
- 480, 894, 910, 435, 626, 488, 489, 709, 702, 1077,
- 1078, 1079, 703, 704, 1005, 80, 81, 82, 247, 83,
- 248, 84, 85, 249, 733, 250, 251, 252, 86, 87,
- 155, 309, 310, 666, 88, 277, 278, 279, 280, 89,
- 288, 289, 90, 293, 294, 91, 298, 299, 92, 93,
- 312, 565, 94, 157, 316, 317, 485, 95, 175, 96,
- 176, 177, 895, 798, 98, 179, 183, 184, 322, 323,
- 884, 885, 705, 706, 99, 570, 896, 101, 897, 1168,
- 102, 711, 313, 104, 492, 1009, 1045, 493, 1010
+ 76, 77, 78, 203, 79, 309, 310, 495, 311, 312,
+ 498, 923, 942, 453, 647, 927, 509, 730, 723, 1117,
+ 1118, 1119, 724, 725, 1044, 80, 81, 82, 253, 83,
+ 254, 84, 85, 255, 754, 256, 257, 258, 86, 87,
+ 155, 315, 316, 687, 88, 283, 284, 285, 286, 89,
+ 294, 295, 90, 299, 300, 91, 304, 305, 92, 93,
+ 318, 585, 94, 157, 322, 323, 503, 95, 175, 96,
+ 176, 177, 924, 211, 212, 819, 98, 179, 325, 326,
+ 505, 327, 184, 333, 334, 913, 914, 726, 727, 99,
+ 214, 215, 591, 925, 101, 217, 218, 926, 1208, 102,
+ 732, 319, 104, 512, 830, 831, 1048, 1085, 513, 1049
};
/* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If
@@ -1298,656 +1316,672 @@ static const yytype_int16 yydefgoto[] =
number is the opposite. If YYTABLE_NINF, syntax error. */
static const yytype_int16 yytable[] =
{
- 40, 393, 223, 56, 60, 325, 109, 327, 324, 450,
- 257, 960, 276, 110, 111, 501, 112, 406, 113, 500,
- 114, 899, 115, 883, 180, 181, 116, 311, 117, 886,
- 118, 297, 119, 292, 120, 970, 121, 803, 122, 287,
- 123, 863, 697, 888, 253, 578, 889, 674, 124, 274,
- 329, 660, 700, 1054, 735, 125, 924, 126, 54, 127,
- 483, 128, 45, 129, 1107, 130, 132, 134, 136, 136,
- 139, 141, 136, 144, 136, 141, 136, 141, 136, 141,
- 136, 141, 154, 156, 254, 178, 178, 178, 456, 769,
- 1042, 750, 856, 764, 860, 419, 1003, 860, 864, 1281,
- 860, 868, 198, 860, 200, 882, 860, 1056, 1050, 1052,
- 394, 419, 832, 438, 7, 2, 15, 833, 875, 1,
- 783, 824, 786, 15, 789, 4, 792, 2, 794, 12,
- 1134, 1115, 105, 419, 5, 965, 836, 4, 433, 1259,
- 296, 10, 1055, 420, 231, 214, 397, 5, 1115, 1274,
- 1274, 5, 1279, 1283, 33, 1288, 667, 1293, 1293, 473,
- 1297, 33, 238, 5, 832, 19, 484, 24, 441, 833,
- 421, 233, 1125, 495, 865, 455, 131, 869, 1346, 1001,
- 872, 1008, 494, 233, 405, 673, 421, 987, 1052, 34,
- 1024, 31, 32, 591, 26, 282, 335, 301, 29, 1228,
- 5, 336, 302, 338, 311, 1117, 340, 341, 421, 667,
- 182, 828, 349, 1337, 1041, 1120, 948, 964, 950, 21,
- 645, 1342, 1117, 185, 10, 1120, 351, 352, 1147, 1059,
- 447, 355, 818, 819, 356, 1347, 671, 672, 1299, 1348,
- -619, 360, 694, 36, 988, 364, 860, 990, 860, 259,
- 367, 1232, 860, 1149, 907, 370, 273, 908, 844, 698,
- 373, 848, 566, 809, 1099, 376, 456, 379, 998, 1256,
- 1084, 381, 1170, 1171, 31, 32, 1, 592, 383, 922,
- 881, 912, 898, 920, 388, 1060, 1105, 1082, 398, 915,
- 628, 414, 927, 412, 134, 598, 929, 5, 236, 5,
- 932, 934, 935, 669, 670, 938, 939, 237, 667, 941,
- -621, 454, 1071, 452, 134, 19, 1072, 1073, 1074, 1075,
- 989, 286, 462, 991, 267, 992, 671, 672, 238, 993,
- 300, 301, 17, 1038, 476, 768, 672, 479, 657, 34,
- 415, 659, 1061, 1063, 860, 233, 268, 437, 447, 696,
- 2, 26, 5, 448, 444, 29, 5, 5, 650, 5,
- 4, 667, 498, 461, 499, 281, 667, 1270, 1270, 504,
- 1277, 670, 620, 622, 1076, 5, 725, 698, 670, 512,
- 1259, 1090, 656, 654, 638, 640, 311, 513, 652, 1129,
- 516, -622, 1132, 671, 672, 649, 520, 395, 396, 1231,
- 671, 672, 631, -623, 1111, 393, 632, 810, 1112, 1113,
- 1114, 533, 621, 623, 5, 308, 1140, 537, 1062, 1064,
- 1065, 1066, 321, 500, 639, 641, 393, 1030, 1031, 1032,
- 1033, 1336, 447, 718, 1339, 1252, 720, 843, 464, 1341,
- 5, 467, 1344, 659, 470, 1267, 1345, 10, 326, 1,
- 571, -30, 501, 1289, 575, 216, 579, 581, 1153, 416,
- 21, 1366, 106, 107, 236, 291, 1116, 433, 238, 1160,
- 1161, 714, 17, 237, 618, 206, 207, 631, 625, 1365,
- 7, 632, 271, -59, 36, 1367, 5, 5, -59, -59,
- -59, 642, 1141, 1142, 1143, 667, 420, 31, 32, 669,
- 670, 238, 583, 1103, 832, 17, 588, 5, 813, 833,
- 487, 131, 215, 216, 5, 217, 218, 219, 220, 221,
- 314, 315, 671, 672, 26, 768, 633, 1083, 29, 708,
- 553, 1111, 554, 178, 491, 1112, 1113, 1114, 396, 432,
- 5, 5, 395, 1258, 1258, 1259, 1259, 710, 846, 445,
- 446, 659, 849, 220, 221, 1227, 1251, 724, 459, 814,
- 815, 816, 5, 1254, 691, 466, 1268, 1259, 469, 691,
- 1118, 472, 553, 691, 845, 1130, 473, 405, 138, 482,
- 1136, 143, -51, 146, 554, 148, 766, 150, 617, 152,
- 593, 594, 624, 1116, 627, 668, 744, 629, 630, 878,
- 1215, 637, 1222, 870, 1111, 554, 873, 1046, 1112, 1113,
- 1114, 1007, 648, 672, 5, 318, 319, 320, 651, 1259,
- 486, 653, 490, 973, 655, 765, 393, 974, 975, 976,
- 233, 405, 820, 659, 849, 661, 671, 672, 1292, 1292,
- 778, 905, 781, 1016, 1017, 784, 390, 787, 925, 790,
- 1230, 793, 131, 215, 795, 921, 217, 218, 219, 768,
- 1109, 1110, 799, 945, 946, 802, 1116, 804, 800, 801,
- 854, 858, 807, 1111, 1046, 857, 986, 1112, 1113, 1114,
- 1115, 215, 811, 5, 217, 218, 219, 220, 221, 766,
- 577, 767, 667, 1069, 1236, 668, 669, 670, 768, 1152,
- 1007, 1156, 829, 1111, 647, 982, 1131, 1112, 1113, 1114,
- 147, 1275, 149, 5, 151, 1294, 153, 1268, 1259, 671,
- 672, 673, 1287, 1046, 215, 216, 473, 217, 218, 219,
- 1137, 967, 5, 768, 823, 1116, 43, 826, 272, 861,
- 721, 667, 866, 1002, 668, 669, 670, 587, 890, 831,
- 265, 876, 839, 158, 1117, 159, 994, 642, 996, 160,
- 642, 161, 1023, 162, 266, 1116, 971, 659, 671, 672,
- 673, 215, 532, 163, 217, 218, 219, 855, 164, 859,
- 853, 646, 859, 393, 1224, 859, 165, 166, 859, 167,
- 478, 859, 255, 168, 256, 662, 913, 691, 663, 169,
- 664, 665, 170, 1, 2, 891, 1057, 171, 172, 3,
- 173, 174, 796, 97, 4, 100, 5, 6, 5, 1349,
- 103, 1085, 0, 7, 0, 0, 8, 667, 0, 0,
- 668, 669, 670, 9, 10, 0, 11, 0, 12, 967,
- 0, 659, 0, 13, 699, 14, 949, 0, 15, 0,
- 1067, 16, 0, 0, 671, 672, 673, 0, 0, 17,
- 5, 0, 18, 0, 19, 20, 21, 22, 0, 667,
- 0, 829, 668, 669, 670, 23, 24, 25, 26, 27,
- 0, 28, 29, 30, 31, 32, 33, 0, 34, 35,
- 36, 0, 0, 0, 0, 0, 671, 672, 673, 215,
- 216, 999, 217, 218, 219, 220, 221, 0, 215, 963,
- 1004, 217, 218, 219, 220, 221, 967, 0, 767, 1111,
- 1144, 0, 0, 1112, 1113, 1114, 1115, 0, 0, 5,
- 0, 859, 0, 859, 0, 0, 0, 859, 667, 1020,
- 0, 668, 669, 670, 0, 0, 0, 691, 1135, 215,
- 216, 0, 217, 218, 219, 220, 221, 0, 0, 767,
- 5, 0, 0, 3, 0, 671, 672, 673, 1043, 667,
- 5, 6, 668, 669, 670, 0, 0, 0, 829, 667,
- 8, 1116, 668, 669, 670, 967, 699, 9, 710, 0,
- 0, 0, 0, 0, 0, 0, 671, 672, 673, 14,
- 1117, 642, 0, 1081, 0, 16, 671, 672, 673, 1089,
- 0, 1091, 0, 1094, 0, 0, 18, 0, 0, 20,
- 0, 22, 0, 0, 0, 0, 0, 0, 0, 859,
+ 40, 335, 56, 411, 109, 336, 229, 60, 468, 338,
+ 328, 110, 111, 330, 112, 282, 113, 695, 114, 824,
+ 115, 180, 181, 721, 116, 997, 117, 520, 118, 521,
+ 119, 929, 120, 915, 121, 424, 122, 317, 123, 298,
+ 259, 508, 1007, 303, 912, 280, 124, 599, 959, 293,
+ 681, 917, 45, 125, 918, 126, 1094, 127, 263, 128,
+ 1147, 129, 892, 130, 132, 134, 136, 136, 139, 141,
+ 136, 144, 136, 141, 136, 141, 136, 141, 136, 141,
+ 154, 156, 183, 178, 178, 178, 756, 771, 54, 911,
+ 501, 474, 790, 785, 1, 893, 260, 1321, 897, 904,
+ 885, 1, 889, 1042, 340, 889, 1, 198, 889, 200,
+ 456, 889, 1090, 1092, 889, 412, 242, 1155, 437, 1096,
+ 5, 15, 1082, 465, 5, 243, 507, 804, 438, 807,
+ 5, 810, 5, 813, 1174, 815, 287, 437, 437, 856,
+ 182, 688, 237, 220, 857, 2, 244, 105, 5, 5,
+ 17, 1155, 719, 244, 5, 4, 1095, 17, 307, 1299,
+ 33, 415, 2, 432, 491, 329, 131, 1002, 331, 693,
+ 26, 502, 4, 19, 29, 7, 1386, 26, 324, 324,
+ 185, 29, 26, 472, 1165, 515, 29, 514, 465, 473,
+ 12, 1064, 1157, 1092, 439, 288, 5, 1040, 34, 451,
+ 346, 239, 308, 1268, 182, 347, 983, 349, 985, 15,
+ 351, 352, 1001, 439, 439, 239, 1047, 719, 239, 423,
+ 612, 691, 1026, 360, 848, 317, 1157, 459, 24, 718,
+ 362, 363, 1099, 302, 1339, 366, 841, 842, 367, 861,
+ 1081, -621, 1187, 692, 693, 371, 279, 666, 33, 375,
+ 894, 910, 465, 898, 378, 1027, 901, -623, 1029, 381,
+ 5, 877, 869, 1037, 384, 1189, 832, 1139, 889, 387,
+ 889, 390, 5, 1296, 889, 392, 586, 10, 474, 265,
+ 944, 715, 394, 613, 1272, 397, 1210, 1211, 937, 950,
+ 957, 955, 940, 406, 1111, 314, 649, 416, 1112, 1113,
+ 1114, 1115, 430, 134, 273, 306, 307, 962, 1160, 619,
+ 1124, 964, 21, 1145, 1122, 967, 969, 970, 1160, 1307,
+ 973, 974, 470, 134, 976, 1100, 274, 1329, 31, 32,
+ -624, 480, 5, 1078, 652, 2, 482, 36, 653, 485,
+ 5, 688, 488, 494, 5, 4, 497, 789, -625, 688,
+ 433, 329, 678, 504, 331, 680, 1116, 455, 1101, 1103,
+ -59, 413, 414, 717, 466, -59, -59, -59, 462, 19,
+ 694, 889, 106, 107, 479, 292, 692, 693, 518, 21,
+ 519, 671, 1130, 652, 297, 524, 1151, 653, 641, 643,
+ 1152, 1153, 1154, 746, 34, 532, 5, 856, 852, 10,
+ 659, 661, 857, 533, 36, 1169, 536, 5, 1172, 675,
+ 1028, 670, 540, 1030, 677, 1031, 317, 411, 673, 1032,
+ 244, 5, 1271, 332, 1151, 1308, 1299, 553, 1152, 1153,
+ 1154, 242, 1180, 557, 5, 833, 520, 1298, 411, 1299,
+ 243, 506, 337, 739, 642, 644, 741, 510, 1156, -30,
+ 31, 32, 1070, 1071, 1072, 1073, 660, 662, 680, 1193,
+ 1310, 1310, 1292, 1317, 5, 868, 222, 1298, 592, 1299,
+ 1200, 1201, 596, 521, 600, 602, 131, 221, 222, 434,
+ 223, 224, 225, 226, 227, 1406, 1156, 690, 691, 735,
+ 451, 5, 639, 5, 7, 638, 646, 856, 1299, 645,
+ 688, 648, 857, 5, 650, 651, 206, 207, 658, 663,
+ 692, 693, 438, 1102, 1104, 1105, 1106, 1123, 573, 669,
+ 574, 413, 604, 836, 1376, 672, 609, 1379, 674, 1143,
+ 507, 676, 1381, 221, 10, 1384, 223, 224, 225, 1385,
+ 511, -51, 682, 574, 5, 789, 654, 414, 729, 837,
+ 838, 839, 178, 688, 1255, 244, 1262, 1291, 691, 17,
+ 1158, 320, 321, 875, 1294, 1170, 680, 878, 423, 277,
+ 1176, 147, 1405, 149, 1086, 151, 745, 153, 1407, 731,
+ 692, 693, 573, 5, 712, 31, 32, 1181, 1182, 1183,
+ 712, 491, 688, 787, 712, 689, 690, 691, 870, 1314,
+ 1314, 689, 1319, 1323, 1086, 1328, 574, 1333, 1333, 907,
+ 1337, 693, 1151, 226, 227, 765, 1152, 1153, 1154, 692,
+ 693, 694, 5, 614, 615, 843, 928, 1299, 899, 239,
+ 423, 902, 1151, 408, 1046, 960, 1152, 1153, 1154, 956,
+ 1270, 786, 5, 450, 692, 693, 1308, 1299, 1332, 1332,
+ 1267, 883, 411, 463, 464, 886, 680, 878, 887, 799,
+ 598, 802, 477, 1377, 805, 1025, 808, 1109, 811, 484,
+ 814, 1382, 487, 816, 1156, 490, 1055, 1056, 980, 981,
+ 1276, 820, 1192, 500, 823, 1387, 825, 1196, 789, 1388,
+ 668, 828, 1171, 138, 1156, 1334, 143, 465, 146, 1315,
+ 148, 834, 150, 465, 152, 5, 821, 822, 1149, 1150,
+ 1177, 5, 935, 1327, 688, 43, 278, 689, 690, 691,
+ 688, 853, 608, 689, 690, 691, 719, 742, 1046, 789,
+ 909, 720, 719, 919, 1020, 158, 159, 720, 160, 161,
+ 1010, 692, 693, 694, 1011, 1012, 1013, 692, 693, 694,
+ 162, 271, 272, 847, 846, 491, 1008, 850, 890, 163,
+ 552, 895, 164, 667, 789, 1041, 1264, 165, 858, 855,
+ 905, 5, 864, 166, 167, 496, 663, 168, 261, 663,
+ 688, 262, 683, 221, 690, 691, 223, 224, 225, 226,
+ 227, 787, 684, 788, 685, 1033, 1063, 1035, 884, 680,
+ 888, 686, 169, 888, 882, 170, 888, 692, 693, 888,
+ 171, 1004, 888, 172, 411, 173, 131, 221, 712, 946,
+ 223, 224, 225, 174, 1, 2, 920, 97, 221, 222,
+ 3, 223, 224, 225, 817, 4, 396, 5, 6, 100,
+ 1097, 452, 454, 400, 7, 457, 458, 8, 403, 1389,
+ 103, 992, 1125, 0, 9, 10, 0, 11, 476, 12,
+ 0, 0, 0, 0, 13, 483, 14, 0, 486, 15,
+ 0, 489, 16, 984, 0, 680, 0, 0, 0, 499,
+ 17, 0, 0, 18, 0, 19, 20, 21, 22, 0,
+ 0, 0, 0, 0, 1107, 0, 23, 24, 0, 25,
+ 26, 27, 853, 28, 29, 30, 31, 32, 33, 0,
+ 34, 35, 36, 1151, 1086, 0, 5, 1152, 1153, 1154,
+ 1155, 0, 0, 5, 0, 688, 1004, 0, 689, 690,
+ 691, 0, 688, 0, 1038, 689, 690, 691, 3, 0,
+ 0, 1000, 720, 1043, 731, 0, 6, 0, 0, 0,
+ 0, 0, 692, 693, 694, 8, 0, 0, 0, 692,
+ 693, 694, 9, 0, 1184, 11, 888, 0, 888, 0,
+ 0, 0, 888, 0, 1060, 1156, 0, 0, 0, 0,
+ 16, 465, 712, 0, 0, 0, 0, 0, 0, 5,
+ 0, 18, 0, 0, 20, 1157, 22, 0, 688, 0,
+ 0, 689, 690, 691, 1004, 1083, 0, 25, 5, 27,
+ 719, 28, 0, 30, 0, 0, 853, 688, 0, 35,
+ 689, 690, 691, 0, 0, 692, 693, 694, 0, 0,
+ 0, 0, 0, 0, 720, 0, 0, 0, 0, 663,
+ 0, 1121, 0, 0, 692, 693, 694, 1129, 186, 1131,
+ 187, 1134, 188, 189, 0, 190, 0, 191, 192, 0,
+ 193, 194, 195, 197, 195, 199, 195, 201, 202, 888,
+ 204, 0, 205, 1004, 0, 0, 0, 0, 1146, 0,
+ 0, 0, 0, 0, 712, 1167, 0, 1167, 0, 0,
+ 1167, 0, 209, 0, 210, 213, 216, 5, 219, 0,
+ 0, 0, 853, 0, 0, 0, 688, 0, 0, 689,
+ 690, 691, 0, 0, 0, 0, 1175, 0, 0, 0,
+ 0, 1190, 0, 1191, 0, 1380, 0, 712, 0, 0,
+ 0, 0, 712, 692, 693, 694, 0, 712, 1202, 0,
+ 0, 0, 0, 1004, 0, 0, 853, 853, 0, 0,
+ 0, 0, 0, 341, 0, 343, 0, 0, 1265, 0,
+ 0, 0, 348, 0, 350, 1378, 0, 0, 353, 354,
+ 0, 0, 0, 1383, 355, 356, 357, 358, 0, 359,
+ 195, 361, 221, 222, 0, 223, 224, 225, 226, 227,
+ 364, 0, 788, 0, 0, 368, 369, 0, 370, 712,
+ 0, 0, 0, 0, 374, 0, 0, 712, 376, 377,
+ 0, 0, 0, 379, 380, 0, 0, 0, 382, 383,
+ 0, 0, 0, 5, 0, 0, 388, 0, 0, 0,
+ 391, 1295, 688, 393, 0, 689, 690, 691, 0, 0,
+ 395, 0, 398, 399, 401, 402, 404, 1151, 405, 0,
+ 0, 1152, 1153, 1154, 1155, 0, 0, 5, 0, 692,
+ 693, 694, 0, 1345, 0, 1348, 688, 0, 0, 689,
+ 690, 691, 1353, 0, 0, 0, 1175, 1300, 1300, 1309,
+ 1309, 0, 1316, 1320, 0, 1325, 1300, 1330, 1330, 0,
+ 1335, 0, 0, 692, 693, 694, 221, 0, 0, 223,
+ 224, 225, 226, 227, 0, 0, 788, 0, 0, 1156,
+ 621, 622, 623, 624, 625, 626, 627, 628, 629, 630,
+ 631, 632, 633, 634, 0, 0, 0, 0, 0, 1157,
+ 0, 0, 516, 517, 0, 0, 0, 0, 0, 343,
+ 522, 0, 525, 0, 0, 0, 526, 528, 529, 0,
+ 530, 621, 622, 623, 624, 625, 626, 627, 628, 629,
+ 0, 535, 0, 0, 537, 538, 0, 539, 0, 541,
+ 542, 0, 544, 545, 0, 546, 0, 548, 549, 550,
+ 0, 0, 364, 0, 0, 0, 0, 555, 556, 0,
+ 0, 559, 560, 0, 0, 0, 0, 0, 565, 566,
+ 0, 568, 569, 0, 571, 572, 0, 0, 0, 0,
+ 0, 0, 3, 0, 582, 583, 584, 0, 0, 5,
+ 6, 589, 0, 590, 0, 593, 0, 594, 688, 8,
+ 0, 689, 690, 691, 0, 0, 9, 131, 221, 222,
+ 0, 223, 224, 225, 226, 227, 221, 222, 14, 223,
+ 224, 225, 226, 227, 16, 692, 693, 694, 0, 0,
+ 0, 0, 0, 0, 0, 18, 0, 0, 20, 0,
+ 22, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 25, 0, 27, 0, 28, 0, 30, 0, 0,
- 1106, 0, 0, 35, 691, 0, 0, 1127, 0, 1127,
- 0, 0, 1127, 0, 3, 967, 0, 0, 0, 0,
- 0, 0, 6, 0, 829, 0, 0, 0, 131, 215,
- 216, 8, 217, 218, 219, 220, 221, 0, 9, 0,
- 0, 11, 0, 1150, 0, 1151, 0, 691, 0, 0,
- 0, 1340, 691, 0, 447, 0, 16, 691, 0, 0,
- 1162, 0, 5, 0, 0, 0, 0, 18, 829, 829,
- 20, 667, 22, 0, 668, 669, 670, 0, 0, 0,
- 1225, 1338, 25, 698, 27, 0, 28, 0, 30, 1343,
- 0, 0, 0, 0, 35, 0, 0, 0, 671, 672,
- 673, 600, 601, 602, 603, 604, 605, 606, 607, 608,
- 609, 610, 611, 612, 613, 0, 186, 0, 187, 691,
- 188, 189, 0, 190, 0, 191, 192, 691, 193, 194,
- 195, 197, 195, 199, 195, 201, 202, 5, 204, 0,
- 205, 0, 0, 0, 0, 0, 667, 0, 0, 668,
- 669, 670, 0, 1255, 434, 436, 1135, 0, 439, 440,
- 209, 0, 210, 211, 212, 0, 213, 0, 0, 0,
- 0, 458, 0, 671, 672, 673, 0, 0, 465, 0,
- 0, 468, 0, 0, 471, 1305, 0, 1308, 0, 0,
- 0, 0, 481, 0, 1313, 0, 0, 1260, 1260, 1269,
- 1269, 0, 1276, 1280, 0, 1285, 1260, 1290, 1290, 0,
- 1295, 0, 0, 0, 0, 330, 0, 332, 0, 0,
- 0, 0, 0, 0, 337, 0, 339, 0, 0, 0,
- 342, 343, 0, 0, 0, 0, 344, 345, 346, 347,
- 0, 348, 195, 350, 0, 0, 0, 0, 0, 0,
- 0, 0, 353, 0, 0, 3, 0, 357, 358, 0,
- 359, 0, 0, 6, 0, 0, 363, 0, 0, 0,
- 365, 366, 8, 0, 0, 368, 369, 0, 0, 9,
- 371, 372, 0, 0, 0, 0, 0, 0, 377, 0,
- 0, 14, 380, 0, 0, 382, 0, 16, 0, 447,
- 0, 384, 385, 386, 0, 387, 0, 5, 18, 0,
- 0, 20, 0, 22, 0, 0, 667, 0, 0, 668,
- 669, 670, 0, 25, 0, 27, 0, 28, 698, 30,
- 447, 0, 880, 699, 0, 35, 0, 0, 5, 0,
- 0, 0, 0, 671, 672, 673, 0, 667, 0, 0,
- 668, 669, 670, 0, 0, 0, 0, 0, 0, 698,
- 0, 0, 0, 0, 699, 600, 601, 602, 603, 604,
- 605, 606, 607, 608, 671, 672, 673, 0, 0, 0,
- 0, 0, 496, 497, 0, 0, 0, 0, 0, 332,
- 502, 0, 505, 0, 0, 0, 506, 508, 509, 0,
- 510, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 515, 0, 0, 517, 518, 0, 519, 0, 521,
- 522, 0, 524, 525, 0, 526, 0, 528, 529, 530,
- 0, 0, 353, 0, 0, 0, 0, 535, 536, 0,
- 0, 539, 540, 0, 0, 0, 0, 0, 545, 546,
- 0, 548, 549, 0, 551, 552, 0, 0, 0, 0,
- 0, 0, 0, 0, 562, 563, 564, 0, 0, 568,
- 0, 569, 0, 572, 0, 573, 1172, 1173, 1174, 1175,
- 1176, 1177, 1178, 1179, 1180, 1181, 1182, 1183, 1184, 1185,
- 1186, 1187, 1188, 1189, 1190, 1191, 1192, 1193, 1194, 1195,
- 1196, 1197, 1198, 1199, 1200, 1201, 1202, 1203, 1204, 1205,
- 1206, 1207, 1208, 1209, 1210, 1211, 1216, 1173, 1174, 1175,
- 1176, 1177, 1178, 1179, 1217, 1181, 1182, 1183, 1184, 1185,
- 1186, 1187, 1188, 1189, 1190, 1191, 1192, 1193, 1194, 1195,
- 1196, 1197, 1198, 1199, 1200, 1201, 1202, 1203, 1204, 1218,
- 1219, 1207, 1208, 1209, 1210, 1211, 0, 0, 0, 0,
- 715, 374, 375, 0, 378, 0, 0, 502, 0, 0,
- 502, 0, 506, 0, 722, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 727, 728, 729,
- 0, 0, 730, 731, 732, 734, 732, 0, 0, 737,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 746, 747, 749, 747, 0, 751, 0, 752, 0,
- 754, 0, 756, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 776,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 777, 0, 779, 0, 0, 782, 0, 785, 0,
- 788, 0, 791, 0, 791, 0, 0, 564, 0, 0,
- 797, 0, 0, 0, 0, 569, 569, 0, 573, 0,
- 0, 0, 805, 0, 0, 0, 0, 808, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 531, 0, 0,
- 0, 0, 534, 0, 0, 0, 0, 0, 0, 541,
- 542, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1173, 1174, 1175, 1176, 1177, 1178, 1179, 560, 1181, 1182,
- 1183, 1184, 1185, 1186, 1187, 1188, 1189, 1190, 1191, 1192,
- 1193, 1194, 1195, 1196, 1197, 1198, 1199, 1200, 1201, 1202,
- 1203, 1204, 0, 0, 1207, 1208, 1209, 1210, 1211, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 722, 0, 805, 0, 0, 0, 0,
- 0, 0, 0, 903, 0, 0, 732, 0, 0, 732,
- 0, 909, 0, 911, 747, 0, 0, 0, 0, 914,
- 0, 0, 747, 0, 0, 916, 752, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 791, 0,
- 928, 0, 791, 0, 0, 0, 931, 933, 791, 0,
- 0, 937, 791, 0, 940, 791, 0, 942, 0, 0,
- 943, 0, 0, 0, 0, 797, 797, 947, 0, 573,
- 0, 951, 952, 0, 0, 0, 0, 0, 0, 0,
- 0, 955, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 742, 743, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 35, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 3, 0, 736, 0, 0, 0, 0, 0, 6,
+ 522, 0, 0, 522, 0, 526, 0, 743, 8, 0,
+ 0, 0, 0, 0, 0, 9, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 14, 0, 0,
+ 748, 749, 750, 16, 0, 751, 752, 753, 755, 753,
+ 0, 0, 758, 0, 18, 0, 0, 20, 0, 22,
+ 0, 0, 0, 0, 767, 768, 770, 768, 0, 772,
+ 25, 773, 27, 775, 28, 777, 30, 0, 0, 0,
+ 0, 0, 35, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 797, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 798, 0, 800, 0, 0, 803,
+ 0, 806, 0, 809, 0, 812, 0, 812, 0, 0,
+ 584, 0, 0, 818, 0, 0, 0, 0, 590, 590,
+ 0, 594, 0, 0, 0, 826, 0, 0, 0, 0,
+ 829, 1212, 1213, 1214, 1215, 1216, 1217, 1218, 1219, 1220,
+ 1221, 1222, 1223, 1224, 1225, 1226, 1227, 1228, 1229, 1230,
+ 1231, 1232, 1233, 1234, 1235, 1236, 1237, 1238, 1239, 1240,
+ 1241, 1242, 1243, 1244, 1245, 1246, 1247, 1248, 1249, 1250,
+ 1251, 1256, 1213, 1214, 1215, 1216, 1217, 1218, 1219, 1257,
+ 1221, 1222, 1223, 1224, 1225, 1226, 1227, 1228, 1229, 1230,
+ 1231, 1232, 1233, 1234, 1235, 1236, 1237, 1238, 1239, 1240,
+ 1241, 1242, 1243, 1244, 1258, 1259, 1247, 1248, 1249, 1250,
+ 1251, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 743, 0,
+ 826, 0, 0, 0, 0, 0, 0, 0, 933, 0,
+ 0, 753, 0, 0, 0, 753, 0, 941, 0, 943,
+ 768, 0, 0, 0, 0, 0, 947, 0, 0, 768,
+ 0, 0, 951, 773, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 812,
+ 0, 963, 0, 812, 0, 0, 0, 966, 968, 812,
+ 0, 0, 972, 812, 0, 975, 812, 0, 977, 0,
+ 0, 978, 0, 0, 0, 0, 818, 818, 982, 0,
+ 594, 0, 986, 987, 0, 0, 0, 0, 0, 0,
+ 0, 0, 990, 991, 1213, 1214, 1215, 1216, 1217, 1218,
+ 1219, 0, 1221, 1222, 1223, 1224, 1225, 1226, 1227, 1228,
+ 1229, 1230, 1231, 1232, 1233, 1234, 1235, 1236, 1237, 1238,
+ 1239, 1240, 1241, 1242, 1243, 1244, 0, 0, 1247, 1248,
+ 1249, 1250, 1251, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 1006, 0, 0,
- 1011, 1012, 1013, 0, 0, 0, 0, 909, 909, 0,
- 0, 0, 0, 1019, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 1022, 0, 0, 0, 0, 1026,
- 1027, 1028, 0, 1029, 791, 791, 791, 0, 1034, 0,
- 1035, 0, 0, 0, 573, 0, 1040, 0, 805, 0,
- 0, 0, 1044, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1045, 0, 0, 0, 0, 1050,
+ 1051, 1052, 0, 0, 0, 0, 941, 941, 0, 0,
+ 0, 0, 1058, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1062, 0, 0, 0, 0, 0, 0,
+ 1066, 1067, 1068, 0, 1069, 812, 812, 812, 0, 1074,
+ 0, 1075, 0, 0, 0, 594, 0, 1080, 0, 826,
+ 0, 0, 0, 1084, 0, 291, 0, 296, 0, 301,
+ 0, 0, 313, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 285, 0, 290, 0, 295, 0, 0, 307, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1087, 0, 573, 0, 1092, 0, 0, 0, 1096, 1097,
- 0, 0, 0, 1100, 1101, 0, 1102, 0, 0, 791,
- 0, 1104, 0, 0, 0, 0, 0, 0, 0, 0,
- 805, 0, 0, 0, 0, 1108, 0, 1044, 1044, 0,
- 0, 0, 0, 0, 0, 0, 900, 901, 902, 904,
+ 0, 0, 1127, 0, 594, 0, 1132, 0, 0, 0,
+ 1136, 1137, 0, 0, 0, 1140, 1141, 0, 1142, 0,
+ 0, 812, 0, 1144, 0, 0, 0, 0, 0, 0,
+ 0, 0, 826, 0, 0, 0, 0, 1148, 0, 1084,
+ 1084, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 918, 0, 0, 0, 0, 1087, 573,
- 0, 1154, 1155, 0, 1092, 1157, 0, 0, 0, 0,
- 1159, 573, 0, 1163, 0, 0, 0, 0, 0, 0,
- 1165, 1167, 0, 0, 0, 0, 0, 0, 0, 389,
- 0, 0, 0, 0, 0, 0, 404, 0, 410, 411,
- 0, 0, 0, 1235, 1165, 1237, 0, 0, 0, 0,
- 0, 0, 0, 1238, 443, 0, 0, 0, 0, 451,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 1239, 1240,
- 0, 0, 0, 0, 0, 0, 0, 1242, 1243, 1245,
- 1246, 1247, 1248, 0, 0, 1250, 0, 573, 0, 805,
- 0, 0, 0, 0, 573, 0, 0, 0, 0, 1014,
- 0, 0, 1015, 0, 0, 0, 0, 1018, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 1021, 0,
- 0, 0, 514, 0, 0, 0, 1303, 0, 1306, 0,
- 0, 0, 0, 523, 0, 1311, 0, 1314, 0, 0,
- 0, 0, 1318, 0, 0, 0, 1322, 0, 0, 0,
- 1325, 0, 538, 0, 0, 1329, 0, 0, 543, 544,
- 0, 0, 547, 0, 0, 550, 0, 0, 0, 0,
- 0, 0, 559, 0, 0, 561, 0, 0, 0, 0,
- 567, 0, 0, 0, 0, 0, 0, 0, 0, 576,
- 0, 0, 0, 1095, 0, 0, 0, 1167, 0, 0,
- 1351, 1353, 590, 0, 0, 1357, 597, 0, 0, 0,
+ 1127, 594, 0, 1194, 1195, 0, 1132, 1197, 0, 0,
+ 0, 0, 1199, 594, 0, 1203, 0, 0, 0, 0,
+ 0, 0, 1205, 1207, 407, 0, 0, 0, 0, 0,
+ 0, 422, 0, 428, 429, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1275, 1205, 1277, 0, 461,
+ 0, 0, 0, 0, 469, 1278, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 636, 0, 0, 0, 0, 0, 0, 644,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1279, 1280, 0, 0, 0, 0, 0, 0, 0, 1282,
+ 1283, 1285, 1286, 1287, 1288, 0, 0, 1290, 0, 594,
+ 0, 826, 0, 0, 0, 0, 594, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 695, 0, 0, 0, 0, 707, 0, 0, 0, 713,
- 0, 0, 0, 1158, 0, 716, 0, 717, 0, 0,
- 0, 719, 0, 0, 0, 0, 0, 723, 1169, 0,
- 0, 0, 0, 0, 726, 0, 0, 0, 0, 0,
+ 385, 386, 0, 389, 534, 0, 0, 0, 1343, 0,
+ 1346, 0, 0, 0, 0, 543, 0, 1351, 0, 1354,
+ 0, 0, 0, 0, 1358, 0, 0, 0, 1362, 0,
+ 0, 0, 1365, 0, 558, 0, 0, 1369, 0, 0,
+ 563, 564, 0, 0, 567, 0, 0, 570, 0, 0,
+ 0, 0, 0, 0, 579, 0, 0, 581, 0, 0,
+ 0, 0, 587, 0, 588, 0, 0, 0, 0, 0,
+ 0, 0, 0, 597, 0, 0, 0, 0, 0, 1207,
+ 0, 0, 1391, 1393, 0, 0, 611, 1397, 0, 0,
+ 618, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 657, 0, 0, 0,
+ 0, 0, 0, 665, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 736,
- 0, 0, 738, 739, 740, 741, 0, 0, 0, 0,
- 0, 0, 745, 0, 0, 0, 0, 0, 0, 0,
- 0, 753, 0, 755, 0, 757, 758, 759, 760, 761,
- 762, 763, 0, 0, 0, 0, 775, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 1253, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 716, 0, 0, 0, 0, 0,
+ 728, 0, 0, 0, 734, 0, 0, 0, 551, 0,
+ 737, 0, 738, 554, 0, 0, 740, 0, 0, 0,
+ 561, 562, 744, 0, 0, 0, 0, 0, 0, 747,
+ 0, 0, 0, 0, 0, 0, 0, 0, 580, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 1300, 0, 0, 0, 1301,
- 1302, 0, 1304, 0, 1307, 0, 0, 0, 1309, 1310,
- 0, 1312, 0, 1315, 0, 1316, 1317, 0, 1319, 1320,
- 1321, 0, 1323, 0, 1324, 0, 1326, 1327, 825, 1328,
- 827, 1330, 1331, 0, 1332, 0, 1333, 0, 0, 0,
- 0, 0, 0, 838, 0, 840, 0, 0, 0, 0,
+ 0, 0, 0, 0, 757, 0, 0, 759, 760, 761,
+ 762, 0, 0, 0, 0, 0, 0, 766, 0, 0,
+ 0, 0, 0, 0, 0, 0, 774, 0, 776, 0,
+ 0, 779, 0, 781, 0, 783, 0, 0, 0, 0,
+ 0, 796, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 1350, 1352, 0, 1354, 0,
- 1356, 1358, 0, 1360, 1361, 1362, 1363, 1364, 0, 0,
- 0, 0, 0, 887, 0, 0, 0, 0, 0, 0,
- 0, 892, 0, 0, 1368, 0, 1370, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 906, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 919, 0, 0, 0, 0, 0, 0, 0, 926, 0,
- 0, 0, 0, 0, 0, 0, 0, 930, 0, 0,
- 0, 0, 936, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 944, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 953, 0, 0, 0, 0,
- 0, 0, 954, 0, 956, 957, 958, 959, 0, 0,
- 0, 0, 961, 962, 0, 966, 0, 969, 0, 0,
- 972, 0, 980, 981, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 849, 0, 851, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 863, 0,
+ 865, 0, 0, 0, 0, 0, 0, 871, 0, 872,
+ 0, 873, 0, 874, 0, 0, 763, 764, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 778, 0, 780, 0, 782, 0, 784,
+ 0, 0, 0, 0, 0, 0, 0, 0, 916, 0,
+ 0, 0, 0, 0, 0, 0, 921, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 936, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1025, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 1037, 0, 1039, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 1053, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 1070, 0, 0, 0, 0, 1080, 0, 0, 0,
- 1086, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 965, 0, 0, 0, 0, 971, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 979, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 988, 0,
+ 0, 0, 0, 0, 0, 989, 0, 0, 993, 994,
+ 995, 996, 0, 0, 0, 0, 998, 0, 0, 999,
+ 0, 1003, 0, 1006, 0, 0, 0, 0, 0, 1009,
+ 0, 1017, 1018, 1019, 0, 0, 0, 0, 0, 0,
+ 1023, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 930, 931, 932, 934, 0, 0, 0, 938,
+ 939, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 945, 0, 0, 948, 949, 0, 0, 0, 0, 0,
+ 0, 953, 954, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 961, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1065, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1077, 0,
+ 1079, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1093, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1110, 0, 0, 0, 0,
+ 1120, 0, 0, 0, 1126, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1133, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1146, 0, 1148, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1053,
+ 0, 0, 1054, 0, 1173, 0, 0, 1057, 0, 0,
+ 1059, 0, 0, 0, 1186, 0, 1188, 0, 1061, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1164, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 1223, 0, 0, 0, 0, 0, 0,
- 0, 1229, 0, 1233, 1234, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1204, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1263, 0, 0,
+ 0, 0, 0, 0, 0, 1269, 0, 1273, 1274, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1135, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 1241, 0, 0,
- 0, 0, 0, 0, 0, 1249, 0, 0, 0, 0,
+ 0, 1281, 0, 0, 0, 0, 0, 0, 0, 1289,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 1257, 0, 0, 0, 0, 0, 0, 0, 1284,
- 0, 0, 0, 0, 0, 0, 0, 1298, 0, 0,
+ 0, 0, 0, 0, 0, 1297, 0, 0, 0, 0,
+ 0, 0, 0, 1324, 0, 0, 0, 0, 0, 0,
+ 0, 1338, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1198, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1209, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1374, 1375,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 1334, 1335, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1395,
+ 0, 0, 1399, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1293, 0, 0, 0, 0, 1409, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1340, 0,
+ 0, 0, 1341, 1342, 0, 1344, 0, 1347, 0, 0,
+ 0, 1349, 1350, 0, 1352, 0, 1355, 0, 1356, 1357,
+ 0, 1359, 1360, 1361, 0, 1363, 0, 1364, 0, 1366,
+ 1367, 0, 1368, 0, 1370, 1371, 0, 1372, 0, 1373,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 1355, 0, 0, 1359, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 1369
+ 0, 0, 0, 0, 0, 0, 0, 0, 1390, 1392,
+ 0, 1394, 0, 1396, 1398, 0, 1400, 1401, 1402, 1403,
+ 1404, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1408, 0, 1410
};
static const yytype_int16 yycheck[] =
{
- 0, 326, 186, 0, 0, 222, 45, 229, 214, 353,
- 190, 903, 194, 52, 53, 406, 55, 332, 57, 406,
- 59, 812, 61, 797, 128, 129, 65, 205, 67, 797,
- 69, 201, 71, 199, 73, 913, 75, 705, 77, 197,
- 79, 782, 568, 799, 189, 497, 802, 564, 87, 194,
- 230, 558, 569, 1019, 623, 94, 850, 96, 0, 98,
- 382, 100, 0, 102, 1081, 104, 108, 109, 110, 111,
- 112, 113, 114, 115, 116, 117, 118, 119, 120, 121,
- 122, 123, 124, 125, 189, 127, 128, 129, 358, 660,
- 1006, 641, 777, 657, 779, 6, 951, 782, 782, 1243,
- 785, 785, 149, 788, 151, 797, 791, 1022, 1012, 1013,
- 327, 6, 7, 345, 24, 5, 49, 12, 793, 4,
- 683, 732, 685, 49, 687, 15, 689, 5, 691, 39,
- 1096, 14, 0, 6, 17, 909, 747, 15, 48, 22,
- 73, 35, 1020, 16, 186, 184, 330, 17, 14, 1239,
- 1240, 17, 1242, 1243, 87, 1245, 26, 1247, 1248, 376,
- 1250, 87, 56, 17, 7, 65, 383, 77, 348, 12,
- 81, 61, 1087, 390, 782, 357, 146, 785, 1322, 947,
- 788, 955, 388, 61, 62, 55, 81, 928, 1092, 89,
- 984, 85, 86, 508, 79, 195, 235, 51, 83, 1165,
- 17, 240, 202, 242, 382, 88, 245, 246, 81, 26,
- 40, 737, 259, 1303, 1005, 1087, 884, 909, 886, 67,
- 535, 1311, 88, 162, 35, 1097, 265, 266, 1106, 1023,
- 9, 270, 728, 729, 273, 1325, 53, 54, 1255, 1329,
- 162, 280, 564, 91, 928, 284, 931, 931, 933, 191,
- 289, 1167, 937, 1108, 823, 294, 194, 826, 754, 38,
- 299, 768, 484, 715, 1058, 304, 536, 306, 943, 1235,
- 1044, 310, 1150, 1151, 85, 86, 4, 509, 317, 850,
- 797, 831, 808, 847, 323, 1026, 1077, 1043, 330, 839,
- 522, 336, 855, 335, 336, 512, 859, 17, 19, 17,
- 863, 864, 865, 30, 31, 868, 869, 28, 26, 872,
- 162, 356, 7, 355, 356, 65, 11, 12, 13, 14,
- 928, 71, 364, 931, 3, 933, 53, 54, 56, 937,
- 50, 51, 60, 1001, 376, 660, 54, 379, 555, 89,
- 337, 558, 1026, 1027, 1029, 61, 25, 344, 9, 566,
- 5, 79, 17, 353, 350, 83, 17, 17, 540, 17,
- 15, 26, 401, 363, 403, 23, 26, 1239, 1240, 408,
- 1242, 31, 517, 518, 69, 17, 598, 38, 31, 418,
- 22, 1049, 552, 549, 529, 530, 564, 426, 546, 1091,
- 429, 162, 1094, 53, 54, 540, 435, 32, 33, 1167,
- 53, 54, 7, 162, 7, 730, 11, 722, 11, 12,
- 13, 450, 517, 518, 17, 64, 1100, 456, 1026, 1027,
- 1028, 1029, 41, 810, 529, 530, 751, 990, 991, 992,
- 993, 1303, 9, 584, 1306, 1226, 587, 752, 365, 1311,
- 17, 368, 1314, 660, 371, 1238, 1318, 35, 149, 4,
- 489, 149, 843, 1246, 493, 148, 498, 499, 1126, 57,
- 67, 1353, 158, 159, 19, 72, 69, 48, 56, 1137,
- 1138, 575, 60, 28, 516, 160, 161, 7, 520, 1351,
- 24, 11, 70, 155, 91, 1357, 17, 17, 160, 161,
- 162, 533, 1100, 1101, 1102, 26, 16, 85, 86, 30,
- 31, 56, 502, 1066, 7, 60, 506, 17, 725, 12,
- 25, 146, 147, 148, 17, 150, 151, 152, 153, 154,
- 74, 75, 53, 54, 79, 850, 526, 1044, 83, 571,
- 154, 7, 156, 575, 47, 11, 12, 13, 33, 341,
- 17, 17, 32, 20, 20, 22, 22, 45, 765, 351,
- 352, 768, 769, 153, 154, 1163, 1224, 596, 360, 150,
- 151, 152, 17, 1231, 564, 367, 21, 22, 370, 569,
- 1087, 373, 154, 573, 756, 1092, 793, 62, 111, 381,
- 1097, 114, 154, 116, 156, 118, 155, 120, 515, 122,
- 58, 59, 519, 69, 521, 29, 635, 524, 525, 146,
- 1155, 528, 1157, 787, 7, 156, 790, 8, 11, 12,
- 13, 955, 539, 54, 17, 210, 211, 212, 545, 22,
- 384, 548, 386, 7, 551, 658, 951, 11, 12, 13,
- 61, 62, 730, 850, 851, 562, 53, 54, 1247, 1248,
- 679, 821, 681, 964, 965, 684, 326, 686, 851, 688,
- 1167, 690, 146, 147, 693, 848, 150, 151, 152, 984,
- 1084, 1085, 701, 882, 883, 704, 69, 706, 702, 703,
- 777, 779, 711, 7, 8, 778, 928, 11, 12, 13,
- 14, 147, 724, 17, 150, 151, 152, 153, 154, 155,
- 496, 157, 26, 1035, 1171, 29, 30, 31, 1023, 1125,
- 1044, 1131, 744, 7, 537, 922, 1092, 11, 12, 13,
- 117, 1240, 119, 17, 121, 1248, 123, 21, 22, 53,
- 54, 55, 1245, 8, 147, 148, 943, 150, 151, 152,
- 1097, 911, 17, 1058, 731, 69, 0, 734, 194, 781,
- 589, 26, 784, 949, 29, 30, 31, 505, 804, 746,
- 192, 793, 749, 126, 88, 126, 940, 799, 942, 126,
- 802, 126, 984, 126, 192, 69, 914, 984, 53, 54,
- 55, 147, 449, 126, 150, 151, 152, 777, 126, 779,
- 776, 536, 782, 1108, 1159, 785, 126, 126, 788, 126,
- 377, 791, 189, 126, 189, 563, 835, 797, 563, 126,
- 563, 563, 126, 4, 5, 805, 1023, 126, 126, 10,
- 126, 126, 694, 0, 15, 0, 17, 18, 17, 1334,
- 0, 1044, -1, 24, -1, -1, 27, 26, -1, -1,
- 29, 30, 31, 34, 35, -1, 37, -1, 39, 1019,
- -1, 1058, -1, 44, 43, 46, 885, -1, 49, -1,
- 1034, 52, -1, -1, 53, 54, 55, -1, -1, 60,
- 17, -1, 63, -1, 65, 66, 67, 68, -1, 26,
- -1, 913, 29, 30, 31, 76, 77, 78, 79, 80,
- -1, 82, 83, 84, 85, 86, 87, -1, 89, 90,
- 91, -1, -1, -1, -1, -1, 53, 54, 55, 147,
- 148, 943, 150, 151, 152, 153, 154, -1, 147, 909,
- 952, 150, 151, 152, 153, 154, 1096, -1, 157, 7,
- 1104, -1, -1, 11, 12, 13, 14, -1, -1, 17,
- -1, 931, -1, 933, -1, -1, -1, 937, 26, 978,
- -1, 29, 30, 31, -1, -1, -1, 947, 36, 147,
- 148, -1, 150, 151, 152, 153, 154, -1, -1, 157,
- 17, -1, -1, 10, -1, 53, 54, 55, 1007, 26,
- 17, 18, 29, 30, 31, -1, -1, -1, 1020, 26,
- 27, 69, 29, 30, 31, 1165, 43, 34, 45, -1,
- -1, -1, -1, -1, -1, -1, 53, 54, 55, 46,
- 88, 1043, -1, 1042, -1, 52, 53, 54, 55, 1048,
- -1, 1050, -1, 1052, -1, -1, 63, -1, -1, 66,
- -1, 68, -1, -1, -1, -1, -1, -1, -1, 1029,
- -1, 78, -1, 80, -1, 82, -1, 84, -1, -1,
- 1079, -1, -1, 90, 1044, -1, -1, 1089, -1, 1091,
- -1, -1, 1094, -1, 10, 1235, -1, -1, -1, -1,
- -1, -1, 18, -1, 1106, -1, -1, -1, 146, 147,
- 148, 27, 150, 151, 152, 153, 154, -1, 34, -1,
- -1, 37, -1, 1122, -1, 1124, -1, 1087, -1, -1,
- -1, 1308, 1092, -1, 9, -1, 52, 1097, -1, -1,
- 1139, -1, 17, -1, -1, -1, -1, 63, 1150, 1151,
- 66, 26, 68, -1, 29, 30, 31, -1, -1, -1,
- 1162, 1305, 78, 38, 80, -1, 82, -1, 84, 1313,
- -1, -1, -1, -1, 90, -1, -1, -1, 53, 54,
- 55, 92, 93, 94, 95, 96, 97, 98, 99, 100,
- 101, 102, 103, 104, 105, -1, 133, -1, 135, 1159,
- 137, 138, -1, 140, -1, 142, 143, 1167, 145, 146,
- 147, 148, 149, 150, 151, 152, 153, 17, 155, -1,
- 157, -1, -1, -1, -1, -1, 26, -1, -1, 29,
- 30, 31, -1, 1232, 342, 343, 36, -1, 346, 347,
- 177, -1, 179, 180, 181, -1, 183, -1, -1, -1,
- -1, 359, -1, 53, 54, 55, -1, -1, 366, -1,
- -1, 369, -1, -1, 372, 1264, -1, 1266, -1, -1,
- -1, -1, 380, -1, 1273, -1, -1, 1237, 1238, 1239,
- 1240, -1, 1242, 1243, -1, 1245, 1246, 1247, 1248, -1,
- 1250, -1, -1, -1, -1, 232, -1, 234, -1, -1,
- -1, -1, -1, -1, 241, -1, 243, -1, -1, -1,
- 247, 248, -1, -1, -1, -1, 253, 254, 255, 256,
- -1, 258, 259, 260, -1, -1, -1, -1, -1, -1,
- -1, -1, 269, -1, -1, 10, -1, 274, 275, -1,
- 277, -1, -1, 18, -1, -1, 283, -1, -1, -1,
- 287, 288, 27, -1, -1, 292, 293, -1, -1, 34,
- 297, 298, -1, -1, -1, -1, -1, -1, 305, -1,
- -1, 46, 309, -1, -1, 312, -1, 52, -1, 9,
- -1, 318, 319, 320, -1, 322, -1, 17, 63, -1,
- -1, 66, -1, 68, -1, -1, 26, -1, -1, 29,
- 30, 31, -1, 78, -1, 80, -1, 82, 38, 84,
- 9, -1, 42, 43, -1, 90, -1, -1, 17, -1,
- -1, -1, -1, 53, 54, 55, -1, 26, -1, -1,
- 29, 30, 31, -1, -1, -1, -1, -1, -1, 38,
- -1, -1, -1, -1, 43, 92, 93, 94, 95, 96,
- 97, 98, 99, 100, 53, 54, 55, -1, -1, -1,
- -1, -1, 399, 400, -1, -1, -1, -1, -1, 406,
- 407, -1, 409, -1, -1, -1, 413, 414, 415, -1,
- 417, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 428, -1, -1, 431, 432, -1, 434, -1, 436,
- 437, -1, 439, 440, -1, 442, -1, 444, 445, 446,
- -1, -1, 449, -1, -1, -1, -1, 454, 455, -1,
- -1, 458, 459, -1, -1, -1, -1, -1, 465, 466,
- -1, 468, 469, -1, 471, 472, -1, -1, -1, -1,
- -1, -1, -1, -1, 481, 482, 483, -1, -1, 486,
- -1, 488, -1, 490, -1, 492, 106, 107, 108, 109,
- 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
- 120, 121, 122, 123, 124, 125, 126, 127, 128, 129,
- 130, 131, 132, 133, 134, 135, 136, 137, 138, 139,
- 140, 141, 142, 143, 144, 145, 106, 107, 108, 109,
- 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
- 120, 121, 122, 123, 124, 125, 126, 127, 128, 129,
- 130, 131, 132, 133, 134, 135, 136, 137, 138, 139,
- 140, 141, 142, 143, 144, 145, -1, -1, -1, -1,
- 577, 302, 303, -1, 305, -1, -1, 584, -1, -1,
- 587, -1, 589, -1, 591, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 614, 615, 616,
- -1, -1, 619, 620, 621, 622, 623, -1, -1, 626,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 638, 639, 640, 641, -1, 643, -1, 645, -1,
- 647, -1, 649, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, 666,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 678, -1, 680, -1, -1, 683, -1, 685, -1,
- 687, -1, 689, -1, 691, -1, -1, 694, -1, -1,
- 697, -1, -1, -1, -1, 702, 703, -1, 705, -1,
- -1, -1, 709, -1, -1, -1, -1, 714, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 448, -1, -1,
- -1, -1, 453, -1, -1, -1, -1, -1, -1, 460,
- 461, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 107, 108, 109, 110, 111, 112, 113, 478, 115, 116,
- 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
- 127, 128, 129, 130, 131, 132, 133, 134, 135, 136,
- 137, 138, -1, -1, 141, 142, 143, 144, 145, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 810, -1, 812, -1, -1, -1, -1,
- -1, -1, -1, 820, -1, -1, 823, -1, -1, 826,
- -1, 828, -1, 830, 831, -1, -1, -1, -1, 836,
- -1, -1, 839, -1, -1, 842, 843, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, 855, -1,
- 857, -1, 859, -1, -1, -1, 863, 864, 865, -1,
- -1, 868, 869, -1, 871, 872, -1, 874, -1, -1,
- 877, -1, -1, -1, -1, 882, 883, 884, -1, 886,
- -1, 888, 889, -1, -1, -1, -1, -1, -1, -1,
- -1, 898, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 633, 634, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 0, 220, 0, 337, 45, 228, 186, 0, 364, 235,
+ 213, 52, 53, 216, 55, 194, 57, 584, 59, 726,
+ 61, 128, 129, 590, 65, 933, 67, 424, 69, 424,
+ 71, 835, 73, 818, 75, 343, 77, 205, 79, 199,
+ 189, 401, 946, 201, 818, 194, 87, 517, 879, 197,
+ 578, 820, 0, 94, 823, 96, 1058, 98, 190, 100,
+ 1121, 102, 803, 104, 108, 109, 110, 111, 112, 113,
+ 114, 115, 116, 117, 118, 119, 120, 121, 122, 123,
+ 124, 125, 130, 127, 128, 129, 644, 662, 0, 818,
+ 393, 369, 681, 678, 4, 803, 189, 1283, 806, 814,
+ 798, 4, 800, 986, 236, 803, 4, 149, 806, 151,
+ 356, 809, 1051, 1052, 812, 338, 19, 14, 6, 1062,
+ 17, 49, 1045, 9, 17, 28, 25, 704, 16, 706,
+ 17, 708, 17, 710, 1136, 712, 23, 6, 6, 7,
+ 40, 26, 186, 184, 12, 5, 56, 0, 17, 17,
+ 60, 14, 38, 56, 17, 15, 1060, 60, 51, 22,
+ 88, 341, 5, 347, 387, 213, 147, 941, 216, 54,
+ 80, 394, 15, 65, 84, 24, 1362, 80, 78, 78,
+ 163, 84, 80, 367, 1127, 408, 84, 406, 9, 368,
+ 39, 1022, 89, 1132, 82, 195, 17, 982, 90, 48,
+ 241, 61, 202, 1205, 40, 246, 913, 248, 915, 49,
+ 251, 252, 941, 82, 82, 61, 990, 38, 61, 62,
+ 528, 31, 963, 265, 753, 393, 89, 359, 77, 589,
+ 271, 272, 1063, 73, 1295, 276, 749, 750, 279, 768,
+ 1044, 163, 1146, 53, 54, 286, 194, 555, 88, 290,
+ 803, 818, 9, 806, 295, 963, 809, 163, 966, 300,
+ 17, 789, 775, 978, 305, 1148, 736, 1098, 966, 310,
+ 968, 312, 17, 1275, 972, 316, 502, 35, 556, 191,
+ 855, 584, 323, 529, 1207, 326, 1190, 1191, 846, 864,
+ 879, 876, 850, 334, 7, 64, 542, 341, 11, 12,
+ 13, 14, 346, 347, 3, 50, 51, 884, 1127, 532,
+ 1084, 888, 67, 1117, 1083, 892, 893, 894, 1137, 1278,
+ 897, 898, 366, 367, 901, 1066, 25, 1286, 86, 87,
+ 163, 375, 17, 1040, 7, 5, 376, 92, 11, 379,
+ 17, 26, 382, 387, 17, 15, 390, 681, 163, 26,
+ 348, 399, 575, 397, 402, 578, 69, 355, 1066, 1067,
+ 156, 32, 33, 586, 364, 161, 162, 163, 361, 65,
+ 55, 1069, 159, 160, 374, 71, 53, 54, 419, 67,
+ 421, 560, 1089, 7, 72, 426, 7, 11, 537, 538,
+ 11, 12, 13, 619, 90, 436, 17, 7, 758, 35,
+ 549, 550, 12, 444, 92, 1131, 447, 17, 1134, 569,
+ 963, 560, 453, 966, 572, 968, 584, 751, 566, 972,
+ 56, 17, 1207, 41, 7, 21, 22, 468, 11, 12,
+ 13, 19, 1140, 474, 17, 743, 833, 20, 772, 22,
+ 28, 398, 150, 605, 537, 538, 608, 404, 69, 150,
+ 86, 87, 1029, 1030, 1031, 1032, 549, 550, 681, 1166,
+ 1279, 1280, 1266, 1282, 17, 773, 149, 20, 509, 22,
+ 1177, 1178, 513, 868, 518, 519, 147, 148, 149, 57,
+ 151, 152, 153, 154, 155, 1393, 69, 30, 31, 596,
+ 48, 17, 536, 17, 24, 535, 540, 7, 22, 539,
+ 26, 541, 12, 17, 544, 545, 161, 162, 548, 553,
+ 53, 54, 16, 1066, 1067, 1068, 1069, 1084, 155, 559,
+ 157, 32, 522, 746, 1343, 565, 526, 1346, 568, 1106,
+ 25, 571, 1351, 148, 35, 1354, 151, 152, 153, 1358,
+ 47, 155, 582, 157, 17, 879, 546, 33, 592, 151,
+ 152, 153, 596, 26, 1195, 56, 1197, 1264, 31, 60,
+ 1127, 74, 75, 786, 1271, 1132, 789, 790, 62, 70,
+ 1137, 117, 1391, 119, 8, 121, 617, 123, 1397, 45,
+ 53, 54, 155, 17, 584, 86, 87, 1140, 1141, 1142,
+ 590, 814, 26, 156, 594, 29, 30, 31, 777, 1279,
+ 1280, 29, 1282, 1283, 8, 1285, 157, 1287, 1288, 147,
+ 1290, 54, 7, 154, 155, 656, 11, 12, 13, 53,
+ 54, 55, 17, 58, 59, 751, 829, 22, 808, 61,
+ 62, 811, 7, 337, 990, 880, 11, 12, 13, 877,
+ 1207, 679, 17, 352, 53, 54, 21, 22, 1287, 1288,
+ 1203, 798, 986, 362, 363, 799, 879, 880, 800, 700,
+ 516, 702, 371, 1343, 705, 963, 707, 1075, 709, 378,
+ 711, 1351, 381, 714, 69, 384, 1001, 1002, 911, 912,
+ 1211, 722, 1165, 392, 725, 1365, 727, 1171, 1022, 1369,
+ 557, 732, 1132, 111, 69, 1288, 114, 9, 116, 1280,
+ 118, 745, 120, 9, 122, 17, 723, 724, 1124, 1125,
+ 1137, 17, 844, 1285, 26, 0, 194, 29, 30, 31,
+ 26, 765, 525, 29, 30, 31, 38, 610, 1084, 1063,
+ 42, 43, 38, 825, 957, 126, 126, 43, 126, 126,
+ 7, 53, 54, 55, 11, 12, 13, 53, 54, 55,
+ 126, 192, 192, 753, 752, 978, 947, 755, 802, 126,
+ 467, 805, 126, 556, 1098, 984, 1199, 126, 768, 767,
+ 814, 17, 770, 126, 126, 388, 820, 126, 189, 823,
+ 26, 189, 583, 148, 30, 31, 151, 152, 153, 154,
+ 155, 156, 583, 158, 583, 975, 1022, 977, 798, 1022,
+ 800, 583, 126, 803, 797, 126, 806, 53, 54, 809,
+ 126, 943, 812, 126, 1148, 126, 147, 148, 818, 860,
+ 151, 152, 153, 126, 4, 5, 826, 0, 148, 149,
+ 10, 151, 152, 153, 715, 15, 325, 17, 18, 0,
+ 1063, 353, 354, 328, 24, 357, 358, 27, 330, 1374,
+ 0, 928, 1084, -1, 34, 35, -1, 37, 370, 39,
+ -1, -1, -1, -1, 44, 377, 46, -1, 380, 49,
+ -1, 383, 52, 914, -1, 1098, -1, -1, -1, 391,
+ 60, -1, -1, 63, -1, 65, 66, 67, 68, -1,
+ -1, -1, -1, -1, 1074, -1, 76, 77, -1, 79,
+ 80, 81, 946, 83, 84, 85, 86, 87, 88, -1,
+ 90, 91, 92, 7, 8, -1, 17, 11, 12, 13,
+ 14, -1, -1, 17, -1, 26, 1058, -1, 29, 30,
+ 31, -1, 26, -1, 978, 29, 30, 31, 10, -1,
+ -1, 941, 43, 987, 45, -1, 18, -1, -1, -1,
+ -1, -1, 53, 54, 55, 27, -1, -1, -1, 53,
+ 54, 55, 34, -1, 1144, 37, 966, -1, 968, -1,
+ -1, -1, 972, -1, 1015, 69, -1, -1, -1, -1,
+ 52, 9, 982, -1, -1, -1, -1, -1, -1, 17,
+ -1, 63, -1, -1, 66, 89, 68, -1, 26, -1,
+ -1, 29, 30, 31, 1136, 1046, -1, 79, 17, 81,
+ 38, 83, -1, 85, -1, -1, 1060, 26, -1, 91,
+ 29, 30, 31, -1, -1, 53, 54, 55, -1, -1,
+ -1, -1, -1, -1, 43, -1, -1, -1, -1, 1083,
+ -1, 1082, -1, -1, 53, 54, 55, 1088, 133, 1090,
+ 135, 1092, 137, 138, -1, 140, -1, 142, 143, -1,
+ 145, 146, 147, 148, 149, 150, 151, 152, 153, 1069,
+ 155, -1, 157, 1205, -1, -1, -1, -1, 1119, -1,
+ -1, -1, -1, -1, 1084, 1129, -1, 1131, -1, -1,
+ 1134, -1, 177, -1, 179, 180, 181, 17, 183, -1,
+ -1, -1, 1146, -1, -1, -1, 26, -1, -1, 29,
+ 30, 31, -1, -1, -1, -1, 36, -1, -1, -1,
+ -1, 1162, -1, 1164, -1, 1348, -1, 1127, -1, -1,
+ -1, -1, 1132, 53, 54, 55, -1, 1137, 1179, -1,
+ -1, -1, -1, 1275, -1, -1, 1190, 1191, -1, -1,
+ -1, -1, -1, 238, -1, 240, -1, -1, 1202, -1,
+ -1, -1, 247, -1, 249, 1345, -1, -1, 253, 254,
+ -1, -1, -1, 1353, 259, 260, 261, 262, -1, 264,
+ 265, 266, 148, 149, -1, 151, 152, 153, 154, 155,
+ 275, -1, 158, -1, -1, 280, 281, -1, 283, 1199,
+ -1, -1, -1, -1, 289, -1, -1, 1207, 293, 294,
+ -1, -1, -1, 298, 299, -1, -1, -1, 303, 304,
+ -1, -1, -1, 17, -1, -1, 311, -1, -1, -1,
+ 315, 1272, 26, 318, -1, 29, 30, 31, -1, -1,
+ 325, -1, 327, 328, 329, 330, 331, 7, 333, -1,
+ -1, 11, 12, 13, 14, -1, -1, 17, -1, 53,
+ 54, 55, -1, 1304, -1, 1306, 26, -1, -1, 29,
+ 30, 31, 1313, -1, -1, -1, 36, 1277, 1278, 1279,
+ 1280, -1, 1282, 1283, -1, 1285, 1286, 1287, 1288, -1,
+ 1290, -1, -1, 53, 54, 55, 148, -1, -1, 151,
+ 152, 153, 154, 155, -1, -1, 158, -1, -1, 69,
+ 93, 94, 95, 96, 97, 98, 99, 100, 101, 102,
+ 103, 104, 105, 106, -1, -1, -1, -1, -1, 89,
+ -1, -1, 417, 418, -1, -1, -1, -1, -1, 424,
+ 425, -1, 427, -1, -1, -1, 431, 432, 433, -1,
+ 435, 93, 94, 95, 96, 97, 98, 99, 100, 101,
+ -1, 446, -1, -1, 449, 450, -1, 452, -1, 454,
+ 455, -1, 457, 458, -1, 460, -1, 462, 463, 464,
+ -1, -1, 467, -1, -1, -1, -1, 472, 473, -1,
+ -1, 476, 477, -1, -1, -1, -1, -1, 483, 484,
+ -1, 486, 487, -1, 489, 490, -1, -1, -1, -1,
+ -1, -1, 10, -1, 499, 500, 501, -1, -1, 17,
+ 18, 506, -1, 508, -1, 510, -1, 512, 26, 27,
+ -1, 29, 30, 31, -1, -1, 34, 147, 148, 149,
+ -1, 151, 152, 153, 154, 155, 148, 149, 46, 151,
+ 152, 153, 154, 155, 52, 53, 54, 55, -1, -1,
+ -1, -1, -1, -1, -1, 63, -1, -1, 66, -1,
+ 68, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 79, -1, 81, -1, 83, -1, 85, -1, -1,
+ -1, -1, -1, 91, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 10, -1, 598, -1, -1, -1, -1, -1, 18,
+ 605, -1, -1, 608, -1, 610, -1, 612, 27, -1,
+ -1, -1, -1, -1, -1, 34, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 46, -1, -1,
+ 635, 636, 637, 52, -1, 640, 641, 642, 643, 644,
+ -1, -1, 647, -1, 63, -1, -1, 66, -1, 68,
+ -1, -1, -1, -1, 659, 660, 661, 662, -1, 664,
+ 79, 666, 81, 668, 83, 670, 85, -1, -1, -1,
+ -1, -1, 91, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 687, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 699, -1, 701, -1, -1, 704,
+ -1, 706, -1, 708, -1, 710, -1, 712, -1, -1,
+ 715, -1, -1, 718, -1, -1, -1, -1, 723, 724,
+ -1, 726, -1, -1, -1, 730, -1, -1, -1, -1,
+ 735, 107, 108, 109, 110, 111, 112, 113, 114, 115,
+ 116, 117, 118, 119, 120, 121, 122, 123, 124, 125,
+ 126, 127, 128, 129, 130, 131, 132, 133, 134, 135,
+ 136, 137, 138, 139, 140, 141, 142, 143, 144, 145,
+ 146, 107, 108, 109, 110, 111, 112, 113, 114, 115,
+ 116, 117, 118, 119, 120, 121, 122, 123, 124, 125,
+ 126, 127, 128, 129, 130, 131, 132, 133, 134, 135,
+ 136, 137, 138, 139, 140, 141, 142, 143, 144, 145,
+ 146, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 833, -1,
+ 835, -1, -1, -1, -1, -1, -1, -1, 843, -1,
+ -1, 846, -1, -1, -1, 850, -1, 852, -1, 854,
+ 855, -1, -1, -1, -1, -1, 861, -1, -1, 864,
+ -1, -1, 867, 868, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 884,
+ -1, 886, -1, 888, -1, -1, -1, 892, 893, 894,
+ -1, -1, 897, 898, -1, 900, 901, -1, 903, -1,
+ -1, 906, -1, -1, -1, -1, 911, 912, 913, -1,
+ 915, -1, 917, 918, -1, -1, -1, -1, -1, -1,
+ -1, -1, 927, 928, 108, 109, 110, 111, 112, 113,
+ 114, -1, 116, 117, 118, 119, 120, 121, 122, 123,
+ 124, 125, 126, 127, 128, 129, 130, 131, 132, 133,
+ 134, 135, 136, 137, 138, 139, -1, -1, 142, 143,
+ 144, 145, 146, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 954, -1, -1,
- 957, 958, 959, -1, -1, -1, -1, 964, 965, -1,
- -1, -1, -1, 970, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 981, -1, -1, -1, -1, 986,
- 987, 988, -1, 990, 991, 992, 993, -1, 995, -1,
- 997, -1, -1, -1, 1001, -1, 1003, -1, 1005, -1,
- -1, -1, 1009, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 989, -1, -1, -1, -1, 994,
+ 995, 996, -1, -1, -1, -1, 1001, 1002, -1, -1,
+ -1, -1, 1007, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 1018, -1, -1, -1, -1, -1, -1,
+ 1025, 1026, 1027, -1, 1029, 1030, 1031, 1032, -1, 1034,
+ -1, 1036, -1, -1, -1, 1040, -1, 1042, -1, 1044,
+ -1, -1, -1, 1048, -1, 196, -1, 198, -1, 200,
+ -1, -1, 203, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 196, -1, 198, -1, 200, -1, -1, 203, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 1047, -1, 1049, -1, 1051, -1, -1, -1, 1055, 1056,
- -1, -1, -1, 1060, 1061, -1, 1063, -1, -1, 1066,
- -1, 1068, -1, -1, -1, -1, -1, -1, -1, -1,
- 1077, -1, -1, -1, -1, 1082, -1, 1084, 1085, -1,
- -1, -1, -1, -1, -1, -1, 817, 818, 819, 820,
+ -1, -1, 1087, -1, 1089, -1, 1091, -1, -1, -1,
+ 1095, 1096, -1, -1, -1, 1100, 1101, -1, 1103, -1,
+ -1, 1106, -1, 1108, -1, -1, -1, -1, -1, -1,
+ -1, -1, 1117, -1, -1, -1, -1, 1122, -1, 1124,
+ 1125, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 844, -1, -1, -1, -1, 1125, 1126,
- -1, 1128, 1129, -1, 1131, 1132, -1, -1, -1, -1,
- 1137, 1138, -1, 1140, -1, -1, -1, -1, -1, -1,
- 1147, 1148, -1, -1, -1, -1, -1, -1, -1, 324,
- -1, -1, -1, -1, -1, -1, 331, -1, 333, 334,
- -1, -1, -1, 1170, 1171, 1172, -1, -1, -1, -1,
- -1, -1, -1, 1180, 349, -1, -1, -1, -1, 354,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, 1205, 1206,
- -1, -1, -1, -1, -1, -1, -1, 1214, 1215, 1216,
- 1217, 1218, 1219, -1, -1, 1222, -1, 1224, -1, 1226,
- -1, -1, -1, -1, 1231, -1, -1, -1, -1, 960,
- -1, -1, 963, -1, -1, -1, -1, 968, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, 979, -1,
- -1, -1, 427, -1, -1, -1, 1263, -1, 1265, -1,
- -1, -1, -1, 438, -1, 1272, -1, 1274, -1, -1,
- -1, -1, 1279, -1, -1, -1, 1283, -1, -1, -1,
- 1287, -1, 457, -1, -1, 1292, -1, -1, 463, 464,
- -1, -1, 467, -1, -1, 470, -1, -1, -1, -1,
- -1, -1, 477, -1, -1, 480, -1, -1, -1, -1,
- 485, -1, -1, -1, -1, -1, -1, -1, -1, 494,
- -1, -1, -1, 1054, -1, -1, -1, 1334, -1, -1,
- 1337, 1338, 507, -1, -1, 1342, 511, -1, -1, -1,
+ 1165, 1166, -1, 1168, 1169, -1, 1171, 1172, -1, -1,
+ -1, -1, 1177, 1178, -1, 1180, -1, -1, -1, -1,
+ -1, -1, 1187, 1188, 335, -1, -1, -1, -1, -1,
+ -1, 342, -1, 344, 345, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1210, 1211, 1212, -1, 360,
+ -1, -1, -1, -1, 365, 1220, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 527, -1, -1, -1, -1, -1, -1, 534,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 1245, 1246, -1, -1, -1, -1, -1, -1, -1, 1254,
+ 1255, 1256, 1257, 1258, 1259, -1, -1, 1262, -1, 1264,
+ -1, 1266, -1, -1, -1, -1, 1271, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 565, -1, -1, -1, -1, 570, -1, -1, -1, 574,
- -1, -1, -1, 1134, -1, 580, -1, 582, -1, -1,
- -1, 586, -1, -1, -1, -1, -1, 592, 1149, -1,
- -1, -1, -1, -1, 599, -1, -1, -1, -1, -1,
+ 308, 309, -1, 311, 445, -1, -1, -1, 1303, -1,
+ 1305, -1, -1, -1, -1, 456, -1, 1312, -1, 1314,
+ -1, -1, -1, -1, 1319, -1, -1, -1, 1323, -1,
+ -1, -1, 1327, -1, 475, -1, -1, 1332, -1, -1,
+ 481, 482, -1, -1, 485, -1, -1, 488, -1, -1,
+ -1, -1, -1, -1, 495, -1, -1, 498, -1, -1,
+ -1, -1, 503, -1, 505, -1, -1, -1, -1, -1,
+ -1, -1, -1, 514, -1, -1, -1, -1, -1, 1374,
+ -1, -1, 1377, 1378, -1, -1, 527, 1382, -1, -1,
+ 531, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 547, -1, -1, -1,
+ -1, -1, -1, 554, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, 624,
- -1, -1, 627, 628, 629, 630, -1, -1, -1, -1,
- -1, -1, 637, -1, -1, -1, -1, -1, -1, -1,
- -1, 646, -1, 648, -1, 650, 651, 652, 653, 654,
- 655, 656, -1, -1, -1, -1, 661, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 1228, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 585, -1, -1, -1, -1, -1,
+ 591, -1, -1, -1, 595, -1, -1, -1, 466, -1,
+ 601, -1, 603, 471, -1, -1, 607, -1, -1, -1,
+ 478, 479, 613, -1, -1, -1, -1, -1, -1, 620,
+ -1, -1, -1, -1, -1, -1, -1, -1, 496, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 1256, -1, -1, -1, 1260,
- 1261, -1, 1263, -1, 1265, -1, -1, -1, 1269, 1270,
- -1, 1272, -1, 1274, -1, 1276, 1277, -1, 1279, 1280,
- 1281, -1, 1283, -1, 1285, -1, 1287, 1288, 733, 1290,
- 735, 1292, 1293, -1, 1295, -1, 1297, -1, -1, -1,
- -1, -1, -1, 748, -1, 750, -1, -1, -1, -1,
+ -1, -1, -1, -1, 645, -1, -1, 648, 649, 650,
+ 651, -1, -1, -1, -1, -1, -1, 658, -1, -1,
+ -1, -1, -1, -1, -1, -1, 667, -1, 669, -1,
+ -1, 672, -1, 674, -1, 676, -1, -1, -1, -1,
+ -1, 682, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 1336, 1337, -1, 1339, -1,
- 1341, 1342, -1, 1344, 1345, 1346, 1347, 1348, -1, -1,
- -1, -1, -1, 798, -1, -1, -1, -1, -1, -1,
- -1, 806, -1, -1, 1365, -1, 1367, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 822, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 845, -1, -1, -1, -1, -1, -1, -1, 853, -1,
- -1, -1, -1, -1, -1, -1, -1, 862, -1, -1,
- -1, -1, 867, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 879, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 890, -1, -1, -1, -1,
- -1, -1, 897, -1, 899, 900, 901, 902, -1, -1,
- -1, -1, 907, 908, -1, 910, -1, 912, -1, -1,
- 915, -1, 917, 918, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 754, -1, 756, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 769, -1,
+ 771, -1, -1, -1, -1, -1, -1, 778, -1, 780,
+ -1, 782, -1, 784, -1, -1, 654, 655, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 671, -1, 673, -1, 675, -1, 677,
+ -1, -1, -1, -1, -1, -1, -1, -1, 819, -1,
+ -1, -1, -1, -1, -1, -1, 827, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 845, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 985, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 1000, -1, 1002, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 1018, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 1036, -1, -1, -1, -1, 1041, -1, -1, -1,
- 1045, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 891, -1, -1, -1, -1, 896, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 908, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 919, -1,
+ -1, -1, -1, -1, -1, 926, -1, -1, 929, 930,
+ 931, 932, -1, -1, -1, -1, 937, -1, -1, 940,
+ -1, 942, -1, 944, -1, -1, -1, -1, -1, 950,
+ -1, 952, 953, 954, -1, -1, -1, -1, -1, -1,
+ 961, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 840, 841, 842, 843, -1, -1, -1, 847,
+ 848, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 858, -1, -1, 861, 862, -1, -1, -1, -1, -1,
+ -1, 869, 870, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 882, -1, -1, -1, -1, -1,
+ -1, -1, -1, 1024, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 1039, -1,
+ 1041, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1057, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1076, -1, -1, -1, -1,
+ 1081, -1, -1, -1, 1085, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 1095, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 1105, -1, 1107, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 997,
+ -1, -1, 1000, -1, 1135, -1, -1, 1005, -1, -1,
+ 1008, -1, -1, -1, 1145, -1, 1147, -1, 1016, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 1145, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 1158, -1, -1, -1, -1, -1, -1,
- -1, 1166, -1, 1168, 1169, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 1185, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1198, -1, -1,
+ -1, -1, -1, -1, -1, 1206, -1, 1208, 1209, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1094, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 1212, -1, -1,
- -1, -1, -1, -1, -1, 1220, -1, -1, -1, -1,
+ -1, 1252, -1, -1, -1, -1, -1, -1, -1, 1260,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 1236, -1, -1, -1, -1, -1, -1, -1, 1244,
- -1, -1, -1, -1, -1, -1, -1, 1252, -1, -1,
+ -1, -1, -1, -1, -1, 1276, -1, -1, -1, -1,
+ -1, -1, -1, 1284, -1, -1, -1, -1, -1, -1,
+ -1, 1292, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1174, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 1189, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 1339, 1340,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 1299, 1300, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 1380,
+ -1, -1, 1383, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 1268, -1, -1, -1, -1, 1406, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 1296, -1,
+ -1, -1, 1300, 1301, -1, 1303, -1, 1305, -1, -1,
+ -1, 1309, 1310, -1, 1312, -1, 1314, -1, 1316, 1317,
+ -1, 1319, 1320, 1321, -1, 1323, -1, 1325, -1, 1327,
+ 1328, -1, 1330, -1, 1332, 1333, -1, 1335, -1, 1337,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 1340, -1, -1, 1343, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 1366
+ -1, -1, -1, -1, -1, -1, -1, -1, 1376, 1377,
+ -1, 1379, -1, 1381, 1382, -1, 1384, 1385, 1386, 1387,
+ 1388, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1405, -1, 1407
};
/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
@@ -1956,215 +1990,220 @@ static const yytype_uint16 yystos[] =
{
0, 4, 5, 10, 15, 17, 18, 24, 27, 34,
35, 37, 39, 44, 46, 49, 52, 60, 63, 65,
- 66, 67, 68, 76, 77, 78, 79, 80, 82, 83,
- 84, 85, 86, 87, 89, 90, 91, 164, 165, 166,
- 237, 239, 303, 304, 307, 309, 330, 331, 332, 333,
- 334, 335, 338, 339, 341, 343, 351, 352, 358, 359,
- 370, 372, 383, 384, 385, 392, 393, 394, 395, 396,
- 397, 398, 399, 400, 401, 402, 403, 404, 405, 407,
- 428, 429, 430, 432, 434, 435, 441, 442, 447, 452,
- 455, 458, 461, 462, 465, 470, 472, 475, 477, 487,
- 489, 490, 493, 495, 496, 0, 158, 159, 201, 201,
- 201, 201, 201, 201, 201, 201, 201, 201, 201, 201,
- 201, 201, 201, 201, 201, 201, 201, 201, 201, 201,
- 201, 146, 204, 240, 204, 310, 204, 337, 337, 204,
- 344, 204, 353, 337, 204, 373, 337, 353, 337, 353,
- 337, 353, 337, 353, 204, 443, 204, 466, 332, 333,
- 334, 335, 358, 384, 385, 395, 399, 403, 428, 441,
- 447, 452, 455, 458, 461, 471, 473, 474, 204, 478,
- 478, 478, 40, 479, 480, 162, 203, 203, 203, 203,
- 203, 203, 203, 203, 203, 203, 354, 203, 354, 203,
- 354, 203, 203, 406, 203, 203, 160, 161, 202, 203,
- 203, 203, 203, 203, 201, 147, 148, 150, 151, 152,
- 153, 154, 167, 168, 169, 171, 173, 174, 177, 179,
- 180, 204, 241, 61, 311, 313, 19, 28, 56, 304,
- 309, 320, 321, 340, 351, 366, 367, 431, 433, 436,
- 438, 439, 440, 320, 340, 431, 433, 171, 345, 341,
- 360, 361, 363, 364, 365, 366, 367, 3, 25, 374,
- 375, 70, 307, 309, 320, 386, 393, 448, 449, 450,
- 451, 23, 237, 355, 356, 202, 71, 397, 453, 454,
- 202, 72, 401, 456, 457, 202, 73, 405, 459, 460,
- 50, 51, 237, 408, 409, 411, 412, 202, 64, 444,
- 445, 462, 463, 495, 74, 75, 467, 468, 479, 479,
- 479, 41, 481, 482, 166, 179, 149, 167, 178, 171,
- 203, 238, 203, 305, 308, 201, 201, 203, 201, 203,
- 201, 201, 203, 203, 203, 203, 203, 203, 203, 354,
- 203, 201, 201, 203, 371, 201, 201, 203, 203, 203,
- 201, 203, 258, 203, 201, 203, 203, 201, 203, 203,
- 201, 203, 203, 201, 258, 258, 201, 203, 258, 201,
- 203, 201, 203, 201, 203, 203, 203, 203, 201, 202,
- 172, 175, 176, 180, 179, 32, 33, 168, 204, 242,
- 243, 244, 246, 247, 202, 62, 311, 316, 317, 341,
- 202, 202, 204, 314, 310, 351, 57, 322, 323, 6,
- 16, 81, 267, 268, 270, 271, 273, 336, 347, 348,
- 204, 368, 368, 48, 414, 416, 414, 351, 336, 414,
- 414, 171, 346, 202, 370, 368, 368, 9, 237, 377,
- 379, 202, 204, 376, 310, 393, 273, 387, 414, 368,
- 237, 237, 204, 357, 267, 414, 368, 267, 414, 368,
- 267, 414, 368, 179, 183, 185, 204, 410, 408, 204,
- 413, 414, 368, 463, 179, 469, 481, 25, 418, 419,
- 481, 47, 497, 500, 166, 179, 203, 203, 201, 201,
- 305, 308, 203, 306, 201, 203, 203, 312, 203, 203,
- 203, 325, 201, 201, 202, 203, 201, 203, 203, 203,
- 201, 203, 203, 202, 203, 203, 203, 342, 203, 203,
- 203, 258, 371, 201, 258, 203, 203, 201, 202, 203,
- 203, 258, 258, 202, 202, 203, 203, 202, 203, 203,
- 202, 203, 203, 154, 156, 182, 184, 188, 191, 202,
- 258, 202, 203, 203, 203, 464, 167, 202, 203, 203,
- 488, 201, 203, 203, 206, 201, 202, 243, 246, 204,
- 245, 204, 248, 237, 319, 168, 318, 316, 237, 315,
- 202, 311, 336, 58, 59, 326, 328, 202, 179, 324,
- 92, 93, 94, 95, 96, 97, 98, 99, 100, 101,
- 102, 103, 104, 105, 274, 275, 276, 267, 204, 349,
- 320, 340, 320, 340, 267, 204, 417, 267, 336, 267,
- 267, 7, 11, 237, 259, 263, 202, 267, 320, 340,
- 320, 340, 204, 380, 202, 311, 387, 274, 267, 320,
- 393, 267, 397, 267, 401, 267, 405, 179, 186, 179,
- 192, 267, 436, 438, 439, 440, 446, 26, 29, 30,
- 31, 53, 54, 55, 207, 209, 210, 211, 212, 213,
- 214, 215, 218, 219, 220, 222, 223, 228, 230, 233,
- 234, 237, 249, 250, 463, 202, 179, 418, 38, 43,
- 207, 379, 421, 425, 426, 485, 486, 202, 204, 420,
- 45, 494, 207, 202, 478, 203, 202, 202, 306, 202,
- 306, 312, 203, 202, 201, 167, 202, 203, 203, 203,
- 203, 203, 203, 437, 203, 437, 202, 203, 202, 202,
- 202, 202, 258, 258, 201, 202, 203, 203, 362, 203,
- 362, 203, 203, 202, 203, 202, 203, 202, 202, 202,
- 202, 202, 202, 202, 184, 182, 155, 157, 180, 181,
- 189, 192, 197, 198, 199, 202, 203, 203, 201, 203,
- 208, 201, 203, 208, 201, 203, 208, 201, 203, 208,
- 201, 203, 208, 201, 208, 201, 464, 203, 476, 201,
- 488, 488, 201, 206, 201, 203, 327, 201, 203, 246,
- 311, 204, 329, 179, 150, 151, 152, 277, 277, 277,
- 170, 172, 350, 351, 347, 202, 351, 202, 418, 204,
- 265, 351, 7, 12, 257, 262, 347, 369, 202, 351,
- 202, 170, 381, 311, 277, 393, 179, 187, 192, 179,
- 193, 181, 200, 370, 211, 237, 249, 214, 218, 237,
- 249, 204, 216, 222, 228, 233, 204, 221, 228, 233,
- 168, 224, 233, 168, 231, 183, 204, 235, 146, 205,
- 42, 207, 421, 425, 483, 484, 485, 202, 380, 380,
- 318, 237, 202, 370, 414, 475, 489, 491, 418, 327,
- 258, 258, 258, 203, 258, 171, 202, 437, 437, 203,
- 415, 203, 362, 201, 203, 362, 203, 378, 258, 202,
- 184, 200, 181, 190, 197, 193, 202, 208, 203, 208,
- 202, 203, 208, 203, 208, 208, 202, 203, 208, 208,
- 203, 208, 203, 203, 202, 476, 476, 203, 206, 201,
- 206, 203, 203, 202, 202, 203, 202, 202, 202, 202,
- 257, 202, 202, 237, 421, 425, 202, 171, 266, 202,
- 265, 369, 202, 7, 11, 12, 13, 255, 256, 382,
- 202, 202, 179, 194, 195, 217, 219, 222, 228, 233,
- 228, 233, 233, 233, 168, 225, 168, 232, 183, 204,
- 236, 485, 166, 381, 204, 427, 203, 379, 425, 498,
- 501, 203, 203, 203, 258, 258, 415, 415, 258, 203,
- 201, 258, 203, 167, 197, 202, 203, 203, 203, 203,
- 208, 208, 208, 208, 203, 203, 229, 202, 206, 202,
- 203, 327, 494, 201, 203, 499, 8, 278, 281, 279,
- 281, 280, 281, 202, 266, 265, 278, 179, 196, 197,
- 222, 228, 233, 228, 233, 233, 233, 168, 226, 259,
- 202, 7, 11, 12, 13, 14, 69, 422, 423, 424,
- 202, 201, 380, 207, 425, 501, 202, 203, 269, 201,
- 206, 201, 203, 272, 201, 258, 203, 203, 388, 197,
- 203, 203, 203, 208, 203, 327, 201, 491, 203, 499,
- 499, 7, 11, 12, 13, 14, 69, 88, 207, 251,
- 252, 253, 254, 260, 264, 278, 302, 204, 282, 282,
- 207, 280, 282, 202, 266, 36, 207, 302, 389, 390,
- 228, 233, 233, 233, 168, 227, 202, 265, 202, 381,
- 201, 201, 269, 206, 203, 203, 272, 203, 258, 203,
- 206, 206, 201, 203, 202, 203, 261, 203, 492, 258,
- 265, 265, 106, 107, 108, 109, 110, 111, 112, 113,
- 114, 115, 116, 117, 118, 119, 120, 121, 122, 123,
- 124, 125, 126, 127, 128, 129, 130, 131, 132, 133,
- 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
- 144, 145, 283, 286, 295, 295, 106, 114, 139, 140,
- 288, 291, 295, 202, 389, 204, 391, 233, 266, 202,
- 207, 485, 494, 202, 202, 203, 261, 203, 203, 203,
- 203, 202, 203, 203, 293, 203, 203, 203, 203, 202,
- 203, 206, 327, 258, 206, 201, 266, 202, 20, 22,
- 237, 252, 284, 296, 297, 300, 301, 284, 21, 237,
- 252, 285, 298, 299, 300, 285, 237, 252, 287, 300,
- 237, 260, 294, 300, 202, 237, 289, 296, 300, 284,
- 237, 290, 298, 300, 290, 237, 292, 300, 202, 491,
- 258, 258, 258, 203, 258, 201, 203, 258, 201, 258,
- 258, 203, 258, 201, 203, 258, 258, 258, 203, 258,
- 258, 258, 203, 258, 258, 203, 258, 258, 258, 203,
- 258, 258, 258, 258, 202, 202, 252, 300, 168, 252,
- 179, 252, 300, 168, 252, 252, 260, 300, 300, 492,
- 258, 203, 258, 203, 258, 202, 258, 203, 258, 202,
- 258, 258, 258, 258, 258, 252, 257, 252, 258, 202,
- 258
+ 66, 67, 68, 76, 77, 79, 80, 81, 83, 84,
+ 85, 86, 87, 88, 90, 91, 92, 165, 166, 167,
+ 238, 240, 304, 305, 308, 310, 331, 332, 333, 334,
+ 335, 336, 339, 340, 342, 344, 352, 353, 359, 360,
+ 371, 373, 384, 385, 386, 393, 394, 395, 396, 397,
+ 398, 399, 400, 401, 402, 403, 404, 405, 406, 408,
+ 429, 430, 431, 433, 435, 436, 442, 443, 448, 453,
+ 456, 459, 462, 463, 466, 471, 473, 476, 480, 493,
+ 497, 498, 503, 505, 506, 0, 159, 160, 202, 202,
+ 202, 202, 202, 202, 202, 202, 202, 202, 202, 202,
+ 202, 202, 202, 202, 202, 202, 202, 202, 202, 202,
+ 202, 147, 205, 241, 205, 311, 205, 338, 338, 205,
+ 345, 205, 354, 338, 205, 374, 338, 354, 338, 354,
+ 338, 354, 338, 354, 205, 444, 205, 467, 333, 334,
+ 335, 336, 359, 385, 386, 396, 400, 404, 429, 442,
+ 448, 453, 456, 459, 462, 472, 474, 475, 205, 481,
+ 481, 481, 40, 485, 486, 163, 204, 204, 204, 204,
+ 204, 204, 204, 204, 204, 204, 355, 204, 355, 204,
+ 355, 204, 204, 407, 204, 204, 161, 162, 203, 204,
+ 204, 477, 478, 204, 494, 495, 204, 499, 500, 204,
+ 202, 148, 149, 151, 152, 153, 154, 155, 168, 169,
+ 170, 172, 174, 175, 178, 180, 181, 205, 242, 61,
+ 312, 314, 19, 28, 56, 305, 310, 321, 322, 341,
+ 352, 367, 368, 432, 434, 437, 439, 440, 441, 321,
+ 341, 432, 434, 172, 346, 342, 361, 362, 364, 365,
+ 366, 367, 368, 3, 25, 375, 376, 70, 308, 310,
+ 321, 387, 394, 449, 450, 451, 452, 23, 238, 356,
+ 357, 203, 71, 398, 454, 455, 203, 72, 402, 457,
+ 458, 203, 73, 406, 460, 461, 50, 51, 238, 409,
+ 410, 412, 413, 203, 64, 445, 446, 463, 464, 505,
+ 74, 75, 468, 469, 78, 482, 483, 485, 482, 485,
+ 482, 485, 41, 487, 488, 167, 180, 150, 168, 179,
+ 172, 204, 239, 204, 306, 309, 202, 202, 204, 202,
+ 204, 202, 202, 204, 204, 204, 204, 204, 204, 204,
+ 355, 204, 202, 202, 204, 372, 202, 202, 204, 204,
+ 204, 202, 204, 259, 204, 202, 204, 204, 202, 204,
+ 204, 202, 204, 204, 202, 259, 259, 202, 204, 259,
+ 202, 204, 202, 204, 202, 204, 478, 202, 204, 204,
+ 495, 204, 204, 500, 204, 204, 202, 203, 173, 176,
+ 177, 181, 180, 32, 33, 169, 205, 243, 244, 245,
+ 247, 248, 203, 62, 312, 317, 318, 342, 203, 203,
+ 205, 315, 311, 352, 57, 323, 324, 6, 16, 82,
+ 268, 269, 271, 272, 274, 337, 348, 349, 205, 369,
+ 369, 48, 415, 417, 415, 352, 337, 415, 415, 172,
+ 347, 203, 371, 369, 369, 9, 238, 378, 380, 203,
+ 205, 377, 311, 394, 274, 388, 415, 369, 238, 238,
+ 205, 358, 268, 415, 369, 268, 415, 369, 268, 415,
+ 369, 180, 184, 186, 205, 411, 409, 205, 414, 415,
+ 369, 464, 180, 470, 205, 484, 487, 25, 419, 420,
+ 487, 47, 507, 512, 167, 180, 204, 204, 202, 202,
+ 306, 309, 204, 307, 202, 204, 204, 313, 204, 204,
+ 204, 326, 202, 202, 203, 204, 202, 204, 204, 204,
+ 202, 204, 204, 203, 204, 204, 204, 343, 204, 204,
+ 204, 259, 372, 202, 259, 204, 204, 202, 203, 204,
+ 204, 259, 259, 203, 203, 204, 204, 203, 204, 204,
+ 203, 204, 204, 155, 157, 183, 185, 189, 192, 203,
+ 259, 203, 204, 204, 204, 465, 168, 203, 203, 204,
+ 204, 496, 202, 204, 204, 207, 202, 203, 244, 247,
+ 205, 246, 205, 249, 238, 320, 169, 319, 317, 238,
+ 316, 203, 312, 337, 58, 59, 327, 329, 203, 180,
+ 325, 93, 94, 95, 96, 97, 98, 99, 100, 101,
+ 102, 103, 104, 105, 106, 275, 276, 277, 268, 205,
+ 350, 321, 341, 321, 341, 268, 205, 418, 268, 337,
+ 268, 268, 7, 11, 238, 260, 264, 203, 268, 321,
+ 341, 321, 341, 205, 381, 203, 312, 388, 275, 268,
+ 321, 394, 268, 398, 268, 402, 268, 406, 180, 187,
+ 180, 193, 268, 437, 439, 440, 441, 447, 26, 29,
+ 30, 31, 53, 54, 55, 208, 210, 211, 212, 213,
+ 214, 215, 216, 219, 220, 221, 223, 224, 229, 231,
+ 234, 235, 238, 250, 251, 464, 203, 180, 419, 38,
+ 43, 208, 380, 422, 426, 427, 491, 492, 203, 205,
+ 421, 45, 504, 208, 203, 481, 204, 203, 203, 307,
+ 203, 307, 313, 204, 203, 202, 168, 203, 204, 204,
+ 204, 204, 204, 204, 438, 204, 438, 203, 204, 203,
+ 203, 203, 203, 259, 259, 202, 203, 204, 204, 363,
+ 204, 363, 204, 204, 203, 204, 203, 204, 259, 203,
+ 259, 203, 259, 203, 259, 185, 183, 156, 158, 181,
+ 182, 190, 193, 198, 199, 200, 203, 204, 204, 202,
+ 204, 209, 202, 204, 209, 202, 204, 209, 202, 204,
+ 209, 202, 204, 209, 202, 209, 202, 465, 204, 479,
+ 202, 496, 496, 202, 207, 202, 204, 328, 202, 204,
+ 508, 509, 247, 312, 205, 330, 180, 151, 152, 153,
+ 278, 278, 278, 171, 173, 351, 352, 238, 348, 203,
+ 352, 203, 419, 205, 266, 352, 7, 12, 238, 258,
+ 263, 348, 370, 203, 352, 203, 171, 382, 312, 278,
+ 394, 203, 203, 203, 203, 180, 188, 193, 180, 194,
+ 182, 201, 371, 212, 238, 250, 215, 219, 238, 250,
+ 205, 217, 223, 229, 234, 205, 222, 229, 234, 169,
+ 225, 234, 169, 232, 184, 205, 236, 147, 206, 42,
+ 208, 422, 426, 489, 490, 491, 203, 381, 381, 319,
+ 238, 203, 371, 415, 476, 497, 501, 419, 482, 328,
+ 259, 259, 259, 204, 259, 172, 203, 438, 259, 259,
+ 438, 204, 416, 204, 363, 259, 202, 204, 259, 259,
+ 363, 204, 379, 259, 259, 185, 201, 182, 191, 198,
+ 194, 259, 209, 204, 209, 203, 204, 209, 204, 209,
+ 209, 203, 204, 209, 209, 204, 209, 204, 204, 203,
+ 479, 479, 204, 207, 202, 207, 204, 204, 203, 203,
+ 204, 204, 509, 203, 203, 203, 203, 258, 203, 203,
+ 238, 422, 426, 203, 172, 267, 203, 266, 370, 203,
+ 7, 11, 12, 13, 256, 257, 383, 203, 203, 203,
+ 180, 195, 196, 203, 218, 220, 223, 229, 234, 229,
+ 234, 234, 234, 169, 226, 169, 233, 184, 205, 237,
+ 491, 167, 382, 205, 428, 204, 380, 426, 510, 513,
+ 204, 204, 204, 259, 259, 416, 416, 259, 204, 259,
+ 202, 259, 204, 168, 198, 203, 204, 204, 204, 204,
+ 209, 209, 209, 209, 204, 204, 230, 203, 207, 203,
+ 204, 328, 504, 202, 204, 511, 8, 279, 282, 280,
+ 282, 281, 282, 203, 267, 266, 279, 180, 197, 198,
+ 223, 229, 234, 229, 234, 234, 234, 169, 227, 260,
+ 203, 7, 11, 12, 13, 14, 69, 423, 424, 425,
+ 203, 202, 381, 208, 426, 513, 203, 204, 270, 202,
+ 207, 202, 204, 273, 202, 259, 204, 204, 389, 198,
+ 204, 204, 204, 209, 204, 328, 202, 501, 204, 511,
+ 511, 7, 11, 12, 13, 14, 69, 89, 208, 252,
+ 253, 254, 255, 261, 265, 279, 303, 205, 283, 283,
+ 208, 281, 283, 203, 267, 36, 208, 303, 390, 391,
+ 229, 234, 234, 234, 169, 228, 203, 266, 203, 382,
+ 202, 202, 270, 207, 204, 204, 273, 204, 259, 204,
+ 207, 207, 202, 204, 203, 204, 262, 204, 502, 259,
+ 266, 266, 107, 108, 109, 110, 111, 112, 113, 114,
+ 115, 116, 117, 118, 119, 120, 121, 122, 123, 124,
+ 125, 126, 127, 128, 129, 130, 131, 132, 133, 134,
+ 135, 136, 137, 138, 139, 140, 141, 142, 143, 144,
+ 145, 146, 284, 287, 296, 296, 107, 115, 140, 141,
+ 289, 292, 296, 203, 390, 205, 392, 234, 267, 203,
+ 208, 491, 504, 203, 203, 204, 262, 204, 204, 204,
+ 204, 203, 204, 204, 294, 204, 204, 204, 204, 203,
+ 204, 207, 328, 259, 207, 202, 267, 203, 20, 22,
+ 238, 253, 285, 297, 298, 301, 302, 285, 21, 238,
+ 253, 286, 299, 300, 301, 286, 238, 253, 288, 301,
+ 238, 261, 295, 301, 203, 238, 290, 297, 301, 285,
+ 238, 291, 299, 301, 291, 238, 293, 301, 203, 501,
+ 259, 259, 259, 204, 259, 202, 204, 259, 202, 259,
+ 259, 204, 259, 202, 204, 259, 259, 259, 204, 259,
+ 259, 259, 204, 259, 259, 204, 259, 259, 259, 204,
+ 259, 259, 259, 259, 203, 203, 253, 301, 169, 253,
+ 180, 253, 301, 169, 253, 253, 261, 301, 301, 502,
+ 259, 204, 259, 204, 259, 203, 259, 204, 259, 203,
+ 259, 259, 259, 259, 259, 253, 258, 253, 259, 203,
+ 259
};
/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
static const yytype_uint16 yyr1[] =
{
- 0, 163, 164, 164, 164, 164, 164, 164, 164, 164,
- 164, 164, 165, 165, 165, 165, 165, 165, 166, 166,
- 167, 168, 168, 169, 170, 171, 171, 172, 172, 173,
- 174, 175, 176, 177, 177, 178, 178, 179, 179, 179,
- 179, 180, 180, 181, 182, 183, 183, 183, 184, 184,
- 185, 186, 187, 188, 189, 189, 190, 190, 191, 192,
- 193, 194, 194, 194, 195, 196, 197, 197, 198, 199,
- 199, 200, 200, 201, 201, 202, 202, 203, 204, 205,
- 206, 206, 207, 207, 207, 208, 208, 208, 209, 209,
- 210, 210, 210, 211, 211, 211, 211, 212, 213, 214,
- 215, 216, 217, 217, 217, 217, 217, 217, 217, 217,
- 217, 217, 217, 217, 217, 217, 217, 218, 218, 218,
- 218, 218, 218, 218, 218, 218, 218, 218, 218, 218,
- 218, 218, 219, 220, 221, 222, 223, 224, 225, 226,
- 227, 228, 229, 229, 230, 231, 232, 233, 234, 235,
- 235, 236, 236, 237, 238, 238, 238, 238, 238, 238,
- 238, 239, 240, 241, 241, 242, 242, 243, 244, 245,
- 246, 247, 248, 249, 250, 251, 251, 252, 253, 254,
- 254, 254, 254, 254, 255, 256, 256, 256, 256, 257,
- 258, 258, 259, 260, 261, 261, 262, 262, 263, 263,
- 264, 264, 265, 266, 267, 267, 267, 268, 269, 269,
- 269, 269, 270, 271, 272, 272, 272, 273, 274, 274,
- 274, 274, 274, 274, 274, 274, 274, 275, 275, 275,
- 276, 276, 277, 277, 277, 278, 279, 280, 281, 282,
- 283, 283, 283, 283, 283, 283, 283, 283, 283, 284,
- 284, 284, 284, 284, 284, 284, 284, 285, 285, 285,
- 285, 285, 285, 285, 285, 286, 286, 287, 287, 287,
- 287, 288, 288, 288, 288, 288, 288, 288, 288, 288,
- 289, 289, 289, 289, 290, 290, 290, 290, 291, 291,
- 292, 292, 293, 293, 294, 294, 294, 294, 295, 295,
- 295, 295, 295, 295, 295, 295, 295, 295, 295, 295,
- 295, 295, 295, 295, 295, 295, 295, 295, 295, 295,
- 295, 295, 295, 295, 295, 295, 295, 295, 295, 295,
- 295, 295, 295, 295, 296, 297, 298, 299, 300, 301,
- 302, 303, 303, 304, 305, 305, 306, 306, 307, 308,
- 308, 309, 310, 311, 312, 312, 313, 314, 315, 316,
- 317, 318, 319, 320, 321, 322, 323, 324, 324, 324,
- 325, 325, 326, 327, 327, 328, 328, 329, 330, 330,
- 330, 331, 331, 332, 333, 334, 335, 336, 336, 337,
- 338, 338, 339, 339, 340, 340, 341, 342, 342, 342,
- 343, 343, 344, 345, 346, 347, 348, 348, 349, 350,
- 350, 351, 352, 352, 352, 353, 354, 354, 354, 354,
- 355, 356, 357, 358, 359, 359, 360, 360, 360, 360,
- 361, 362, 362, 362, 362, 363, 364, 365, 366, 367,
- 368, 369, 370, 371, 371, 371, 372, 373, 374, 375,
- 375, 376, 377, 378, 378, 379, 380, 381, 382, 383,
- 383, 384, 385, 386, 386, 387, 388, 388, 388, 388,
- 388, 389, 390, 391, 392, 392, 393, 394, 394, 394,
- 395, 396, 396, 397, 398, 398, 399, 400, 401, 402,
- 402, 403, 404, 405, 406, 406, 406, 406, 406, 407,
- 407, 408, 409, 410, 410, 411, 412, 413, 414, 415,
- 415, 415, 415, 416, 417, 418, 419, 420, 421, 422,
- 423, 424, 424, 424, 424, 424, 424, 425, 426, 427,
- 428, 428, 428, 429, 429, 430, 431, 431, 432, 433,
- 433, 434, 435, 436, 437, 437, 438, 439, 440, 441,
- 442, 443, 444, 445, 446, 446, 446, 446, 447, 448,
- 448, 449, 450, 451, 452, 453, 454, 455, 456, 457,
- 458, 459, 460, 461, 462, 462, 462, 462, 462, 462,
- 462, 462, 462, 462, 462, 462, 463, 463, 464, 464,
- 464, 465, 466, 467, 468, 468, 469, 469, 469, 470,
- 471, 471, 472, 473, 473, 473, 473, 473, 473, 473,
- 473, 473, 473, 473, 473, 473, 473, 474, 474, 474,
- 474, 474, 474, 474, 475, 476, 476, 476, 476, 476,
- 476, 476, 477, 478, 479, 480, 481, 482, 483, 484,
- 485, 486, 487, 488, 488, 488, 488, 488, 489, 490,
- 491, 491, 491, 491, 492, 492, 492, 492, 493, 494,
- 495, 496, 497, 498, 498, 499, 499, 499, 499, 500,
- 501
+ 0, 164, 165, 165, 165, 165, 165, 165, 165, 165,
+ 165, 165, 166, 166, 166, 166, 166, 166, 167, 167,
+ 168, 169, 169, 170, 171, 172, 172, 173, 173, 174,
+ 175, 176, 177, 178, 178, 179, 179, 180, 180, 180,
+ 180, 181, 181, 182, 183, 184, 184, 184, 185, 185,
+ 186, 187, 188, 189, 190, 190, 191, 191, 192, 193,
+ 194, 195, 195, 195, 196, 197, 198, 198, 199, 200,
+ 200, 201, 201, 202, 202, 203, 203, 204, 205, 206,
+ 207, 207, 208, 208, 208, 209, 209, 209, 210, 210,
+ 211, 211, 211, 212, 212, 212, 212, 213, 214, 215,
+ 216, 217, 218, 218, 218, 218, 218, 218, 218, 218,
+ 218, 218, 218, 218, 218, 218, 218, 219, 219, 219,
+ 219, 219, 219, 219, 219, 219, 219, 219, 219, 219,
+ 219, 219, 220, 221, 222, 223, 224, 225, 226, 227,
+ 228, 229, 230, 230, 231, 232, 233, 234, 235, 236,
+ 236, 237, 237, 238, 239, 239, 239, 239, 239, 239,
+ 239, 240, 241, 242, 242, 243, 243, 244, 245, 246,
+ 247, 248, 249, 250, 251, 252, 252, 253, 254, 255,
+ 255, 255, 255, 255, 256, 257, 257, 257, 257, 258,
+ 259, 259, 260, 261, 262, 262, 263, 263, 264, 264,
+ 265, 265, 266, 267, 268, 268, 268, 269, 270, 270,
+ 270, 270, 271, 272, 273, 273, 273, 274, 275, 275,
+ 275, 275, 275, 275, 275, 275, 275, 276, 276, 276,
+ 277, 277, 278, 278, 278, 279, 280, 281, 282, 283,
+ 284, 284, 284, 284, 284, 284, 284, 284, 284, 285,
+ 285, 285, 285, 285, 285, 285, 285, 286, 286, 286,
+ 286, 286, 286, 286, 286, 287, 287, 288, 288, 288,
+ 288, 289, 289, 289, 289, 289, 289, 289, 289, 289,
+ 290, 290, 290, 290, 291, 291, 291, 291, 292, 292,
+ 293, 293, 294, 294, 295, 295, 295, 295, 296, 296,
+ 296, 296, 296, 296, 296, 296, 296, 296, 296, 296,
+ 296, 296, 296, 296, 296, 296, 296, 296, 296, 296,
+ 296, 296, 296, 296, 296, 296, 296, 296, 296, 296,
+ 296, 296, 296, 296, 297, 298, 299, 300, 301, 302,
+ 303, 304, 304, 305, 306, 306, 307, 307, 308, 309,
+ 309, 310, 311, 312, 313, 313, 314, 315, 316, 317,
+ 318, 319, 320, 321, 322, 323, 324, 325, 325, 325,
+ 326, 326, 327, 328, 328, 329, 329, 330, 331, 331,
+ 331, 332, 332, 333, 334, 335, 336, 337, 337, 338,
+ 339, 339, 340, 340, 341, 341, 342, 343, 343, 343,
+ 344, 344, 345, 346, 347, 348, 349, 349, 350, 351,
+ 351, 352, 353, 353, 353, 354, 355, 355, 355, 355,
+ 356, 357, 358, 359, 360, 360, 361, 361, 361, 361,
+ 362, 363, 363, 363, 363, 363, 364, 365, 366, 367,
+ 368, 369, 370, 371, 372, 372, 372, 373, 374, 375,
+ 376, 376, 377, 378, 379, 379, 380, 381, 382, 383,
+ 384, 384, 385, 386, 387, 387, 388, 389, 389, 389,
+ 389, 389, 390, 391, 392, 393, 393, 394, 395, 395,
+ 395, 396, 397, 397, 398, 399, 399, 400, 401, 402,
+ 403, 403, 404, 405, 406, 407, 407, 407, 407, 407,
+ 408, 408, 409, 410, 411, 411, 412, 413, 414, 415,
+ 416, 416, 416, 416, 417, 418, 419, 420, 421, 422,
+ 423, 424, 425, 425, 425, 425, 425, 425, 426, 427,
+ 428, 429, 429, 429, 430, 430, 431, 432, 432, 433,
+ 434, 434, 435, 436, 437, 438, 438, 438, 439, 440,
+ 441, 442, 443, 444, 445, 446, 447, 447, 447, 447,
+ 448, 449, 449, 450, 451, 452, 453, 454, 455, 456,
+ 457, 458, 459, 460, 461, 462, 463, 463, 463, 463,
+ 463, 463, 463, 463, 463, 463, 463, 463, 464, 464,
+ 465, 465, 465, 466, 467, 468, 469, 469, 470, 470,
+ 470, 471, 472, 472, 473, 474, 474, 474, 474, 474,
+ 474, 474, 474, 474, 474, 474, 474, 474, 474, 475,
+ 475, 475, 475, 475, 475, 475, 476, 477, 477, 478,
+ 479, 479, 479, 479, 479, 479, 479, 480, 481, 482,
+ 483, 484, 485, 486, 487, 488, 489, 490, 491, 492,
+ 493, 494, 494, 495, 496, 496, 496, 496, 496, 497,
+ 498, 499, 499, 500, 501, 501, 501, 501, 502, 502,
+ 502, 502, 503, 504, 505, 506, 507, 508, 508, 509,
+ 510, 510, 511, 511, 511, 511, 512, 513
};
/* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */
@@ -2213,31 +2252,32 @@ static const yytype_uint8 yyr2[] =
1, 1, 1, 1, 1, 6, 1, 1, 1, 4,
2, 7, 1, 1, 1, 1, 0, 2, 3, 5,
4, 1, 1, 10, 1, 1, 1, 1, 1, 1,
- 7, 0, 2, 4, 2, 9, 7, 9, 1, 1,
- 1, 1, 7, 0, 3, 3, 1, 1, 5, 1,
- 1, 1, 7, 0, 3, 1, 1, 1, 1, 1,
- 1, 8, 10, 1, 1, 10, 0, 3, 5, 3,
- 2, 5, 1, 1, 1, 1, 5, 1, 1, 1,
- 8, 1, 1, 5, 1, 1, 8, 1, 5, 1,
- 1, 8, 1, 5, 0, 3, 5, 3, 3, 1,
- 1, 4, 1, 1, 1, 4, 1, 1, 7, 0,
- 3, 3, 3, 1, 1, 5, 1, 1, 9, 1,
- 5, 1, 1, 1, 1, 1, 1, 7, 1, 1,
- 1, 1, 1, 1, 1, 10, 1, 1, 10, 1,
- 1, 10, 10, 7, 0, 2, 9, 7, 9, 10,
- 1, 1, 8, 1, 1, 1, 1, 1, 10, 1,
- 1, 6, 8, 1, 10, 6, 1, 10, 6, 1,
- 10, 6, 1, 9, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 0, 3,
- 2, 1, 1, 4, 1, 1, 1, 2, 3, 4,
- 1, 3, 1, 1, 1, 1, 1, 1, 1, 1,
+ 7, 0, 3, 5, 3, 3, 9, 7, 9, 1,
+ 1, 1, 1, 7, 0, 3, 3, 1, 1, 5,
+ 1, 1, 1, 7, 0, 3, 1, 1, 1, 1,
+ 1, 1, 8, 10, 1, 1, 10, 0, 3, 5,
+ 3, 2, 5, 1, 1, 1, 1, 5, 1, 1,
+ 1, 8, 1, 1, 5, 1, 1, 8, 1, 5,
+ 1, 1, 8, 1, 5, 0, 3, 5, 3, 3,
+ 1, 1, 4, 1, 1, 1, 4, 1, 1, 7,
+ 0, 3, 3, 3, 1, 1, 5, 1, 1, 9,
+ 1, 5, 1, 1, 1, 1, 1, 1, 7, 1,
+ 1, 1, 1, 1, 1, 1, 10, 1, 1, 10,
+ 1, 1, 10, 10, 7, 0, 3, 3, 9, 7,
+ 9, 10, 1, 1, 9, 1, 1, 1, 1, 1,
+ 10, 1, 1, 7, 9, 1, 10, 7, 1, 10,
+ 7, 1, 10, 7, 1, 9, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 3, 2, 1, 1, 4, 1, 1, 1, 2,
+ 3, 4, 1, 3, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 11, 0, 3, 3, 3, 5,
- 3, 2, 1, 1, 4, 1, 4, 1, 4, 1,
- 4, 1, 9, 0, 3, 3, 3, 2, 1, 19,
- 1, 1, 1, 1, 0, 6, 3, 2, 1, 1,
- 9, 1, 9, 1, 1, 0, 3, 3, 2, 1,
- 7
+ 1, 1, 1, 1, 1, 1, 4, 3, 1, 8,
+ 0, 3, 3, 3, 5, 3, 2, 1, 1, 4,
+ 1, 1, 4, 1, 4, 1, 4, 1, 4, 1,
+ 4, 3, 1, 6, 0, 3, 3, 3, 2, 1,
+ 4, 3, 1, 16, 1, 1, 1, 1, 0, 6,
+ 3, 2, 1, 1, 9, 1, 4, 3, 1, 6,
+ 1, 1, 0, 3, 3, 2, 1, 7
};
diff --git a/src/wkt2_generated_parser.h b/src/wkt2_generated_parser.h
index baeb0b4f..80b0c34b 100644
--- a/src/wkt2_generated_parser.h
+++ b/src/wkt2_generated_parser.h
@@ -121,76 +121,77 @@ extern int pj_wkt2_debug;
T_COORDEPOCH = 330,
T_COORDINATEMETADATA = 331,
T_POINTMOTIONOPERATION = 332,
- T_GEODETICCRS = 333,
- T_GEODETICDATUM = 334,
- T_PROJECTEDCRS = 335,
- T_PRIMEMERIDIAN = 336,
- T_GEOGRAPHICCRS = 337,
- T_TRF = 338,
- T_VERTICALCRS = 339,
- T_VERTICALDATUM = 340,
- T_VRF = 341,
- T_TIMEDATUM = 342,
- T_TEMPORALQUANTITY = 343,
- T_ENGINEERINGDATUM = 344,
- T_ENGINEERINGCRS = 345,
- T_PARAMETRICDATUM = 346,
- T_AFFINE = 347,
- T_CARTESIAN = 348,
- T_CYLINDRICAL = 349,
- T_ELLIPSOIDAL = 350,
- T_LINEAR = 351,
- T_PARAMETRIC = 352,
- T_POLAR = 353,
- T_SPHERICAL = 354,
- T_VERTICAL = 355,
- T_TEMPORAL = 356,
- T_TEMPORALCOUNT = 357,
- T_TEMPORALMEASURE = 358,
- T_ORDINAL = 359,
- T_TEMPORALDATETIME = 360,
- T_NORTH = 361,
- T_NORTHNORTHEAST = 362,
- T_NORTHEAST = 363,
- T_EASTNORTHEAST = 364,
- T_EAST = 365,
- T_EASTSOUTHEAST = 366,
- T_SOUTHEAST = 367,
- T_SOUTHSOUTHEAST = 368,
- T_SOUTH = 369,
- T_SOUTHSOUTHWEST = 370,
- T_SOUTHWEST = 371,
- T_WESTSOUTHWEST = 372,
- T_WEST = 373,
- T_WESTNORTHWEST = 374,
- T_NORTHWEST = 375,
- T_NORTHNORTHWEST = 376,
- T_UP = 377,
- T_DOWN = 378,
- T_GEOCENTRICX = 379,
- T_GEOCENTRICY = 380,
- T_GEOCENTRICZ = 381,
- T_COLUMNPOSITIVE = 382,
- T_COLUMNNEGATIVE = 383,
- T_ROWPOSITIVE = 384,
- T_ROWNEGATIVE = 385,
- T_DISPLAYRIGHT = 386,
- T_DISPLAYLEFT = 387,
- T_DISPLAYUP = 388,
- T_DISPLAYDOWN = 389,
- T_FORWARD = 390,
- T_AFT = 391,
- T_PORT = 392,
- T_STARBOARD = 393,
- T_CLOCKWISE = 394,
- T_COUNTERCLOCKWISE = 395,
- T_TOWARDS = 396,
- T_AWAYFROM = 397,
- T_FUTURE = 398,
- T_PAST = 399,
- T_UNSPECIFIED = 400,
- T_STRING = 401,
- T_UNSIGNED_INTEGER_DIFFERENT_ONE_TWO_THREE = 402
+ T_VERSION = 333,
+ T_GEODETICCRS = 334,
+ T_GEODETICDATUM = 335,
+ T_PROJECTEDCRS = 336,
+ T_PRIMEMERIDIAN = 337,
+ T_GEOGRAPHICCRS = 338,
+ T_TRF = 339,
+ T_VERTICALCRS = 340,
+ T_VERTICALDATUM = 341,
+ T_VRF = 342,
+ T_TIMEDATUM = 343,
+ T_TEMPORALQUANTITY = 344,
+ T_ENGINEERINGDATUM = 345,
+ T_ENGINEERINGCRS = 346,
+ T_PARAMETRICDATUM = 347,
+ T_AFFINE = 348,
+ T_CARTESIAN = 349,
+ T_CYLINDRICAL = 350,
+ T_ELLIPSOIDAL = 351,
+ T_LINEAR = 352,
+ T_PARAMETRIC = 353,
+ T_POLAR = 354,
+ T_SPHERICAL = 355,
+ T_VERTICAL = 356,
+ T_TEMPORAL = 357,
+ T_TEMPORALCOUNT = 358,
+ T_TEMPORALMEASURE = 359,
+ T_ORDINAL = 360,
+ T_TEMPORALDATETIME = 361,
+ T_NORTH = 362,
+ T_NORTHNORTHEAST = 363,
+ T_NORTHEAST = 364,
+ T_EASTNORTHEAST = 365,
+ T_EAST = 366,
+ T_EASTSOUTHEAST = 367,
+ T_SOUTHEAST = 368,
+ T_SOUTHSOUTHEAST = 369,
+ T_SOUTH = 370,
+ T_SOUTHSOUTHWEST = 371,
+ T_SOUTHWEST = 372,
+ T_WESTSOUTHWEST = 373,
+ T_WEST = 374,
+ T_WESTNORTHWEST = 375,
+ T_NORTHWEST = 376,
+ T_NORTHNORTHWEST = 377,
+ T_UP = 378,
+ T_DOWN = 379,
+ T_GEOCENTRICX = 380,
+ T_GEOCENTRICY = 381,
+ T_GEOCENTRICZ = 382,
+ T_COLUMNPOSITIVE = 383,
+ T_COLUMNNEGATIVE = 384,
+ T_ROWPOSITIVE = 385,
+ T_ROWNEGATIVE = 386,
+ T_DISPLAYRIGHT = 387,
+ T_DISPLAYLEFT = 388,
+ T_DISPLAYUP = 389,
+ T_DISPLAYDOWN = 390,
+ T_FORWARD = 391,
+ T_AFT = 392,
+ T_PORT = 393,
+ T_STARBOARD = 394,
+ T_CLOCKWISE = 395,
+ T_COUNTERCLOCKWISE = 396,
+ T_TOWARDS = 397,
+ T_AWAYFROM = 398,
+ T_FUTURE = 399,
+ T_PAST = 400,
+ T_UNSPECIFIED = 401,
+ T_STRING = 402,
+ T_UNSIGNED_INTEGER_DIFFERENT_ONE_TWO_THREE = 403
};
#endif
diff --git a/src/wkt2_grammar.y b/src/wkt2_grammar.y
index dddb0b30..6773d1e1 100644
--- a/src/wkt2_grammar.y
+++ b/src/wkt2_grammar.y
@@ -115,6 +115,7 @@
%token T_COORDEPOCH "COORDEPOCH"
%token T_COORDINATEMETADATA "COORDINATEMETADATA"
%token T_POINTMOTIONOPERATION "POINTMOTIONOPERATION"
+%token T_VERSION "VERSION"
/* WKT2 alternate (longer or shorter) */
%token T_GEODETICCRS "GEODETICCRS";
@@ -993,29 +994,30 @@ base_geodetic_crs: base_static_geodetic_crs | base_dynamic_geodetic_crs |
base_static_geodetic_crs: base_geodetic_crs_keyword left_delimiter base_crs_name
wkt_separator geodetic_reference_frame_or_geodetic_datum_ensemble_without_pm
- opt_separator_pm_ellipsoidal_cs_unit
+ opt_separator_pm_ellipsoidal_cs_unit_opt_separator_identifier_list
right_delimiter
-opt_separator_pm_ellipsoidal_cs_unit:
- | wkt_separator prime_meridian
- | wkt_separator prime_meridian wkt_separator ellipsoidal_cs_unit
- | wkt_separator ellipsoidal_cs_unit
+opt_separator_pm_ellipsoidal_cs_unit_opt_separator_identifier_list:
+ | wkt_separator prime_meridian opt_separator_identifier_list
+ | wkt_separator prime_meridian wkt_separator ellipsoidal_cs_unit opt_separator_identifier_list
+ | wkt_separator ellipsoidal_cs_unit opt_separator_identifier_list
+ | wkt_separator identifier opt_separator_identifier_list
base_dynamic_geodetic_crs: base_geodetic_crs_keyword left_delimiter base_crs_name
wkt_separator dynamic_crs
wkt_separator geodetic_reference_frame_without_pm
- opt_separator_pm_ellipsoidal_cs_unit
+ opt_separator_pm_ellipsoidal_cs_unit_opt_separator_identifier_list
right_delimiter
base_static_geographic_crs: base_geographic_crs_keyword left_delimiter base_crs_name
wkt_separator geodetic_reference_frame_or_geodetic_datum_ensemble_without_pm
- opt_separator_pm_ellipsoidal_cs_unit
+ opt_separator_pm_ellipsoidal_cs_unit_opt_separator_identifier_list
right_delimiter
base_dynamic_geographic_crs: base_geographic_crs_keyword left_delimiter base_crs_name
wkt_separator dynamic_crs
wkt_separator geodetic_reference_frame_without_pm
- opt_separator_pm_ellipsoidal_cs_unit
+ opt_separator_pm_ellipsoidal_cs_unit_opt_separator_identifier_list
right_delimiter
base_geodetic_crs_keyword: T_BASEGEODCRS
@@ -1281,27 +1283,28 @@ derived_dynamic_geog_crs: geographic_crs_keyword
base_static_geod_crs: base_geodetic_crs_keyword left_delimiter base_crs_name
wkt_separator geodetic_reference_frame_or_geodetic_datum_ensemble_without_pm
- opt_separator_pm
+ opt_separator_pm_opt_separator_identifier_list
right_delimiter
-opt_separator_pm:
- | wkt_separator prime_meridian
+opt_separator_pm_opt_separator_identifier_list:
+ | wkt_separator prime_meridian opt_separator_identifier_list
+ | wkt_separator identifier opt_separator_identifier_list
base_dynamic_geod_crs: base_geodetic_crs_keyword left_delimiter base_crs_name
wkt_separator dynamic_crs
wkt_separator geodetic_reference_frame_without_pm
- opt_separator_pm
+ opt_separator_pm_opt_separator_identifier_list
right_delimiter
base_static_geog_crs: base_geographic_crs_keyword left_delimiter base_crs_name
wkt_separator geodetic_reference_frame_or_geodetic_datum_ensemble_without_pm
- opt_separator_pm
+ opt_separator_pm_opt_separator_identifier_list
right_delimiter
base_dynamic_geog_crs: base_geographic_crs_keyword left_delimiter base_crs_name
wkt_separator dynamic_crs
wkt_separator geodetic_reference_frame_without_pm
- opt_separator_pm
+ opt_separator_pm_opt_separator_identifier_list
right_delimiter
// Derived projected CRS
@@ -1319,6 +1322,7 @@ derived_crs_name: quoted_latin_text
base_projected_crs: base_projected_crs_keyword left_delimiter base_crs_name
wkt_separator base_geodetic_geographic_crs
wkt_separator map_projection
+ opt_separator_identifier_list
right_delimiter
base_projected_crs_keyword: T_BASEPROJCRS
@@ -1337,11 +1341,15 @@ derived_vertical_crs: vertical_crs_keyword left_delimiter crs_name
base_vertical_crs: base_static_vertical_crs | base_dynamic_vertical_crs
base_static_vertical_crs: base_vertical_crs_keyword left_delimiter base_crs_name
- wkt_separator vertical_reference_frame right_delimiter
+ wkt_separator vertical_reference_frame
+ opt_separator_identifier_list
+ right_delimiter
base_dynamic_vertical_crs: base_vertical_crs_keyword left_delimiter base_crs_name
wkt_separator dynamic_crs
- wkt_separator vertical_reference_frame right_delimiter
+ wkt_separator vertical_reference_frame
+ opt_separator_identifier_list
+ right_delimiter
base_vertical_crs_keyword: T_BASEVERTCRS
@@ -1355,7 +1363,9 @@ derived_engineering_crs: engineering_crs_keyword left_delimiter crs_name
right_delimiter
base_engineering_crs: base_engineering_crs_keyword left_delimiter base_crs_name
- wkt_separator engineering_datum right_delimiter
+ wkt_separator engineering_datum
+ opt_separator_identifier_list
+ right_delimiter
base_engineering_crs_keyword: T_BASEENGCRS
@@ -1369,7 +1379,9 @@ derived_parametric_crs: parametric_crs_keyword left_delimiter crs_name
right_delimiter
base_parametric_crs: base_parametric_crs_keyword left_delimiter base_crs_name
- wkt_separator parametric_datum right_delimiter
+ wkt_separator parametric_datum
+ opt_separator_identifier_list
+ right_delimiter
base_parametric_crs_keyword: T_BASEPARAMCRS
@@ -1383,7 +1395,9 @@ derived_temporal_crs: temporal_crs_keyword left_delimiter crs_name
right_delimiter
base_temporal_crs: base_temporal_crs_keyword left_delimiter base_crs_name
- wkt_separator temporal_datum right_delimiter
+ wkt_separator temporal_datum
+ opt_separator_identifier_list
+ right_delimiter
base_temporal_crs_keyword: T_BASETIMECRS
@@ -1451,6 +1465,13 @@ dynamic_crs_coordinate_metadata: dynamic_geodetic_crs | dynamic_geographic_crs |
// Coordinate operations
coordinate_operation: operation_keyword left_delimiter operation_name
+ coordinate_operation_next
+
+coordinate_operation_next:
+ wkt_separator operation_version coordinate_operation_end
+ | coordinate_operation_end
+
+coordinate_operation_end:
wkt_separator source_crs wkt_separator target_crs
wkt_separator operation_method
opt_parameter_or_parameter_file_list_opt_interpolation_crs_opt_operation_accuracy_opt_separator_scope_extent_identifier_remark
@@ -1468,6 +1489,13 @@ operation_keyword: T_COORDINATEOPERATION
operation_name: quoted_latin_text
+operation_version: operation_version_keyword left_delimiter
+ operation_version_text right_delimiter
+
+operation_version_keyword: T_VERSION
+
+operation_version_text: quoted_latin_text
+
source_crs: source_crs_keyword left_delimiter crs right_delimiter
source_crs_keyword: T_SOURCECRS
@@ -1488,6 +1516,13 @@ operation_accuracy_keyword: T_OPERATIONACCURACY
// Point motion operation
point_motion_operation: point_motion_keyword left_delimiter operation_name
+ point_motion_operation_next
+
+point_motion_operation_next:
+ wkt_separator operation_version point_motion_operation_end
+ | point_motion_operation_end
+
+point_motion_operation_end:
wkt_separator source_crs
wkt_separator operation_method
opt_parameter_or_parameter_file_list_opt_operation_accuracy_opt_separator_scope_extent_identifier_remark
@@ -1506,6 +1541,13 @@ point_motion_keyword: T_POINTMOTIONOPERATION
concatenated_operation: concatenated_operation_keyword left_delimiter
operation_name
+ concatenated_operation_next
+
+concatenated_operation_next:
+ wkt_separator operation_version concatenated_operation_end
+ | concatenated_operation_end
+
+concatenated_operation_end:
wkt_separator source_crs wkt_separator target_crs
wkt_separator step_keyword left_delimiter step right_delimiter
wkt_separator step_keyword left_delimiter step right_delimiter
@@ -1535,8 +1577,16 @@ bound_crs: bound_crs_keyword left_delimiter
bound_crs_keyword: T_BOUNDCRS
abridged_coordinate_transformation: abridged_transformation_keyword left_delimiter
- operation_name wkt_separator
- operation_method wkt_separator
+ operation_name
+ abridged_coordinate_transformation_next
+
+abridged_coordinate_transformation_next:
+ wkt_separator operation_version abridged_coordinate_transformation_end
+ | abridged_coordinate_transformation_end
+
+abridged_coordinate_transformation_end:
+ wkt_separator operation_method
+ wkt_separator
abridged_parameter_or_parameter_file
opt_end_abridged_coordinate_transformation
right_delimiter
diff --git a/src/wkt2_parser.cpp b/src/wkt2_parser.cpp
index f77c7ceb..921d6dd4 100644
--- a/src/wkt2_parser.cpp
+++ b/src/wkt2_parser.cpp
@@ -100,7 +100,7 @@ static const wkt2_tokens tokens[] = {
PAIR(GEOGRAPHICCRS), PAIR(TRF), PAIR(VERTICALCRS), PAIR(VERTICALDATUM),
PAIR(VRF), PAIR(TIMEDATUM), PAIR(TEMPORALQUANTITY), PAIR(ENGINEERINGDATUM),
PAIR(ENGINEERINGCRS), PAIR(PARAMETRICDATUM), PAIR(EPOCH), PAIR(COORDEPOCH),
- PAIR(COORDINATEMETADATA), PAIR(POINTMOTIONOPERATION),
+ PAIR(COORDINATEMETADATA), PAIR(POINTMOTIONOPERATION), PAIR(VERSION),
// CS types
PAIR(AFFINE), PAIR(CARTESIAN), PAIR(CYLINDRICAL), PAIR(ELLIPSOIDAL),