1 /****************************************************************************** 2 * Project: PROJ.4 3 * Purpose: Internal plumbing for the PROJ.4 library. 4 * 5 * Author: Thomas Knudsen, <thokn@sdfe.dk> 6 * 7 ****************************************************************************** 8 * Copyright (c) 2016, 2017, Thomas Knudsen / SDFE 9 * 10 * Permission is hereby granted, free of charge, to any person obtaining a 11 * copy of this software and associated documentation files (the "Software"), 12 * to deal in the Software without restriction, including without limitation 13 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 14 * and/or sell copies of the Software, and to permit persons to whom the 15 * Software is furnished to do so, subject to the following conditions: 16 * 17 * The above copyright notice and this permission notice shall be included 18 * in all copies or substantial portions of the Software. 19 * 20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 21 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO COORD SHALL 23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26 * DEALINGS IN THE SOFTWARE. 27 *****************************************************************************/ 28 29 #ifndef PROJ_INTERNAL_H 30 #define PROJ_INTERNAL_H 31 32 #ifndef __cplusplus 33 #error "proj_internal.h can only be included from a C++ file" 34 #endif 35 36 #ifndef ACCEPT_USE_OF_DEPRECATED_PROJ_API_H 37 #define ACCEPT_USE_OF_DEPRECATED_PROJ_API_H 38 #endif 39 40 #ifdef _MSC_VER 41 # ifndef _CRT_SECURE_NO_DEPRECATE 42 # define _CRT_SECURE_NO_DEPRECATE 43 # endif 44 # ifndef _CRT_NONSTDC_NO_DEPRECATE 45 # define _CRT_NONSTDC_NO_DEPRECATE 46 # endif 47 /* enable predefined math constants M_* for MS Visual Studio workaround */ 48 # ifndef _USE_MATH_DEFINES 49 # define _USE_MATH_DEFINES 50 # endif 51 #endif 52 53 /* standard inclusions */ 54 #include <limits.h> 55 #include <math.h> 56 #include <stddef.h> 57 #include <stdio.h> 58 #include <stdlib.h> 59 #include <string.h> 60 61 #include "proj/common.hpp" 62 #include "proj/coordinateoperation.hpp" 63 64 #include <string> 65 #include <vector> 66 67 #include "proj.h" 68 69 #ifdef PROJ_API_H 70 #error proj_internal.h must be included before proj_api.h 71 #endif 72 73 #ifdef PROJ_RENAME_SYMBOLS 74 #include "proj_symbol_rename.h" 75 #endif 76 77 #define STATIC_ASSERT(COND) ((void)sizeof(char[(COND) ? 1 : -1])) 78 79 #ifndef PJ_TODEG 80 #define PJ_TODEG(rad) ((rad)*180.0/M_PI) 81 #endif 82 #ifndef PJ_TORAD 83 #define PJ_TORAD(deg) ((deg)*M_PI/180.0) 84 #endif 85 86 /* Maximum latitudinal overshoot accepted */ 87 #define PJ_EPS_LAT 1e-12 88 89 #define C_NAMESPACE extern "C" 90 #define C_NAMESPACE_VAR extern "C" 91 92 #ifndef NULL 93 # define NULL 0 94 #endif 95 96 #ifndef FALSE 97 # define FALSE 0 98 #endif 99 100 #ifndef TRUE 101 # define TRUE 1 102 #endif 103 104 #ifndef MAX 105 # define MIN(a,b) ((a<b) ? a : b) 106 # define MAX(a,b) ((a>b) ? a : b) 107 #endif 108 109 #ifndef ABS 110 # define ABS(x) ((x<0) ? (-1*(x)) : x) 111 #endif 112 113 #if INT_MAX == 2147483647 114 typedef int pj_int32; 115 #elif LONG_MAX == 2147483647 116 typedef long pj_int32; 117 #else 118 #warning It seems no 32-bit integer type is available 119 #endif 120 121 /* maximum path/filename */ 122 #ifndef MAX_PATH_FILENAME 123 #define MAX_PATH_FILENAME 1024 124 #endif 125 126 /* If we still haven't got M_PI*, we rely on our own defines. 127 * For example, this is necessary when compiling with gcc and 128 * the -ansi flag. 129 */ 130 #ifndef M_PI 131 #define M_PI 3.14159265358979323846 132 #define M_PI_2 1.57079632679489661923 133 #define M_PI_4 0.78539816339744830962 134 #define M_2_PI 0.63661977236758134308 135 #endif 136 137 /* M_SQRT2 might be missing */ 138 #ifndef M_SQRT2 139 #define M_SQRT2 1.41421356237309504880 140 #endif 141 142 /* some more useful math constants and aliases */ 143 #define M_FORTPI M_PI_4 /* pi/4 */ 144 #define M_HALFPI M_PI_2 /* pi/2 */ 145 #define M_PI_HALFPI 4.71238898038468985769 /* 1.5*pi */ 146 #define M_TWOPI 6.28318530717958647693 /* 2*pi */ 147 #define M_TWO_D_PI M_2_PI /* 2/pi */ 148 #define M_TWOPI_HALFPI 7.85398163397448309616 /* 2.5*pi */ 149 150 151 /* maximum tag id length for +init and default files */ 152 #ifndef ID_TAG_MAX 153 #define ID_TAG_MAX 50 154 #endif 155 156 /* Use WIN32 as a standard windows 32 bit declaration */ 157 #if defined(_WIN32) && !defined(WIN32) 158 # define WIN32 159 #endif 160 161 #if defined(_WINDOWS) && !defined(WIN32) 162 # define WIN32 163 #endif 164 165 /* directory delimiter for DOS support */ 166 #ifdef WIN32 167 #define DIR_CHAR '\\' 168 #else 169 #define DIR_CHAR '/' 170 #endif 171 172 enum pj_io_units { 173 PJ_IO_UNITS_WHATEVER = 0, /* Doesn't matter (or depends on pipeline neighbours) */ 174 PJ_IO_UNITS_CLASSIC = 1, /* Scaled meters (right), projected system */ 175 PJ_IO_UNITS_PROJECTED = 2, /* Meters, projected system */ 176 PJ_IO_UNITS_CARTESIAN = 3, /* Meters, 3D cartesian system */ 177 PJ_IO_UNITS_RADIANS = 4, /* Radians */ 178 PJ_IO_UNITS_DEGREES = 5, /* Degrees */ 179 180 }; 181 enum pj_io_units pj_left (PJ *P); 182 enum pj_io_units pj_right (PJ *P); 183 184 PJ_COORD PROJ_DLL proj_coord_error (void); 185 186 void proj_context_errno_set (PJ_CONTEXT *ctx, int err); 187 void PROJ_DLL proj_context_set (PJ *P, PJ_CONTEXT *ctx); 188 void proj_context_inherit (PJ *parent, PJ *child); 189 190 struct projCppContext; 191 /* not sure why we need to export it, but mingw needs it */ 192 void PROJ_DLL proj_context_delete_cpp_context(struct projCppContext* cppContext); 193 194 PJ_COORD pj_fwd4d (PJ_COORD coo, PJ *P); 195 PJ_COORD pj_inv4d (PJ_COORD coo, PJ *P); 196 197 PJ_COORD PROJ_DLL pj_approx_2D_trans (PJ *P, PJ_DIRECTION direction, PJ_COORD coo); 198 PJ_COORD PROJ_DLL pj_approx_3D_trans (PJ *P, PJ_DIRECTION direction, PJ_COORD coo); 199 200 void PROJ_DLL proj_log_error (PJ *P, const char *fmt, ...); 201 void proj_log_debug (PJ *P, const char *fmt, ...); 202 void proj_log_trace (PJ *P, const char *fmt, ...); 203 204 void proj_context_log_debug (PJ_CONTEXT *ctx, const char *fmt, ...); 205 206 int pj_ellipsoid (PJ *); 207 void pj_inherit_ellipsoid_def (const PJ *src, PJ *dst); 208 int pj_calc_ellipsoid_params (PJ *P, double a, double es); 209 210 /* Geographical to geocentric latitude - another of the "simple, but useful" */ 211 PJ_COORD pj_geocentric_latitude (const PJ *P, PJ_DIRECTION direction, PJ_COORD coord); 212 213 char PROJ_DLL *pj_chomp (char *c); 214 char PROJ_DLL *pj_shrink (char *c); 215 size_t pj_trim_argc (char *args); 216 char **pj_trim_argv (size_t argc, char *args); 217 char *pj_make_args (size_t argc, char **argv); 218 219 typedef struct { double r, i; } COMPLEX; 220 221 /* Forward declarations and typedefs for stuff needed inside the PJ object */ 222 struct PJconsts; 223 224 union PJ_COORD; 225 struct geod_geodesic; 226 struct ARG_list; 227 struct PJ_REGION_S; 228 typedef struct PJ_REGION_S PJ_Region; 229 typedef struct ARG_list paralist; /* parameter list */ 230 231 #ifndef PROJ_H 232 typedef struct PJconsts PJ; /* the PJ object herself */ 233 typedef union PJ_COORD PJ_COORD; 234 #endif 235 236 struct PJ_REGION_S { 237 double ll_long; /* lower left corner coordinates (radians) */ 238 double ll_lat; 239 double ur_long; /* upper right corner coordinates (radians) */ 240 double ur_lat; 241 }; 242 243 struct PJ_AREA { 244 int bbox_set; 245 double west_lon_degree; 246 double south_lat_degree; 247 double east_lon_degree; 248 double north_lat_degree; 249 }; 250 251 struct projCtx_t; 252 typedef struct projCtx_t projCtx_t; 253 254 /***************************************************************************** 255 256 Some function types that are especially useful when working with PJs 257 258 ****************************************************************************** 259 260 PJ_CONSTRUCTOR: 261 262 A function taking a pointer-to-PJ as arg, and returning a pointer-to-PJ. 263 Historically called twice: First with a 0 argument, to allocate memory, 264 second with the first return value as argument, for actual setup. 265 266 PJ_DESTRUCTOR: 267 268 A function taking a pointer-to-PJ and an integer as args, then first 269 handling the deallocation of the PJ, afterwards handing the integer over 270 to the error reporting subsystem, and finally returning a null pointer in 271 support of the "return free (P)" (aka "get the hell out of here") idiom. 272 273 PJ_OPERATOR: 274 275 A function taking a PJ_COORD and a pointer-to-PJ as args, applying the 276 PJ to the PJ_COORD, and returning the resulting PJ_COORD. 277 278 *****************************************************************************/ 279 typedef PJ *(* PJ_CONSTRUCTOR) (PJ *); 280 typedef PJ *(* PJ_DESTRUCTOR) (PJ *, int); 281 typedef PJ_COORD (* PJ_OPERATOR) (PJ_COORD, PJ *); 282 /****************************************************************************/ 283 284 285 /* datum_type values */ 286 #define PJD_UNKNOWN 0 287 #define PJD_3PARAM 1 288 #define PJD_7PARAM 2 289 #define PJD_GRIDSHIFT 3 290 #define PJD_WGS84 4 /* WGS84 (or anything considered equivalent) */ 291 292 struct CoordOperation 293 { 294 int idxInOriginalList; 295 double minxSrc = 0.0; 296 double minySrc = 0.0; 297 double maxxSrc = 0.0; 298 double maxySrc = 0.0; 299 double minxDst = 0.0; 300 double minyDst = 0.0; 301 double maxxDst = 0.0; 302 double maxyDst = 0.0; 303 PJ* pj = nullptr; 304 std::string name{}; 305 double accuracy = -1.0; 306 bool isOffshore = false; 307 CoordOperationCoordOperation308 CoordOperation(int idxInOriginalListIn, 309 double minxSrcIn, double minySrcIn, double maxxSrcIn, double maxySrcIn, 310 double minxDstIn, double minyDstIn, double maxxDstIn, double maxyDstIn, 311 PJ* pjIn, const std::string& nameIn, double accuracyIn, bool isOffshoreIn): 312 idxInOriginalList(idxInOriginalListIn), 313 minxSrc(minxSrcIn), minySrc(minySrcIn), maxxSrc(maxxSrcIn), maxySrc(maxySrcIn), 314 minxDst(minxDstIn), minyDst(minyDstIn), maxxDst(maxxDstIn), maxyDst(maxyDstIn), 315 pj(pjIn), name(nameIn), 316 accuracy(accuracyIn), 317 isOffshore(isOffshoreIn) 318 { 319 } 320 321 CoordOperation(const CoordOperation&) = delete; 322 CoordOperationCoordOperation323 CoordOperation(CoordOperation&& other): 324 idxInOriginalList(other.idxInOriginalList), 325 minxSrc(other.minxSrc), minySrc(other.minySrc), maxxSrc(other.maxxSrc), maxySrc(other.maxySrc), 326 minxDst(other.minxDst), minyDst(other.minyDst), maxxDst(other.maxxDst), maxyDst(other.maxyDst), 327 name(std::move(other.name)), 328 accuracy(other.accuracy), 329 isOffshore(other.isOffshore) { 330 pj = other.pj; 331 other.pj = nullptr; 332 } 333 334 CoordOperation& operator=(const CoordOperation&) = delete; 335 ~CoordOperationCoordOperation336 ~CoordOperation() 337 { 338 proj_destroy(pj); 339 } 340 }; 341 342 enum class TMercAlgo 343 { 344 AUTO, // Poder/Engsager if far from central meridian, otherwise Evenden/Snyder 345 EVENDEN_SNYDER, 346 PODER_ENGSAGER, 347 }; 348 349 /* base projection data structure */ 350 struct PJconsts { 351 352 /************************************************************************************* 353 354 G E N E R A L P A R A M E T E R S T R U C T 355 356 ************************************************************************************** 357 358 TODO: Need some description here - especially about the thread context... 359 This is the struct behind the PJ typedef 360 361 **************************************************************************************/ 362 363 projCtx_t *ctx = nullptr; 364 const char *descr = nullptr; /* From pj_list.h or individual PJ_*.c file */ 365 paralist *params = nullptr; /* Parameter list */ 366 char *def_full = nullptr; /* Full textual definition (usually 0 - set by proj_pj_info) */ 367 PJconsts *parent = nullptr; /* Parent PJ of pipeline steps - nullptr if not a pipeline step */ 368 369 /* For debugging / logging purposes */ 370 char *def_size = nullptr; /* Shape and size parameters extracted from params */ 371 char *def_shape = nullptr; 372 char *def_spherification = nullptr; 373 char *def_ellps = nullptr; 374 375 struct geod_geodesic *geod = nullptr; /* For geodesic computations */ 376 void *opaque = nullptr; /* Projection specific parameters, Defined in PJ_*.c */ 377 int inverted = 0; /* Tell high level API functions to swap inv/fwd */ 378 379 380 /************************************************************************************* 381 382 F U N C T I O N P O I N T E R S 383 384 ************************************************************************************** 385 386 For projection xxx, these are pointers to functions in the corresponding 387 PJ_xxx.c file. 388 389 pj_init() delegates the setup of these to pj_projection_specific_setup_xxx(), 390 a name which is currently hidden behind the magic curtain of the PROJECTION 391 macro. 392 393 **************************************************************************************/ 394 395 396 PJ_XY (*fwd)(PJ_LP, PJ *) = nullptr; 397 PJ_LP (*inv)(PJ_XY, PJ *) = nullptr; 398 PJ_XYZ (*fwd3d)(PJ_LPZ, PJ *) = nullptr; 399 PJ_LPZ (*inv3d)(PJ_XYZ, PJ *) = nullptr; 400 PJ_OPERATOR fwd4d = nullptr; 401 PJ_OPERATOR inv4d = nullptr; 402 403 PJ_DESTRUCTOR destructor = nullptr; 404 void (*reassign_context)(PJ*, projCtx_t *) = nullptr; 405 406 407 /************************************************************************************* 408 409 E L L I P S O I D P A R A M E T E R S 410 411 ************************************************************************************** 412 413 Despite YAGNI, we add a large number of ellipsoidal shape parameters, which 414 are not yet set up in pj_init. They are, however, inexpensive to compute, 415 compared to the overall time taken for setting up the complex PJ object 416 (cf. e.g. https://en.wikipedia.org/wiki/Angular_eccentricity). 417 418 But during single point projections it will often be a useful thing to have 419 these readily available without having to recompute at every pj_fwd / pj_inv 420 call. 421 422 With this wide selection, we should be ready for quite a number of geodetic 423 algorithms, without having to incur further ABI breakage. 424 425 **************************************************************************************/ 426 427 /* The linear parameters */ 428 429 double a = 0.0; /* semimajor axis (radius if eccentricity==0) */ 430 double b = 0.0; /* semiminor axis */ 431 double ra = 0.0; /* 1/a */ 432 double rb = 0.0; /* 1/b */ 433 434 /* The eccentricities */ 435 436 double alpha = 0.0; /* angular eccentricity */ 437 double e = 0.0; /* first eccentricity */ 438 double es = 0.0; /* first eccentricity squared */ 439 double e2 = 0.0; /* second eccentricity */ 440 double e2s = 0.0; /* second eccentricity squared */ 441 double e3 = 0.0; /* third eccentricity */ 442 double e3s = 0.0; /* third eccentricity squared */ 443 double one_es = 0.0; /* 1 - e^2 */ 444 double rone_es = 0.0; /* 1/one_es */ 445 446 447 /* The flattenings */ 448 double f = 0.0; /* first flattening */ 449 double f2 = 0.0; /* second flattening */ 450 double n = 0.0; /* third flattening */ 451 double rf = 0.0; /* 1/f */ 452 double rf2 = 0.0; /* 1/f2 */ 453 double rn = 0.0; /* 1/n */ 454 455 /* This one's for GRS80 */ 456 double J = 0.0; /* "Dynamic form factor" */ 457 458 double es_orig = 0.0; /* es and a before any +proj related adjustment */ 459 double a_orig = 0.0; 460 461 462 /************************************************************************************* 463 464 C O O R D I N A T E H A N D L I N G 465 466 **************************************************************************************/ 467 468 int over = 0; /* Over-range flag */ 469 int geoc = 0; /* Geocentric latitude flag */ 470 int is_latlong = 0; /* proj=latlong ... not really a projection at all */ 471 int is_geocent = 0; /* proj=geocent ... not really a projection at all */ 472 int need_ellps = 0; /* 0 for operations that are purely cartesian */ 473 int skip_fwd_prepare = 0; 474 int skip_fwd_finalize = 0; 475 int skip_inv_prepare = 0; 476 int skip_inv_finalize = 0; 477 478 enum pj_io_units left = PJ_IO_UNITS_WHATEVER; /* Flags for input/output coordinate types */ 479 enum pj_io_units right = PJ_IO_UNITS_WHATEVER; 480 481 /* These PJs are used for implementing cs2cs style coordinate handling in the 4D API */ 482 PJ *axisswap = nullptr; 483 PJ *cart = nullptr; 484 PJ *cart_wgs84 = nullptr; 485 PJ *helmert = nullptr; 486 PJ *hgridshift = nullptr; 487 PJ *vgridshift = nullptr; 488 489 490 /************************************************************************************* 491 492 C A R T O G R A P H I C O F F S E T S 493 494 **************************************************************************************/ 495 496 double lam0 = 0.0; /* central meridian */ 497 double phi0 = 0.0; /* central parallel */ 498 double x0 = 0.0; /* false easting */ 499 double y0 = 0.0; /* false northing */ 500 double z0 = 0.0; /* height origin */ 501 double t0 = 0.0; /* time origin */ 502 503 504 /************************************************************************************* 505 506 S C A L I N G 507 508 **************************************************************************************/ 509 510 double k0 = 0.0; /* General scaling factor - e.g. the 0.9996 of UTM */ 511 double to_meter = 0.0, fr_meter = 0.0; /* Plane coordinate scaling. Internal unit [m] */ 512 double vto_meter = 0.0, vfr_meter = 0.0; /* Vertical scaling. Internal unit [m] */ 513 514 515 /************************************************************************************* 516 517 D A T U M S A N D H E I G H T S Y S T E M S 518 519 ************************************************************************************** 520 521 It may be possible, and meaningful, to move the list parts of this up to the 522 PJ_CONTEXT level. 523 524 **************************************************************************************/ 525 526 int datum_type = PJD_UNKNOWN; /* PJD_UNKNOWN/3PARAM/7PARAM/GRIDSHIFT/WGS84 */ 527 double datum_params[7] = {0,0,0,0,0,0,0}; /* Parameters for 3PARAM and 7PARAM */ 528 529 int has_geoid_vgrids = 0; /* used by legacy transform.cpp */ 530 void* hgrids_legacy = nullptr; /* used by legacy transform.cpp. Is a pointer to a ListOfHGrids* */ 531 void* vgrids_legacy = nullptr; /* used by legacy transform.cpp. Is a pointer to a ListOfVGrids* */ 532 533 double from_greenwich = 0.0; /* prime meridian offset (in radians) */ 534 double long_wrap_center = 0.0; /* 0.0 for -180 to 180, actually in radians*/ 535 int is_long_wrap_set = 0; 536 char axis[4] = {0,0,0,0}; /* Axis order, pj_transform/pj_adjust_axis */ 537 538 /************************************************************************************* 539 ISO-19111 interface 540 **************************************************************************************/ 541 542 NS_PROJ::common::IdentifiedObjectPtr iso_obj{}; 543 544 // cached results 545 mutable std::string lastWKT{}; 546 mutable std::string lastPROJString{}; 547 mutable std::string lastJSONString{}; 548 mutable bool gridsNeededAsked = false; 549 mutable std::vector<NS_PROJ::operation::GridDescription> gridsNeeded{}; 550 551 /************************************************************************************* 552 proj_create_crs_to_crs() alternative coordinate operations 553 **************************************************************************************/ 554 std::vector<CoordOperation> alternativeCoordinateOperations{}; 555 int iCurCoordOp = -1; 556 557 /************************************************************************************* 558 559 E N D O F G E N E R A L P A R A M E T E R S T R U C T 560 561 **************************************************************************************/ 562 563 PJconsts(); 564 PJconsts(const PJconsts &) = delete; 565 PJconsts &operator=(const PJconsts &) = delete; 566 }; 567 568 569 570 571 /* Parameter list (a copy of the +proj=... etc. parameters) */ 572 struct ARG_list { 573 paralist *next; 574 char used; 575 #if (defined(__GNUC__) && __GNUC__ >= 8) || (defined(__clang__) && __clang_major__ >= 9) 576 char param[]; /* variable-length member */ 577 /* Safer to use [] for gcc 8. See https://github.com/OSGeo/proj.4/pull/1087 */ 578 /* and https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86914 */ 579 #else 580 char param[1]; /* variable-length member */ 581 #endif 582 }; 583 584 585 typedef union { double f; int i; char *s; } PROJVALUE; 586 587 588 struct PJ_DATUMS { 589 const char *id; /* datum keyword */ 590 const char *defn; /* ie. "to_wgs84=..." */ 591 const char *ellipse_id; /* ie from ellipse table */ 592 const char *comments; /* EPSG code, etc */ 593 }; 594 595 596 struct DERIVS { 597 double x_l, x_p; /* derivatives of x for lambda-phi */ 598 double y_l, y_p; /* derivatives of y for lambda-phi */ 599 }; 600 601 struct FACTORS { 602 struct DERIVS der; 603 double h, k; /* meridional, parallel scales */ 604 double omega, thetap; /* angular distortion, theta prime */ 605 double conv; /* convergence */ 606 double s; /* areal scale factor */ 607 double a, b; /* max-min scale error */ 608 int code; /* always 0 */ 609 }; 610 611 /* library errors */ 612 #define PJD_ERR_NO_ARGS -1 613 #define PJD_ERR_NO_OPTION_IN_INIT_FILE -2 614 #define PJD_ERR_NO_COLON_IN_INIT_STRING -3 615 #define PJD_ERR_PROJ_NOT_NAMED -4 616 #define PJD_ERR_UNKNOWN_PROJECTION_ID -5 617 #define PJD_ERR_INVALID_ECCENTRICITY -6 618 #define PJD_ERR_UNKNOWN_UNIT_ID -7 619 #define PJD_ERR_INVALID_BOOLEAN_PARAM -8 620 #define PJD_ERR_UNKNOWN_ELLP_PARAM -9 621 #define PJD_ERR_REV_FLATTENING_IS_ZERO -10 622 #define PJD_ERR_REF_RAD_LARGER_THAN_90 -11 623 #define PJD_ERR_ES_LESS_THAN_ZERO -12 624 #define PJD_ERR_MAJOR_AXIS_NOT_GIVEN -13 625 #define PJD_ERR_LAT_OR_LON_EXCEED_LIMIT -14 626 #define PJD_ERR_INVALID_X_OR_Y -15 627 #define PJD_ERR_WRONG_FORMAT_DMS_VALUE -16 628 #define PJD_ERR_NON_CONV_INV_MERI_DIST -17 629 #define PJD_ERR_NON_CON_INV_PHI2 -18 630 #define PJD_ERR_ACOS_ASIN_ARG_TOO_LARGE -19 631 #define PJD_ERR_TOLERANCE_CONDITION -20 632 #define PJD_ERR_CONIC_LAT_EQUAL -21 633 #define PJD_ERR_LAT_LARGER_THAN_90 -22 634 #define PJD_ERR_LAT1_IS_ZERO -23 635 #define PJD_ERR_LAT_TS_LARGER_THAN_90 -24 636 #define PJD_ERR_CONTROL_POINT_NO_DIST -25 637 #define PJD_ERR_NO_ROTATION_PROJ -26 638 #define PJD_ERR_W_OR_M_ZERO_OR_LESS -27 639 #define PJD_ERR_LSAT_NOT_IN_RANGE -28 640 #define PJD_ERR_PATH_NOT_IN_RANGE -29 641 #define PJD_ERR_INVALID_H -30 642 #define PJD_ERR_K_LESS_THAN_ZERO -31 643 #define PJD_ERR_LAT_1_OR_2_ZERO_OR_90 -32 644 #define PJD_ERR_LAT_0_OR_ALPHA_EQ_90 -33 645 #define PJD_ERR_ELLIPSOID_USE_REQUIRED -34 646 #define PJD_ERR_INVALID_UTM_ZONE -35 647 /* -36 no longer used */ 648 #define PJD_ERR_FAILED_TO_FIND_PROJ -37 649 #define PJD_ERR_FAILED_TO_LOAD_GRID -38 650 #define PJD_ERR_INVALID_M_OR_N -39 651 #define PJD_ERR_N_OUT_OF_RANGE -40 652 #define PJD_ERR_LAT_1_2_UNSPECIFIED -41 653 #define PJD_ERR_ABS_LAT1_EQ_ABS_LAT2 -42 654 #define PJD_ERR_LAT_0_HALF_PI_FROM_MEAN -43 655 #define PJD_ERR_UNPARSEABLE_CS_DEF -44 656 #define PJD_ERR_GEOCENTRIC -45 657 #define PJD_ERR_UNKNOWN_PRIME_MERIDIAN -46 658 #define PJD_ERR_AXIS -47 659 #define PJD_ERR_GRID_AREA -48 660 #define PJD_ERR_INVALID_SWEEP_AXIS -49 661 #define PJD_ERR_MALFORMED_PIPELINE -50 662 #define PJD_ERR_UNIT_FACTOR_LESS_THAN_0 -51 663 #define PJD_ERR_INVALID_SCALE -52 664 #define PJD_ERR_NON_CONVERGENT -53 665 #define PJD_ERR_MISSING_ARGS -54 666 #define PJD_ERR_LAT_0_IS_ZERO -55 667 #define PJD_ERR_ELLIPSOIDAL_UNSUPPORTED -56 668 #define PJD_ERR_TOO_MANY_INITS -57 669 #define PJD_ERR_INVALID_ARG -58 670 #define PJD_ERR_INCONSISTENT_UNIT -59 671 #define PJD_ERR_MUTUALLY_EXCLUSIVE_ARGS -60 672 #define PJD_ERR_GENERIC_ERROR -61 673 #define PJD_ERR_NETWORK_ERROR -62 674 /* NOTE: Remember to update src/strerrno.cpp, src/apps/gie.cpp and transient_error in */ 675 /* src/transform.cpp when adding new value */ 676 677 // Legacy 678 struct projFileAPI_t; 679 680 struct projCppContext; 681 682 struct projNetworkCallbacksAndData 683 { 684 bool enabled = false; 685 bool enabled_env_variable_checked = false; // whereas we have checked PROJ_NETWORK env variable 686 proj_network_open_cbk_type open = nullptr; 687 proj_network_close_cbk_type close = nullptr; 688 proj_network_get_header_value_cbk_type get_header_value = nullptr; 689 proj_network_read_range_type read_range = nullptr; 690 void* user_data = nullptr; 691 }; 692 693 struct projGridChunkCache 694 { 695 bool enabled = true; 696 std::string filename{}; 697 long long max_size = 300 * 1024 * 1024; 698 int ttl = 86400; // 1 day 699 }; 700 701 struct projFileApiCallbackAndData 702 { 703 PROJ_FILE_HANDLE* (*open_cbk)(PJ_CONTEXT *ctx, const char *filename, PROJ_OPEN_ACCESS access, void* user_data) = nullptr; 704 size_t (*read_cbk)(PJ_CONTEXT *ctx, PROJ_FILE_HANDLE*, void* buffer, size_t size, void* user_data) = nullptr; 705 size_t (*write_cbk)(PJ_CONTEXT *ctx, PROJ_FILE_HANDLE*, const void* buffer, size_t size, void* user_data) = nullptr; 706 int (*seek_cbk)(PJ_CONTEXT *ctx, PROJ_FILE_HANDLE*, long long offset, int whence, void* user_data) = nullptr; 707 unsigned long long (*tell_cbk)(PJ_CONTEXT *ctx, PROJ_FILE_HANDLE*, void* user_data) = nullptr; 708 void (*close_cbk)(PJ_CONTEXT *ctx, PROJ_FILE_HANDLE*, void* user_data) = nullptr; 709 710 int (*exists_cbk)(PJ_CONTEXT *ctx, const char *filename, void* user_data) = nullptr; 711 int (*mkdir_cbk)(PJ_CONTEXT *ctx, const char *filename, void* user_data) = nullptr; 712 int (*unlink_cbk)(PJ_CONTEXT *ctx, const char *filename, void* user_data) = nullptr; 713 int (*rename_cbk)(PJ_CONTEXT *ctx, const char *oldPath, const char *newPath, void* user_data) = nullptr; 714 715 void* user_data = nullptr; 716 }; 717 718 /* proj thread context */ 719 struct projCtx_t { 720 int last_errno = 0; 721 int debug_level = 0; 722 void (*logger)(void *, int, const char *) = nullptr; 723 void *logger_app_data = nullptr; 724 struct projFileAPI_t *fileapi_legacy = nullptr; // for proj_api.h legacy API 725 struct projCppContext* cpp_context = nullptr; /* internal context for C++ code */ 726 int use_proj4_init_rules = -1; /* -1 = unknown, 0 = no, 1 = yes */ 727 int epsg_file_exists = -1; /* -1 = unknown, 0 = no, 1 = yes */ 728 std::string ca_bundle_path{}; 729 730 std::string env_var_proj_lib{}; // content of PROJ_LIB environment variable. Use Filemanager::getProjLibEnvVar() to access 731 std::vector<std::string> search_paths{}; 732 const char **c_compat_paths = nullptr; // same, but for projinfo usage 733 734 const char* (*file_finder_legacy) (const char*) = nullptr; // Only for proj_api compat. To remove once it is removed 735 const char* (*file_finder) (PJ_CONTEXT *, const char*, void* user_data) = nullptr; 736 void* file_finder_user_data = nullptr; 737 738 bool defer_grid_opening = false; // set transiently by pj_obj_create() 739 740 projFileApiCallbackAndData fileApi{}; 741 std::string custom_sqlite3_vfs_name{}; 742 std::string user_writable_directory{}; 743 744 // BEGIN ini file settings 745 bool iniFileLoaded = false; 746 std::string endpoint{}; 747 projNetworkCallbacksAndData networking{}; 748 projGridChunkCache gridChunkCache{}; 749 TMercAlgo defaultTmercAlgo = TMercAlgo::PODER_ENGSAGER; // can be overridden by content of proj.ini 750 // END ini file settings 751 752 int projStringParserCreateFromPROJStringRecursionCounter = 0; // to avoid potential infinite recursion in PROJStringParser::createFromPROJString() 753 int pipelineInitRecursiongCounter = 0; // to avoid potential infinite recursion in pipeline.cpp 754 755 756 projCtx_t() = default; 757 projCtx_t(const projCtx_t&); 758 ~projCtx_t(); 759 760 projCtx_t& operator= (const projCtx_t&) = delete; 761 762 projCppContext* get_cpp_context(); 763 void safeAutoCloseDbIfNeeded(); 764 void set_search_paths(const std::vector<std::string>& search_paths_in); 765 void set_ca_bundle_path(const std::string& ca_bundle_path_in); 766 767 static projCtx_t createDefault(); 768 }; 769 770 /* Generate pj_list external or make list from include file */ 771 #ifndef PJ_DATUMS__ 772 C_NAMESPACE_VAR struct PJ_DATUMS pj_datums[]; 773 #endif 774 775 776 777 778 779 #ifdef PJ_LIB__ 780 #define PROJ_HEAD(name, desc) static const char des_##name [] = desc 781 782 #define OPERATION(name, NEED_ELLPS) \ 783 \ 784 pj_projection_specific_setup_##name (PJ *P); \ 785 C_NAMESPACE PJ *pj_##name (PJ *P); \ 786 \ 787 C_NAMESPACE_VAR const char * const pj_s_##name = des_##name; \ 788 \ 789 C_NAMESPACE PJ *pj_##name (PJ *P) { \ 790 if (P) \ 791 return pj_projection_specific_setup_##name (P); \ 792 P = pj_new(); \ 793 if (nullptr==P) \ 794 return nullptr; \ 795 P->descr = des_##name; \ 796 P->need_ellps = NEED_ELLPS; \ 797 P->left = PJ_IO_UNITS_RADIANS; \ 798 P->right = PJ_IO_UNITS_CLASSIC; \ 799 return P; \ 800 } \ 801 \ 802 PJ *pj_projection_specific_setup_##name (PJ *P) 803 804 /* In ISO19000 lingo, an operation is either a conversion or a transformation */ 805 #define CONVERSION(name, need_ellps) OPERATION (name, need_ellps) 806 #define TRANSFORMATION(name, need_ellps) OPERATION (name, need_ellps) 807 808 /* In PROJ.4 a projection is a conversion taking angular input and giving scaled linear output */ 809 #define PROJECTION(name) CONVERSION (name, 1) 810 811 #endif /* def PJ_LIB__ */ 812 813 /* procedure prototypes */ 814 double PROJ_DLL dmstor(const char *, char **); 815 double dmstor_ctx(projCtx_t *ctx, const char *, char **); 816 void PROJ_DLL set_rtodms(int, int); 817 char PROJ_DLL *rtodms(char *, double, int, int); 818 double PROJ_DLL adjlon(double); 819 double aacos(projCtx_t *,double); 820 double aasin(projCtx_t *,double); 821 double asqrt(double); 822 double aatan2(double, double); 823 824 PROJVALUE PROJ_DLL pj_param(projCtx_t *ctx, paralist *, const char *); 825 paralist PROJ_DLL *pj_param_exists (paralist *list, const char *parameter); 826 paralist PROJ_DLL *pj_mkparam(const char *); 827 paralist *pj_mkparam_ws (const char *str, const char **next_str); 828 829 830 int PROJ_DLL pj_ell_set(projCtx_t *ctx, paralist *, double *, double *); 831 int pj_datum_set(projCtx_t *,paralist *, PJ *); 832 int pj_angular_units_set(paralist *, PJ *); 833 834 paralist *pj_clone_paralist( const paralist* ); 835 paralist *pj_search_initcache( const char *filekey ); 836 void pj_insert_initcache( const char *filekey, const paralist *list); 837 paralist *pj_expand_init(projCtx_t *ctx, paralist *init); 838 839 void *pj_dealloc_params (projCtx_t *ctx, paralist *start, int errlev); 840 841 842 double *pj_enfn(double); 843 double pj_mlfn(double, double, double, const double *); 844 double pj_inv_mlfn(projCtx_t *, double, double, const double *); 845 double pj_qsfn(double, double, double); 846 double pj_tsfn(double, double, double); 847 double pj_msfn(double, double, double); 848 double PROJ_DLL pj_phi2(projCtx_t *, const double, const double); 849 double pj_qsfn_(double, PJ *); 850 double *pj_authset(double); 851 double pj_authlat(double, double *); 852 853 COMPLEX pj_zpoly1(COMPLEX, const COMPLEX *, int); 854 COMPLEX pj_zpolyd1(COMPLEX, const COMPLEX *, int, COMPLEX *); 855 856 int pj_deriv(PJ_LP, double, const PJ *, struct DERIVS *); 857 int pj_factors(PJ_LP, const PJ *, double, struct FACTORS *); 858 859 void *proj_mdist_ini(double); 860 double proj_mdist(double, double, double, const void *); 861 double proj_inv_mdist(projCtx_t *ctx, double, const void *); 862 void *pj_gauss_ini(double, double, double *,double *); 863 PJ_LP pj_gauss(projCtx_t *, PJ_LP, const void *); 864 PJ_LP pj_inv_gauss(projCtx_t *, PJ_LP, const void *); 865 866 struct PJ_DATUMS PROJ_DLL *pj_get_datums_ref( void ); 867 868 PJ *pj_new(void); 869 PJ *pj_default_destructor (PJ *P, int errlev); 870 871 double PROJ_DLL pj_atof( const char* nptr ); 872 double pj_strtod( const char *nptr, char **endptr ); 873 void pj_freeup_plain (PJ *P); 874 875 PJ* pj_init_ctx_with_allow_init_epsg( projCtx_t *ctx, int argc, char **argv, int allow_init_epsg ); 876 877 std::string PROJ_DLL pj_add_type_crs_if_needed(const std::string& str); 878 std::string pj_double_quote_string_param_if_needed(const std::string& str); 879 880 PJ *pj_create_internal (PJ_CONTEXT *ctx, const char *definition); 881 PJ *pj_create_argv_internal (PJ_CONTEXT *ctx, int argc, char **argv); 882 883 // For use by projinfo 884 void pj_load_ini(PJ_CONTEXT* ctx); 885 886 // Exported for testing purposes only 887 std::string PROJ_DLL pj_context_get_grid_cache_filename(PJ_CONTEXT *ctx); 888 889 // For use by projsync 890 void PROJ_DLL pj_context_set_user_writable_directory(PJ_CONTEXT* ctx, const std::string& path); 891 std::string PROJ_DLL pj_get_relative_share_proj(PJ_CONTEXT *ctx); 892 893 std::vector<CoordOperation> pj_create_prepared_operations(PJ_CONTEXT *ctx, 894 const PJ *source_crs, 895 const PJ *target_crs, 896 PJ_OBJ_LIST* op_list); 897 898 int pj_get_suggested_operation(PJ_CONTEXT *ctx, 899 const std::vector<CoordOperation>& opList, 900 const int iExcluded[2], 901 PJ_DIRECTION direction, 902 PJ_COORD coord); 903 904 const PJ_UNITS *pj_list_linear_units(); 905 const PJ_UNITS *pj_list_angular_units(); 906 907 void pj_clear_hgridshift_knowngrids_cache(); 908 void pj_clear_vgridshift_knowngrids_cache(); 909 910 PJ_LP pj_generic_inverse_2d(PJ_XY xy, PJ *P, PJ_LP lpInitial); 911 912 /* classic public API */ 913 #include "proj_api.h" 914 915 #endif /* ndef PROJ_INTERNAL_H */ 916