From 5d22d137b1be282bdc14c1d12ab8f669f58d41a6 Mon Sep 17 00:00:00 2001 From: Charles Karney Date: Mon, 26 Oct 2020 12:44:18 -0400 Subject: Update Mercator projection Introduction ------------ The existing formulation for the Mercator projection is "satisfactory"; it is reasonably accurate. However for a core projection like Mercator, I think we should strive for full double precision accuracy. This commit uses cleaner, more accurate, and faster methods for computing the forward and inverse projections. These use the formulation in terms of hyperbolic functions that are manifestly odd in latitude psi = asinh(tan(phi)) - e * atanh(e * sin(phi)) (phi = latitude; psi = isometric latitude = Mercator y coordinate). Contrast this with the existing formulation psi = log(tan(pi/4 - phi/2)) - e/2 * log((1 + e * sin(phi)) / (1 - e * sin(phi))) where psi(-phi) isn't exactly equal to -psi(phi) and psi(0) isn't guaranteed to be 0. Implementation -------------- There's no particular issue implementing the forward projection, just apply the formulas above. The inverse projection is tricky because there's no closed form solution for the inverse. The existing code for the inverse uses an iterative method from Snyder. This is the usual hokey function iteration, and, as usual, the convergence rate is linear (error reduced by a constant factor on each iteration). This is OK (just) for low accuracy work. But nowadays, something with quadratic convergence (e.g., Newton's method, number of correct digits doubles on each iteration) is preferred (and used here). More on this later. The solution for phi(psi) I use is described in my TM paper and I lifted the specific formulation from GeographicLib's Math::tauf, which uses the same underlying machinery for all conformal projections. It solves for tan(phi) in terms of sinh(psi) which as a near identity mapping is ideal for Newton's method. For comparison I also look at the approach adopted by Poder + Engsager in their TM paper and implemented in etmerc. This uses trigonometric series (accurate to n^6) to convert phi <-> chi. psi is then given by psi = asinh(tan(chi)) Accuracy -------- I tested just the routines for transforming phi <-> psi from merc.cpp and measured the errors (converted to true nm = nanometers) for the forward and inverse mapping. I also included in my analysis the method used by etmerc. This uses a trigonometric series to convert phi <-> chi = atan(sinh(psi)), the conformal latitude. forward inverse max rms max rms old merc 3.60 0.85 2189.47 264.81 etmerc 1.82 0.38 1.42 0.37 new merc 1.83 0.30 2.12 0.31 1 nm is pretty much the absolute limit for accuracy in double precision (1 nm = 10e6 m / 2^53, approximately), and 5 nm is probably the limit on what you should routinely expect. So the old merc inverse is considerably less accurate that it could be. The old merc forward is OK on accuracy -- except that if does not preserve the parity of the projection. The accuracy of etmerc is fine (the truncation error of the 6th order series is small compared with the round-off error). However, situation reverses as the flattening is increased. E.g., at f = 1/150, the max error for the inverse projection is 8 nm. etmerc is OK for terrestrial applications, but couldn't be used for Mars. Timing ------ Here's what I get with g++ -O3 on various Linux machines with recent versions of g++. As always, you should take these with a grain of salt. You might expect the relative timings to vary by 20% or so when switching between compilers/machines. Times per call in ns = nanoseconds. forward inverse old merc 121 360 etmerc 4e-6 1.4 new merc 20 346 The new merc method is 6 times faster at the forward projection and modestly faster at the inverse projection (despite being more accurate). The latter result is because it only take 2 iterations of Newton's method to get full accuracy compared with an average of 5 iterations for the old method to get only um accuracy. A shocking aspect of these timings is how fast etmerc is. Another is that forward etmerc is streaks faster that inverse etmerc (it made be doubt my timing code). Evidently, asinh(tan(chi)) is a lot faster to compute than atan(sinh(psi)). The hesitation about adopting etmerc then comes down to: * the likelihood that Mercator may be used for non-terrestrial bodies; * the question of whether the timing benefits for the etmerc method would be noticeable in a realistic application; * need to duplicate the machinery for evaluating the coefficients for the series and for Clenshaw summation in the current code layout. Ripple effects ============== The Mercator routines used the the Snyder method, pj_tsfn and pj_phi2, are used in other projections. These relate phi to t = exp(-psi) (a rather bizarre choice in my book). I've retrofitted these to use the more accurate methods. These do the "right thing" for phi in [-pi/2, pi/2] , t in [0, inf], and e in [0, 1). NANs are properly handled. Of course, phi = pi/2 in double precision is actually less than pi/2, so cos(pi/2) > 0. So no special handling is needed for pi/2. Even if angles were handled in such a way that 90deg were exactly represented, these routines would still "work", with, e.g., tan(pi/2) -> inf. (A caution: with long doubles = a 64-bit fraction, we have cos(pi/2) < 0; and now we would need to be careful.) As a consequence, there no need for error handling in pj_tsfn; the HUGE_VAL return has gone and, of course, HUGE_VAL is a perfectly legal input to tsfn's inverse, phi2, which would return -pi/2. This "error handling" was only needed for e = 1, a case which is filtered out upstream. I will note that bad argument handling is much more natural using NAN instead of HUGE_VAL. See issue #2376 I've renamed the error condition for non-convergence of the inverse projection from "non-convergent inverse phi2" to "non-convergent sinh(psi) to tan(phi)". Now that pj_tsfn and pj_phi2 now return "better" results, there were some malfunctions in the projections that called them, specifically gstmerc, lcc, and tobmerc. * gstmerc invoked pj_tsfn(phi, sinphi, e) with a value of sinphi that wasn't equal to sin(phi). Disaster followed. I fixed this. I also replaced numerous occurrences of "-1.0 * x" by "-x". (Defining a function with arguments phi and sinphi is asking for trouble.) * lcc incorrectly thinks that the projection isn't defined for standard latitude = +/- 90d. This happens to be false (it reduces to polar stereographic in this limit). The check was whether tsfn(phi) = 0 (which only tested for the north pole not the south pole). However since tsfn(pi/2) now (correctly) returns a nonzero result, this test fails. I now just test for |phi| = pi/2. This is clearer and catches both poles (I'm assuming that the current implementation will probably fail in these cases). * tobmerc similarly thinks that phi close to +/- pi/2 can't be transformed even though psi(pi/2) is only 38. I'm disincline to fight this. However I did tighten up the failure condition (strict equality of |phi| == pi/2). OTHER STUFF =========== Testing ------- builtins.gei: I tightened up the tests for merc (and while I was about it etmerc and tmerc) to reflect full double precision accuracy. My test values are generated with MPFR enabled code and so should be accurate to all digits given. For the record, for GRS80 I use f = 1/298.2572221008827112431628366 in these calculations. pj_phi2_test: many of the tests were bogus testing irrelevant input parameters, like negative values of exp(-psi), and freezing in the arbitrary behavior of phi2. I've reworked most for the tests to be semi-useful. @schwehr can you review. Documentation ------------- I've updated merc.rst to outline the calculation of the inverse projection. phi2.cpp includes detailed notes about applying Newton's method to find tan(phi) in terms of sinh(psi). Future work ----------- lcc needs some tender loving care. It can easily (and should) be modified to allow stdlat = +/- 90 (reduces to polar stereographic), stdlat = 0 and stdlat_1 + stdlat_2 = 0 (reduces to Mercator). A little more elbow grease will allow the treatment of stdlat_1 close to stdlat_2 using divided differences. (See my implementation of the LambertConformalConic class in GeographicLib.) All the places where pj_tsfn and pj_phi2 are called need to be reworked to cut out the use of Snyder's t = exp(-psi() variable and instead use sinh(psi). Maybe include the machinery for series conversions between all auxiliary latitudes as "support functions". Then etmerc could use this (as could mlfn for computing meridional distance). merc could offer the etmerc style projection via chi as an option when the flattening is sufficiently small. --- docs/source/operations/projections/merc.rst | 30 ++++- src/phi2.cpp | 175 +++++++++++++++++++--------- src/proj_internal.h | 3 +- src/projections/gstmerc.cpp | 18 +-- src/projections/lcc.cpp | 10 +- src/projections/merc.cpp | 26 +---- src/projections/tobmerc.cpp | 19 ++- src/strerrno.cpp | 2 +- src/tsfn.cpp | 29 +++-- test/gie/builtins.gie | 108 ++++++++++++----- test/unit/pj_phi2_test.cpp | 84 +++++++------ 11 files changed, 324 insertions(+), 180 deletions(-) diff --git a/docs/source/operations/projections/merc.rst b/docs/source/operations/projections/merc.rst index 7b6e13da..2107b7b2 100644 --- a/docs/source/operations/projections/merc.rst +++ b/docs/source/operations/projections/merc.rst @@ -158,7 +158,35 @@ Inverse projection \lambda = \frac{x}{k_0 a}; \quad \psi = \frac{y}{k_0 a} The latitude :math:`\phi` is found by inverting the equation for -:math:`\psi` iteratively. +:math:`\psi`. This follows the method given by :cite:`Karney2011tm`. +Start by introducing the conformal latitude + +.. math:: + \chi = \tan^{-1}\sinh\psi + +The tangents of the latitudes :math:`\tau = \tan\phi` and :math:`\tau' = +\tan\chi = \sinh\psi` are related by + +.. math:: + \tau' = \tau \sqrt{1 + \sigma^2} - \sigma \sqrt{1 + \tau^2} + +where + +.. math:: + \sigma = \sinh\bigl(e \tanh^{-1}(e \tau/\sqrt{1 + \tau^2}) \bigr) + +This is obtained by taking the :math:`\sinh` of the equation for +:math:`\psi` and using the multiple argument formula. The equation for +:math:`\tau'` can be solved to give :math:`\tau` using Newton's method +using :math:`\tau = \tau'/(1 - e^2)` as an initial guess and with the +needed derivative given by + +..math:: + \frac{d\tau'}{d\tau} = \frac{1 - e^2}{1 + (1 - e^2)\tau^2} + \sqrt{1 + \tau'^2} \sqrt{1 + \tau^2} + +This converges after no more than 2 iterations. Finally set +:math:`\phi=\tan^{-1}\tau`. Further reading ############### diff --git a/src/phi2.cpp b/src/phi2.cpp index b81456b0..eb6d5c82 100644 --- a/src/phi2.cpp +++ b/src/phi2.cpp @@ -1,6 +1,7 @@ /* Determine latitude angle phi-2. */ #include +#include #include "proj.h" #include "proj_internal.h" @@ -8,61 +9,125 @@ static const double TOL = 1.0e-10; static const int N_ITER = 15; +double pj_sinhpsi2tanphi(projCtx ctx, const double taup, const double e) { + /**************************************************************************** + * Convert tau' = sinh(psi) = tan(chi) to tau = tan(phi). The code is taken + * from GeographicLib::Math::tauf(taup, e). + * + * Here + * phi = geographic latitude (radians) + * psi is the isometric latitude + * psi = asinh(tan(phi)) - e * atanh(e * sin(phi)) + * = asinh(tan(chi)) + * chi is the conformal latitude + * + * The representation of latitudes via their tangents, tan(phi) and tan(chi), + * maintains full *relative* accuracy close to latitude = 0 and +/- pi/2. + * This is sometimes important, e.g., to compute the scale of the transverse + * Mercator projection which involves cos(phi)/cos(chi) tan(phi) + * + * From Karney (2011), Eq. 7, + * + * tau' = sinh(psi) = sinh(asinh(tan(phi)) - e * atanh(e * sin(phi))) + * = tan(phi) * cosh(e * atanh(e * sin(phi))) - + * sec(phi) * sinh(e * atanh(e * sin(phi))) + * = tau * sqrt(1 + sigma^2) - sqrt(1 + tau^2) * sigma + * where + * sigma = sinh(e * atanh( e * tau / sqrt(1 + tau^2) )) + * + * For e small, + * + * tau' = (1 - e^2) * tau + * + * The relation tau'(tau) can therefore by reliably inverted by Newton's + * method with + * + * tau = tau' / (1 - e^2) + * + * as an initial guess. Newton's method requires dtau'/dtau. Noting that + * + * dsigma/dtau = e^2 * sqrt(1 + sigma^2) / + * (sqrt(1 + tau^2) * (1 + (1 - e^2) * tau^2)) + * d(sqrt(1 + tau^2))/dtau = tau / sqrt(1 + tau^2) + * + * we have + * + * dtau'/dtau = (1 - e^2) * sqrt(1 + tau'^2) * sqrt(1 + tau^2) / + * (1 + (1 - e^2) * tau^2) + * + * This works fine unless tau^2 and tau'^2 overflows. This may be partially + * cured by writing, e.g., sqrt(1 + tau^2) as hypot(1, tau). However, nan + * will still be generated with tau' = inf, since (inf - inf) will appear in + * the Newton iteration. + * + * If we note that for sufficiently large |tau|, i.e., |tau| >= 2/sqrt(eps), + * sqrt(1 + tau^2) = |tau| and + * + * tau' = exp(- e * atanh(e)) * tau + * + * So + * + * tau = exp(e * atanh(e)) * tau' + * + * can be returned unless |tau| >= 2/sqrt(eps); this then avoids overflow + * problems for large tau' and returns the correct result for tau' = +/-inf + * and nan. + * + * Newton's method usually take 2 iterations to converge to double precision + * accuracy (for WGS84 flattening). However only 1 iteration is needed for + * |chi| < 3.35 deg. In addition, only 1 iteration is needed for |chi| > + * 89.18 deg (tau' > 70), if tau = exp(e * atanh(e)) * tau' is used as the + * starting guess. + ****************************************************************************/ + + constexpr int numit = 5; + // min iterations = 1, max iterations = 2; mean = 1.954 + constexpr double tol = sqrt(std::numeric_limits::epsilon()) / 10; + constexpr double tmax = 2 / sqrt(std::numeric_limits::epsilon()); + double + e2m = 1 - e * e, + tau = fabs(taup) > 70 ? taup * exp(e * atanh(e)) : taup / e2m, + stol = tol * std::max(1.0, fabs(taup)); + if (!(fabs(tau) < tmax)) return tau; // handles +/-inf and nan and e = 1 + // if (e2m < 0) return std::numeric_limits::quiet_NaN(); + int i = numit; + for (; i; --i) { + double tau1 = sqrt(1 + tau * tau), + sig = sinh( e * atanh(e * tau / tau1) ), + taupa = sqrt(1 + sig * sig) * tau - sig * tau1, + dtau = (taup - taupa) * (1 + e2m * tau * tau) / + ( e2m * sqrt(1 + tau * tau) * sqrt(1 + taupa * taupa) ); + tau += dtau; + if (!(fabs(dtau) >= stol)) + break; + } + if (i == 0) + pj_ctx_set_errno(ctx, PJD_ERR_NON_CONV_SINHPSI2TANPHI); + return tau; +} + /*****************************************************************************/ double pj_phi2(projCtx ctx, const double ts0, const double e) { -/****************************************************************************** -Determine latitude angle phi-2. -Inputs: - ts = exp(-psi) where psi is the isometric latitude (dimensionless) - e = eccentricity of the ellipsoid (dimensionless) -Output: - phi = geographic latitude (radians) -Here isometric latitude is defined by - psi = log( tan(pi/4 + phi/2) * - ( (1 - e*sin(phi)) / (1 + e*sin(phi)) )^(e/2) ) - = asinh(tan(phi)) - e * atanh(e * sin(phi)) -This routine inverts this relation using the iterative scheme given -by Snyder (1987), Eqs. (7-9) - (7-11) -*******************************************************************************/ - const double eccnth = .5 * e; - double ts = ts0; -#ifdef no_longer_used_original_convergence_on_exact_dphi - double Phi = M_HALFPI - 2. * atan(ts); -#endif - int i = N_ITER; - - for(;;) { - /* - * sin(Phi) = sin(PI/2 - 2* atan(ts)) - * = cos(2*atan(ts)) - * = 2*cos^2(atan(ts)) - 1 - * = 2 / (1 + ts^2) - 1 - * = (1 - ts^2) / (1 + ts^2) - */ - const double sinPhi = (1 - ts * ts) / (1 + ts * ts); - const double con = e * sinPhi; - double old_ts = ts; - ts = ts0 * pow((1. - con) / (1. + con), eccnth); -#ifdef no_longer_used_original_convergence_on_exact_dphi - /* The convergence criterion is nominally on exact dphi */ - const double newPhi = M_HALFPI - 2. * atan(ts); - const double dphi = newPhi - Phi; - Phi = newPhi; -#else - /* If we don't immediately update Phi from this, we can - * change the conversion criterion to save us computing atan() at each step. - * Particularly we can observe that: - * |atan(ts) - atan(old_ts)| <= |ts - old_ts| - * So if |ts - old_ts| matches our convergence criterion, we're good. - */ - const double dphi = 2 * (ts - old_ts); -#endif - if (fabs(dphi) > TOL && --i) { - continue; - } - break; - } - if (i <= 0) - pj_ctx_set_errno(ctx, PJD_ERR_NON_CON_INV_PHI2); - return M_HALFPI - 2. * atan(ts); + /**************************************************************************** + * Determine latitude angle phi-2. + * Inputs: + * ts = exp(-psi) where psi is the isometric latitude (dimensionless) + * e = eccentricity of the ellipsoid (dimensionless) + * Output: + * phi = geographic latitude (radians) + * Here isometric latitude is defined by + * psi = log( tan(pi/4 + phi/2) * + * ( (1 - e*sin(phi)) / (1 + e*sin(phi)) )^(e/2) ) + * = asinh(tan(phi)) - e * atanh(e * sin(phi)) + * + * OLD: This routine inverts this relation using the iterative scheme given + * by Snyder (1987), Eqs. (7-9) - (7-11). + * + * NEW: This routine writes converts t = exp(-psi) to + * + * tau' = sinh(psi) = (1/t - t)/2 + * + * returns atan(sinpsi2tanphi(tau')) + ***************************************************************************/ + return atan(pj_sinhpsi2tanphi(ctx, (1/ts0 - ts0) / 2, e)); } diff --git a/src/proj_internal.h b/src/proj_internal.h index 79b1da10..203765a3 100644 --- a/src/proj_internal.h +++ b/src/proj_internal.h @@ -626,7 +626,7 @@ struct FACTORS { #define PJD_ERR_INVALID_X_OR_Y -15 #define PJD_ERR_WRONG_FORMAT_DMS_VALUE -16 #define PJD_ERR_NON_CONV_INV_MERI_DIST -17 -#define PJD_ERR_NON_CON_INV_PHI2 -18 +#define PJD_ERR_NON_CONV_SINHPSI2TANPHI -18 #define PJD_ERR_ACOS_ASIN_ARG_TOO_LARGE -19 #define PJD_ERR_TOLERANCE_CONDITION -20 #define PJD_ERR_CONIC_LAT_EQUAL -21 @@ -846,6 +846,7 @@ double pj_qsfn(double, double, double); double pj_tsfn(double, double, double); double pj_msfn(double, double, double); double PROJ_DLL pj_phi2(projCtx_t *, const double, const double); +double pj_sinhpsi2tanphi(projCtx_t *, const double, const double); double pj_qsfn_(double, PJ *); double *pj_authset(double); double pj_authlat(double, double *); diff --git a/src/projections/gstmerc.cpp b/src/projections/gstmerc.cpp index 808d9ef7..50814bb5 100644 --- a/src/projections/gstmerc.cpp +++ b/src/projections/gstmerc.cpp @@ -28,9 +28,9 @@ static PJ_XY gstmerc_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forw double L, Ls, sinLs1, Ls1; L = Q->n1*lp.lam; - Ls = Q->c + Q->n1 * log(pj_tsfn(-1.0 * lp.phi, -1.0 * sin(lp.phi), P->e)); + Ls = Q->c + Q->n1 * log(pj_tsfn(-lp.phi, -sin(lp.phi), P->e)); sinLs1 = sin(L) / cosh(Ls); - Ls1 = log(pj_tsfn(-1.0 * asin(sinLs1), 0.0, 0.0)); + Ls1 = log(pj_tsfn(-asin(sinLs1), -sinLs1, 0.0)); xy.x = (Q->XS + Q->n2*Ls1) * P->ra; xy.y = (Q->YS + Q->n2*atan(sinh(Ls) / cos(L))) * P->ra; @@ -45,9 +45,9 @@ static PJ_LP gstmerc_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inve L = atan(sinh((xy.x * P->a - Q->XS) / Q->n2) / cos((xy.y * P->a - Q->YS) / Q->n2)); sinC = sin((xy.y * P->a - Q->YS) / Q->n2) / cosh((xy.x * P->a - Q->XS) / Q->n2); - LC = log(pj_tsfn(-1.0 * asin(sinC), 0.0, 0.0)); + LC = log(pj_tsfn(-asin(sinC), -sinC, 0.0)); lp.lam = L / Q->n1; - lp.phi = -1.0 * pj_phi2(P->ctx, exp((LC - Q->c) / Q->n1), P->e); + lp.phi = -pj_phi2(P->ctx, exp((LC - Q->c) / Q->n1), P->e); return lp; } @@ -60,13 +60,13 @@ PJ *PROJECTION(gstmerc) { P->opaque = Q; Q->lamc = P->lam0; - Q->n1 = sqrt(1.0 + P->es * pow(cos(P->phi0), 4.0) / (1.0 - P->es)); + Q->n1 = sqrt(1 + P->es * pow(cos(P->phi0), 4.0) / (1 - P->es)); Q->phic = asin(sin(P->phi0) / Q->n1); - Q->c = log(pj_tsfn(-1.0 * Q->phic, 0.0, 0.0)) - - Q->n1 * log(pj_tsfn(-1.0 * P->phi0, -1.0 * sin(P->phi0), P->e)); - Q->n2 = P->k0 * P->a * sqrt(1.0 - P->es) / (1.0 - P->es * sin(P->phi0) * sin(P->phi0)); + Q->c = log(pj_tsfn(-Q->phic, -sin(P->phi0) / Q->n1, 0.0)) + - Q->n1 * log(pj_tsfn(-P->phi0, -sin(P->phi0), P->e)); + Q->n2 = P->k0 * P->a * sqrt(1 - P->es) / (1 - P->es * sin(P->phi0) * sin(P->phi0)); Q->XS = 0; - Q->YS = -1.0 * Q->n2 * Q->phic; + Q->YS = -Q->n2 * Q->phic; P->inv = gstmerc_s_inverse; P->fwd = gstmerc_s_forward; diff --git a/src/projections/lcc.cpp b/src/projections/lcc.cpp index 91ffc511..b83b8072 100644 --- a/src/projections/lcc.cpp +++ b/src/projections/lcc.cpp @@ -106,10 +106,10 @@ PJ *PROJECTION(lcc) { double ml1, m1; m1 = pj_msfn(sinphi, cosphi, P->es); - ml1 = pj_tsfn(Q->phi1, sinphi, P->e); - if( ml1 == 0 ) { + if( abs(Q->phi1) == M_HALFPI ) { return pj_default_destructor(P, PJD_ERR_LAT_1_OR_2_ZERO_OR_90); } + ml1 = pj_tsfn(Q->phi1, sinphi, P->e); if (secant) { /* secant cone */ sinphi = sin(Q->phi2); Q->n = log(m1 / pj_msfn(sinphi, cos(Q->phi2), P->es)); @@ -117,10 +117,10 @@ PJ *PROJECTION(lcc) { // 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); + if( abs(Q->phi2) == M_HALFPI ) { + return pj_default_destructor(P, PJD_ERR_LAT_1_OR_2_ZERO_OR_90); } + const double ml2 = pj_tsfn(Q->phi2, sinphi, P->e); const double denom = log(ml1 / ml2); if( denom == 0 ) { // Not quite, but es is very close to 1... diff --git a/src/projections/merc.cpp b/src/projections/merc.cpp index a77d7517..472cb43f 100644 --- a/src/projections/merc.cpp +++ b/src/projections/merc.cpp @@ -10,45 +10,25 @@ PROJ_HEAD(merc, "Mercator") "\n\tCyl, Sph&Ell\n\tlat_ts="; PROJ_HEAD(webmerc, "Web Mercator / Pseudo Mercator") "\n\tCyl, Ell\n\t"; -#define EPS10 1.e-10 -static double logtanpfpim1(double x) { /* log(tan(x/2 + M_FORTPI)) */ - if (fabs(x) <= DBL_EPSILON) { - /* tan(M_FORTPI + .5 * x) can be approximated by 1.0 + x */ - return log1p(x); - } - return log(tan(M_FORTPI + .5 * x)); -} - 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); - return xy; - } xy.x = P->k0 * lp.lam; - xy.y = - P->k0 * log(pj_tsfn(lp.phi, sin(lp.phi), P->e)); + xy.y = P->k0 * (asinh(tan(lp.phi)) - P->e * atanh(P->e * sin(lp.phi))); return xy; } 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); - return xy; -} xy.x = P->k0 * lp.lam; - xy.y = P->k0 * logtanpfpim1(lp.phi); + xy.y = P->k0 * asinh(tan(lp.phi)); return xy; } 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); - return lp; -} + lp.phi = atan(pj_sinhpsi2tanphi(P->ctx, sinh(xy.y / P->k0), P->e)); lp.lam = xy.x / P->k0; return lp; } diff --git a/src/projections/tobmerc.cpp b/src/projections/tobmerc.cpp index a1616036..f05a9b6b 100644 --- a/src/projections/tobmerc.cpp +++ b/src/projections/tobmerc.cpp @@ -9,27 +9,24 @@ PROJ_HEAD(tobmerc, "Tobler-Mercator") "\n\tCyl, Sph"; -#define EPS10 1.e-10 -static double logtanpfpim1(double x) { /* log(tan(x/2 + M_FORTPI)) */ - if (fabs(x) <= DBL_EPSILON) { - /* tan(M_FORTPI + .5 * x) can be approximated by 1.0 + x */ - return log1p(x); - } - return log(tan(M_FORTPI + .5 * x)); -} - static PJ_XY tobmerc_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */ PJ_XY xy = {0.0, 0.0}; double cosphi; - if (fabs(fabs(lp.phi) - M_HALFPI) <= EPS10) { + if (fabs(lp.phi) >= M_HALFPI) { + // builtins.gie tests "Test expected failure at the poles:". However + // given that M_HALFPI is strictly less than pi/2 in double precision, + // it's not clear why shouldn't just return a large result for xy.y (and + // it's not even that large, merely 38.025...). Even if the logic was + // such that phi was strictly equal to pi/2, allowing xy.y = inf would be + // a reasonable result. proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION); return xy; } cosphi = cos(lp.phi); xy.x = P->k0 * lp.lam * cosphi * cosphi; - xy.y = P->k0 * logtanpfpim1(lp.phi); + xy.y = P->k0 * asinh(tan(lp.phi)); return xy; } diff --git a/src/strerrno.cpp b/src/strerrno.cpp index 5ae0d7e1..1c8673d0 100644 --- a/src/strerrno.cpp +++ b/src/strerrno.cpp @@ -27,7 +27,7 @@ pj_err_list[] = { "invalid x or y", /* -15 */ "improperly formed DMS value", /* -16 */ "non-convergent inverse meridional dist", /* -17 */ - "non-convergent inverse phi2", /* -18 */ + "non-convergent sinh(psi) to tan(phi)", /* -18 */ "acos/asin: |arg| >1.+1e-14", /* -19 */ "tolerance condition error", /* -20 */ "conic lat_1 = -lat_2", /* -21 */ diff --git a/src/tsfn.cpp b/src/tsfn.cpp index 32da09f2..fe8f29ed 100644 --- a/src/tsfn.cpp +++ b/src/tsfn.cpp @@ -4,14 +4,25 @@ #include "proj_internal.h" double pj_tsfn(double phi, double sinphi, double e) { - double denominator; - sinphi *= e; + /**************************************************************************** + * Determine function ts(phi) defined in Snyder (1987), Eq. (7-10) + * Inputs: + * phi = geographic latitude (radians) + * e = eccentricity of the ellipsoid (dimensionless) + * Output: + * ts = exp(-psi) where psi is the isometric latitude (dimensionless) + * Here isometric latitude is defined by + * psi = log( tan(pi/4 + phi/2) * + * ( (1 - e*sin(phi)) / (1 + e*sin(phi)) )^(e/2) ) + * = asinh(tan(phi)) - e * atanh(e * sin(phi)) + ***************************************************************************/ - /* avoid zero division, fail gracefully */ - denominator = 1.0 + sinphi; - if (denominator == 0.0) - return HUGE_VAL; - - return (tan (.5 * (M_HALFPI - phi)) / - pow((1. - sinphi) / (denominator), .5 * e)); + double cosphi = cos(phi); + // exp(-asinh(tan(phi))) = 1 / (tan(phi) + sec(phi)) + // = cos(phi) / (1 + sin(phi)) good for phi > 0 + // = (1 - sin(phi)) / cos(phi) good for phi < 0 + return exp(e * atanh(e * sinphi)) * + ( sinphi > 0 ? + cosphi / (1 + sinphi) : + (1 - sinphi) / cosphi ); } diff --git a/test/gie/builtins.gie b/test/gie/builtins.gie index 02e6766e..402433ca 100644 --- a/test/gie/builtins.gie +++ b/test/gie/builtins.gie @@ -1423,9 +1423,9 @@ expect -0.001790143 -0.000895247 =============================================================================== ------------------------------------------------------------------------------- -operation +proj=etmerc +ellps=GRS80 +zone=30 +operation +proj=etmerc +ellps=GRS80 ------------------------------------------------------------------------------- -tolerance 0.1 mm +tolerance 50e-9 m accept 2 1 expect 222650.796797586 110642.229411933 accept 2 -1 @@ -1434,17 +1434,24 @@ accept -2 1 expect -222650.796797586 110642.229411933 accept -2 -1 expect -222650.796797586 -110642.229411933 +accept 30 89.9999 +expect 5.584698978 10001956.056248082 +accept 44.69 35.37 +expect 4168136.489446198 4985511.302287407 direction inverse accept 200 100 -expect 0.001796631 0.000904369 +expect 0.00179663056816 0.00090436947663 accept 200 -100 -expect 0.001796631 -0.000904369 +expect 0.00179663056816 -0.00090436947663 accept -200 100 -expect -0.001796631 0.000904369 +expect -0.00179663056816 0.00090436947663 accept -200 -100 -expect -0.001796631 -0.000904369 - +expect -0.00179663056816 -0.00090436947663 +accept 6 1.0001e7 +expect 0.35596960759234 89.99135362646302 +accept 4168136.489446198 4985511.302287407 +expect 44.69 35.37 =============================================================================== # Fahey @@ -3355,30 +3362,54 @@ expect -0.001953415 -0.000820580 ------------------------------------------------------------------------------- operation +proj=merc +ellps=GRS80 ------------------------------------------------------------------------------- -tolerance 0.1 mm +tolerance 0 m +accept 0 0 +expect 0 0 +tolerance 50e-9 m accept 2 1 -expect 222638.981586547 110579.965218250 +expect 222638.981586547 110579.965218249 accept 2 -1 expect 222638.981586547 -110579.965218249 accept -2 1 -expect -222638.981586547 110579.965218250 +expect -222638.981586547 110579.965218249 accept -2 -1 expect -222638.981586547 -110579.965218249 +# inflate tolerance by scale (k = 5.7e15) +tolerance 3e8 +accept 0 89.99999999999999 +expect 0 235805185.015130176 +accept 0 -89.99999999999999 +expect 0 -235805185.015130176 direction inverse +tolerance 0 m +accept 0 0 +expect 0 0 +tolerance 50e-9 m accept 200 100 -expect 0.001796631 0.000904369 +expect 0.00179663056824 0.00090436947704 accept 200 -100 -expect 0.001796631 -0.000904369 +expect 0.00179663056824 -0.00090436947704 accept -200 100 -expect -0.001796631 0.000904369 +expect -0.00179663056824 0.00090436947704 accept -200 -100 -expect -0.001796631 -0.000904369 +expect -0.00179663056824 -0.00090436947704 +accept 0 235805185.015130176 +expect 0 89.99999999999999 +accept 0 -235805185.015130176 +expect 0 -89.99999999999999 +accept 0 1e10 +expect 0 90 +accept 0 -1e10 +expect 0 -90 ------------------------------------------------------------------------------- operation +proj=merc +R=6400000 ------------------------------------------------------------------------------- -tolerance 0.1 mm +tolerance 0 m +accept 0 0 +expect 0 0 +tolerance 50e-9 m accept 2 1 expect 223402.144255274 111706.743574944 accept 2 -1 @@ -3389,25 +3420,32 @@ accept -2 -1 expect -223402.144255274 -111706.743574944 direction inverse +tolerance 0 m +accept 0 0 +expect 0 0 +tolerance 50e-9 m accept 200 100 -expect 0.001790493 0.000895247 +expect 0.00179049310978 0.00089524655486 accept 200 -100 -expect 0.001790493 -0.000895247 +expect 0.00179049310978 -0.00089524655486 accept -200 100 -expect -0.001790493 0.000895247 +expect -0.00179049310978 0.00089524655486 accept -200 -100 -expect -0.001790493 -0.000895247 - +expect -0.00179049310978 -0.00089524655486 ------------------------------------------------------------------------------- operation +proj=merc +R=1 ------------------------------------------------------------------------------- # Test the numerical stability of the inverse spherical Mercator ------------------------------------------------------------------------------- -tolerance 1e-15 m -accept 0 1e-15 +tolerance 1e-17 m +accept 0 57.295779513e-15 expect 0 1e-15 +direction inverse +accept 0 1e-15 +expect 0 57.295779513e-15 + =============================================================================== # Miller Oblated Stereographic @@ -5658,25 +5696,33 @@ expect -0.001790143 0.511651393 ------------------------------------------------------------------------------- operation +proj=tmerc +ellps=GRS80 ------------------------------------------------------------------------------- -tolerance 0.1 mm +tolerance 50e-9 m accept 2 1 -expect 222650.796795778 110642.229411927 +expect 222650.796797586 110642.229411933 accept 2 -1 -expect 222650.796795778 -110642.229411927 +expect 222650.796797586 -110642.229411933 accept -2 1 -expect -222650.796795778 110642.229411927 +expect -222650.796797586 110642.229411933 accept -2 -1 -expect -222650.796795778 -110642.229411927 +expect -222650.796797586 -110642.229411933 +accept 30 89.9999 +expect 5.584698978 10001956.056248082 +accept 44.69 35.37 +expect 4168136.489446198 4985511.302287407 direction inverse accept 200 100 -expect 0.001796631 0.000904369 +expect 0.00179663056816 0.00090436947663 accept 200 -100 -expect 0.001796631 -0.000904369 +expect 0.00179663056816 -0.00090436947663 accept -200 100 -expect -0.001796631 0.000904369 +expect -0.00179663056816 0.00090436947663 accept -200 -100 -expect -0.001796631 -0.000904369 +expect -0.00179663056816 -0.00090436947663 +accept 6 1.0001e7 +expect 0.35596960759234 89.99135362646302 +accept 4168136.489446198 4985511.302287407 +expect 44.69 35.37 ------------------------------------------------------------------------------- operation +proj=tmerc +R=6400000 diff --git a/test/unit/pj_phi2_test.cpp b/test/unit/pj_phi2_test.cpp index c4db6e52..ac728306 100644 --- a/test/unit/pj_phi2_test.cpp +++ b/test/unit/pj_phi2_test.cpp @@ -39,47 +39,63 @@ namespace { TEST(PjPhi2Test, Basic) { projCtx ctx = pj_get_default_ctx(); - EXPECT_DOUBLE_EQ(M_PI_2, pj_phi2(ctx, 0.0, 0.0)); + // Remove tests with |e| >= 1. Expectation is that only sane values of e + // (and nan is here reckoned to be sane) are passed to pj_phi2. Thus the + // return value with other values of e is "implementation dependent". - EXPECT_NEAR(0.0, pj_phi2(ctx, 1.0, 0.0), 1e-16); - EXPECT_DOUBLE_EQ(M_PI_2, pj_phi2(ctx, 0.0, 1.0)); - EXPECT_DOUBLE_EQ(M_PI, pj_phi2(ctx, -1.0, 0.0)); - EXPECT_DOUBLE_EQ(M_PI_2, pj_phi2(ctx, 0.0, -1.0)); - - EXPECT_NEAR(0.0, pj_phi2(ctx, 1.0, 1.0), 1e-16); - EXPECT_DOUBLE_EQ(M_PI, pj_phi2(ctx, -1.0, -1.0)); - - // TODO(schwehr): M_PI_4, M_PI_2, M_PI, M_E - // https://www.gnu.org/software/libc/manual/html_node/Mathematical-Constants.html - - EXPECT_DOUBLE_EQ(-0.95445818456292697, pj_phi2(ctx, M_PI, 0.0)); - EXPECT_TRUE(std::isnan(pj_phi2(ctx, 0.0, M_PI))); - EXPECT_DOUBLE_EQ(4.0960508381527205, pj_phi2(ctx, -M_PI, 0.0)); - EXPECT_TRUE(std::isnan(pj_phi2(ctx, 0.0, -M_PI))); + const auto inf = std::numeric_limits::infinity(); + const auto nan = std::numeric_limits::quiet_NaN(); - EXPECT_TRUE(std::isnan(pj_phi2(ctx, M_PI, M_PI))); - EXPECT_TRUE(std::isnan(pj_phi2(ctx, -M_PI, -M_PI))); + // Use EXPECT_EQ instead of EXPECT_DOUBLE_EQ. Strict equality is demanded + // here. + EXPECT_EQ( M_PI_2, pj_phi2(ctx, +0.0, 0.0)); + EXPECT_EQ( 0.0 , pj_phi2(ctx, 1.0, 0.0)); + EXPECT_EQ(-M_PI_2, pj_phi2(ctx, inf, 0.0)); + // We don't expect pj_phi2 to be called with negative ts (since ts = + // exp(-psi)). However, in the current implementation it is odd in ts. + // N.B. ts = +0.0 and ts = -0.0 return different results. + EXPECT_EQ(-M_PI_2, pj_phi2(ctx, -0.0, 0.0)); + EXPECT_EQ( 0.0 , pj_phi2(ctx, -1.0, 0.0)); + EXPECT_EQ(+M_PI_2, pj_phi2(ctx, -inf, 0.0)); + + double e = 0.2; + EXPECT_EQ( M_PI_2, pj_phi2(ctx, +0.0, e)); + EXPECT_EQ( 0.0 , pj_phi2(ctx, 1.0, e)); + EXPECT_EQ(-M_PI_2, pj_phi2(ctx, inf, e)); + EXPECT_EQ(-M_PI_2, pj_phi2(ctx, -0.0, e)); + EXPECT_EQ( 0.0 , pj_phi2(ctx, -1.0, e)); + EXPECT_EQ(+M_PI_2, pj_phi2(ctx, -inf, e)); + + EXPECT_TRUE(std::isnan(pj_phi2(ctx, nan, 0.0))); + EXPECT_TRUE(std::isnan(pj_phi2(ctx, nan, e ))); + EXPECT_TRUE(std::isnan(pj_phi2(ctx, +0.0, nan))); + EXPECT_TRUE(std::isnan(pj_phi2(ctx, 1.0, nan))); + EXPECT_TRUE(std::isnan(pj_phi2(ctx, inf, nan))); + EXPECT_TRUE(std::isnan(pj_phi2(ctx, -0.0, nan))); + EXPECT_TRUE(std::isnan(pj_phi2(ctx, -1.0, nan))); + EXPECT_TRUE(std::isnan(pj_phi2(ctx, -inf, nan))); + EXPECT_TRUE(std::isnan(pj_phi2(ctx, nan, nan))); + + EXPECT_DOUBLE_EQ( M_PI/3, pj_phi2(ctx, 1/(sqrt(3.0)+2), 0.0)); + EXPECT_DOUBLE_EQ( M_PI/4, pj_phi2(ctx, 1/(sqrt(2.0)+1), 0.0)); + EXPECT_DOUBLE_EQ( M_PI/6, pj_phi2(ctx, 1/ sqrt(3.0) , 0.0)); + EXPECT_DOUBLE_EQ(-M_PI/3, pj_phi2(ctx, sqrt(3.0)+2 , 0.0)); + EXPECT_DOUBLE_EQ(-M_PI/4, pj_phi2(ctx, sqrt(2.0)+1 , 0.0)); + EXPECT_DOUBLE_EQ(-M_PI/6, pj_phi2(ctx, sqrt(3.0) , 0.0)); + + // generate with exp(e * atanh(e * sin(phi))) / (tan(phi) + sec(phi)) + EXPECT_DOUBLE_EQ( M_PI/3, pj_phi2(ctx, 0.27749174377027023413, e)); + EXPECT_DOUBLE_EQ( M_PI/4, pj_phi2(ctx, 0.42617788119104192995, e)); + EXPECT_DOUBLE_EQ( M_PI/6, pj_phi2(ctx, 0.58905302448626726064, e)); + EXPECT_DOUBLE_EQ(-M_PI/3, pj_phi2(ctx, 3.6037108218537833089, e)); + EXPECT_DOUBLE_EQ(-M_PI/4, pj_phi2(ctx, 2.3464380582241712935, e)); + EXPECT_DOUBLE_EQ(-M_PI/6, pj_phi2(ctx, 1.6976400399134411849, e)); } -TEST(PjPhi2Test, AvoidUndefinedBehavior) { - auto ctx = pj_get_default_ctx(); +} // namespace - const auto nan = std::numeric_limits::quiet_NaN(); - EXPECT_TRUE(std::isnan(pj_phi2(ctx, nan, 0.0))); - EXPECT_TRUE(std::isnan(pj_phi2(ctx, 0.0, nan))); - EXPECT_TRUE(std::isnan(pj_phi2(ctx, nan, nan))); - // We do not really care about the values that follow. - const auto inf = std::numeric_limits::infinity(); - EXPECT_DOUBLE_EQ(-M_PI_2, pj_phi2(ctx, inf, 0.0)); - EXPECT_TRUE(std::isnan(pj_phi2(ctx, 0.0, inf))); - EXPECT_DOUBLE_EQ(4.7123889803846897, pj_phi2(ctx, -inf, 0.0)); - EXPECT_TRUE(std::isnan(pj_phi2(ctx, 0.0, -inf))); - EXPECT_TRUE(std::isnan(pj_phi2(ctx, inf, inf))); - EXPECT_TRUE(std::isnan(pj_phi2(ctx, -inf, -inf))); -} -} // namespace -- cgit v1.2.3 From b3a20c5b9c6efbeb0d6f528aad1d4e6bb4332bfa Mon Sep 17 00:00:00 2001 From: Charles Karney Date: Mon, 26 Oct 2020 13:58:42 -0400 Subject: Try to fix compiler complaints for max and constexpr sqrt --- src/apps/gie.cpp | 2 +- src/phi2.cpp | 5 +++-- test/gie/builtins.gie | 8 ++++++++ 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/apps/gie.cpp b/src/apps/gie.cpp index 8940afde..2fe854fa 100644 --- a/src/apps/gie.cpp +++ b/src/apps/gie.cpp @@ -1124,7 +1124,7 @@ static const struct errno_vs_err_const lookup[] = { {"pjd_err_invalid_x_or_y" , -15}, {"pjd_err_wrong_format_dms_value" , -16}, {"pjd_err_non_conv_inv_meri_dist" , -17}, - {"pjd_err_non_con_inv_phi2" , -18}, + {"pjd_err_non_conv_sinhpsi2tanphi" , -18}, {"pjd_err_acos_asin_arg_too_large" , -19}, {"pjd_err_tolerance_condition" , -20}, {"pjd_err_conic_lat_equal" , -21}, diff --git a/src/phi2.cpp b/src/phi2.cpp index eb6d5c82..6e810240 100644 --- a/src/phi2.cpp +++ b/src/phi2.cpp @@ -2,6 +2,7 @@ #include #include +#include #include "proj.h" #include "proj_internal.h" @@ -82,8 +83,8 @@ double pj_sinhpsi2tanphi(projCtx ctx, const double taup, const double e) { constexpr int numit = 5; // min iterations = 1, max iterations = 2; mean = 1.954 - constexpr double tol = sqrt(std::numeric_limits::epsilon()) / 10; - constexpr double tmax = 2 / sqrt(std::numeric_limits::epsilon()); + static const double tol = sqrt(std::numeric_limits::epsilon()) / 10; + static const double tmax = 2 / sqrt(std::numeric_limits::epsilon()); double e2m = 1 - e * e, tau = fabs(taup) > 70 ? taup * exp(e * atanh(e)) : taup / e2m, diff --git a/test/gie/builtins.gie b/test/gie/builtins.gie index 402433ca..2432ccb0 100644 --- a/test/gie/builtins.gie +++ b/test/gie/builtins.gie @@ -1434,8 +1434,10 @@ accept -2 1 expect -222650.796797586 110642.229411933 accept -2 -1 expect -222650.796797586 -110642.229411933 +# near pole accept 30 89.9999 expect 5.584698978 10001956.056248082 +# 3900 km from central meridian accept 44.69 35.37 expect 4168136.489446198 4985511.302287407 @@ -1448,8 +1450,10 @@ accept -200 100 expect -0.00179663056816 0.00090436947663 accept -200 -100 expect -0.00179663056816 -0.00090436947663 +# near pole accept 6 1.0001e7 expect 0.35596960759234 89.99135362646302 +# 3900 km from central meridian accept 4168136.489446198 4985511.302287407 expect 44.69 35.37 @@ -5705,8 +5709,10 @@ accept -2 1 expect -222650.796797586 110642.229411933 accept -2 -1 expect -222650.796797586 -110642.229411933 +# near pole accept 30 89.9999 expect 5.584698978 10001956.056248082 +# 3900 km from central meridian accept 44.69 35.37 expect 4168136.489446198 4985511.302287407 @@ -5719,8 +5725,10 @@ accept -200 100 expect -0.00179663056816 0.00090436947663 accept -200 -100 expect -0.00179663056816 -0.00090436947663 +# near pole accept 6 1.0001e7 expect 0.35596960759234 89.99135362646302 +# 3900 km from central meridian accept 4168136.489446198 4985511.302287407 expect 44.69 35.37 -- cgit v1.2.3 From 1b484f853061e8577d95205f27e1ebbdbf80ec47 Mon Sep 17 00:00:00 2001 From: Charles Karney Date: Mon, 26 Oct 2020 14:05:06 -0400 Subject: Address comments by @schwehr --- src/tsfn.cpp | 2 +- test/unit/pj_phi2_test.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/tsfn.cpp b/src/tsfn.cpp index fe8f29ed..a0960a66 100644 --- a/src/tsfn.cpp +++ b/src/tsfn.cpp @@ -21,7 +21,7 @@ double pj_tsfn(double phi, double sinphi, double e) { // exp(-asinh(tan(phi))) = 1 / (tan(phi) + sec(phi)) // = cos(phi) / (1 + sin(phi)) good for phi > 0 // = (1 - sin(phi)) / cos(phi) good for phi < 0 - return exp(e * atanh(e * sinphi)) * + return exp(e * atanh(e * sinphi)) * ( sinphi > 0 ? cosphi / (1 + sinphi) : (1 - sinphi) / cosphi ); diff --git a/test/unit/pj_phi2_test.cpp b/test/unit/pj_phi2_test.cpp index ac728306..f344a3d0 100644 --- a/test/unit/pj_phi2_test.cpp +++ b/test/unit/pj_phi2_test.cpp @@ -43,8 +43,8 @@ TEST(PjPhi2Test, Basic) { // (and nan is here reckoned to be sane) are passed to pj_phi2. Thus the // return value with other values of e is "implementation dependent". - const auto inf = std::numeric_limits::infinity(); - const auto nan = std::numeric_limits::quiet_NaN(); + constexpr auto inf = std::numeric_limits::infinity(); + constexpr auto nan = std::numeric_limits::quiet_NaN(); // Use EXPECT_EQ instead of EXPECT_DOUBLE_EQ. Strict equality is demanded // here. @@ -58,7 +58,7 @@ TEST(PjPhi2Test, Basic) { EXPECT_EQ( 0.0 , pj_phi2(ctx, -1.0, 0.0)); EXPECT_EQ(+M_PI_2, pj_phi2(ctx, -inf, 0.0)); - double e = 0.2; + constexpr double e = 0.2; EXPECT_EQ( M_PI_2, pj_phi2(ctx, +0.0, e)); EXPECT_EQ( 0.0 , pj_phi2(ctx, 1.0, e)); EXPECT_EQ(-M_PI_2, pj_phi2(ctx, inf, e)); @@ -83,7 +83,7 @@ TEST(PjPhi2Test, Basic) { EXPECT_DOUBLE_EQ(-M_PI/4, pj_phi2(ctx, sqrt(2.0)+1 , 0.0)); EXPECT_DOUBLE_EQ(-M_PI/6, pj_phi2(ctx, sqrt(3.0) , 0.0)); - // generate with exp(e * atanh(e * sin(phi))) / (tan(phi) + sec(phi)) + // Generated with exp(e * atanh(e * sin(phi))) / (tan(phi) + sec(phi)) EXPECT_DOUBLE_EQ( M_PI/3, pj_phi2(ctx, 0.27749174377027023413, e)); EXPECT_DOUBLE_EQ( M_PI/4, pj_phi2(ctx, 0.42617788119104192995, e)); EXPECT_DOUBLE_EQ( M_PI/6, pj_phi2(ctx, 0.58905302448626726064, e)); -- cgit v1.2.3 From 6c2363e88f8eb86e1331b3dc5f05897436ad9c43 Mon Sep 17 00:00:00 2001 From: Charles Karney Date: Mon, 26 Oct 2020 14:57:52 -0400 Subject: phi2.cpp: remove unused static consts + minor code tweak --- src/phi2.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/phi2.cpp b/src/phi2.cpp index 6e810240..c60ca055 100644 --- a/src/phi2.cpp +++ b/src/phi2.cpp @@ -7,9 +7,6 @@ #include "proj.h" #include "proj_internal.h" -static const double TOL = 1.0e-10; -static const int N_ITER = 15; - double pj_sinhpsi2tanphi(projCtx ctx, const double taup, const double e) { /**************************************************************************** * Convert tau' = sinh(psi) = tan(chi) to tau = tan(phi). The code is taken @@ -97,7 +94,7 @@ double pj_sinhpsi2tanphi(projCtx ctx, const double taup, const double e) { sig = sinh( e * atanh(e * tau / tau1) ), taupa = sqrt(1 + sig * sig) * tau - sig * tau1, dtau = (taup - taupa) * (1 + e2m * tau * tau) / - ( e2m * sqrt(1 + tau * tau) * sqrt(1 + taupa * taupa) ); + ( e2m * tau1 * sqrt(1 + taupa * taupa) ); tau += dtau; if (!(fabs(dtau) >= stol)) break; -- cgit v1.2.3 From 1081e496a0fc7e45c6eb4703b0fc402bf2a9e945 Mon Sep 17 00:00:00 2001 From: Charles Karney Date: Mon, 26 Oct 2020 16:06:19 -0400 Subject: lcc.cpp: fix abs -> fabs Also some corrected information... Timing UPDATED -------------- Sorry the previous timing data was wrong. Here are corrected values.. Here's what I get with g++ -O3 on two Linux machines with recent versions of g++. As always, you should take these with a grain of salt. Times per call in ns = nanoseconds. Fedora 31 Ubuntu 18 g++-9.3.1 g++-7.5.0 fwd inv fwd inv old merc 207 461 217 522 new merc 228 457 168 410 etmerc 212 196 174 147 The new forward method is the 10% slower (resp 20% faster) on Fedora 31 (resp Ubuntu 18). The new inverse method is the same speed (resp 20% faster) on Fedora 31 (resp Ubuntu 18). Roughly speaking the speed comparison is a wash. Maybe we should pay attention more to the Fedora 31 results since these are with a newer version of the compiler. I would still make the argument that a 20% time penalty (which in a full PROJ pipeline would probably be no more than a 5% penalty) would be a worthwhile price to pay for a more robust implementation of the projection. --- src/projections/lcc.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/projections/lcc.cpp b/src/projections/lcc.cpp index b83b8072..46378ce4 100644 --- a/src/projections/lcc.cpp +++ b/src/projections/lcc.cpp @@ -106,7 +106,7 @@ PJ *PROJECTION(lcc) { double ml1, m1; m1 = pj_msfn(sinphi, cosphi, P->es); - if( abs(Q->phi1) == M_HALFPI ) { + if( fabs(Q->phi1) == M_HALFPI ) { return pj_default_destructor(P, PJD_ERR_LAT_1_OR_2_ZERO_OR_90); } ml1 = pj_tsfn(Q->phi1, sinphi, P->e); @@ -117,7 +117,7 @@ PJ *PROJECTION(lcc) { // Not quite, but es is very close to 1... return pj_default_destructor(P, PJD_ERR_INVALID_ECCENTRICITY); } - if( abs(Q->phi2) == M_HALFPI ) { + if( fabs(Q->phi2) == M_HALFPI ) { return pj_default_destructor(P, PJD_ERR_LAT_1_OR_2_ZERO_OR_90); } const double ml2 = pj_tsfn(Q->phi2, sinphi, P->e); -- cgit v1.2.3 From ee35d15db597801a86314dc8a47da7de10c9d8f2 Mon Sep 17 00:00:00 2001 From: Charles Karney Date: Mon, 26 Oct 2020 17:50:51 -0400 Subject: phi2.cpp: Slight cosmetic changes to sinpsi2tanphi. --- src/phi2.cpp | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/phi2.cpp b/src/phi2.cpp index c60ca055..7bbb5679 100644 --- a/src/phi2.cpp +++ b/src/phi2.cpp @@ -80,23 +80,29 @@ double pj_sinhpsi2tanphi(projCtx ctx, const double taup, const double e) { constexpr int numit = 5; // min iterations = 1, max iterations = 2; mean = 1.954 - static const double tol = sqrt(std::numeric_limits::epsilon()) / 10; - static const double tmax = 2 / sqrt(std::numeric_limits::epsilon()); - double + static const double + rooteps = sqrt(std::numeric_limits::epsilon()), + tol = rooteps / 10, // the convergence criterion for Newton's method + tmax = 2 / rooteps; // the large arg limit is exact for tau > tmax + const double e2m = 1 - e * e, - tau = fabs(taup) > 70 ? taup * exp(e * atanh(e)) : taup / e2m, stol = tol * std::max(1.0, fabs(taup)); - if (!(fabs(tau) < tmax)) return tau; // handles +/-inf and nan and e = 1 + // The initial guess. 70 corresponds to chi = 89.18 deg (see above) + double tau = fabs(taup) > 70 ? taup * exp(e * atanh(e)) : taup / e2m; + if (!(fabs(tau) < tmax)) // handles +/-inf and nan and e = 1 + return tau; + // If we need to deal with e > 1, then we could include: // if (e2m < 0) return std::numeric_limits::quiet_NaN(); int i = numit; for (; i; --i) { - double tau1 = sqrt(1 + tau * tau), + double + tau1 = sqrt(1 + tau * tau), sig = sinh( e * atanh(e * tau / tau1) ), taupa = sqrt(1 + sig * sig) * tau - sig * tau1, - dtau = (taup - taupa) * (1 + e2m * tau * tau) / - ( e2m * tau1 * sqrt(1 + taupa * taupa) ); + dtau = ( (taup - taupa) * (1 + e2m * (tau * tau)) / + (e2m * tau1 * sqrt(1 + taupa * taupa)) ); tau += dtau; - if (!(fabs(dtau) >= stol)) + if (!(fabs(dtau) >= stol)) // backwards test to allow nans to succeed. break; } if (i == 0) -- cgit v1.2.3 From 75a8436b2491dbc1eebb196ea42b961fd011a52e Mon Sep 17 00:00:00 2001 From: Charles Karney Date: Mon, 26 Oct 2020 18:29:19 -0400 Subject: Use sincos optimization in merc_e_forward. Revised timing data... Times per call in ns = nanoseconds. Fedora 31 Ubuntu 18 g++-9.3.1 g++-7.5.0 fwd inv fwd inv old merc 207 461 217 522 new merc 159 457 137 410 etmerc 212 196 174 147 The new forward method is now 25% faster (resp 35% faster) on Fedora 31 (resp Ubuntu 18). The new inverse method is the same speed (resp 20% faster) on Fedora 31 (resp Ubuntu 18). The accuracy is hardly affected: rms error increases from 0.30 nm to 0.33 nm, max error increases from 1.83 nm to 1.84 nm (a barely noticeable degradation). --- src/projections/merc.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/projections/merc.cpp b/src/projections/merc.cpp index 472cb43f..e5da3967 100644 --- a/src/projections/merc.cpp +++ b/src/projections/merc.cpp @@ -13,7 +13,8 @@ PROJ_HEAD(webmerc, "Web Mercator / Pseudo Mercator") "\n\tCyl, Ell\n\t"; static PJ_XY merc_e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */ PJ_XY xy = {0.0,0.0}; xy.x = P->k0 * lp.lam; - xy.y = P->k0 * (asinh(tan(lp.phi)) - P->e * atanh(P->e * sin(lp.phi))); + double sphi = sin(lp.phi), cphi = cos(lp.phi); + xy.y = P->k0 * (asinh(sphi/cphi) - P->e * atanh(P->e * sphi)); return xy; } -- cgit v1.2.3 From 6bd7c777f8e789f8ea34a6aa68104ab44a31beee Mon Sep 17 00:00:00 2001 From: Charles Karney Date: Mon, 26 Oct 2020 19:03:26 -0400 Subject: Fix/add some comments. --- src/phi2.cpp | 2 +- src/projections/merc.cpp | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/phi2.cpp b/src/phi2.cpp index 7bbb5679..b9b37765 100644 --- a/src/phi2.cpp +++ b/src/phi2.cpp @@ -127,7 +127,7 @@ double pj_phi2(projCtx ctx, const double ts0, const double e) { * OLD: This routine inverts this relation using the iterative scheme given * by Snyder (1987), Eqs. (7-9) - (7-11). * - * NEW: This routine writes converts t = exp(-psi) to + * NEW: This routine converts t = exp(-psi) to * * tau' = sinh(psi) = (1/t - t)/2 * diff --git a/src/projections/merc.cpp b/src/projections/merc.cpp index e5da3967..39685478 100644 --- a/src/projections/merc.cpp +++ b/src/projections/merc.cpp @@ -13,6 +13,8 @@ PROJ_HEAD(webmerc, "Web Mercator / Pseudo Mercator") "\n\tCyl, Ell\n\t"; static PJ_XY merc_e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */ PJ_XY xy = {0.0,0.0}; xy.x = P->k0 * lp.lam; + // Instead of calling tan and sin, call sin and cos which the compiler + // optimizes to a single call to sincos. double sphi = sin(lp.phi), cphi = cos(lp.phi); xy.y = P->k0 * (asinh(sphi/cphi) - P->e * atanh(P->e * sphi)); return xy; -- cgit v1.2.3 From 94e36270ca393bd7b107bf690f09fd8ec1cd046b Mon Sep 17 00:00:00 2001 From: Charles Karney Date: Tue, 27 Oct 2020 10:02:27 -0400 Subject: Use nm units in builtins.gie. Remove backward looking comments in code. --- src/phi2.cpp | 10 +++++----- src/tsfn.cpp | 3 +++ test/gie/builtins.gie | 12 ++++++------ test/unit/pj_phi2_test.cpp | 9 ++++----- 4 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/phi2.cpp b/src/phi2.cpp index b9b37765..0fdca47c 100644 --- a/src/phi2.cpp +++ b/src/phi2.cpp @@ -116,6 +116,7 @@ double pj_phi2(projCtx ctx, const double ts0, const double e) { * Determine latitude angle phi-2. * Inputs: * ts = exp(-psi) where psi is the isometric latitude (dimensionless) + * this variable is defined in Snyder (1987), Eq. (7-10) * e = eccentricity of the ellipsoid (dimensionless) * Output: * phi = geographic latitude (radians) @@ -123,13 +124,12 @@ double pj_phi2(projCtx ctx, const double ts0, const double e) { * psi = log( tan(pi/4 + phi/2) * * ( (1 - e*sin(phi)) / (1 + e*sin(phi)) )^(e/2) ) * = asinh(tan(phi)) - e * atanh(e * sin(phi)) + * = asinh(tan(chi)) + * chi = conformal latitude * - * OLD: This routine inverts this relation using the iterative scheme given - * by Snyder (1987), Eqs. (7-9) - (7-11). + * This routine converts t = exp(-psi) to * - * NEW: This routine converts t = exp(-psi) to - * - * tau' = sinh(psi) = (1/t - t)/2 + * tau' = tan(chi) = sinh(psi) = (1/t - t)/2 * * returns atan(sinpsi2tanphi(tau')) ***************************************************************************/ diff --git a/src/tsfn.cpp b/src/tsfn.cpp index a0960a66..8ed258d6 100644 --- a/src/tsfn.cpp +++ b/src/tsfn.cpp @@ -11,10 +11,13 @@ double pj_tsfn(double phi, double sinphi, double e) { * e = eccentricity of the ellipsoid (dimensionless) * Output: * ts = exp(-psi) where psi is the isometric latitude (dimensionless) + * = 1 / (tan(chi) + sec(chi)) * Here isometric latitude is defined by * psi = log( tan(pi/4 + phi/2) * * ( (1 - e*sin(phi)) / (1 + e*sin(phi)) )^(e/2) ) * = asinh(tan(phi)) - e * atanh(e * sin(phi)) + * = asinh(tan(chi)) + * chi = conformal latitude ***************************************************************************/ double cosphi = cos(phi); diff --git a/test/gie/builtins.gie b/test/gie/builtins.gie index 2432ccb0..1ec59b7a 100644 --- a/test/gie/builtins.gie +++ b/test/gie/builtins.gie @@ -1425,7 +1425,7 @@ expect -0.001790143 -0.000895247 ------------------------------------------------------------------------------- operation +proj=etmerc +ellps=GRS80 ------------------------------------------------------------------------------- -tolerance 50e-9 m +tolerance 50 nm accept 2 1 expect 222650.796797586 110642.229411933 accept 2 -1 @@ -3369,7 +3369,7 @@ operation +proj=merc +ellps=GRS80 tolerance 0 m accept 0 0 expect 0 0 -tolerance 50e-9 m +tolerance 50 nm accept 2 1 expect 222638.981586547 110579.965218249 accept 2 -1 @@ -3389,7 +3389,7 @@ direction inverse tolerance 0 m accept 0 0 expect 0 0 -tolerance 50e-9 m +tolerance 50 nm accept 200 100 expect 0.00179663056824 0.00090436947704 accept 200 -100 @@ -3413,7 +3413,7 @@ operation +proj=merc +R=6400000 tolerance 0 m accept 0 0 expect 0 0 -tolerance 50e-9 m +tolerance 50 nm accept 2 1 expect 223402.144255274 111706.743574944 accept 2 -1 @@ -3427,7 +3427,7 @@ direction inverse tolerance 0 m accept 0 0 expect 0 0 -tolerance 50e-9 m +tolerance 50 nm accept 200 100 expect 0.00179049310978 0.00089524655486 accept 200 -100 @@ -5700,7 +5700,7 @@ expect -0.001790143 0.511651393 ------------------------------------------------------------------------------- operation +proj=tmerc +ellps=GRS80 ------------------------------------------------------------------------------- -tolerance 50e-9 m +tolerance 50 nm accept 2 1 expect 222650.796797586 110642.229411933 accept 2 -1 diff --git a/test/unit/pj_phi2_test.cpp b/test/unit/pj_phi2_test.cpp index f344a3d0..fdedae98 100644 --- a/test/unit/pj_phi2_test.cpp +++ b/test/unit/pj_phi2_test.cpp @@ -39,15 +39,14 @@ namespace { TEST(PjPhi2Test, Basic) { projCtx ctx = pj_get_default_ctx(); - // Remove tests with |e| >= 1. Expectation is that only sane values of e - // (and nan is here reckoned to be sane) are passed to pj_phi2. Thus the - // return value with other values of e is "implementation dependent". + // Expectation is that only sane values of e (and nan is here reckoned to + // be sane) are passed to pj_phi2. Thus the return value with other values + // of e is "implementation dependent". constexpr auto inf = std::numeric_limits::infinity(); constexpr auto nan = std::numeric_limits::quiet_NaN(); - // Use EXPECT_EQ instead of EXPECT_DOUBLE_EQ. Strict equality is demanded - // here. + // Strict equality is demanded here. EXPECT_EQ( M_PI_2, pj_phi2(ctx, +0.0, 0.0)); EXPECT_EQ( 0.0 , pj_phi2(ctx, 1.0, 0.0)); EXPECT_EQ(-M_PI_2, pj_phi2(ctx, inf, 0.0)); -- cgit v1.2.3 From 692fc26b6d494aeaa85658314bc020a5cd6da7a1 Mon Sep 17 00:00:00 2001 From: Charles Karney Date: Tue, 27 Oct 2020 16:44:43 -0400 Subject: merc.cpp + phi2.cpp: Avoid declaring multiple variables in 1 statement. --- src/phi2.cpp | 23 ++++++++++------------- src/projections/merc.cpp | 3 ++- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/src/phi2.cpp b/src/phi2.cpp index 0fdca47c..1c48d67f 100644 --- a/src/phi2.cpp +++ b/src/phi2.cpp @@ -80,13 +80,11 @@ double pj_sinhpsi2tanphi(projCtx ctx, const double taup, const double e) { constexpr int numit = 5; // min iterations = 1, max iterations = 2; mean = 1.954 - static const double - rooteps = sqrt(std::numeric_limits::epsilon()), - tol = rooteps / 10, // the convergence criterion for Newton's method - tmax = 2 / rooteps; // the large arg limit is exact for tau > tmax - const double - e2m = 1 - e * e, - stol = tol * std::max(1.0, fabs(taup)); + static const double rooteps = sqrt(std::numeric_limits::epsilon()); + static const double tol = rooteps / 10; // the criterion for Newton's method + static const double tmax = 2 / rooteps; // threshold for large arg limit exact + const double e2m = 1 - e * e; + const double stol = tol * std::max(1.0, fabs(taup)); // The initial guess. 70 corresponds to chi = 89.18 deg (see above) double tau = fabs(taup) > 70 ? taup * exp(e * atanh(e)) : taup / e2m; if (!(fabs(tau) < tmax)) // handles +/-inf and nan and e = 1 @@ -95,12 +93,11 @@ double pj_sinhpsi2tanphi(projCtx ctx, const double taup, const double e) { // if (e2m < 0) return std::numeric_limits::quiet_NaN(); int i = numit; for (; i; --i) { - double - tau1 = sqrt(1 + tau * tau), - sig = sinh( e * atanh(e * tau / tau1) ), - taupa = sqrt(1 + sig * sig) * tau - sig * tau1, - dtau = ( (taup - taupa) * (1 + e2m * (tau * tau)) / - (e2m * tau1 * sqrt(1 + taupa * taupa)) ); + double tau1 = sqrt(1 + tau * tau); + double sig = sinh( e * atanh(e * tau / tau1) ); + double taupa = sqrt(1 + sig * sig) * tau - sig * tau1; + double dtau = ( (taup - taupa) * (1 + e2m * (tau * tau)) / + (e2m * tau1 * sqrt(1 + taupa * taupa)) ); tau += dtau; if (!(fabs(dtau) >= stol)) // backwards test to allow nans to succeed. break; diff --git a/src/projections/merc.cpp b/src/projections/merc.cpp index 39685478..3a0ed7b4 100644 --- a/src/projections/merc.cpp +++ b/src/projections/merc.cpp @@ -15,7 +15,8 @@ static PJ_XY merc_e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward xy.x = P->k0 * lp.lam; // Instead of calling tan and sin, call sin and cos which the compiler // optimizes to a single call to sincos. - double sphi = sin(lp.phi), cphi = cos(lp.phi); + double sphi = sin(lp.phi); + double cphi = cos(lp.phi); xy.y = P->k0 * (asinh(sphi/cphi) - P->e * atanh(P->e * sphi)); return xy; } -- cgit v1.2.3 From c08da1a6604f9cb422bb71e34b6006ede6146642 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Sat, 31 Oct 2020 10:52:44 +0100 Subject: proj_create_ellipsoidal_2D/3D_cs(): doc improvement --- src/iso19111/c_api.cpp | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/iso19111/c_api.cpp b/src/iso19111/c_api.cpp index 7582f37f..f4f6e6a2 100644 --- a/src/iso19111/c_api.cpp +++ b/src/iso19111/c_api.cpp @@ -4438,8 +4438,9 @@ PJ *proj_create_cartesian_2D_cs(PJ_CONTEXT *ctx, PJ_CARTESIAN_CS_2D_TYPE type, * * @param ctx PROJ context, or NULL for default context * @param type Coordinate system type. - * @param unit_name Unit name. - * @param unit_conv_factor Unit conversion factor to SI. + * @param unit_name Name of the angular units. Or NULL for Degree + * @param unit_conv_factor Conversion factor from the angular unit to radian. + * Or 0 for Degree if unit_name == NULL. Otherwise should be not NULL * * @return Object that must be unreferenced with * proj_destroy(), or NULL in case of error. @@ -4478,13 +4479,17 @@ PJ *proj_create_ellipsoidal_2D_cs(PJ_CONTEXT *ctx, * * @param ctx PROJ context, or NULL for default context * @param type Coordinate system type. - * @param horizontal_angular_unit_name Horizontal angular unit name. - * @param horizontal_angular_unit_conv_factor Horizontal angular unit conversion - * factor to SI. - * @param vertical_linear_unit_name Vertical linear unit name. + * @param horizontal_angular_unit_name Name of the angular units. Or NULL for + * Degree. + * @param horizontal_angular_unit_conv_factor Conversion factor from the angular + * unit to radian. Or 0 for Degree if horizontal_angular_unit_name == NULL. + * Otherwise should be not NULL + * @param vertical_linear_unit_name Vertical linear unit name. Or NULL for + * Metre. * @param vertical_linear_unit_conv_factor Vertical linear unit conversion - * factor to SI. - * + * factor to metre. Or 0 for Metre if vertical_linear_unit_name == NULL. + * Otherwise should be not NULL + * @return Object that must be unreferenced with * proj_destroy(), or NULL in case of error. * @since 6.3 -- cgit v1.2.3 From baed8dae4980698873500dec16b158638df71318 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Sat, 31 Oct 2020 13:59:25 +0100 Subject: Make sure that remarks is preserved when substituting (EPSG) grid name by PROJ one --- src/iso19111/coordinateoperation.cpp | 7 ++++++- test/cli/testprojinfo_out.dist | 15 ++++++++++----- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/iso19111/coordinateoperation.cpp b/src/iso19111/coordinateoperation.cpp index be15b3e0..599e04bd 100644 --- a/src/iso19111/coordinateoperation.cpp +++ b/src/iso19111/coordinateoperation.cpp @@ -8836,11 +8836,16 @@ createSimilarPropertiesTransformation(TransformationNNPtr obj) { // The domain(s) are unchanged addDomains(map, obj.get()); - std::string forwardName = obj->nameStr(); + const std::string &forwardName = obj->nameStr(); if (!forwardName.empty()) { map.set(common::IdentifiedObject::NAME_KEY, forwardName); } + const std::string &remarks = obj->remarks(); + if (!remarks.empty()) { + map.set(common::IdentifiedObject::REMARKS_KEY, remarks); + } + addModifiedIdentifier(map, obj.get(), false, true); return map; diff --git a/test/cli/testprojinfo_out.dist b/test/cli/testprojinfo_out.dist index 245bb258..7da5add7 100644 --- a/test/cli/testprojinfo_out.dist +++ b/test/cli/testprojinfo_out.dist @@ -317,7 +317,8 @@ COORDINATEOPERATION["NAD27 to NAD83 (3)", SCOPE["Historic record only - now superseded - see remarks."], AREA["Canada - onshore and offshore - Alberta; British Columbia; Manitoba; New Brunswick; Newfoundland and Labrador; Northwest Territories; Nova Scotia; Nunavut; Ontario; Prince Edward Island; Quebec; Saskatchewan; Yukon."], BBOX[40.04,-141.01,86.46,-47.74]], - ID["DERIVED_FROM(EPSG)",1312]] + ID["DERIVED_FROM(EPSG)",1312], + REMARK["Uses NTv1 method. Replaced in Quebec by code 1462 and elsewhere in 1997 by NTv2 (transformation code 1313). Input expects longitudes to be positive west; EPSG GeogCRS NAD27 (code 4267) and NAD83 (code 4269) have longitudes positive east."]] ------------------------------------- Operation No. 2: @@ -371,7 +372,8 @@ COORDINATEOPERATION["NAD27 to NAD83 (4)", SCOPE["Transformation of coordinates at 1m to 2m level of accuracy."], AREA["Canada - onshore - Alberta; British Columbia; Manitoba; New Brunswick; Newfoundland and Labrador; Northwest Territories; Nova Scotia; Nunavut; Ontario; Prince Edward Island; Quebec; Saskatchewan; Yukon; offshore east coast."], BBOX[40.04,-141.01,83.17,-47.74]], - ID["DERIVED_FROM(EPSG)",1313]] + ID["DERIVED_FROM(EPSG)",1313], + REMARK["Uses NTv2 data files. Replaces NTv1 (transformation code 1312) except in Quebec. Input expects longitudes to be positive west; EPSG GeogCRS NAD27 (code 4267) and (code 4269) have longitudes positive east. May be used as tfm to WGS 84 - see code 1693."]] ------------------------------------- Operation No. 3: @@ -425,7 +427,8 @@ COORDINATEOPERATION["NAD27 to NAD83 (1)", SCOPE["Transformation of coordinates at 0.2m level of accuracy."], AREA["United States (USA) - CONUS including EEZ -onshore and offshore - Alabama; Arizona; Arkansas; California; Colorado; Connecticut; Delaware; Florida; Georgia; Idaho; Illinois; Indiana; Iowa; Kansas; Kentucky; Louisiana; Maine; Maryland; Massachusetts; Michigan; Minnesota; Mississippi; Missouri; Montana; Nebraska; Nevada; New Hampshire; New Jersey; New Mexico; New York; North Carolina; North Dakota; Ohio; Oklahoma; Oregon; Pennsylvania; Rhode Island; South Carolina; South Dakota; Tennessee; Texas; Utah; Vermont; Virginia; Washington; West Virginia; Wisconsin; Wyoming. US Gulf of Mexico (GoM) OCS."], BBOX[23.81,-129.17,49.38,-65.69]], - ID["DERIVED_FROM(EPSG)",1241]] + ID["DERIVED_FROM(EPSG)",1241], + REMARK["Uses NADCON method which expects longitudes positive west; EPSG GeogCRS NAD27 (code 4267) and NAD83 (code 4269) have longitudes positive east."]] ------------------------------------- Operation No. 4: @@ -479,7 +482,8 @@ COORDINATEOPERATION["NAD27 to NAD83 (2)", SCOPE["Geodesy."], AREA["United States (USA) - Alaska including EEZ."], BBOX[47.88,167.65,74.71,-129.99]], - ID["DERIVED_FROM(EPSG)",1243]] + ID["DERIVED_FROM(EPSG)",1243], + REMARK["Uses NADCON method which expects longitudes positive west; EPSG GeogCRS NAD27 (code 4267) and NAD83 (code 4269) have longitudes positive east. May be used as transformation to WGS 84 - see NAD27 to WGS 84 (85) (code 15864)."]] ------------------------------------- Operation No. 5: @@ -533,7 +537,8 @@ COORDINATEOPERATION["NAD27 to NAD83 (6)", SCOPE["Transformation of coordinates at 1m to 2m level of accuracy."], AREA["Canada - Quebec."], BBOX[44.99,-79.85,62.62,-57.1]], - ID["DERIVED_FROM(EPSG)",1573]] + ID["DERIVED_FROM(EPSG)",1573], + REMARK["Also distributed with file name QUE27-83.gsb. Replaces NAD27 to NAD83 (5) (code 1462). Uses NT method which expects longitudes positive west; EPSG GeogCRSs NAD27 (code 4267) and NAD83 (code 4269) have longitudes positive east."]] ------------------------------------- Operation No. 6: -- cgit v1.2.3 From 67718853e1248656cc35caa5a605ac102ec7e985 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Sat, 31 Oct 2020 15:47:52 +0100 Subject: Fill remarks for PROJ-based operation mixing horizontal and vertical transformations --- src/iso19111/coordinateoperation.cpp | 63 ++++++++++++++++++++++++++++++++++++ test/unit/test_operation.cpp | 8 +++++ 2 files changed, 71 insertions(+) diff --git a/src/iso19111/coordinateoperation.cpp b/src/iso19111/coordinateoperation.cpp index 599e04bd..e9d73f52 100644 --- a/src/iso19111/coordinateoperation.cpp +++ b/src/iso19111/coordinateoperation.cpp @@ -12620,6 +12620,55 @@ createGeodToGeodPROJBased(const crs::CRSNNPtr &geodSrc, // --------------------------------------------------------------------------- +static std::string +getRemarks(const std::vector &ops) { + std::string remarks; + for (const auto &op : ops) { + const auto &opRemarks = op->remarks(); + if (!opRemarks.empty()) { + if (!remarks.empty()) { + remarks += '\n'; + } + + std::string opName(op->nameStr()); + if (starts_with(opName, INVERSE_OF)) { + opName = opName.substr(INVERSE_OF.size()); + } + + remarks += "For "; + remarks += opName; + + const auto &ids = op->identifiers(); + if (!ids.empty()) { + std::string authority(*ids.front()->codeSpace()); + if (starts_with(authority, "INVERSE(") && + authority.back() == ')') { + authority = authority.substr(strlen("INVERSE("), + authority.size() - 1 - + strlen("INVERSE(")); + } + if (starts_with(authority, "DERIVED_FROM(") && + authority.back() == ')') { + authority = authority.substr(strlen("DERIVED_FROM("), + authority.size() - 1 - + strlen("DERIVED_FROM(")); + } + + remarks += " ("; + remarks += authority; + remarks += ':'; + remarks += ids.front()->code(); + remarks += ')'; + } + remarks += ": "; + remarks += opRemarks; + } + } + return remarks; +} + +// --------------------------------------------------------------------------- + static CoordinateOperationNNPtr createHorizVerticalPROJBased( const crs::CRSNNPtr &sourceCRS, const crs::CRSNNPtr &targetCRS, const operation::CoordinateOperationNNPtr &horizTransform, @@ -12645,6 +12694,10 @@ static CoordinateOperationNNPtr createHorizVerticalPROJBased( properties.set(common::ObjectUsage::DOMAIN_OF_VALIDITY_KEY, NN_NO_CHECK(extent)); } + const auto &remarks = verticalTransform->remarks(); + if (!remarks.empty()) { + properties.set(common::IdentifiedObject::REMARKS_KEY, remarks); + } return createPROJBased( properties, exportable, sourceCRS, targetCRS, nullptr, verticalTransform->coordinateOperationAccuracies(), @@ -12669,6 +12722,11 @@ static CoordinateOperationNNPtr createHorizVerticalPROJBased( NN_NO_CHECK(extent)); } + const auto remarks = getRemarks(ops); + if (!remarks.empty()) { + properties.set(common::IdentifiedObject::REMARKS_KEY, remarks); + } + std::vector accuracies; const double accuracy = getAccuracy(ops); if (accuracy >= 0.0) { @@ -12729,6 +12787,11 @@ static CoordinateOperationNNPtr createHorizVerticalHorizPROJBased( NN_NO_CHECK(extent)); } + const auto remarks = getRemarks(ops); + if (!remarks.empty()) { + properties.set(common::IdentifiedObject::REMARKS_KEY, remarks); + } + std::vector accuracies; const double accuracy = getAccuracy(ops); if (accuracy >= 0.0) { diff --git a/test/unit/test_operation.cpp b/test/unit/test_operation.cpp index ce4b866b..1181b6d8 100644 --- a/test/unit/test_operation.cpp +++ b/test/unit/test_operation.cpp @@ -8734,6 +8734,14 @@ TEST(operation, compoundCRS_to_geogCRS_3D_context) { "+multiplier=1 " "+step +proj=unitconvert +xy_in=rad +xy_out=deg " "+step +proj=axisswap +order=2,1"); + EXPECT_EQ(list[0]->remarks(), + "For NAD83(NSRS2007) to NAVD88 height (1) (EPSG:9173): Uses " + "Geoid09 hybrid model. Replaced by 2012 model (CT code 6326)." + "\n" + "For NAD83(NSRS2007) to WGS 84 (1) (EPSG:15931): " + "Approximation at the +/- 1m level assuming that " + "NAD83(NSRS2007) is equivalent to WGS 84 within the accuracy " + "of the transformation."); } // NAD83 + NAVD88 height --> WGS 84 -- cgit v1.2.3 From 6e7124c8b16dcc00e4a3f4336d1535f9655f1aa3 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Sat, 31 Oct 2020 15:53:15 +0100 Subject: Doxygen: improve doc of functions related to Datum/DatumEnsemble --- src/iso19111/c_api.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/iso19111/c_api.cpp b/src/iso19111/c_api.cpp index 7582f37f..f463dc2a 100644 --- a/src/iso19111/c_api.cpp +++ b/src/iso19111/c_api.cpp @@ -2049,6 +2049,8 @@ PJ *proj_get_ellipsoid(PJ_CONTEXT *ctx, const PJ *obj) { // --------------------------------------------------------------------------- /** \brief Get the horizontal datum from a CRS + * + * This function may return a Datum or DatumEnsemble object. * * The returned object must be unreferenced with proj_destroy() after * use. @@ -7986,6 +7988,9 @@ double proj_coordoperation_get_accuracy(PJ_CONTEXT *ctx, // --------------------------------------------------------------------------- /** \brief Returns the datum of a SingleCRS. + * + * If that function returns NULL, @see proj_crs_get_datum_ensemble() to + * potentially get a DatumEnsemble instead. * * The returned object must be unreferenced with proj_destroy() after * use. @@ -8017,6 +8022,9 @@ PJ *proj_crs_get_datum(PJ_CONTEXT *ctx, const PJ *crs) { // --------------------------------------------------------------------------- /** \brief Returns the datum ensemble of a SingleCRS. + * + * If that function returns NULL, @see proj_crs_get_datum() to + * potentially get a Datum instead. * * The returned object must be unreferenced with proj_destroy() after * use. -- cgit v1.2.3 From 82695cce869e1bcf2eb2a8ff078b679b6a21c663 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Thu, 8 Oct 2020 17:08:27 +0200 Subject: When reading from database, possibly return Geographic/GeodeticCRS with a DatumEnsemble, typically for WGS 84 and ETRS89 ('breaking change') --- include/proj/io.hpp | 6 ++ src/iso19111/factory.cpp | 158 +++++++++++++++++++++++++++++------------ src/iso19111/io.cpp | 4 ++ test/cli/testprojinfo_out.dist | 116 ++++++++++++++++++++++++++---- test/unit/test_c_api.cpp | 11 ++- test/unit/test_factory.cpp | 18 +++-- 6 files changed, 248 insertions(+), 65 deletions(-) diff --git a/include/proj/io.hpp b/include/proj/io.hpp index 20dcedfe..35e924ec 100644 --- a/include/proj/io.hpp +++ b/include/proj/io.hpp @@ -1225,6 +1225,12 @@ class PROJ_GCC_DLL AuthorityFactory { private: PROJ_OPAQUE_PRIVATE_DATA + + PROJ_INTERNAL void + createGeodeticDatumOrEnsemble(const std::string &code, + datum::GeodeticReferenceFramePtr &outDatum, + datum::DatumEnsemblePtr &outDatumEnsemble, + bool turnEnsembleAsDatum) const; }; // --------------------------------------------------------------------------- diff --git a/src/iso19111/factory.cpp b/src/iso19111/factory.cpp index 5d02aeea..cce80b8a 100644 --- a/src/iso19111/factory.cpp +++ b/src/iso19111/factory.cpp @@ -192,6 +192,13 @@ struct DatabaseContext::Private { void cache(const std::string &code, const datum::GeodeticReferenceFrameNNPtr &datum); + datum::DatumEnsemblePtr + // cppcheck-suppress functionStatic + getDatumEnsembleFromCache(const std::string &code); + // cppcheck-suppress functionStatic + void cache(const std::string &code, + const datum::DatumEnsembleNNPtr &datumEnsemble); + datum::EllipsoidPtr // cppcheck-suppress functionStatic getEllipsoidFromCache(const std::string &code); @@ -258,6 +265,7 @@ struct DatabaseContext::Private { LRUCacheOfObjects cacheCRS_{CACHE_SIZE}; LRUCacheOfObjects cacheEllipsoid_{CACHE_SIZE}; LRUCacheOfObjects cacheGeodeticDatum_{CACHE_SIZE}; + LRUCacheOfObjects cacheDatumEnsemble_{CACHE_SIZE}; LRUCacheOfObjects cachePrimeMeridian_{CACHE_SIZE}; LRUCacheOfObjects cacheCS_{CACHE_SIZE}; LRUCacheOfObjects cacheExtent_{CACHE_SIZE}; @@ -417,6 +425,22 @@ void DatabaseContext::Private::cache( // --------------------------------------------------------------------------- +datum::DatumEnsemblePtr +DatabaseContext::Private::getDatumEnsembleFromCache(const std::string &code) { + util::BaseObjectPtr obj; + getFromCache(cacheDatumEnsemble_, code, obj); + return std::static_pointer_cast(obj); +} + +// --------------------------------------------------------------------------- + +void DatabaseContext::Private::cache( + const std::string &code, const datum::DatumEnsembleNNPtr &datumEnsemble) { + insertIntoCache(cacheDatumEnsemble_, code, datumEnsemble.as_nullable()); +} + +// --------------------------------------------------------------------------- + datum::EllipsoidPtr DatabaseContext::Private::getEllipsoidFromCache(const std::string &code) { util::BaseObjectPtr obj; @@ -1064,18 +1088,6 @@ std::string DatabaseContext::getOldProjGridName(const std::string &gridName) { // --------------------------------------------------------------------------- -// FIXME: as we don't support datum ensemble yet, add it from name -static std::string removeEnsembleSuffix(const std::string &name) { - if (name == "World Geodetic System 1984 ensemble") { - return "World Geodetic System 1984"; - } else if (name == "European Terrestrial Reference System 1989 ensemble") { - return "European Terrestrial Reference System 1989"; - } - return name; -} - -// --------------------------------------------------------------------------- - /** \brief Gets the alias name from an official name. * * @param officialName Official name. Mandatory @@ -2012,18 +2024,38 @@ AuthorityFactory::createEllipsoid(const std::string &code) const { datum::GeodeticReferenceFrameNNPtr AuthorityFactory::createGeodeticDatum(const std::string &code) const { + + datum::GeodeticReferenceFramePtr datum; + datum::DatumEnsemblePtr datumEnsemble; + constexpr bool turnEnsembleAsDatum = true; + createGeodeticDatumOrEnsemble(code, datum, datumEnsemble, + turnEnsembleAsDatum); + return NN_NO_CHECK(datum); +} + +// --------------------------------------------------------------------------- + +void AuthorityFactory::createGeodeticDatumOrEnsemble( + const std::string &code, datum::GeodeticReferenceFramePtr &outDatum, + datum::DatumEnsemblePtr &outDatumEnsemble, bool turnEnsembleAsDatum) const { const auto cacheKey(d->authority() + code); { - auto datum = d->context()->d->getGeodeticDatumFromCache(cacheKey); - if (datum) { - return NN_NO_CHECK(datum); + outDatumEnsemble = d->context()->d->getDatumEnsembleFromCache(cacheKey); + if (outDatumEnsemble) { + if (!turnEnsembleAsDatum) + return; + outDatumEnsemble = nullptr; + } + outDatum = d->context()->d->getGeodeticDatumFromCache(cacheKey); + if (outDatum) { + return; } } auto res = d->runWithCodeParam("SELECT name, ellipsoid_auth_name, ellipsoid_code, " "prime_meridian_auth_name, prime_meridian_code, " "publication_date, frame_reference_epoch, " - "deprecated FROM geodetic_datum " + "ensemble_accuracy, deprecated FROM geodetic_datum " "WHERE " "auth_name = ? AND code = ?", code); @@ -2040,29 +2072,63 @@ AuthorityFactory::createGeodeticDatum(const std::string &code) const { const auto &prime_meridian_code = row[4]; const auto &publication_date = row[5]; const auto &frame_reference_epoch = row[6]; - const bool deprecated = row[7] == "1"; - auto ellipsoid = d->createFactory(ellipsoid_auth_name) - ->createEllipsoid(ellipsoid_code); - auto pm = d->createFactory(prime_meridian_auth_name) - ->createPrimeMeridian(prime_meridian_code); - auto props = d->createPropertiesSearchUsages( - "geodetic_datum", code, removeEnsembleSuffix(name), deprecated); - auto anchor = util::optional(); - if (!publication_date.empty()) { - props.set("PUBLICATION_DATE", publication_date); + const auto &ensemble_accuracy = row[7]; + const bool deprecated = row[8] == "1"; + + std::string massagedName = name; + if (turnEnsembleAsDatum) { + if (name == "World Geodetic System 1984 ensemble") { + massagedName = "World Geodetic System 1984"; + } else if (name == + "European Terrestrial Reference System 1989 ensemble") { + massagedName = "European Terrestrial Reference System 1989"; + } + } + auto props = d->createPropertiesSearchUsages("geodetic_datum", code, + massagedName, deprecated); + + if (!turnEnsembleAsDatum && !ensemble_accuracy.empty()) { + auto resMembers = + d->run("SELECT member_auth_name, member_code FROM " + "geodetic_datum_ensemble_member WHERE " + "ensemble_auth_name = ? AND ensemble_code = ? " + "ORDER BY sequence", + {d->authority(), code}); + + std::vector members; + for (const auto &memberRow : resMembers) { + members.push_back( + d->createFactory(memberRow[0])->createDatum(memberRow[1])); + } + auto datumEnsemble = datum::DatumEnsemble::create( + props, std::move(members), + metadata::PositionalAccuracy::create(ensemble_accuracy)); + d->context()->d->cache(cacheKey, datumEnsemble); + outDatumEnsemble = datumEnsemble.as_nullable(); + } else { + auto ellipsoid = d->createFactory(ellipsoid_auth_name) + ->createEllipsoid(ellipsoid_code); + auto pm = d->createFactory(prime_meridian_auth_name) + ->createPrimeMeridian(prime_meridian_code); + + auto anchor = util::optional(); + if (!publication_date.empty()) { + props.set("PUBLICATION_DATE", publication_date); + } + auto datum = frame_reference_epoch.empty() + ? datum::GeodeticReferenceFrame::create( + props, ellipsoid, anchor, pm) + : util::nn_static_pointer_cast< + datum::GeodeticReferenceFrame>( + datum::DynamicGeodeticReferenceFrame::create( + props, ellipsoid, anchor, pm, + common::Measure( + c_locale_stod(frame_reference_epoch), + common::UnitOfMeasure::YEAR), + util::optional())); + d->context()->d->cache(cacheKey, datum); + outDatum = datum.as_nullable(); } - auto datum = - frame_reference_epoch.empty() - ? datum::GeodeticReferenceFrame::create(props, ellipsoid, - anchor, pm) - : util::nn_static_pointer_cast( - datum::DynamicGeodeticReferenceFrame::create( - props, ellipsoid, anchor, pm, - common::Measure(c_locale_stod(frame_reference_epoch), - common::UnitOfMeasure::YEAR), - util::optional())); - d->context()->d->cache(cacheKey, datum); - return datum; } catch (const std::exception &ex) { throw buildFactoryException("geodetic reference frame", code, ex); } @@ -2472,20 +2538,24 @@ AuthorityFactory::createGeodeticCRS(const std::string &code, auto cs = d->createFactory(cs_auth_name)->createCoordinateSystem(cs_code); - auto datum = - d->createFactory(datum_auth_name)->createGeodeticDatum(datum_code); + datum::GeodeticReferenceFramePtr datum; + datum::DatumEnsemblePtr datumEnsemble; + constexpr bool turnEnsembleAsDatum = false; + d->createFactory(datum_auth_name) + ->createGeodeticDatumOrEnsemble(datum_code, datum, datumEnsemble, + turnEnsembleAsDatum); auto ellipsoidalCS = util::nn_dynamic_pointer_cast(cs); if ((type == GEOG_2D || type == GEOG_3D) && ellipsoidalCS) { auto crsRet = crs::GeographicCRS::create( - props, datum, NN_NO_CHECK(ellipsoidalCS)); + props, datum, datumEnsemble, NN_NO_CHECK(ellipsoidalCS)); d->context()->d->cache(cacheKey, crsRet); return crsRet; } auto geocentricCS = util::nn_dynamic_pointer_cast(cs); if (type == GEOCENTRIC && geocentricCS) { - auto crsRet = crs::GeodeticCRS::create(props, datum, + auto crsRet = crs::GeodeticCRS::create(props, datum, datumEnsemble, NN_NO_CHECK(geocentricCS)); d->context()->d->cache(cacheKey, crsRet); return crsRet; @@ -5617,7 +5687,7 @@ std::string AuthorityFactory::getOfficialNameFromAlias( if (res.empty()) { // shouldn't happen normally return std::string(); } - return removeEnsembleSuffix(res.front()[0]); + return res.front()[0]; } } return std::string(); @@ -5667,7 +5737,7 @@ std::string AuthorityFactory::getOfficialNameFromAlias( outTableName = row[1]; outAuthName = row[2]; outCode = row[3]; - return removeEnsembleSuffix(row[0]); + return row[0]; } } diff --git a/src/iso19111/io.cpp b/src/iso19111/io.cpp index f4ec7740..fde697ad 100644 --- a/src/iso19111/io.cpp +++ b/src/iso19111/io.cpp @@ -2110,6 +2110,10 @@ GeodeticReferenceFrameNNPtr WKTParser::Private::buildGeodeticReferenceFrame( name = "World Geodetic System 1984"; authNameFromAlias = Identifier::EPSG; codeFromAlias = "6326"; + } else if (name == "D_ETRS_1989") { + name = "European Terrestrial Reference System 1989"; + authNameFromAlias = Identifier::EPSG; + codeFromAlias = "6258"; } else { tableNameForAlias = "geodetic_datum"; } diff --git a/test/cli/testprojinfo_out.dist b/test/cli/testprojinfo_out.dist index 7da5add7..2d4990ee 100644 --- a/test/cli/testprojinfo_out.dist +++ b/test/cli/testprojinfo_out.dist @@ -4,9 +4,16 @@ PROJ.4 string: WKT2:2019 string: GEOGCRS["WGS 84", - DATUM["World Geodetic System 1984", + ENSEMBLE["World Geodetic System 1984 ensemble", + MEMBER["World Geodetic System 1984 (Transit)"], + MEMBER["World Geodetic System 1984 (G730)"], + MEMBER["World Geodetic System 1984 (G873)"], + MEMBER["World Geodetic System 1984 (G1150)"], + MEMBER["World Geodetic System 1984 (G1674)"], + MEMBER["World Geodetic System 1984 (G1762)"], ELLIPSOID["WGS 84",6378137,298.257223563, - LENGTHUNIT["metre",1]]], + LENGTHUNIT["metre",1]], + ENSEMBLEACCURACY[2.0]], PRIMEM["Greenwich",0, ANGLEUNIT["degree",0.0174532925199433]], CS[ellipsoidal,2], @@ -59,9 +66,16 @@ GEODCRS["WGS 84", Testing projinfo -o WKT2_2019 EPSG:4326 WKT2:2019 string: GEOGCRS["WGS 84", - DATUM["World Geodetic System 1984", + ENSEMBLE["World Geodetic System 1984 ensemble", + MEMBER["World Geodetic System 1984 (Transit)"], + MEMBER["World Geodetic System 1984 (G730)"], + MEMBER["World Geodetic System 1984 (G873)"], + MEMBER["World Geodetic System 1984 (G1150)"], + MEMBER["World Geodetic System 1984 (G1674)"], + MEMBER["World Geodetic System 1984 (G1762)"], ELLIPSOID["WGS 84",6378137,298.257223563, - LENGTHUNIT["metre",1]]], + LENGTHUNIT["metre",1]], + ENSEMBLEACCURACY[2.0]], PRIMEM["Greenwich",0, ANGLEUNIT["degree",0.0174532925199433]], CS[ellipsoidal,2], @@ -102,9 +116,16 @@ GEODCRS["WGS 84", WKT2:2019 string: GEOGCRS["WGS 84", - DATUM["World Geodetic System 1984", + ENSEMBLE["World Geodetic System 1984 ensemble", + MEMBER["World Geodetic System 1984 (Transit)"], + MEMBER["World Geodetic System 1984 (G730)"], + MEMBER["World Geodetic System 1984 (G873)"], + MEMBER["World Geodetic System 1984 (G1150)"], + MEMBER["World Geodetic System 1984 (G1674)"], + MEMBER["World Geodetic System 1984 (G1762)"], ELLIPSOID["WGS 84",6378137,298.257223563, - LENGTHUNIT["metre",1]]], + LENGTHUNIT["metre",1]], + ENSEMBLEACCURACY[2.0]], PRIMEM["Greenwich",0, ANGLEUNIT["degree",0.0174532925199433]], CS[ellipsoidal,2], @@ -142,13 +163,61 @@ PROJJSON: "$schema": "https://proj.org/schemas/v0.2/projjson.schema.json", "type": "GeographicCRS", "name": "WGS 84", - "datum": { - "type": "GeodeticReferenceFrame", - "name": "World Geodetic System 1984", + "datum_ensemble": { + "name": "World Geodetic System 1984 ensemble", + "members": [ + { + "name": "World Geodetic System 1984 (Transit)", + "id": { + "authority": "EPSG", + "code": 1166 + } + }, + { + "name": "World Geodetic System 1984 (G730)", + "id": { + "authority": "EPSG", + "code": 1152 + } + }, + { + "name": "World Geodetic System 1984 (G873)", + "id": { + "authority": "EPSG", + "code": 1153 + } + }, + { + "name": "World Geodetic System 1984 (G1150)", + "id": { + "authority": "EPSG", + "code": 1154 + } + }, + { + "name": "World Geodetic System 1984 (G1674)", + "id": { + "authority": "EPSG", + "code": 1155 + } + }, + { + "name": "World Geodetic System 1984 (G1762)", + "id": { + "authority": "EPSG", + "code": 1156 + } + } + ], "ellipsoid": { "name": "WGS 84", "semi_major_axis": 6378137, "inverse_flattening": 298.257223563 + }, + "accuracy": "2.0", + "id": { + "authority": "EPSG", + "code": 6326 } }, "coordinate_system": { @@ -1023,9 +1092,16 @@ PROJ.4 string: WKT2:2019 string: PROJCRS["WGS 84 / UTM zone 31N", BASEGEOGCRS["WGS 84", - DATUM["World Geodetic System 1984", + ENSEMBLE["World Geodetic System 1984 ensemble", + MEMBER["World Geodetic System 1984 (Transit)"], + MEMBER["World Geodetic System 1984 (G730)"], + MEMBER["World Geodetic System 1984 (G873)"], + MEMBER["World Geodetic System 1984 (G1150)"], + MEMBER["World Geodetic System 1984 (G1674)"], + MEMBER["World Geodetic System 1984 (G1762)"], ELLIPSOID["WGS 84",6378137,298.257223563, - LENGTHUNIT["metre",1]]], + LENGTHUNIT["metre",1]], + ENSEMBLEACCURACY[2.0]], PRIMEM["Greenwich",0, ANGLEUNIT["degree",0.0174532925199433]], ID["EPSG",4979]], @@ -1198,9 +1274,23 @@ Testing -k operation EPSG:8457 -o PROJ -q Testing D_WGS_1984 WKT2:2019 string: -DATUM["World Geodetic System 1984", +ENSEMBLE["World Geodetic System 1984 ensemble", + MEMBER["World Geodetic System 1984 (Transit)", + ID["EPSG",1166]], + MEMBER["World Geodetic System 1984 (G730)", + ID["EPSG",1152]], + MEMBER["World Geodetic System 1984 (G873)", + ID["EPSG",1153]], + MEMBER["World Geodetic System 1984 (G1150)", + ID["EPSG",1154]], + MEMBER["World Geodetic System 1984 (G1674)", + ID["EPSG",1155]], + MEMBER["World Geodetic System 1984 (G1762)", + ID["EPSG",1156]], ELLIPSOID["WGS 84",6378137,298.257223563, - LENGTHUNIT["metre",1]], + LENGTHUNIT["metre",1], + ID["EPSG",7030]], + ENSEMBLEACCURACY[2.0], ID["EPSG",6326]] Testing -k datum D_WGS_1984 diff --git a/test/unit/test_c_api.cpp b/test/unit/test_c_api.cpp index 5da6b369..a72aa72e 100644 --- a/test/unit/test_c_api.cpp +++ b/test/unit/test_c_api.cpp @@ -4841,9 +4841,16 @@ TEST_F(CApi, proj_create_derived_geographic_crs) { const char *expected_wkt = "GEOGCRS[\"my rotated CRS\",\n" " BASEGEOGCRS[\"WGS 84\",\n" - " DATUM[\"World Geodetic System 1984\",\n" + " ENSEMBLE[\"World Geodetic System 1984 ensemble\",\n" + " MEMBER[\"World Geodetic System 1984 (Transit)\"],\n" + " MEMBER[\"World Geodetic System 1984 (G730)\"],\n" + " MEMBER[\"World Geodetic System 1984 (G873)\"],\n" + " MEMBER[\"World Geodetic System 1984 (G1150)\"],\n" + " MEMBER[\"World Geodetic System 1984 (G1674)\"],\n" + " MEMBER[\"World Geodetic System 1984 (G1762)\"],\n" " ELLIPSOID[\"WGS 84\",6378137,298.257223563,\n" - " LENGTHUNIT[\"metre\",1]]],\n" + " LENGTHUNIT[\"metre\",1]],\n" + " ENSEMBLEACCURACY[2.0]],\n" " PRIMEM[\"Greenwich\",0,\n" " ANGLEUNIT[\"degree\",0.0174532925199433]]],\n" " DERIVINGCONVERSION[\"Pole rotation (GRIB convention)\",\n" diff --git a/test/unit/test_factory.cpp b/test/unit/test_factory.cpp index 1005d49b..c869fa50 100644 --- a/test/unit/test_factory.cpp +++ b/test/unit/test_factory.cpp @@ -531,8 +531,10 @@ TEST(factory, AuthorityFactory_createGeodeticCRS_geographic2D) { EXPECT_EQ(gcrs->identifiers()[0]->code(), "4326"); EXPECT_EQ(*(gcrs->identifiers()[0]->codeSpace()), "EPSG"); EXPECT_EQ(*(gcrs->name()->description()), "WGS 84"); - EXPECT_TRUE( - gcrs->datum()->isEquivalentTo(factory->createDatum("6326").get())); + ASSERT_TRUE(gcrs->datum() == nullptr); + ASSERT_TRUE(gcrs->datumEnsemble() != nullptr); + EXPECT_TRUE(gcrs->datumEnsemble()->isEquivalentTo( + factory->createDatumEnsemble("6326").get())); EXPECT_TRUE(gcrs->coordinateSystem()->isEquivalentTo( factory->createCoordinateSystem("6422").get())); auto domain = crs->domains()[0]; @@ -566,8 +568,10 @@ TEST(factory, AuthorityFactory_createGeodeticCRS_geographic3D) { EXPECT_EQ(gcrs->identifiers()[0]->code(), "4979"); EXPECT_EQ(*(gcrs->identifiers()[0]->codeSpace()), "EPSG"); EXPECT_EQ(*(gcrs->name()->description()), "WGS 84"); - EXPECT_TRUE( - gcrs->datum()->isEquivalentTo(factory->createDatum("6326").get())); + ASSERT_TRUE(gcrs->datum() == nullptr); + ASSERT_TRUE(gcrs->datumEnsemble() != nullptr); + EXPECT_TRUE(gcrs->datumEnsemble()->isEquivalentTo( + factory->createDatumEnsemble("6326").get())); EXPECT_TRUE(gcrs->coordinateSystem()->isEquivalentTo( factory->createCoordinateSystem("6423").get())); } @@ -582,8 +586,10 @@ TEST(factory, AuthorityFactory_createGeodeticCRS_geocentric) { EXPECT_EQ(crs->identifiers()[0]->code(), "4978"); EXPECT_EQ(*(crs->identifiers()[0]->codeSpace()), "EPSG"); EXPECT_EQ(*(crs->name()->description()), "WGS 84"); - EXPECT_TRUE( - crs->datum()->isEquivalentTo(factory->createDatum("6326").get())); + ASSERT_TRUE(crs->datum() == nullptr); + ASSERT_TRUE(crs->datumEnsemble() != nullptr); + EXPECT_TRUE(crs->datumEnsemble()->isEquivalentTo( + factory->createDatumEnsemble("6326").get())); EXPECT_TRUE(crs->coordinateSystem()->isEquivalentTo( factory->createCoordinateSystem("6500").get())); } -- cgit v1.2.3 From c2b0dcc468b4e722e46fe10fca93fe70a95fcb8e Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Thu, 8 Oct 2020 18:41:57 +0200 Subject: When reading from database, possibly return VerticalCRS with a DatumEnsemble Only occurence for now is EPSG:9451 'BI height' using the 'British Isles height ensemble' --- include/proj/io.hpp | 6 ++++ src/iso19111/factory.cpp | 84 ++++++++++++++++++++++++++++++++++------------ test/unit/test_factory.cpp | 14 ++++++++ 3 files changed, 83 insertions(+), 21 deletions(-) diff --git a/include/proj/io.hpp b/include/proj/io.hpp index 35e924ec..a30b04dc 100644 --- a/include/proj/io.hpp +++ b/include/proj/io.hpp @@ -1231,6 +1231,12 @@ class PROJ_GCC_DLL AuthorityFactory { datum::GeodeticReferenceFramePtr &outDatum, datum::DatumEnsemblePtr &outDatumEnsemble, bool turnEnsembleAsDatum) const; + + PROJ_INTERNAL void + createVerticalDatumOrEnsemble(const std::string &code, + datum::VerticalReferenceFramePtr &outDatum, + datum::DatumEnsemblePtr &outDatumEnsemble, + bool turnEnsembleAsDatum) const; }; // --------------------------------------------------------------------------- diff --git a/src/iso19111/factory.cpp b/src/iso19111/factory.cpp index cce80b8a..301b88be 100644 --- a/src/iso19111/factory.cpp +++ b/src/iso19111/factory.cpp @@ -2146,9 +2146,23 @@ void AuthorityFactory::createGeodeticDatumOrEnsemble( datum::VerticalReferenceFrameNNPtr AuthorityFactory::createVerticalDatum(const std::string &code) const { + datum::VerticalReferenceFramePtr datum; + datum::DatumEnsemblePtr datumEnsemble; + constexpr bool turnEnsembleAsDatum = true; + createVerticalDatumOrEnsemble(code, datum, datumEnsemble, + turnEnsembleAsDatum); + return NN_NO_CHECK(datum); +} + +// --------------------------------------------------------------------------- + +void AuthorityFactory::createVerticalDatumOrEnsemble( + const std::string &code, datum::VerticalReferenceFramePtr &outDatum, + datum::DatumEnsemblePtr &outDatumEnsemble, bool turnEnsembleAsDatum) const { auto res = d->runWithCodeParam("SELECT name, publication_date, " - "frame_reference_epoch, deprecated FROM " + "frame_reference_epoch, ensemble_accuracy, " + "deprecated FROM " "vertical_datum WHERE auth_name = ? AND code = ?", code); if (res.empty()) { @@ -2160,24 +2174,49 @@ AuthorityFactory::createVerticalDatum(const std::string &code) const { const auto &name = row[0]; const auto &publication_date = row[1]; const auto &frame_reference_epoch = row[2]; - const bool deprecated = row[3] == "1"; + const auto &ensemble_accuracy = row[3]; + const bool deprecated = row[4] == "1"; auto props = d->createPropertiesSearchUsages("vertical_datum", code, name, deprecated); - if (!publication_date.empty()) { - props.set("PUBLICATION_DATE", publication_date); - } - if (d->authority() == "ESRI" && starts_with(code, "from_geogdatum_")) { - props.set("VERT_DATUM_TYPE", "2002"); - } - auto anchor = util::optional(); - if (frame_reference_epoch.empty()) { - return datum::VerticalReferenceFrame::create(props, anchor); + if (!turnEnsembleAsDatum && !ensemble_accuracy.empty()) { + auto resMembers = + d->run("SELECT member_auth_name, member_code FROM " + "vertical_datum_ensemble_member WHERE " + "ensemble_auth_name = ? AND ensemble_code = ? " + "ORDER BY sequence", + {d->authority(), code}); + + std::vector members; + for (const auto &memberRow : resMembers) { + members.push_back( + d->createFactory(memberRow[0])->createDatum(memberRow[1])); + } + auto datumEnsemble = datum::DatumEnsemble::create( + props, std::move(members), + metadata::PositionalAccuracy::create(ensemble_accuracy)); + outDatumEnsemble = datumEnsemble.as_nullable(); } else { - return datum::DynamicVerticalReferenceFrame::create( - props, anchor, util::optional(), - common::Measure(c_locale_stod(frame_reference_epoch), - common::UnitOfMeasure::YEAR), - util::optional()); + if (!publication_date.empty()) { + props.set("PUBLICATION_DATE", publication_date); + } + if (d->authority() == "ESRI" && + starts_with(code, "from_geogdatum_")) { + props.set("VERT_DATUM_TYPE", "2002"); + } + auto anchor = util::optional(); + if (frame_reference_epoch.empty()) { + outDatum = datum::VerticalReferenceFrame::create(props, anchor) + .as_nullable(); + } else { + outDatum = + datum::DynamicVerticalReferenceFrame::create( + props, anchor, + util::optional(), + common::Measure(c_locale_stod(frame_reference_epoch), + common::UnitOfMeasure::YEAR), + util::optional()) + .as_nullable(); + } } } catch (const std::exception &ex) { throw buildFactoryException("vertical reference frame", code, ex); @@ -2609,16 +2648,19 @@ AuthorityFactory::createVerticalCRS(const std::string &code) const { const bool deprecated = row[5] == "1"; auto cs = d->createFactory(cs_auth_name)->createCoordinateSystem(cs_code); - auto datum = - d->createFactory(datum_auth_name)->createVerticalDatum(datum_code); - + datum::VerticalReferenceFramePtr datum; + datum::DatumEnsemblePtr datumEnsemble; + constexpr bool turnEnsembleAsDatum = false; + d->createFactory(datum_auth_name) + ->createVerticalDatumOrEnsemble(datum_code, datum, datumEnsemble, + turnEnsembleAsDatum); auto props = d->createPropertiesSearchUsages("vertical_crs", code, name, deprecated); auto verticalCS = util::nn_dynamic_pointer_cast(cs); if (verticalCS) { - auto crsRet = - crs::VerticalCRS::create(props, datum, NN_NO_CHECK(verticalCS)); + auto crsRet = crs::VerticalCRS::create(props, datum, datumEnsemble, + NN_NO_CHECK(verticalCS)); d->context()->d->cache(cacheKey, crsRet); return crsRet; } diff --git a/test/unit/test_factory.cpp b/test/unit/test_factory.cpp index c869fa50..681ac810 100644 --- a/test/unit/test_factory.cpp +++ b/test/unit/test_factory.cpp @@ -619,6 +619,20 @@ TEST(factory, AuthorityFactory_createVerticalCRS) { // --------------------------------------------------------------------------- +TEST(factory, AuthorityFactory_createVerticalCRS_with_datum_ensemble) { + auto factory = AuthorityFactory::create(DatabaseContext::create(), "EPSG"); + EXPECT_THROW(factory->createVerticalCRS("-1"), + NoSuchAuthorityCodeException); + + auto crs = factory->createVerticalCRS("9451"); // BI height + ASSERT_TRUE(crs->datum() == nullptr); + ASSERT_TRUE(crs->datumEnsemble() != nullptr); + EXPECT_TRUE(crs->datumEnsemble()->isEquivalentTo( + factory->createDatumEnsemble("1288").get())); +} + +// --------------------------------------------------------------------------- + TEST(factory, AuthorityFactory_createConversion) { auto factory = AuthorityFactory::create(DatabaseContext::create(), "EPSG"); EXPECT_THROW(factory->createConversion("-1"), NoSuchAuthorityCodeException); -- cgit v1.2.3 From 1e5acb00a0c0fc2533b9bce2e5803da10ed1d8d6 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Thu, 8 Oct 2020 20:59:19 +0200 Subject: projinfo / createObjectsFromName(): support returning a datum ensemble --- docs/source/apps/projinfo.rst | 4 ++-- include/proj/io.hpp | 2 ++ src/apps/projinfo.cpp | 18 ++++++++++----- src/iso19111/c_api.cpp | 2 +- src/iso19111/datum.cpp | 8 +++++++ src/iso19111/factory.cpp | 51 +++++++++++++++++++++++++++++++++++++++++- src/iso19111/io.cpp | 5 +++++ test/cli/testprojinfo | 4 ++++ test/cli/testprojinfo_out.dist | 21 +++++++++++++++++ test/unit/test_factory.cpp | 24 ++++++++++++++++++++ test/unit/test_io.cpp | 8 +++++++ 11 files changed, 137 insertions(+), 10 deletions(-) diff --git a/docs/source/apps/projinfo.rst b/docs/source/apps/projinfo.rst index 05184ef9..a07cf709 100644 --- a/docs/source/apps/projinfo.rst +++ b/docs/source/apps/projinfo.rst @@ -16,7 +16,7 @@ Synopsis ******** | **projinfo** - | [-o formats] [-k crs|operation|datum|ellipsoid] [--summary] [-q] + | [-o formats] [-k crs|operation|datum|ensemble|ellipsoid] [--summary] [-q] | [[--area name_or_code] | [--bbox west_long,south_lat,east_long,north_lat]] | [--spatial-test contains|intersects] | [--crs-extent-use none|both|intersection|smallest] @@ -86,7 +86,7 @@ The following control parameters can appear in any order: .. note:: Before PROJ 6.3.0, WKT1:GDAL was implicitly calling --boundcrs-to-wgs84. This is no longer the case. -.. option:: -k crs|operation|datum|ellipsoid +.. option:: -k crs|operation|datum|ensemble|ellipsoid When used to query a single object with a AUTHORITY:CODE, determines the (k)ind of the object in case there are CRS, coordinate operations or ellipsoids with the same CODE. diff --git a/include/proj/io.hpp b/include/proj/io.hpp index a30b04dc..de8a90fc 100644 --- a/include/proj/io.hpp +++ b/include/proj/io.hpp @@ -1032,6 +1032,8 @@ class PROJ_GCC_DLL AuthorityFactory { DYNAMIC_GEODETIC_REFERENCE_FRAME, /** Object of type datum::DynamicVerticalReferenceFrame */ DYNAMIC_VERTICAL_REFERENCE_FRAME, + /** Object of type datum::DatumEnsemble */ + DATUM_ENSEMBLE, }; PROJ_DLL std::set diff --git a/src/apps/projinfo.cpp b/src/apps/projinfo.cpp index 37b76346..6ee5925a 100644 --- a/src/apps/projinfo.cpp +++ b/src/apps/projinfo.cpp @@ -79,7 +79,8 @@ struct OutputOptions { static void usage() { std::cerr - << "usage: projinfo [-o formats] [-k crs|operation|datum|ellipsoid] " + << "usage: projinfo [-o formats] " + "[-k crs|operation|datum|ensemble|ellipsoid] " "[--summary] [-q]" << std::endl << " ([--area name_or_code] | " @@ -184,11 +185,11 @@ static BaseObjectNNPtr buildObject( 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 if (kind == "datum" && tokens.size() == 2) { - auto urn = "urn:ogc:def:datum:" + tokens[0] + "::" + tokens[1]; + } else if ((kind == "ellipsoid" || kind == "datum" || + kind == "ensemble") && + tokens.size() == 2) { + auto urn = + "urn:ogc:def:" + kind + ":" + tokens[0] + "::" + tokens[1]; obj = createFromUserInput(urn, dbContext).as_nullable(); } else { // Convenience to be able to use C escaped strings... @@ -222,6 +223,9 @@ static BaseObjectNNPtr buildObject( AuthorityFactory::ObjectType::ELLIPSOID); else if (kind == "datum") allowedTypes.push_back(AuthorityFactory::ObjectType::DATUM); + else if (kind == "ensemble") + allowedTypes.push_back( + AuthorityFactory::ObjectType::DATUM_ENSEMBLE); constexpr size_t limitResultCount = 10; auto factory = AuthorityFactory::create(NN_NO_CHECK(dbContext), std::string()); @@ -929,6 +933,8 @@ int main(int argc, char **argv) { objectKind = "ellipsoid"; } else if (ci_equal(kind, "datum")) { objectKind = "datum"; + } else if (ci_equal(kind, "ensemble")) { + objectKind = "ensemble"; } else { std::cerr << "Unrecognized value for option -k: " << kind << std::endl; diff --git a/src/iso19111/c_api.cpp b/src/iso19111/c_api.cpp index 90a414c6..4fb73d31 100644 --- a/src/iso19111/c_api.cpp +++ b/src/iso19111/c_api.cpp @@ -916,7 +916,7 @@ convertPJObjectTypeToObjectType(PJ_TYPE type, bool &valid) { break; case PJ_TYPE_DATUM_ENSEMBLE: - cppType = AuthorityFactory::ObjectType::DATUM; + cppType = AuthorityFactory::ObjectType::DATUM_ENSEMBLE; break; case PJ_TYPE_TEMPORAL_DATUM: diff --git a/src/iso19111/datum.cpp b/src/iso19111/datum.cpp index 5bc8074c..e29f6319 100644 --- a/src/iso19111/datum.cpp +++ b/src/iso19111/datum.cpp @@ -1731,6 +1731,14 @@ void DatumEnsemble::_exportToWKT( formatter->startNode(io::WKTConstants::ENSEMBLEACCURACY, false); formatter->add(positionalAccuracy()->value()); formatter->endNode(); + + // In theory, we should do the following, but currently the WKT grammar + // doesn't allow this + // ObjectUsage::baseExportToWKT(formatter); + if (formatter->outputId()) { + formatID(formatter); + } + formatter->endNode(); } //! @endcond diff --git a/src/iso19111/factory.cpp b/src/iso19111/factory.cpp index 301b88be..0ccfefc1 100644 --- a/src/iso19111/factory.cpp +++ b/src/iso19111/factory.cpp @@ -5452,6 +5452,11 @@ AuthorityFactory::getAuthorityCodes(const ObjectType &type, case ObjectType::CONCATENATED_OPERATION: sql = "SELECT code FROM concatenated_operation WHERE "; break; + case ObjectType::DATUM_ENSEMBLE: + sql = "SELECT code FROM object_view WHERE table_name IN " + "('geodetic_datum', 'vertical_datum') AND " + "type = 'ensemble' AND "; + break; } sql += "auth_name = ?"; @@ -5961,12 +5966,28 @@ AuthorityFactory::createObjectsFromNameEx( res.emplace_back( TableType("concatenated_operation", std::string())); break; + case ObjectType::DATUM_ENSEMBLE: + res.emplace_back(TableType("geodetic_datum", "ensemble")); + res.emplace_back(TableType("vertical_datum", "ensemble")); + break; } } } return res; }; + bool datumEnsembleAllowed = false; + if (allowedObjectTypes.empty()) { + datumEnsembleAllowed = true; + } else { + for (const auto type : allowedObjectTypes) { + if (type == ObjectType::DATUM_ENSEMBLE) { + datumEnsembleAllowed = true; + break; + } + } + } + const auto listTableNameType = getTableAndTypeConstraints(); bool first = true; ListOfParams params; @@ -5984,6 +6005,8 @@ AuthorityFactory::createObjectsFromNameEx( if (!tableNameTypePair.second.empty()) { if (tableNameTypePair.second == "frame_reference_epoch") { sql += "AND frame_reference_epoch IS NOT NULL "; + } else if (tableNameTypePair.second == "ensemble") { + sql += "AND ensemble_accuracy IS NOT NULL "; } else { sql += "AND type = '"; sql += tableNameTypePair.second; @@ -6018,6 +6041,8 @@ AuthorityFactory::createObjectsFromNameEx( if (!tableNameTypePair.second.empty()) { if (tableNameTypePair.second == "frame_reference_epoch") { sql += "AND ov.frame_reference_epoch IS NOT NULL "; + } else if (tableNameTypePair.second == "ensemble") { + sql += "AND ov.ensemble_accuracy IS NOT NULL "; } else { sql += "AND ov.type = '"; sql += tableNameTypePair.second; @@ -6165,7 +6190,7 @@ AuthorityFactory::createObjectsFromNameEx( break; } auto factory = d->createFactory(auth_name); - auto getObject = [&factory]( + auto getObject = [&factory, datumEnsembleAllowed]( const std::string &l_table_name, const std::string &l_code) -> common::IdentifiedObjectNNPtr { if (l_table_name == "prime_meridian") { @@ -6173,8 +6198,32 @@ AuthorityFactory::createObjectsFromNameEx( } else if (l_table_name == "ellipsoid") { return factory->createEllipsoid(l_code); } else if (l_table_name == "geodetic_datum") { + if (datumEnsembleAllowed) { + datum::GeodeticReferenceFramePtr datum; + datum::DatumEnsemblePtr datumEnsemble; + constexpr bool turnEnsembleAsDatum = false; + factory->createGeodeticDatumOrEnsemble( + l_code, datum, datumEnsemble, turnEnsembleAsDatum); + if (datum) { + return NN_NO_CHECK(datum); + } + assert(datumEnsemble); + return NN_NO_CHECK(datumEnsemble); + } return factory->createGeodeticDatum(l_code); } else if (l_table_name == "vertical_datum") { + if (datumEnsembleAllowed) { + datum::VerticalReferenceFramePtr datum; + datum::DatumEnsemblePtr datumEnsemble; + constexpr bool turnEnsembleAsDatum = false; + factory->createVerticalDatumOrEnsemble( + l_code, datum, datumEnsemble, turnEnsembleAsDatum); + if (datum) { + return NN_NO_CHECK(datum); + } + assert(datumEnsemble); + return NN_NO_CHECK(datumEnsemble); + } return factory->createVerticalDatum(l_code); } else if (l_table_name == "geodetic_crs") { return factory->createGeodeticCRS(l_code); diff --git a/src/iso19111/io.cpp b/src/iso19111/io.cpp index fde697ad..b2e5822b 100644 --- a/src/iso19111/io.cpp +++ b/src/iso19111/io.cpp @@ -6267,6 +6267,9 @@ static BaseObjectNNPtr createFromUserInput(const std::string &text, if (type == "datum") { return factory->createDatum(code); } + if (type == "ensemble") { + return factory->createDatumEnsemble(code); + } if (type == "ellipsoid") { return factory->createEllipsoid(code); } @@ -6384,6 +6387,8 @@ static BaseObjectNNPtr createFromUserInput(const std::string &text, ELLIPSOID, AuthorityFactory::ObjectType:: DATUM, + AuthorityFactory::ObjectType:: + DATUM_ENSEMBLE, AuthorityFactory::ObjectType:: COORDINATE_OPERATION}, goOn); diff --git a/test/cli/testprojinfo b/test/cli/testprojinfo index 62713af5..c31cfef0 100755 --- a/test/cli/testprojinfo +++ b/test/cli/testprojinfo @@ -171,6 +171,10 @@ echo 'Testing -k datum EPSG:6326' >> ${OUT} $EXE -k datum EPSG:6326 >>${OUT} 2>&1 echo "" >>${OUT} +echo 'Testing -k ensemble WGS84' >> ${OUT} +$EXE -k ensemble WGS84 >>${OUT} 2>&1 +echo "" >>${OUT} + echo 'Testing -k operation EPSG:8457 -o PROJ -q' >> ${OUT} $EXE -k operation EPSG:8457 -o PROJ -q >>${OUT} 2>&1 echo "" >>${OUT} diff --git a/test/cli/testprojinfo_out.dist b/test/cli/testprojinfo_out.dist index 2d4990ee..174f11d3 100644 --- a/test/cli/testprojinfo_out.dist +++ b/test/cli/testprojinfo_out.dist @@ -1260,6 +1260,27 @@ DATUM["World Geodetic System 1984", LENGTHUNIT["metre",1]], ID["EPSG",6326]] +Testing -k ensemble WGS84 +WKT2:2019 string: +ENSEMBLE["World Geodetic System 1984 ensemble", + MEMBER["World Geodetic System 1984 (Transit)", + ID["EPSG",1166]], + MEMBER["World Geodetic System 1984 (G730)", + ID["EPSG",1152]], + MEMBER["World Geodetic System 1984 (G873)", + ID["EPSG",1153]], + MEMBER["World Geodetic System 1984 (G1150)", + ID["EPSG",1154]], + MEMBER["World Geodetic System 1984 (G1674)", + ID["EPSG",1155]], + MEMBER["World Geodetic System 1984 (G1762)", + ID["EPSG",1156]], + ELLIPSOID["WGS 84",6378137,298.257223563, + LENGTHUNIT["metre",1], + ID["EPSG",7030]], + ENSEMBLEACCURACY[2.0], + ID["EPSG",6326]] + Testing -k operation EPSG:8457 -o PROJ -q +proj=pipeline +step +proj=axisswap +order=2,1 diff --git a/test/unit/test_factory.cpp b/test/unit/test_factory.cpp index 681ac810..8e9b7ab6 100644 --- a/test/unit/test_factory.cpp +++ b/test/unit/test_factory.cpp @@ -3186,6 +3186,29 @@ TEST(factory, createObjectsFromName) { .size(), 1U); + { + auto res = factory->createObjectsFromName( + "World Geodetic System 1984 ensemble", + {AuthorityFactory::ObjectType::DATUM_ENSEMBLE}, false); + EXPECT_EQ(res.size(), 1U); + if (!res.empty()) { + EXPECT_EQ(res.front()->getEPSGCode(), 6326); + EXPECT_TRUE(dynamic_cast(res.front().get()) != + nullptr); + } + } + + { + auto res = factory->createObjectsFromName( + "World Geodetic System 1984 ensemble", {}, false); + EXPECT_EQ(res.size(), 1U); + if (!res.empty()) { + EXPECT_EQ(res.front()->getEPSGCode(), 6326); + EXPECT_TRUE(dynamic_cast(res.front().get()) != + nullptr); + } + } + const auto types = std::vector{ AuthorityFactory::ObjectType::PRIME_MERIDIAN, AuthorityFactory::ObjectType::ELLIPSOID, @@ -3207,6 +3230,7 @@ TEST(factory, createObjectsFromName) { AuthorityFactory::ObjectType::CONVERSION, AuthorityFactory::ObjectType::TRANSFORMATION, AuthorityFactory::ObjectType::CONCATENATED_OPERATION, + AuthorityFactory::ObjectType::DATUM_ENSEMBLE, }; for (const auto type : types) { factory->createObjectsFromName("i_dont_exist", {type}, false, 1); diff --git a/test/unit/test_io.cpp b/test/unit/test_io.cpp index 555d1159..3d8df998 100644 --- a/test/unit/test_io.cpp +++ b/test/unit/test_io.cpp @@ -10444,6 +10444,14 @@ TEST(io, createFromUserInput) { ParsingException); EXPECT_THROW(createFromUserInput("foobar + EGM96 height", dbContext), ParsingException); + + { + auto obj = createFromUserInput("World Geodetic System 1984 ensemble", + dbContext); + auto ensemble = nn_dynamic_pointer_cast(obj); + ASSERT_TRUE(ensemble != nullptr); + EXPECT_EQ(ensemble->identifiers().size(), 1U); + } } // --------------------------------------------------------------------------- -- cgit v1.2.3 From 119888b041258267768d632b89395e7074323326 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Sat, 10 Oct 2020 15:35:29 +0200 Subject: proj.h: add PJ_CATEGORY_DATUM_ENSEMBLE for proj_create_from_database() --- src/iso19111/c_api.cpp | 3 +++ src/proj.h | 3 ++- test/unit/test_c_api.cpp | 7 +++++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/iso19111/c_api.cpp b/src/iso19111/c_api.cpp index 4fb73d31..cbbdcaa8 100644 --- a/src/iso19111/c_api.cpp +++ b/src/iso19111/c_api.cpp @@ -675,6 +675,9 @@ PJ *proj_create_from_database(PJ_CONTEXT *ctx, const char *auth_name, codeStr, usePROJAlternativeGridNames != 0) .as_nullable(); break; + case PJ_CATEGORY_DATUM_ENSEMBLE: + obj = factory->createDatumEnsemble(codeStr).as_nullable(); + break; } return pj_obj_create(ctx, NN_NO_CHECK(obj)); } catch (const std::exception &e) { diff --git a/src/proj.h b/src/proj.h index e77a5984..4185ddbf 100644 --- a/src/proj.h +++ b/src/proj.h @@ -694,7 +694,8 @@ typedef enum PJ_CATEGORY_PRIME_MERIDIAN, PJ_CATEGORY_DATUM, PJ_CATEGORY_CRS, - PJ_CATEGORY_COORDINATE_OPERATION + PJ_CATEGORY_COORDINATE_OPERATION, + PJ_CATEGORY_DATUM_ENSEMBLE } PJ_CATEGORY; /** \brief Object type. */ diff --git a/test/unit/test_c_api.cpp b/test/unit/test_c_api.cpp index a72aa72e..a7c1eb53 100644 --- a/test/unit/test_c_api.cpp +++ b/test/unit/test_c_api.cpp @@ -844,6 +844,13 @@ TEST_F(CApi, proj_create_from_database) { ObjectKeeper keeper(datum); EXPECT_EQ(proj_get_type(datum), PJ_TYPE_GEODETIC_REFERENCE_FRAME); } + { + auto ensemble = proj_create_from_database( + m_ctxt, "EPSG", "6326", PJ_CATEGORY_DATUM_ENSEMBLE, false, nullptr); + ASSERT_NE(ensemble, nullptr); + ObjectKeeper keeper(ensemble); + EXPECT_EQ(proj_get_type(ensemble), PJ_TYPE_DATUM_ENSEMBLE); + } { // International Terrestrial Reference Frame 2008 auto datum = proj_create_from_database( -- cgit v1.2.3 From dd829c94fffba3a0b725504d5c7b42384b2e6ee7 Mon Sep 17 00:00:00 2001 From: Olli Raisa Date: Mon, 2 Nov 2020 09:25:48 +0200 Subject: cmake build: set CURL_ENABLED definition on projinfo build (#2404) Fixes projinfo operation, when --remote-data command line option is parsed. --- src/bin_projinfo.cmake | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/bin_projinfo.cmake b/src/bin_projinfo.cmake index 16c9e9d0..8610a3a7 100644 --- a/src/bin_projinfo.cmake +++ b/src/bin_projinfo.cmake @@ -15,3 +15,7 @@ install(TARGETS binprojinfo if(MSVC AND BUILD_SHARED_LIBS) target_compile_definitions(binprojinfo PRIVATE PROJ_MSVC_DLL_IMPORT=1) endif() + +if(CURL_ENABLED) + target_compile_definitions(binprojinfo PRIVATE -DCURL_ENABLED) +endif() -- cgit v1.2.3 From c64c209f4abeec7ae4e8cdde8d6c5ba9921354fa Mon Sep 17 00:00:00 2001 From: Martin Steinisch Date: Mon, 2 Nov 2020 23:22:18 +0100 Subject: Correct links to github issues in release notes from 7.1.0 to 7.2.0 --- HOWTO-RELEASE | 2 +- docs/source/news.rst | 156 +++++++++++++++++++++++++-------------------------- 2 files changed, 79 insertions(+), 79 deletions(-) diff --git a/HOWTO-RELEASE b/HOWTO-RELEASE index 92c6829c..a18d47e5 100644 --- a/HOWTO-RELEASE +++ b/HOWTO-RELEASE @@ -179,7 +179,7 @@ See step 1.6 above. Do not rename the archives with RC postfixes. These vim substitutions are helpfull when converting NEWS to rst: - :s!(\#\(\d\{4}\))!(`\#\1 `_)! + :s!(\#\(\d\{4}\))!(`\#\1 `_)! :s/^o/*/ - Update download links in `docs/source/download.rst` diff --git a/docs/source/news.rst b/docs/source/news.rst index 4275dd11..65c027f1 100644 --- a/docs/source/news.rst +++ b/docs/source/news.rst @@ -13,72 +13,72 @@ Updates + **Command line tools** * Add multi-line PROJ string export capability, and use it by default in - :program:`projinfo` (unless ``--single-line`` is specified) (`#2381 `_) + :program:`projinfo` (unless ``--single-line`` is specified) (`#2381 `_) + **Coordinate operations** * :ref:`col_urban` projection, implementing a EPSG projection method - used by a number of projected CRS in Colombia (`#2395 `_) + used by a number of projected CRS in Colombia (`#2395 `_) - * :ref:`tinshift` for triangulation-based transformations (`#2344 `_) + * :ref:`tinshift` for triangulation-based transformations (`#2344 `_) - * Added ellipsoidal formulation of :ref:`ortho` (`#2361 `_) + * Added ellipsoidal formulation of :ref:`ortho` (`#2361 `_) + **Database** * Update to EPSG 10.003 and make code base robust to dealing with - WKT CRS with DatumEnsemble (`#2370 `_) + WKT CRS with DatumEnsemble (`#2370 `_) - * Added Finland tinshift operations (`#2392 `_) + * Added Finland tinshift operations (`#2392 `_) * Added transformation from JGD2011 Geographic 3D to JGD2011 - height using GSIGEO2011 (`#2393 `_) + height using GSIGEO2011 (`#2393 `_) * Improve CompoundCRS identification and name morphing in VerticalCRS - with ESRI WKT1 (`#2386 `_) + with ESRI WKT1 (`#2386 `_) * Added OGC:CRS27 and OGC:CRS83 CRS entries for NAD27 and NAD83 - in longitude, latitude order (`#2350 `_) + in longitude, latitude order (`#2350 `_) + **API** - * Added temporal, engineering, and parametric datum :c:type:`PJ_TYPE` enumerations (`#2274 `_) + * Added temporal, engineering, and parametric datum :c:type:`PJ_TYPE` enumerations (`#2274 `_) * Various improvements to context handling (#2329, #2331) * :c:func:`proj_create_vertical_crs_ex()`: add a ``ACCURACY`` option to provide an explicit accuracy, or derive it from the grid name if it is - known (`#2342 `_) + known (`#2342 `_) * :c:func:`proj_crs_create_bound_crs_to_WGS84()`: make it work on verticalCRS/compoundCRS such as EPSG:4326+5773 and - EPSG:4326+3855 (`#2365 `_) + EPSG:4326+3855 (`#2365 `_) - * :cpp:func:`promoteTo3D()`: add a remark with the original CRS identifier (`#2369 `_) + * :cpp:func:`promoteTo3D()`: add a remark with the original CRS identifier (`#2369 `_) - * Added :c:func:`proj_context_clone` (`#2383 `_) + * Added :c:func:`proj_context_clone` (`#2383 `_) Bug fixes --------- -* Avoid core dumps when copying contexts in certain scenarios (`#2324 `_) +* Avoid core dumps when copying contexts in certain scenarios (`#2324 `_) * :c:func:`proj_trans()`: reset errno before attemptying a retry with a new - coordinate operation (`#2353 `_) + coordinate operation (`#2353 `_) * PROJJSON schema corrected to allow prime meridians values with - explicitly stating a unit (degrees assumed) (`#2354 `_) + explicitly stating a unit (degrees assumed) (`#2354 `_) * Adjust :cpp:func:`createBoundCRSToWGS84IfPossible()` and operation filtering - (for POSGAR 2007 to WGS84 issues) (`#2357 `_) + (for POSGAR 2007 to WGS84 issues) (`#2357 `_) -* :cpp:func:`createOperations()`: several fixes affecting NAD83 -> NAD83(2011) (`#2364 `_) +* :cpp:func:`createOperations()`: several fixes affecting NAD83 -> NAD83(2011) (`#2364 `_) * WKT2:2019 import/export: handle DATUM (at top level object) with PRIMEM -* WKT1_ESRI: fix import and export of CompoundCRS (`#2389 `_) +* WKT1_ESRI: fix import and export of CompoundCRS (`#2389 `_) 7.1.1 Release Notes @@ -89,36 +89,36 @@ Bug fixes Updates ------- -* Added various Brazillian grids to the database (`#2277 `_) +* Added various Brazillian grids to the database (`#2277 `_) -* Added geoid file for Canary Islands to the database (`#2312 `_) +* Added geoid file for Canary Islands to the database (`#2312 `_) -* Updated EPSG database to version 9.8.15 (`#2310 `_) +* Updated EPSG database to version 9.8.15 (`#2310 `_) Bug fixes --------- * WKT parser: do not raise warning when parsing a WKT2:2015 TIMECRS - whose TIMEUNIT is at the CS level, and not inside (`#2281 `_) + whose TIMEUNIT is at the CS level, and not inside (`#2281 `_) * Parse '+proj=something_not_latlong +vunits=' without +geoidgrids as a - Projected3D CRS and not a compound CRS with a unknown datum (`#2289 `_) + Projected3D CRS and not a compound CRS with a unknown datum (`#2289 `_) -* C API: Avoid crashing due to missing SANITIZE_CTX() in entry points (`#2293 `_) +* C API: Avoid crashing due to missing SANITIZE_CTX() in entry points (`#2293 `_) -* CMake build: Check "target_clones" before use (`#2297 `_) +* CMake build: Check "target_clones" before use (`#2297 `_) -* PROJ string export of +proj=krovak +czech: make sure we export +czech… (`#2301 `_) +* PROJ string export of +proj=krovak +czech: make sure we export +czech… (`#2301 `_) -* Helmert 2D: do not require a useless +convention= parameter (`#2305 `_) +* Helmert 2D: do not require a useless +convention= parameter (`#2305 `_) -* Fix a few spelling errors ("vgridshit" vs. "vgridshift") (`#2307 `_) +* Fix a few spelling errors ("vgridshit" vs. "vgridshift") (`#2307 `_) -* Fix ability to identify EPSG:2154 as a candidate for 'RGF93_Lambert_93' (`#2316 `_) +* Fix ability to identify EPSG:2154 as a candidate for 'RGF93_Lambert_93' (`#2316 `_) -* WKT importer: tune for Oracle WKT and 'Lambert Conformal Conic' (`#2322 `_) +* WKT importer: tune for Oracle WKT and 'Lambert Conformal Conic' (`#2322 `_) -* Revert compiler generated Fused Multiply Addition optimized routines (`#2328 `_) +* Revert compiler generated Fused Multiply Addition optimized routines (`#2328 `_) @@ -135,7 +135,7 @@ Updates + **New projections** - * Add square conformal projections from libproject (`#2148 `_): + * Add square conformal projections from libproject (`#2148 `_): - :ref:`adams_hemi` @@ -148,117 +148,117 @@ Updates - :ref:`peirce_q` * Adams Square II: map ESRI WKT to PROJ string, and implement iterative - inverse method (`#2157 `_) + inverse method (`#2157 `_) - * Added :ref:`igh_o` projection (`#2226 `_) + * Added :ref:`igh_o` projection (`#2226 `_) - * Add :ref:`wink2` inverse by generic inversion of forward method (`#2243 `_) + * Add :ref:`wink2` inverse by generic inversion of forward method (`#2243 `_) + **Database** * Update to EPSG 9.8.12, ESRI 10.8.1 and import scope and remarks for - conversion (`#2238 `_) (#2267) + conversion (`#2238 `_) (#2267) - * Map the Behrman projection to ``cae`` when converting ESRI CRSes (`#1986 `_) + * Map the Behrman projection to ``cae`` when converting ESRI CRSes (`#1986 `_) - * Support conversion of Flat_Polar_Quartic projection method (`#1987 `_) + * Support conversion of Flat_Polar_Quartic projection method (`#1987 `_) * Register 4 new Austrian height grids (see https://github.com/OSGeo/PROJ-data/pull/13) - and handle 'Vertical Offset by Grid Interpolation (BEV AT)' method (`#1989 `_) + and handle 'Vertical Offset by Grid Interpolation (BEV AT)' method (`#1989 `_) * Add ESRI projection method mappings for Mercator_Variant_A, Mercator_Variant_B - and Transverse_Cylindrical_Equal_Area and various grid mappings (`#2020 `_) (#2195) + and Transverse_Cylindrical_Equal_Area and various grid mappings (`#2020 `_) (#2195) - * Map ESRI Transverse_Mercator_Complex to Transverse Mercator (`#2040 `_) + * Map ESRI Transverse_Mercator_Complex to Transverse Mercator (`#2040 `_) - * Register grids for New Caledonia (see https://github.com/OSGeo/PROJ-data/pull/16) (`#2051 `_) (#2239) + * Register grids for New Caledonia (see https://github.com/OSGeo/PROJ-data/pull/16) (`#2051 `_) (#2239) - * Register NZGD2000 -> ITRF96 transformation for NZGD2000 database (`#2248 `_) + * Register NZGD2000 -> ITRF96 transformation for NZGD2000 database (`#2248 `_) * Register geoid file for UK added - (see https://github.com/OSGeo//PROJ-data/pull/25() (`#2250 `_) + (see https://github.com/OSGeo//PROJ-data/pull/25() (`#2250 `_) - * Register Slovakian geoid transformations with needed code changes (`#2259 `_) + * Register Slovakian geoid transformations with needed code changes (`#2259 `_) - * Register Spanish SPED2ETV2 grid for ED50->ETRS89 (`#2261 `_) + * Register Spanish SPED2ETV2 grid for ED50->ETRS89 (`#2261 `_) + **API** - * Add API function :c:func:`proj_get_units_from_database()` (`#2065 `_) + * Add API function :c:func:`proj_get_units_from_database()` (`#2065 `_) - * Add API function :c:func:`proj_get_suggested_operation()` (`#2068 `_) + * Add API function :c:func:`proj_get_suggested_operation()` (`#2068 `_) - * Add API functions :c:func:`proj_degree_input()` and :c:func:`proj_degree_output()` (`#2144 `_) + * Add API functions :c:func:`proj_degree_input()` and :c:func:`proj_degree_output()` (`#2144 `_) * Moved :c:func:`proj_context_get_url_endpoint()` & :c:func:`proj_context_get_user_writable_directory()` - from ``proj_experimental.h`` to ``proj.h`` (`#2162 `_) + from ``proj_experimental.h`` to ``proj.h`` (`#2162 `_) * :c:func:`createFromUserInput()`: allow compound CRS with the 2 parts given by names, - e.g. 'WGS 84 + EGM96 height' (`#2126 `_) + e.g. 'WGS 84 + EGM96 height' (`#2126 `_) * :c:func:`createOperations()`: when converting CompoundCRS<-->Geographic3DCrs, do not use discard change of ellipsoidal height if a Helmert transformation is - involved (`#2227 `_) + involved (`#2227 `_) + **Optimizations** - * ``tmerc/utm``: add a +algo=auto/evenden_snyder/poder_engsager parameter (`#2030 `_) + * ``tmerc/utm``: add a +algo=auto/evenden_snyder/poder_engsager parameter (`#2030 `_) - * Extended ``tmerc`` (Poder/Engsager): speed optimizations (`#2036 `_) + * Extended ``tmerc`` (Poder/Engsager): speed optimizations (`#2036 `_) - * Approximate ``tmerc`` (Snyder): speed optimizations (`#2039 `_) + * Approximate ``tmerc`` (Snyder): speed optimizations (`#2039 `_) - * :c:func:`pj_phi2()`: speed-up computation (and thus inverse ellipsoidal Mercator and LCC) (`#2052 `_) + * :c:func:`pj_phi2()`: speed-up computation (and thus inverse ellipsoidal Mercator and LCC) (`#2052 `_) - * Inverse ``cart``: speed-up computation by 33% (`#2145 `_) + * Inverse ``cart``: speed-up computation by 33% (`#2145 `_) - * Extended ``tmerc``: speed-up forward path by ~5% (`#2147 `_) + * Extended ``tmerc``: speed-up forward path by ~5% (`#2147 `_) + **Various** - * Follow PDAL's CMake RPATH strategy (`#2009 `_) + * Follow PDAL's CMake RPATH strategy (`#2009 `_) - * WKT import/export: add support for WKT1_ESRI VERTCS synta (`#2024 `_) + * WKT import/export: add support for WKT1_ESRI VERTCS synta (`#2024 `_) - * :program:`projinfo`: add a ``--hide-ballpark`` option (`#2127 `_) + * :program:`projinfo`: add a ``--hide-ballpark`` option (`#2127 `_) - * :program:`gie`: implement a strict mode with `` `` (`#2168 `_) + * :program:`gie`: implement a strict mode with `` `` (`#2168 `_) - * Allow importing WKT1 COMPD_CS with a VERT_DATUM[Ellipsoid,2002] (`#2229 `_) + * Allow importing WKT1 COMPD_CS with a VERT_DATUM[Ellipsoid,2002] (`#2229 `_) - * Add runtime checking that sqlite3 is >= 3.11 (`#2235 `_) + * Add runtime checking that sqlite3 is >= 3.11 (`#2235 `_) Bug fixes --------- * :cpp:func:`createOperations()`: do not remove ballpark transformation if there are only grid - based operations, even if they cover the whole area of use (`#2155 `_) + based operations, even if they cover the whole area of use (`#2155 `_) * :cpp:func:`createFromProjString()`: handle default parameters of '+krovak +type=crs', and - handle ``+czech`` correctly (`#2200 `_) + handle ``+czech`` correctly (`#2200 `_) -* :cpp:func:`ProjectedCRS::identify()`: fix identification of EPSG:3059 (`#2215 `_) +* :cpp:func:`ProjectedCRS::identify()`: fix identification of EPSG:3059 (`#2215 `_) -* Database: add a 'WGS84' alias for the EPSG:4326 CRS (`#2218 `_) +* Database: add a 'WGS84' alias for the EPSG:4326 CRS (`#2218 `_) -* Fixes related to CompoundCRS and BoundCRS (`#2222 `_) +* Fixes related to CompoundCRS and BoundCRS (`#2222 `_) -* Avoid 2 warnings about missing database indices (`#2223 `_) +* Avoid 2 warnings about missing database indices (`#2223 `_) -* Make ``projinfo --3d --boundcrs-to-wgs84`` work better (`#2224 `_) +* Make ``projinfo --3d --boundcrs-to-wgs84`` work better (`#2224 `_) * Many fixes regarding BoundCRS, CompoundCRS, Geographic3D CRS with - non-metre units (`#2234 `_) + non-metre units (`#2234 `_) -* Fix identification of (one of the) ESRI WKT formulations of EPSG:3035 (`#2240 `_) +* Fix identification of (one of the) ESRI WKT formulations of EPSG:3035 (`#2240 `_) -* Avoid using deprecated and removed Windows API function with Mingw32 (`#2246 `_) +* Avoid using deprecated and removed Windows API function with Mingw32 (`#2246 `_) * :cpp:func:`normalizeForVisualization()`: make it switch axis for EPSG:5482 - (RSRGD2000 / RSPS2000) (`#2256 `_) + (RSRGD2000 / RSPS2000) (`#2256 `_) -* Fix access violation in :c:func:`proj_context_get_database_metadata()` (`#2260 `_) +* Fix access violation in :c:func:`proj_context_get_database_metadata()` (`#2260 `_) 7.0.1 Release Notes -- cgit v1.2.3 From 20c987854fb0220cd8cc28278fe5f18279175013 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Tue, 3 Nov 2020 23:17:02 +0100 Subject: docs/Makefile: restore custom 'html' target Fixes #2408 https://github.com/OSGeo/PROJ/pull/2377 removed our customized 'html' and .doxygen_up_to_date targets. Let's restore them --- docs/Makefile | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/docs/Makefile b/docs/Makefile index b9fa8257..22399302 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -4,18 +4,43 @@ # You can set these variables from the command line, and also # from the environment for the first two. SPHINXOPTS ?= +HTMLOPTS ?= -W SPHINXBUILD ?= sphinx-build SOURCEDIR = source BUILDDIR = build +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source + # Put it first so that "make" without argument is like "make help". help: @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) .PHONY: help Makefile +.PHONY: clean +clean: + rm -rf $(BUILDDIR)/* + rm -rf .doxygen_up_to_date + +.doxygen_up_to_date: + ../scripts/doxygen.sh + touch .doxygen_up_to_date + +.PHONY: html +html: .doxygen_up_to_date + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(HTMLOPTS) $(BUILDDIR)/html + # Undoes the hack done in scripts/doxygen.sh + @sed "s/io::Convention_/io::Convention/g" < $(BUILDDIR)/html/development/reference/cpp/io.html | sed "s/>Convention_/>Convention/g" | sed "s/_WKT2/WKT2/g" | sed "s/_WKT1/WKT1/g" > $(BUILDDIR)/html/development/reference/cpp/io.html.tmp + @mv $(BUILDDIR)/html/development/reference/cpp/io.html.tmp $(BUILDDIR)/html/development/reference/cpp/io.html + # Undoes the hacks of scripts/generate_breathe_friendly_general_doc.py + @sed "s/namespace <\/em>//g" < $(BUILDDIR)/html/development/reference/cpp/cpp_general.html > $(BUILDDIR)/html/development/reference/cpp/cpp_general.html.tmp + @mv $(BUILDDIR)/html/development/reference/cpp/cpp_general.html.tmp $(BUILDDIR)/html/development/reference/cpp/cpp_general.html + @cp -r ../schemas $(BUILDDIR)/html/schemas + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + + # Catch-all target: route all unknown targets to Sphinx using the new # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). %: Makefile @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) - -- cgit v1.2.3 From 9c28184f6f32aeaa2951c994453c4f99572a11dc Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Wed, 4 Nov 2020 14:46:10 +0100 Subject: Code formatting --- test/unit/pj_phi2_test.cpp | 56 +++++++++++++++++++++------------------------- 1 file changed, 25 insertions(+), 31 deletions(-) diff --git a/test/unit/pj_phi2_test.cpp b/test/unit/pj_phi2_test.cpp index fdedae98..b4e6b68f 100644 --- a/test/unit/pj_phi2_test.cpp +++ b/test/unit/pj_phi2_test.cpp @@ -47,54 +47,48 @@ TEST(PjPhi2Test, Basic) { constexpr auto nan = std::numeric_limits::quiet_NaN(); // Strict equality is demanded here. - EXPECT_EQ( M_PI_2, pj_phi2(ctx, +0.0, 0.0)); - EXPECT_EQ( 0.0 , pj_phi2(ctx, 1.0, 0.0)); - EXPECT_EQ(-M_PI_2, pj_phi2(ctx, inf, 0.0)); + EXPECT_EQ(M_PI_2, pj_phi2(ctx, +0.0, 0.0)); + EXPECT_EQ(0.0, pj_phi2(ctx, 1.0, 0.0)); + EXPECT_EQ(-M_PI_2, pj_phi2(ctx, inf, 0.0)); // We don't expect pj_phi2 to be called with negative ts (since ts = // exp(-psi)). However, in the current implementation it is odd in ts. // N.B. ts = +0.0 and ts = -0.0 return different results. EXPECT_EQ(-M_PI_2, pj_phi2(ctx, -0.0, 0.0)); - EXPECT_EQ( 0.0 , pj_phi2(ctx, -1.0, 0.0)); + EXPECT_EQ(0.0, pj_phi2(ctx, -1.0, 0.0)); EXPECT_EQ(+M_PI_2, pj_phi2(ctx, -inf, 0.0)); constexpr double e = 0.2; - EXPECT_EQ( M_PI_2, pj_phi2(ctx, +0.0, e)); - EXPECT_EQ( 0.0 , pj_phi2(ctx, 1.0, e)); - EXPECT_EQ(-M_PI_2, pj_phi2(ctx, inf, e)); + EXPECT_EQ(M_PI_2, pj_phi2(ctx, +0.0, e)); + EXPECT_EQ(0.0, pj_phi2(ctx, 1.0, e)); + EXPECT_EQ(-M_PI_2, pj_phi2(ctx, inf, e)); EXPECT_EQ(-M_PI_2, pj_phi2(ctx, -0.0, e)); - EXPECT_EQ( 0.0 , pj_phi2(ctx, -1.0, e)); + EXPECT_EQ(0.0, pj_phi2(ctx, -1.0, e)); EXPECT_EQ(+M_PI_2, pj_phi2(ctx, -inf, e)); - EXPECT_TRUE(std::isnan(pj_phi2(ctx, nan, 0.0))); - EXPECT_TRUE(std::isnan(pj_phi2(ctx, nan, e ))); + EXPECT_TRUE(std::isnan(pj_phi2(ctx, nan, 0.0))); + EXPECT_TRUE(std::isnan(pj_phi2(ctx, nan, e))); EXPECT_TRUE(std::isnan(pj_phi2(ctx, +0.0, nan))); - EXPECT_TRUE(std::isnan(pj_phi2(ctx, 1.0, nan))); - EXPECT_TRUE(std::isnan(pj_phi2(ctx, inf, nan))); + EXPECT_TRUE(std::isnan(pj_phi2(ctx, 1.0, nan))); + EXPECT_TRUE(std::isnan(pj_phi2(ctx, inf, nan))); EXPECT_TRUE(std::isnan(pj_phi2(ctx, -0.0, nan))); EXPECT_TRUE(std::isnan(pj_phi2(ctx, -1.0, nan))); EXPECT_TRUE(std::isnan(pj_phi2(ctx, -inf, nan))); - EXPECT_TRUE(std::isnan(pj_phi2(ctx, nan, nan))); + EXPECT_TRUE(std::isnan(pj_phi2(ctx, nan, nan))); - EXPECT_DOUBLE_EQ( M_PI/3, pj_phi2(ctx, 1/(sqrt(3.0)+2), 0.0)); - EXPECT_DOUBLE_EQ( M_PI/4, pj_phi2(ctx, 1/(sqrt(2.0)+1), 0.0)); - EXPECT_DOUBLE_EQ( M_PI/6, pj_phi2(ctx, 1/ sqrt(3.0) , 0.0)); - EXPECT_DOUBLE_EQ(-M_PI/3, pj_phi2(ctx, sqrt(3.0)+2 , 0.0)); - EXPECT_DOUBLE_EQ(-M_PI/4, pj_phi2(ctx, sqrt(2.0)+1 , 0.0)); - EXPECT_DOUBLE_EQ(-M_PI/6, pj_phi2(ctx, sqrt(3.0) , 0.0)); + EXPECT_DOUBLE_EQ(M_PI / 3, pj_phi2(ctx, 1 / (sqrt(3.0) + 2), 0.0)); + EXPECT_DOUBLE_EQ(M_PI / 4, pj_phi2(ctx, 1 / (sqrt(2.0) + 1), 0.0)); + EXPECT_DOUBLE_EQ(M_PI / 6, pj_phi2(ctx, 1 / sqrt(3.0), 0.0)); + EXPECT_DOUBLE_EQ(-M_PI / 3, pj_phi2(ctx, sqrt(3.0) + 2, 0.0)); + EXPECT_DOUBLE_EQ(-M_PI / 4, pj_phi2(ctx, sqrt(2.0) + 1, 0.0)); + EXPECT_DOUBLE_EQ(-M_PI / 6, pj_phi2(ctx, sqrt(3.0), 0.0)); // Generated with exp(e * atanh(e * sin(phi))) / (tan(phi) + sec(phi)) - EXPECT_DOUBLE_EQ( M_PI/3, pj_phi2(ctx, 0.27749174377027023413, e)); - EXPECT_DOUBLE_EQ( M_PI/4, pj_phi2(ctx, 0.42617788119104192995, e)); - EXPECT_DOUBLE_EQ( M_PI/6, pj_phi2(ctx, 0.58905302448626726064, e)); - EXPECT_DOUBLE_EQ(-M_PI/3, pj_phi2(ctx, 3.6037108218537833089, e)); - EXPECT_DOUBLE_EQ(-M_PI/4, pj_phi2(ctx, 2.3464380582241712935, e)); - EXPECT_DOUBLE_EQ(-M_PI/6, pj_phi2(ctx, 1.6976400399134411849, e)); + EXPECT_DOUBLE_EQ(M_PI / 3, pj_phi2(ctx, 0.27749174377027023413, e)); + EXPECT_DOUBLE_EQ(M_PI / 4, pj_phi2(ctx, 0.42617788119104192995, e)); + EXPECT_DOUBLE_EQ(M_PI / 6, pj_phi2(ctx, 0.58905302448626726064, e)); + EXPECT_DOUBLE_EQ(-M_PI / 3, pj_phi2(ctx, 3.6037108218537833089, e)); + EXPECT_DOUBLE_EQ(-M_PI / 4, pj_phi2(ctx, 2.3464380582241712935, e)); + EXPECT_DOUBLE_EQ(-M_PI / 6, pj_phi2(ctx, 1.6976400399134411849, e)); } } // namespace - - - - - - -- cgit v1.2.3 From 848ee7b6a8bf56a9d967f104ba2ef2ad92dc48d5 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Wed, 4 Nov 2020 15:24:44 +0100 Subject: createBoundCRSToWGS84IfPossible(): make it return same result with a CRS built from EPSG code or WKT1 Related to https://github.com/OSGeo/gdal/issues/3144 --- include/proj/crs.hpp | 5 + src/iso19111/coordinateoperation.cpp | 296 ++++++++++++++++++----------------- src/iso19111/crs.cpp | 6 +- test/unit/test_crs.cpp | 25 +++ 4 files changed, 186 insertions(+), 146 deletions(-) diff --git a/include/proj/crs.hpp b/include/proj/crs.hpp index b607ff9d..ec755728 100644 --- a/include/proj/crs.hpp +++ b/include/proj/crs.hpp @@ -155,6 +155,11 @@ class PROJ_GCC_DLL CRS : public common::ObjectUsage, const; PROJ_INTERNAL bool hasImplicitCS() const; + + PROJ_INTERNAL static CRSNNPtr + getResolvedCRS(const CRSNNPtr &crs, + const io::AuthorityFactoryPtr &authFactory, + metadata::ExtentPtr &extentOut); //! @endcond protected: diff --git a/src/iso19111/coordinateoperation.cpp b/src/iso19111/coordinateoperation.cpp index e9d73f52..4cf1ae89 100644 --- a/src/iso19111/coordinateoperation.cpp +++ b/src/iso19111/coordinateoperation.cpp @@ -15545,149 +15545,6 @@ void CoordinateOperationFactory::Private::createOperationsBoundToCompound( // --------------------------------------------------------------------------- -static crs::CRSNNPtr -getResolvedCRS(const crs::CRSNNPtr &crs, - const CoordinateOperationContextNNPtr &context, - metadata::ExtentPtr &extentOut) { - const auto &authFactory = context->getAuthorityFactory(); - const auto &ids = crs->identifiers(); - const auto &name = crs->nameStr(); - - bool approxExtent; - extentOut = getExtentPossiblySynthetized(crs, approxExtent); - - // We try to "identify" the provided CRS with the ones of the database, - // but in a more restricted way that what identify() does. - // If we get a match from id in priority, and from name as a fallback, and - // that they are equivalent to the input CRS, then use the identified CRS. - // Even if they aren't equivalent, we update extentOut with the one of the - // identified CRS if our input one is absent/not reliable. - - const auto tryToIdentifyByName = [&crs, &name, &authFactory, approxExtent, - &extentOut]( - io::AuthorityFactory::ObjectType objectType) { - if (name != "unknown" && name != "unnamed") { - auto matches = authFactory->createObjectsFromName( - name, {objectType}, false, 2); - if (matches.size() == 1) { - const auto match = - util::nn_static_pointer_cast(matches.front()); - if (approxExtent || !extentOut) { - extentOut = getExtent(match); - } - if (match->isEquivalentTo( - crs.get(), util::IComparable::Criterion::EQUIVALENT)) { - return match; - } - } - } - return crs; - }; - - auto geogCRS = dynamic_cast(crs.get()); - if (geogCRS && authFactory) { - if (!ids.empty()) { - const auto tmpAuthFactory = io::AuthorityFactory::create( - authFactory->databaseContext(), *ids.front()->codeSpace()); - try { - auto resolvedCrs( - tmpAuthFactory->createGeographicCRS(ids.front()->code())); - if (approxExtent || !extentOut) { - extentOut = getExtent(resolvedCrs); - } - if (resolvedCrs->isEquivalentTo( - crs.get(), util::IComparable::Criterion::EQUIVALENT)) { - return util::nn_static_pointer_cast(resolvedCrs); - } - } catch (const std::exception &) { - } - } else { - return tryToIdentifyByName( - geogCRS->coordinateSystem()->axisList().size() == 2 - ? io::AuthorityFactory::ObjectType::GEOGRAPHIC_2D_CRS - : io::AuthorityFactory::ObjectType::GEOGRAPHIC_3D_CRS); - } - } - - auto projectedCrs = dynamic_cast(crs.get()); - if (projectedCrs && authFactory) { - if (!ids.empty()) { - const auto tmpAuthFactory = io::AuthorityFactory::create( - authFactory->databaseContext(), *ids.front()->codeSpace()); - try { - auto resolvedCrs( - tmpAuthFactory->createProjectedCRS(ids.front()->code())); - if (approxExtent || !extentOut) { - extentOut = getExtent(resolvedCrs); - } - if (resolvedCrs->isEquivalentTo( - crs.get(), util::IComparable::Criterion::EQUIVALENT)) { - return util::nn_static_pointer_cast(resolvedCrs); - } - } catch (const std::exception &) { - } - } else { - return tryToIdentifyByName( - io::AuthorityFactory::ObjectType::PROJECTED_CRS); - } - } - - auto compoundCrs = dynamic_cast(crs.get()); - if (compoundCrs && authFactory) { - if (!ids.empty()) { - const auto tmpAuthFactory = io::AuthorityFactory::create( - authFactory->databaseContext(), *ids.front()->codeSpace()); - try { - auto resolvedCrs( - tmpAuthFactory->createCompoundCRS(ids.front()->code())); - if (approxExtent || !extentOut) { - extentOut = getExtent(resolvedCrs); - } - if (resolvedCrs->isEquivalentTo( - crs.get(), util::IComparable::Criterion::EQUIVALENT)) { - return util::nn_static_pointer_cast(resolvedCrs); - } - } catch (const std::exception &) { - } - } else { - auto outCrs = tryToIdentifyByName( - io::AuthorityFactory::ObjectType::COMPOUND_CRS); - const auto &components = compoundCrs->componentReferenceSystems(); - if (outCrs.get() != crs.get()) { - bool hasGeoid = false; - if (components.size() == 2) { - auto vertCRS = - dynamic_cast(components[1].get()); - if (vertCRS && !vertCRS->geoidModel().empty()) { - hasGeoid = true; - } - } - if (!hasGeoid) { - return outCrs; - } - } - if (approxExtent || !extentOut) { - // If we still did not get a reliable extent, then try to - // resolve the components of the compoundCRS, and take the - // intersection of their extent. - extentOut = metadata::ExtentPtr(); - for (const auto &component : components) { - metadata::ExtentPtr componentExtent; - getResolvedCRS(component, context, componentExtent); - if (extentOut && componentExtent) - extentOut = extentOut->intersection( - NN_NO_CHECK(componentExtent)); - else if (componentExtent) - extentOut = componentExtent; - } - } - } - } - return crs; -} - -// --------------------------------------------------------------------------- - /** \brief Find a list of CoordinateOperation from sourceCRS to targetCRS. * * The operations are sorted with the most relevant ones first: by @@ -15723,13 +15580,14 @@ CoordinateOperationFactory::createOperations( const auto &targetBoundCRS = targetCRS->canonicalBoundCRS(); auto l_sourceCRS = srcBoundCRS ? NN_NO_CHECK(srcBoundCRS) : sourceCRS; auto l_targetCRS = targetBoundCRS ? NN_NO_CHECK(targetBoundCRS) : targetCRS; + const auto &authFactory = context->getAuthorityFactory(); metadata::ExtentPtr sourceCRSExtent; auto l_resolvedSourceCRS = - getResolvedCRS(l_sourceCRS, context, sourceCRSExtent); + crs::CRS::getResolvedCRS(l_sourceCRS, authFactory, sourceCRSExtent); metadata::ExtentPtr targetCRSExtent; auto l_resolvedTargetCRS = - getResolvedCRS(l_targetCRS, context, targetCRSExtent); + crs::CRS::getResolvedCRS(l_targetCRS, authFactory, targetCRSExtent); Private::Context contextPrivate(sourceCRSExtent, targetCRSExtent, context); if (context->getSourceAndTargetCRSExtentUse() == @@ -16054,4 +15912,152 @@ PROJBasedOperation::gridsNeeded(const io::DatabaseContextPtr &databaseContext, // --------------------------------------------------------------------------- } // namespace operation + +namespace crs { +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress + +crs::CRSNNPtr CRS::getResolvedCRS(const crs::CRSNNPtr &crs, + const io::AuthorityFactoryPtr &authFactory, + metadata::ExtentPtr &extentOut) { + const auto &ids = crs->identifiers(); + const auto &name = crs->nameStr(); + + bool approxExtent; + extentOut = getExtentPossiblySynthetized(crs, approxExtent); + + // We try to "identify" the provided CRS with the ones of the database, + // but in a more restricted way that what identify() does. + // If we get a match from id in priority, and from name as a fallback, and + // that they are equivalent to the input CRS, then use the identified CRS. + // Even if they aren't equivalent, we update extentOut with the one of the + // identified CRS if our input one is absent/not reliable. + + const auto tryToIdentifyByName = [&crs, &name, &authFactory, approxExtent, + &extentOut]( + io::AuthorityFactory::ObjectType objectType) { + if (name != "unknown" && name != "unnamed") { + auto matches = authFactory->createObjectsFromName( + name, {objectType}, false, 2); + if (matches.size() == 1) { + const auto match = + util::nn_static_pointer_cast(matches.front()); + if (approxExtent || !extentOut) { + extentOut = getExtent(match); + } + if (match->isEquivalentTo( + crs.get(), util::IComparable::Criterion::EQUIVALENT)) { + return match; + } + } + } + return crs; + }; + + auto geogCRS = dynamic_cast(crs.get()); + if (geogCRS && authFactory) { + if (!ids.empty()) { + const auto tmpAuthFactory = io::AuthorityFactory::create( + authFactory->databaseContext(), *ids.front()->codeSpace()); + try { + auto resolvedCrs( + tmpAuthFactory->createGeographicCRS(ids.front()->code())); + if (approxExtent || !extentOut) { + extentOut = getExtent(resolvedCrs); + } + if (resolvedCrs->isEquivalentTo( + crs.get(), util::IComparable::Criterion::EQUIVALENT)) { + return util::nn_static_pointer_cast(resolvedCrs); + } + } catch (const std::exception &) { + } + } else { + return tryToIdentifyByName( + geogCRS->coordinateSystem()->axisList().size() == 2 + ? io::AuthorityFactory::ObjectType::GEOGRAPHIC_2D_CRS + : io::AuthorityFactory::ObjectType::GEOGRAPHIC_3D_CRS); + } + } + + auto projectedCrs = dynamic_cast(crs.get()); + if (projectedCrs && authFactory) { + if (!ids.empty()) { + const auto tmpAuthFactory = io::AuthorityFactory::create( + authFactory->databaseContext(), *ids.front()->codeSpace()); + try { + auto resolvedCrs( + tmpAuthFactory->createProjectedCRS(ids.front()->code())); + if (approxExtent || !extentOut) { + extentOut = getExtent(resolvedCrs); + } + if (resolvedCrs->isEquivalentTo( + crs.get(), util::IComparable::Criterion::EQUIVALENT)) { + return util::nn_static_pointer_cast(resolvedCrs); + } + } catch (const std::exception &) { + } + } else { + return tryToIdentifyByName( + io::AuthorityFactory::ObjectType::PROJECTED_CRS); + } + } + + auto compoundCrs = dynamic_cast(crs.get()); + if (compoundCrs && authFactory) { + if (!ids.empty()) { + const auto tmpAuthFactory = io::AuthorityFactory::create( + authFactory->databaseContext(), *ids.front()->codeSpace()); + try { + auto resolvedCrs( + tmpAuthFactory->createCompoundCRS(ids.front()->code())); + if (approxExtent || !extentOut) { + extentOut = getExtent(resolvedCrs); + } + if (resolvedCrs->isEquivalentTo( + crs.get(), util::IComparable::Criterion::EQUIVALENT)) { + return util::nn_static_pointer_cast(resolvedCrs); + } + } catch (const std::exception &) { + } + } else { + auto outCrs = tryToIdentifyByName( + io::AuthorityFactory::ObjectType::COMPOUND_CRS); + const auto &components = compoundCrs->componentReferenceSystems(); + if (outCrs.get() != crs.get()) { + bool hasGeoid = false; + if (components.size() == 2) { + auto vertCRS = + dynamic_cast(components[1].get()); + if (vertCRS && !vertCRS->geoidModel().empty()) { + hasGeoid = true; + } + } + if (!hasGeoid) { + return outCrs; + } + } + if (approxExtent || !extentOut) { + // If we still did not get a reliable extent, then try to + // resolve the components of the compoundCRS, and take the + // intersection of their extent. + extentOut = metadata::ExtentPtr(); + for (const auto &component : components) { + metadata::ExtentPtr componentExtent; + getResolvedCRS(component, authFactory, componentExtent); + if (extentOut && componentExtent) + extentOut = extentOut->intersection( + NN_NO_CHECK(componentExtent)); + else if (componentExtent) + extentOut = componentExtent; + } + } + } + } + return crs; +} + +//! @endcond + +} // namespace crs NS_PROJ_END diff --git a/src/iso19111/crs.cpp b/src/iso19111/crs.cpp index edc8a71f..84b98984 100644 --- a/src/iso19111/crs.cpp +++ b/src/iso19111/crs.cpp @@ -533,8 +533,12 @@ CRSNNPtr CRS::createBoundCRSToWGS84IfPossible( auto authFactory = io::AuthorityFactory::create( NN_NO_CHECK(dbContext), authority == "any" ? std::string() : authority); + metadata::ExtentPtr extentResolved(extent); + if (!extent) { + getResolvedCRS(thisAsCRS, authFactory, extentResolved); + } auto ctxt = operation::CoordinateOperationContext::create( - authFactory, extent, 0.0); + authFactory, extentResolved, 0.0); ctxt->setAllowUseIntermediateCRS(allowIntermediateCRSUse); // ctxt->setSpatialCriterion( // operation::CoordinateOperationContext::SpatialCriterion::PARTIAL_INTERSECTION); diff --git a/test/unit/test_crs.cpp b/test/unit/test_crs.cpp index a0fee905..38afdce3 100644 --- a/test/unit/test_crs.cpp +++ b/test/unit/test_crs.cpp @@ -5796,6 +5796,31 @@ TEST(crs, crs_createBoundCRSToWGS84IfPossible) { CoordinateOperationContext::IntermediateCRSUse::NEVER), crs_5340); } + + // Check that we get the same result from an EPSG code and a CRS created + // from its WKT1 representation. + { + // Pulkovo 1942 / CS63 zone A2 + auto crs = factory->createCoordinateReferenceSystem("2936"); + + // Two candidate transformations found, so not picking up any + EXPECT_EQ(crs->createBoundCRSToWGS84IfPossible( + dbContext, + CoordinateOperationContext::IntermediateCRSUse::NEVER), + crs); + + auto wkt = crs->exportToWKT( + WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL, dbContext) + .get()); + auto obj = + WKTParser().attachDatabaseContext(dbContext).createFromWKT(wkt); + auto crs_from_wkt = nn_dynamic_pointer_cast(obj); + ASSERT_TRUE(crs_from_wkt != nullptr); + EXPECT_EQ(crs_from_wkt->createBoundCRSToWGS84IfPossible( + dbContext, + CoordinateOperationContext::IntermediateCRSUse::NEVER), + crs_from_wkt); + } } // --------------------------------------------------------------------------- -- cgit v1.2.3 From b56f39dec5464cecd7bc1dbb24042bb51e5c96e5 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Fri, 6 Nov 2020 18:10:47 +0100 Subject: COPYING: update Fixes #2415 - Change mention of PROJ.4 to PROJ - Change 'I' pronoun to Frank Warmerdam --- COPYING | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/COPYING b/COPYING index fa371748..d46f95cd 100644 --- a/COPYING +++ b/COPYING @@ -1,18 +1,19 @@ -All source, data files and other contents of the PROJ.4 package are +All source, data files and other contents of the PROJ package are available under the following terms. Note that the PROJ 4.3 and earlier was "public domain" as is common with US government work, but apparently -this is not a well defined legal term in many countries. I am placing -everything under the following MIT style license because I believe it is +this is not a well defined legal term in many countries. Frank Warmerdam placed +everything under the following MIT style license because he believed it is effectively the same as public domain, allowing anyone to use the code as -they wish, including making proprietary derivatives. +they wish, including making proprietary derivatives. -Though I have put my own name as copyright holder, I don't mean to imply -I did the work. Essentially all work was done by Gerald Evenden. +Initial PROJ 4.3 public domain code was put as Frank Warmerdam as copyright +holder, but he didn't mean to imply he did the work. Essentially all work was +done by Gerald Evenden. - -------------- +Copyright information can be found in source files. - Copyright (c) 2000, Frank Warmerdam + -------------- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -31,4 +32,3 @@ I did the work. Essentially all work was done by Gerald Evenden. 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. - -- cgit v1.2.3 From c87ace69083f9730e0ff675048c0b29f227a6853 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Fri, 6 Nov 2020 19:28:37 +0100 Subject: automake and cmake: install COPYING, NEWS and AUTHORS in /share/doc/proj --- CMakeLists.txt | 4 ++++ Makefile.am | 2 ++ cmake/ProjInstallPath.cmake | 2 +- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a75aa578..ee1444a4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -277,3 +277,7 @@ add_subdirectory(cmake) if(BUILD_TESTING) add_subdirectory(test) endif() + +set(docfiles COPYING NEWS AUTHORS) +install(FILES ${docfiles} + DESTINATION "${DOCDIR}") diff --git a/Makefile.am b/Makefile.am index 8507afe9..4f78ff32 100644 --- a/Makefile.am +++ b/Makefile.am @@ -3,6 +3,8 @@ DIST_SUBDIRS = include src man data cmake test EXTRA_DIST = CMakeLists.txt CITATION README.md +dist_doc_DATA = COPYING NEWS AUTHORS + pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = proj.pc diff --git a/cmake/ProjInstallPath.cmake b/cmake/ProjInstallPath.cmake index 4c63d658..b7f7b821 100644 --- a/cmake/ProjInstallPath.cmake +++ b/cmake/ProjInstallPath.cmake @@ -29,7 +29,7 @@ if(UNIX) set(DEFAULT_LIB_SUBDIR ${CMAKE_INSTALL_LIBDIR}) set(DEFAULT_DATA_SUBDIR ${CMAKE_INSTALL_DATAROOTDIR}/proj) set(DEFAULT_INCLUDE_SUBDIR ${CMAKE_INSTALL_INCLUDEDIR}) - set(DEFAULT_DOC_SUBDIR ${CMAKE_INSTALL_DOCDIR}) + set(DEFAULT_DOC_SUBDIR share/doc/${PROJECT_NAME_LOWER}) set(DEFAULT_CMAKE_SUBDIR ${CMAKE_INSTALL_LIBDIR}/cmake) else() # Common locations for Unix and Mac OS X -- cgit v1.2.3 From af342bf74cd154b653a0f9d931d4ca17001650b9 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Tue, 10 Nov 2020 14:08:30 +0100 Subject: Allow cct to instantiate operations via object codes or names (#2419) Running cct like cct EPSG:8366 or cct "ITRF2014 to ETRF2014 (1)" is now possible. --- docs/source/apps/cct.rst | 27 +++++++++++++++++++++++++++ src/apps/cct.cpp | 36 ++++++++++++++++++++++++++++++++---- test/cli/testcct | 12 ++++++++++++ test/cli/testcct_out.dist | 7 +++++++ 4 files changed, 78 insertions(+), 4 deletions(-) diff --git a/docs/source/apps/cct.rst b/docs/source/apps/cct.rst index 1d2aef20..df81c571 100644 --- a/docs/source/apps/cct.rst +++ b/docs/source/apps/cct.rst @@ -15,6 +15,33 @@ Synopsis **cct** [**-cIostvz** [args]] *+opt[=arg]* ... file ... +or + + **cct** [**-cIostvz** [args]] {operation_reference} file ... + +Where {operation_reference} is one of the possibilities accepted +by :c:func:`proj_create`, provided it expresses a coordinate operation + +- a proj-string, + - a WKT string, + - an object code (like "EPSG:1671" "urn:ogc:def:coordinateOperation:EPSG::1671"), + - an object name. e.g "ITRF2014 to ETRF2014 (1)". In that case as + uniqueness is not guaranteed, heuristics are applied to determine the appropriate best match. + - a OGC URN combining references for concatenated operations + (e.g. "urn:ogc:def:coordinateOperation,coordinateOperation:EPSG::3895,coordinateOperation:EPSG::1618") + - a PROJJSON string. The jsonschema is at https://proj.org/schemas/v0.2/projjson.schema.json + + .. versionadded:: 8.0.0 + + .. note:: + + Before version 8.0.0 only proj-strings could be used to instantiate + operations in :program:`cct`. + + + + + Description *********** diff --git a/src/apps/cct.cpp b/src/apps/cct.cpp index f7413872..4de3cf8e 100644 --- a/src/apps/cct.cpp +++ b/src/apps/cct.cpp @@ -77,6 +77,7 @@ Thomas Knudsen, thokn@sdfe.dk, 2016-05-25/2017-10-26 #include #include #include +#include #include "proj.h" #include "proj_internal.h" @@ -193,9 +194,8 @@ static void print(PJ_LOG_LEVEL log_level, const char *fmt, ...) { free( msg_buf ); } - int main(int argc, char **argv) { - PJ *P; + PJ *P = nullptr; PJ_COORD point; PJ_PROJ_INFO info; OPTARGS *o; @@ -292,8 +292,36 @@ int main(int argc, char **argv) { } /* Setup transformation */ - P = proj_create_argv (nullptr, o->pargc, o->pargv); - if ((nullptr==P) || (0==o->pargc)) { + if (o-> pargc == 0 && o->fargc > 0) { + /* Assume we got a auth:code combination */ + std::string input(o->fargv[0]); + auto n = input.find(":"); + if (n > 0) { + std::string auth = input.substr(0,n); + std::string code = input.substr(n+1, input.length()); + P = proj_create_from_database( + nullptr, auth.c_str(), code.c_str(), PJ_CATEGORY_COORDINATE_OPERATION, 0, nullptr + ); + } + if( P == nullptr ) { + /* if we didn't get a auth:code combo we try to see if the input matches */ + /* anything else */ + P = proj_create(nullptr, o->fargv[0]); + } + + /* If instantiating operation without +-options optargpm thinks the input is */ + /* a file, hence we move all o->fargv entries one place closer to the start */ + /* of the array. This effectively overwrites the input and only leaves a list */ + /* of files in o->fargv. */ + o->fargc = o->fargc-1; + for (int j=0; j < o->fargc; j++) { + o->fargv[j] = o->fargv[j+1]; + } + } else { + P = proj_create_argv (nullptr, o->pargc, o->pargv); + } + + if (nullptr==P) { print (PJ_LOG_ERROR, "%s: Bad transformation arguments - (%s)\n '%s -h' for help", o->progname, pj_strerrno (proj_errno(P)), o->progname); free (o); diff --git a/test/cli/testcct b/test/cli/testcct index 3fb0dd95..bbe698bd 100755 --- a/test/cli/testcct +++ b/test/cli/testcct @@ -32,6 +32,18 @@ echo "Testing cct -d 8 +proj=merc +R=1" >> ${OUT} echo "90 45" 0 | $EXE -d 8 +proj=merc +R=1 >>${OUT} echo "" >>${OUT} +echo "Test cct with object code initialization" >> ${OUT} +echo "3541657.3778 948984.2343 5201383.5231 2020.5" | $EXE EPSG:8366 >>${OUT} + +echo "Test cct with object name initialization" >> ${OUT} +echo "3541657.3778 948984.2343 5201383.5231 2020.5" | $EXE "ITRF2014 to ETRF2014 (1)" >>${OUT} + +echo "Test cct with object code initialization and file input" >> ${OUT} +echo "3541657.3778 948984.2343 5201383.5231 2020.5" >> a +echo "3541658.0000 948985.0000 5201384.0000 2020.5" >> b +$EXE EPSG:8366 a b >>${OUT} +/bin/rm a b + # do 'diff' with distribution results echo "diff ${OUT} with testcct_out.dist" diff -u ${OUT} ${TEST_CLI_DIR}/testcct_out.dist diff --git a/test/cli/testcct_out.dist b/test/cli/testcct_out.dist index 44dd6964..7788f0bb 100644 --- a/test/cli/testcct_out.dist +++ b/test/cli/testcct_out.dist @@ -1,3 +1,10 @@ Testing cct -d 8 +proj=merc +R=1 1.57079633 0.88137359 0.00000000 inf +Test cct with object code initialization + 3541657.9112 948983.7503 5201383.2482 2020.5000 +Test cct with object name initialization + 3541657.9112 948983.7503 5201383.2482 2020.5000 +Test cct with object code initialization and file input + 3541657.9112 948983.7503 5201383.2482 2020.5000 + 3541658.5334 948984.5160 5201383.7251 2020.5000 -- cgit v1.2.3 From a8be7bc87c37f802ddd480b55ba0c19613397892 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Tue, 10 Nov 2020 14:23:09 +0100 Subject: cct.rst: fix indentation --- docs/source/apps/cct.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/apps/cct.rst b/docs/source/apps/cct.rst index df81c571..8f138d92 100644 --- a/docs/source/apps/cct.rst +++ b/docs/source/apps/cct.rst @@ -22,7 +22,7 @@ or Where {operation_reference} is one of the possibilities accepted by :c:func:`proj_create`, provided it expresses a coordinate operation -- a proj-string, + - a proj-string, - a WKT string, - an object code (like "EPSG:1671" "urn:ogc:def:coordinateOperation:EPSG::1671"), - an object name. e.g "ITRF2014 to ETRF2014 (1)". In that case as -- cgit v1.2.3 From 6be4e25c66e805218c851d67157e4d1ddc0a761e Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Tue, 10 Nov 2020 14:40:17 +0100 Subject: cct: allow @filename syntax Similarly as for projinfo, allow "cct @filename" to mean read filename and use its content as if it was provided inline. Useful for WKT or PROJJSON And a tiny improvements, when the object definition contains ':', only try proj_create_from_database() if the left part (authority name) matches a known authority, to avoid a warning. --- docs/source/apps/cct.rst | 27 +++++++++++++- src/apps/cct.cpp | 47 +++++++++++++++++++++--- test/cli/testcct | 93 +++++++++++++++++++++++++++++++++++++++++++++++ test/cli/testcct_out.dist | 2 + 4 files changed, 162 insertions(+), 7 deletions(-) diff --git a/docs/source/apps/cct.rst b/docs/source/apps/cct.rst index 8f138d92..b8504b8d 100644 --- a/docs/source/apps/cct.rst +++ b/docs/source/apps/cct.rst @@ -17,9 +17,9 @@ Synopsis or - **cct** [**-cIostvz** [args]] {operation_reference} file ... + **cct** [**-cIostvz** [args]] {object_definition} file ... -Where {operation_reference} is one of the possibilities accepted +Where {object_definition} is one of the possibilities accepted by :c:func:`proj_create`, provided it expresses a coordinate operation - a proj-string, @@ -39,6 +39,15 @@ by :c:func:`proj_create`, provided it expresses a coordinate operation operations in :program:`cct`. +or + + **cct** [**-cIostvz** [args]] {object_reference} file ... + +where {object_reference} is a filename preceded by the '@' character. The +file referenced by the {object_reference} must contain a valid +{object_definition}. + + .. versionadded:: 8.0.0 @@ -185,6 +194,20 @@ Should give results comparable to the classic :program:`proj` command $ echo 12 56 100 2018.0 auxiliary data | cct +proj=merc 1335833.8895 7522963.2411 100.0000 2018.0000 auxiliary data +7. Coordinate operation referenced through its code + +.. code-block:: console + + $ echo 3541657.3778 948984.2343 5201383.5231 2020.5 | cct EPSG:8366 + 3541657.9112 948983.7503 5201383.2482 2020.5000 + +8. Coordinate operation referenced through its name + +.. code-block:: console + + $ echo 3541657.3778 948984.2343 5201383.5231 2020.5 | cct "ITRF2014 to ETRF2014 (1)" + 3541657.9112 948983.7503 5201383.2482 2020.5000 + Background ********** diff --git a/src/apps/cct.cpp b/src/apps/cct.cpp index 4de3cf8e..c482efc2 100644 --- a/src/apps/cct.cpp +++ b/src/apps/cct.cpp @@ -77,6 +77,8 @@ Thomas Knudsen, thokn@sdfe.dk, 2016-05-25/2017-10-26 #include #include #include + +#include // std::ifstream #include #include "proj.h" @@ -293,20 +295,55 @@ int main(int argc, char **argv) { /* Setup transformation */ if (o-> pargc == 0 && o->fargc > 0) { - /* Assume we got a auth:code combination */ std::string input(o->fargv[0]); + + if (!input.empty() && input[0] == '@') { + std::ifstream fs; + auto filename = input.substr(1); + fs.open(filename, std::fstream::in | std::fstream::binary); + if (!fs.is_open()) { + std::cerr << "cannot open " << filename << std::endl; + std::exit(1); + } + input.clear(); + while (!fs.eof()) { + char buffer[256]; + fs.read(buffer, sizeof(buffer)); + input.append(buffer, static_cast(fs.gcount())); + if (input.size() > 100 * 1000) { + fs.close(); + std::cerr << "too big file " << filename << std::endl; + std::exit(1); + } + } + fs.close(); + } + + /* Assume we got a auth:code combination */ auto n = input.find(":"); if (n > 0) { std::string auth = input.substr(0,n); std::string code = input.substr(n+1, input.length()); - P = proj_create_from_database( - nullptr, auth.c_str(), code.c_str(), PJ_CATEGORY_COORDINATE_OPERATION, 0, nullptr - ); + // Check that the authority matches one of the known ones + auto authorityList = proj_get_authorities_from_database(nullptr); + if( authorityList ) + { + for( auto iter = authorityList; *iter; iter++ ) + { + if( *iter == auth ) { + P = proj_create_from_database( + nullptr, auth.c_str(), code.c_str(), + PJ_CATEGORY_COORDINATE_OPERATION, 0, nullptr); + break; + } + } + proj_string_list_destroy(authorityList); + } } if( P == nullptr ) { /* if we didn't get a auth:code combo we try to see if the input matches */ /* anything else */ - P = proj_create(nullptr, o->fargv[0]); + P = proj_create(nullptr, input.c_str()); } /* If instantiating operation without +-options optargpm thinks the input is */ diff --git a/test/cli/testcct b/test/cli/testcct index bbe698bd..db7c70a9 100755 --- a/test/cli/testcct +++ b/test/cli/testcct @@ -44,6 +44,99 @@ echo "3541658.0000 948985.0000 5201384.0000 2020.5" >> b $EXE EPSG:8366 a b >>${OUT} /bin/rm a b +cat > in.wkt <> ${OUT} +echo "3541657.3778 948984.2343 5201383.5231 2020.5" | $EXE @in.wkt >>${OUT} +rm in.wkt + # do 'diff' with distribution results echo "diff ${OUT} with testcct_out.dist" diff -u ${OUT} ${TEST_CLI_DIR}/testcct_out.dist diff --git a/test/cli/testcct_out.dist b/test/cli/testcct_out.dist index 7788f0bb..353deb17 100644 --- a/test/cli/testcct_out.dist +++ b/test/cli/testcct_out.dist @@ -8,3 +8,5 @@ Test cct with object name initialization Test cct with object code initialization and file input 3541657.9112 948983.7503 5201383.2482 2020.5000 3541658.5334 948984.5160 5201383.7251 2020.5000 +Test cct with WKT in a file + 3541657.9112 948983.7503 5201383.2482 2020.5000 -- cgit v1.2.3 From b38d0143a65fff72635b95a61ed6c4c41802889e Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Wed, 11 Nov 2020 23:56:58 +0100 Subject: Polar stereographic at pole: make it return (0,0) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Due to the improved accuracy of pj_tsfn(), it no longer returns 0 when phi=90° due to the conversion in radians. Some GDAL tests are very sensitive to the pole transforming to (0,0) exactly, so add a special case for that. master only --- src/projections/stere.cpp | 5 ++++- test/gie/builtins.gie | 26 ++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/projections/stere.cpp b/src/projections/stere.cpp index abc4aa13..3fff722d 100644 --- a/src/projections/stere.cpp +++ b/src/projections/stere.cpp @@ -86,7 +86,10 @@ static PJ_XY stere_e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forwar sinphi = -sinphi; /*-fallthrough*/ case N_POLE: - xy.x = Q->akm1 * pj_tsfn (lp.phi, sinphi, P->e); + if( fabs(lp.phi - M_HALFPI) < 1e-15 ) + xy.x = 0; + else + xy.x = Q->akm1 * pj_tsfn (lp.phi, sinphi, P->e); xy.y = - xy.x * coslam; break; } diff --git a/test/gie/builtins.gie b/test/gie/builtins.gie index def30206..add5d925 100644 --- a/test/gie/builtins.gie +++ b/test/gie/builtins.gie @@ -5419,6 +5419,32 @@ accept -200 -100 expect -0.001790493 -0.000895247 +------------------------------------------------------------------------------- +operation +proj=stere +ellps=GRS80 +lat_0=90 +lat_ts=70 +------------------------------------------------------------------------------- +tolerance 1e-15m +accept 0 90 +expect 0 0 +roundtrip 1 + +tolerance 0.1 mm +accept 20 70 +expect 748315.3282 -2055979.4669 +roundtrip 1 + +------------------------------------------------------------------------------- +operation +proj=stere +ellps=GRS80 +lat_0=-90 +lat_ts=-70 +------------------------------------------------------------------------------- +tolerance 1e-15m +accept 0 -90 +expect 0 0 +roundtrip 1 + +tolerance 0.1 mm +accept 20 -70 +expect 748315.3282 2055979.4669 +roundtrip 1 + =============================================================================== # Oblique Stereographic Alternative # Azimuthal, Sph&Ell -- cgit v1.2.3 From 63f9f4e09ab26f1a52751cec15f394e88660b8bf Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Mon, 16 Nov 2020 13:57:09 +0100 Subject: WKT2 parsing: several fixes related to map projection parameter units - WKT2 grammar: accept PARAMETER[name,value,id] without unit - Recognize "Ellipsoid scaling factor" as a parameter with a scaling unit, and defaults to Unity when not specified - WKT2 parsing: implement the requirement of 18-010r7.html#80, that is when a map projection parameter has no explicit unit, use metre/degree/unity as the default unit (contrary to WKT1 parsing rules where they are deduced from the GeogCRS angular unit and coordinate system) --- src/iso19111/io.cpp | 15 +- src/wkt2_generated_parser.c | 1932 ++++++++++++++++++++++--------------------- src/wkt2_grammar.y | 1 + test/unit/test_io.cpp | 17 +- 4 files changed, 998 insertions(+), 967 deletions(-) diff --git a/src/iso19111/io.cpp b/src/iso19111/io.cpp index b2e5822b..623ad6f9 100644 --- a/src/iso19111/io.cpp +++ b/src/iso19111/io.cpp @@ -2944,7 +2944,8 @@ UnitOfMeasure WKTParser::Private::guessUnitForParameter( const UnitOfMeasure &defaultAngularUnit) { UnitOfMeasure unit; // scale must be first because of 'Scale factor on pseudo standard parallel' - if (ci_find(paramName, "scale") != std::string::npos) { + if (ci_find(paramName, "scale") != std::string::npos || + ci_find(paramName, "scaling factor") != std::string::npos) { unit = UnitOfMeasure::SCALE_UNITY; } else if (ci_find(paramName, "latitude") != std::string::npos || ci_find(paramName, "longitude") != std::string::npos || @@ -3876,8 +3877,16 @@ WKTParser::Private::buildProjectedCRS(const WKTNodeNNPtr &node) { return createPseudoMercator(props, NN_NO_CHECK(cartesianCS)); } - auto linearUnit = buildUnitInSubNode(node, UnitOfMeasure::Type::LINEAR); - auto angularUnit = baseGeodCRS->coordinateSystem()->axisList()[0]->unit(); + // For WKT2, if there is no explicit parameter unit, use metre for linear + // units and degree for angular units + auto linearUnit = + !isNull(conversionNode) + ? UnitOfMeasure::METRE + : buildUnitInSubNode(node, UnitOfMeasure::Type::LINEAR); + auto angularUnit = + !isNull(conversionNode) + ? UnitOfMeasure::DEGREE + : baseGeodCRS->coordinateSystem()->axisList()[0]->unit(); auto conversion = !isNull(conversionNode) diff --git a/src/wkt2_generated_parser.c b/src/wkt2_generated_parser.c index feb2cc6b..f7bb5798 100644 --- a/src/wkt2_generated_parser.c +++ b/src/wkt2_generated_parser.c @@ -542,16 +542,16 @@ union yyalloc /* YYFINAL -- State number of the termination state. */ #define YYFINAL 106 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 3132 +#define YYLAST 3219 /* YYNTOKENS -- Number of terminals. */ #define YYNTOKENS 164 /* YYNNTS -- Number of nonterminals. */ #define YYNNTS 353 /* YYNRULES -- Number of rules. */ -#define YYNRULES 694 +#define YYNRULES 695 /* YYNSTATES -- Number of states. */ -#define YYNSTATES 1427 +#define YYNSTATES 1429 /* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned by yylex, with out-of-bounds checking. */ @@ -658,30 +658,30 @@ static const yytype_uint16 yyrline[] = 997, 1003, 1003, 1007, 1007, 1008, 1008, 1010, 1015, 1016, 1017, 1018, 1019, 1021, 1027, 1032, 1038, 1040, 1042, 1044, 1048, 1054, 1055, 1056, 1058, 1060, 1062, 1066, 1066, 1068, - 1070, 1075, 1076, 1078, 1080, 1082, 1084, 1088, 1088, 1090, - 1096, 1103, 1103, 1106, 1113, 1114, 1115, 1116, 1117, 1119, - 1123, 1125, 1127, 1127, 1131, 1136, 1136, 1136, 1140, 1145, - 1145, 1147, 1151, 1151, 1155, 1160, 1162, 1166, 1166, 1170, - 1175, 1177, 1181, 1182, 1183, 1184, 1185, 1187, 1187, 1189, - 1192, 1194, 1194, 1196, 1198, 1200, 1204, 1210, 1211, 1212, - 1213, 1215, 1217, 1221, 1226, 1228, 1231, 1236, 1240, 1246, - 1246, 1246, 1246, 1246, 1246, 1250, 1255, 1257, 1262, 1262, - 1263, 1265, 1265, 1267, 1274, 1274, 1276, 1283, 1283, 1285, - 1292, 1299, 1304, 1305, 1306, 1308, 1314, 1319, 1327, 1333, - 1335, 1337, 1343, 1345, 1345, 1346, 1346, 1350, 1356, 1356, - 1358, 1363, 1369, 1374, 1380, 1385, 1390, 1396, 1401, 1406, - 1412, 1417, 1422, 1428, 1428, 1429, 1429, 1430, 1430, 1431, - 1431, 1432, 1432, 1433, 1433, 1436, 1436, 1438, 1439, 1440, - 1442, 1444, 1448, 1451, 1451, 1454, 1455, 1456, 1458, 1462, - 1463, 1465, 1467, 1467, 1468, 1468, 1469, 1469, 1469, 1470, - 1471, 1471, 1472, 1472, 1473, 1473, 1475, 1475, 1476, 1476, - 1477, 1478, 1478, 1482, 1486, 1487, 1490, 1495, 1496, 1497, - 1498, 1499, 1500, 1501, 1503, 1505, 1507, 1510, 1512, 1514, - 1516, 1518, 1520, 1522, 1524, 1526, 1528, 1533, 1537, 1538, - 1541, 1546, 1547, 1548, 1549, 1550, 1552, 1557, 1562, 1563, - 1566, 1572, 1572, 1572, 1572, 1574, 1575, 1576, 1577, 1579, - 1581, 1586, 1592, 1594, 1599, 1600, 1603, 1609, 1609, 1611, - 1612, 1613, 1614, 1616, 1618 + 1070, 1075, 1076, 1077, 1079, 1081, 1083, 1085, 1089, 1089, + 1091, 1097, 1104, 1104, 1107, 1114, 1115, 1116, 1117, 1118, + 1120, 1124, 1126, 1128, 1128, 1132, 1137, 1137, 1137, 1141, + 1146, 1146, 1148, 1152, 1152, 1156, 1161, 1163, 1167, 1167, + 1171, 1176, 1178, 1182, 1183, 1184, 1185, 1186, 1188, 1188, + 1190, 1193, 1195, 1195, 1197, 1199, 1201, 1205, 1211, 1212, + 1213, 1214, 1216, 1218, 1222, 1227, 1229, 1232, 1237, 1241, + 1247, 1247, 1247, 1247, 1247, 1247, 1251, 1256, 1258, 1263, + 1263, 1264, 1266, 1266, 1268, 1275, 1275, 1277, 1284, 1284, + 1286, 1293, 1300, 1305, 1306, 1307, 1309, 1315, 1320, 1328, + 1334, 1336, 1338, 1344, 1346, 1346, 1347, 1347, 1351, 1357, + 1357, 1359, 1364, 1370, 1375, 1381, 1386, 1391, 1397, 1402, + 1407, 1413, 1418, 1423, 1429, 1429, 1430, 1430, 1431, 1431, + 1432, 1432, 1433, 1433, 1434, 1434, 1437, 1437, 1439, 1440, + 1441, 1443, 1445, 1449, 1452, 1452, 1455, 1456, 1457, 1459, + 1463, 1464, 1466, 1468, 1468, 1469, 1469, 1470, 1470, 1470, + 1471, 1472, 1472, 1473, 1473, 1474, 1474, 1476, 1476, 1477, + 1477, 1478, 1479, 1479, 1483, 1487, 1488, 1491, 1496, 1497, + 1498, 1499, 1500, 1501, 1502, 1504, 1506, 1508, 1511, 1513, + 1515, 1517, 1519, 1521, 1523, 1525, 1527, 1529, 1534, 1538, + 1539, 1542, 1547, 1548, 1549, 1550, 1551, 1553, 1558, 1563, + 1564, 1567, 1573, 1573, 1573, 1573, 1575, 1576, 1577, 1578, + 1580, 1582, 1587, 1593, 1595, 1600, 1601, 1604, 1610, 1610, + 1612, 1613, 1614, 1615, 1617, 1619 }; #endif @@ -933,7 +933,7 @@ static const yytype_uint16 yytoknum[] = #define yypact_value_is_default(Yystate) \ (!!((Yystate) == (-1232))) -#define YYTABLE_NINF -633 +#define YYTABLE_NINF -634 #define yytable_value_is_error(Yytable_value) \ 0 @@ -942,149 +942,149 @@ static const yytype_uint16 yytoknum[] = STATE-NUM. */ static const yytype_int16 yypact[] = { - 2573, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, + 1574, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, - -1232, -1232, -1232, -1232, -1232, -1232, -1232, 114, -1232, -1232, - -1232, 231, -1232, -1232, -1232, 231, -1232, -1232, -1232, -1232, - -1232, -1232, 231, 231, -1232, 231, -1232, -75, 231, -1232, - 231, -1232, 231, -1232, -1232, -1232, 231, -1232, 231, -1232, - 231, -1232, 231, -1232, 231, -1232, 231, -1232, 231, -1232, - 231, -1232, -1232, -1232, -1232, -1232, -1232, -1232, 231, -1232, - -1232, -1232, -1232, -1232, -1232, 231, -1232, 231, -1232, 231, - -1232, 231, -1232, 231, -1232, 231, -1232, -1232, -1232, 33, - 33, 33, 33, 33, -1232, 81, 33, 33, 33, 33, - 33, 33, 33, 33, 33, 33, 33, 33, 33, 879, - 33, 33, 33, 117, -1232, -1232, -75, -1232, -75, -1232, - -75, -75, -1232, -75, -1232, -1232, -1232, 231, -1232, -75, - -75, -1232, -75, -75, -75, -75, -75, -75, -75, -75, - -75, -1232, -75, -1232, -75, -1232, -1232, -1232, -1232, 28, - -1232, -1232, -1232, -1232, -1232, 97, 168, 186, -1232, -1232, - -1232, -1232, 284, -1232, -75, -1232, -75, -75, -75, -1232, - -75, 231, 1038, 176, 66, 66, 713, 33, 287, 179, - 157, 766, 290, 284, 244, 284, 413, 284, 105, 286, - 284, 297, 1406, -1232, -1232, -1232, 428, 101, -1232, -1232, - 101, -1232, -1232, 101, -1232, -1232, 331, 879, -1232, -1232, - -1232, -1232, -1232, -1232, -1232, 728, -1232, -1232, -1232, -1232, - 265, 278, 293, 713, -1232, -75, -1232, -75, 231, -1232, - -1232, -1232, -1232, 231, -75, 231, -75, -1232, 231, 231, - -75, -75, -1232, -1232, -1232, -1232, -75, -75, -75, -75, - -1232, -75, -1232, -75, -75, -75, -1232, -1232, -1232, -1232, - 231, 231, -1232, -1232, -75, 231, -1232, -1232, 231, -75, - -75, -1232, -75, -1232, -1232, 231, -1232, -75, -75, 231, - -1232, -1232, -75, -75, 231, -1232, -1232, -75, -75, 231, - -1232, -1232, -75, -75, 231, -1232, -1232, -75, -75, 231, - -75, 231, -1232, -1232, -75, 231, -1232, -75, -1232, -1232, - -1232, -1232, 231, -1232, -75, 231, -75, -75, -75, -75, - -75, -1232, -75, 231, 284, -1232, 476, 728, -1232, -1232, - 387, 284, 283, 284, 284, 33, 33, 59, 404, 258, - 33, 33, 441, 441, 59, 258, 441, 441, 713, 476, - 284, 452, 33, 33, 349, 284, 33, 33, 88, 477, - 441, 33, 479, -1232, 479, 33, 477, 441, 33, 477, - 441, 33, 477, 441, 33, -1232, -1232, 682, 74, -1232, - 33, 441, 33, 1406, 728, 117, -1232, 33, 331, 117, - -1232, 487, 117, -1232, 331, 469, 879, -1232, 728, -1232, - -1232, -1232, -1232, -1232, -1232, -1232, -1232, -75, -75, 231, - -1232, 231, -1232, -1232, -75, -75, 231, -75, -1232, -1232, - -1232, -75, -75, -75, -1232, -75, 231, -1232, -1232, -1232, - -1232, -1232, -1232, 231, 284, -75, -1232, -75, -75, -1232, - -75, 231, -75, -75, 284, -75, -75, -1232, -75, -75, - 713, 284, -1232, -75, -75, -75, -1232, -75, -75, 231, - -1232, -1232, -75, -75, -75, 231, 284, -75, -75, -75, - -75, -1232, 284, 284, -75, -75, 284, -75, -75, 284, - -75, -75, -1232, -1232, 116, -1232, 284, -75, -1232, 284, - -75, -75, -75, 293, 284, -1232, 284, -75, -1232, -75, - 231, -75, -1232, -75, 231, 284, -1232, 488, 511, 33, - 33, -1232, -1232, 479, -1232, 1192, 486, 479, 284, 176, - 258, 614, 284, 728, 1482, -1232, 477, 56, 56, 477, - 33, 477, 258, -1232, 477, 477, 148, 284, 345, -1232, - -1232, -1232, 477, 56, 56, -1232, -1232, 33, 284, 176, - 477, 1503, -1232, 477, 277, -1232, -1232, -1232, -1232, 477, - -1, -1232, 477, -2, -1232, 477, 22, -1232, -1232, 728, - -1232, -1232, 728, -1232, -1232, -1232, 477, 179, 1669, 284, - 728, -1232, -1232, 487, 1210, 284, 33, 523, 1412, 284, - 33, -1232, -75, -1232, -1232, 284, -1232, 284, -1232, -75, - -1232, 284, -75, -1232, -75, -1232, -75, 284, -1232, -1232, - -1232, 231, -1232, 293, 284, -1232, -1232, -1232, -1232, -1232, - -1232, -1232, -1232, -1232, -75, -1232, -1232, -1232, -1232, -75, - -75, -75, -1232, -75, -75, -75, -75, 284, -1232, -75, - 284, 284, 284, 284, -1232, -1232, -75, -75, 231, -1232, - -1232, -1232, -75, 231, 284, -75, -75, -75, -75, -1232, - -75, -1232, -75, 284, -75, 284, -75, -75, 284, -75, - 284, -75, 284, -75, 159, 401, -1232, 767, 284, -1232, - -1232, -1232, -1232, -75, -1232, -1232, -1232, -1232, -1232, -1232, - -1232, -1232, -1232, -1232, -1232, -75, 231, -75, 231, -1232, - -75, 231, -75, 231, -75, 231, -75, 231, -75, -1232, - 231, -75, -1232, -1232, -75, -1232, -1232, -1232, 231, -75, - -75, 231, -75, 231, -1232, -1232, -75, -1232, 231, -1232, - -1232, -75, 511, -1232, -1232, -1232, -1232, -1232, -1232, 257, - -1232, 33, 728, -1232, 586, 586, 586, 586, 59, 196, - 284, 59, 284, -1232, 487, -1232, -1232, -1232, -1232, -1232, - -1232, 33, -1232, 33, -1232, 59, 141, 284, 59, 284, - 476, 631, -1232, 586, -1232, 88, 284, -1232, 284, -1232, - 284, -1232, 284, -1232, 728, -1232, -1232, 728, 728, -1232, - 415, -1232, -1232, -1232, -1232, 452, 145, 548, 528, -1232, - 33, 547, -1232, 33, 322, -1232, 1192, 325, -1232, 1192, - 267, -1232, 682, -1232, 439, -1232, 980, 284, 33, -1232, - -1232, 33, -1232, 1192, 479, 284, 282, 42, -1232, -1232, - -1232, -75, -1232, -75, -1232, -1232, -1232, -1232, -75, -75, - -75, -75, -75, -75, -75, -1232, -75, -1232, -75, -1232, - -75, -75, -75, -75, -1232, -75, -75, -1232, -75, -1232, - -1232, -75, -75, -75, -75, -1232, -1232, -1232, -1232, -1232, - 433, 415, -1232, 767, 728, -1232, -75, -1232, -75, -1232, - -75, -1232, -75, -1232, -1232, 284, -75, -75, -75, -1232, - 284, -75, -75, -1232, -75, -75, -1232, -75, -1232, -1232, - -75, -1232, 284, -1232, -1232, -75, -75, -75, 231, -75, - -1232, -75, -75, 284, -1232, -1232, -1232, -1232, -1232, -1232, - 284, -75, -75, 284, 284, 284, 284, 284, 284, -1232, - -1232, 284, 259, 284, 713, 713, 284, -1232, 345, -1232, - -1232, 284, 456, 284, 284, 284, -1232, -1232, 728, -1232, - -1232, -1232, 284, -1232, 212, -1232, -1232, 322, -1232, 325, - -1232, -1232, -1232, 325, -1232, -1232, 1192, -1232, 1192, 682, - -1232, -1232, -1232, 1052, -1232, 879, -1232, 476, 33, -1232, - -75, 167, 487, -1232, -1232, -75, -75, -75, -75, -1232, - -1232, -75, -75, -75, -1232, -1232, -75, -75, -1232, -75, - -1232, -1232, -1232, -1232, -1232, -1232, 231, -75, -1232, -75, - -1232, -1232, -1232, 1008, -1232, 284, -75, -75, -75, -1232, - -75, -75, -75, -75, -1232, -75, -1232, -75, -1232, -1232, - 284, -75, 284, -75, -1232, -75, 523, 231, -1232, -75, - -1232, 595, 595, 595, 595, -1232, -1232, -1232, 284, 284, - -1232, 33, -1232, 595, 1080, -1232, -1232, 315, 622, 553, - 325, -1232, -1232, -1232, -1232, 1192, 376, 284, -1232, -1232, - -1232, 775, 284, 231, 33, 1141, 284, -1232, -75, 231, - -75, 231, -75, -75, 231, -1232, -1232, -75, -75, 525, - 1080, -1232, -75, -75, -1232, -75, -1232, -1232, -75, -1232, - -75, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -75, - -1232, 231, -1232, 282, -75, -1232, -75, -75, -1232, 696, - -1232, 33, 688, -1232, 33, -1232, 974, -1232, 33, 713, - 1086, -1232, -1232, 622, 553, 553, -1232, 1192, 284, 33, - 284, 476, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, - -1232, -1232, -1232, -1232, -1232, 231, -1232, 231, -75, -1232, - -75, -1232, -75, -75, -75, -1232, -75, -75, -75, -1232, - -1232, -75, -75, 231, -75, -1232, -1232, -1232, -1232, 284, - -1232, -75, -75, -75, 33, 33, 1412, 2101, -1232, -1232, - 2559, -1232, 2630, 284, 478, -1232, -1232, 33, 553, -1232, - 713, 284, 1469, 284, 284, -75, -75, -1232, -1232, -1232, + -1232, -1232, -1232, -1232, -1232, -1232, -1232, 62, -1232, -1232, + -1232, 98, -1232, -1232, -1232, 98, -1232, -1232, -1232, -1232, + -1232, -1232, 98, 98, -1232, 98, -1232, -87, 98, -1232, + 98, -1232, 98, -1232, -1232, -1232, 98, -1232, 98, -1232, + 98, -1232, 98, -1232, 98, -1232, 98, -1232, 98, -1232, + 98, -1232, -1232, -1232, -1232, -1232, -1232, -1232, 98, -1232, + -1232, -1232, -1232, -1232, -1232, 98, -1232, 98, -1232, 98, + -1232, 98, -1232, 98, -1232, 98, -1232, -1232, -1232, -24, + -24, -24, -24, -24, -1232, 83, -24, -24, -24, -24, + -24, -24, -24, -24, -24, -24, -24, -24, -24, 810, + -24, -24, -24, 113, -1232, -1232, -87, -1232, -87, -1232, + -87, -87, -1232, -87, -1232, -1232, -1232, 98, -1232, -87, + -87, -1232, -87, -87, -87, -87, -87, -87, -87, -87, + -87, -1232, -87, -1232, -87, -1232, -1232, -1232, -1232, 26, + -1232, -1232, -1232, -1232, -1232, 37, 52, 179, -1232, -1232, + -1232, -1232, 360, -1232, -87, -1232, -87, -87, -87, -1232, + -87, 98, 1048, 212, 59, 59, 761, -24, 256, 138, + 156, 467, 304, 360, 203, 360, 322, 360, 217, 314, + 360, 275, 1439, -1232, -1232, -1232, 483, 69, -1232, -1232, + 69, -1232, -1232, 69, -1232, -1232, 335, 810, -1232, -1232, + -1232, -1232, -1232, -1232, -1232, 462, -1232, -1232, -1232, -1232, + 252, 265, 287, 761, -1232, -87, -1232, -87, 98, -1232, + -1232, -1232, -1232, 98, -87, 98, -87, -1232, 98, 98, + -87, -87, -1232, -1232, -1232, -1232, -87, -87, -87, -87, + -1232, -87, -1232, -87, -87, -87, -1232, -1232, -1232, -1232, + 98, 98, -1232, -1232, -87, 98, -1232, -1232, 98, -87, + -87, -1232, -87, -1232, -1232, 98, -1232, -87, -87, 98, + -1232, -1232, -87, -87, 98, -1232, -1232, -87, -87, 98, + -1232, -1232, -87, -87, 98, -1232, -1232, -87, -87, 98, + -87, 98, -1232, -1232, -87, 98, -1232, -87, -1232, -1232, + -1232, -1232, 98, -1232, -87, 98, -87, -87, -87, -87, + -87, -1232, -87, 98, 360, -1232, 416, 462, -1232, -1232, + 558, 360, 75, 360, 360, -24, -24, 78, 390, 102, + -24, -24, 413, 413, 78, 102, 413, 413, 761, 416, + 360, 466, -24, -24, 364, 360, -24, -24, 89, 477, + 413, -24, 488, -1232, 488, -24, 477, 413, -24, 477, + 413, -24, 477, 413, -24, -1232, -1232, 387, 104, -1232, + -24, 413, -24, 1439, 462, 113, -1232, -24, 335, 113, + -1232, 499, 113, -1232, 335, 461, 810, -1232, 462, -1232, + -1232, -1232, -1232, -1232, -1232, -1232, -1232, -87, -87, 98, + -1232, 98, -1232, -1232, -87, -87, 98, -87, -1232, -1232, + -1232, -87, -87, -87, -1232, -87, 98, -1232, -1232, -1232, + -1232, -1232, -1232, 98, 360, -87, -1232, -87, -87, -1232, + -87, 98, -87, -87, 360, -87, -87, -1232, -87, -87, + 761, 360, -1232, -87, -87, -87, -1232, -87, -87, 98, + -1232, -1232, -87, -87, -87, 98, 360, -87, -87, -87, + -87, -1232, 360, 360, -87, -87, 360, -87, -87, 360, + -87, -87, -1232, -1232, 159, -1232, 360, -87, -1232, 360, + -87, -87, -87, 287, 360, -1232, 360, -87, -1232, -87, + 98, -87, -1232, -87, 98, 360, -1232, 481, 486, -24, + -24, -1232, -1232, 488, -1232, 823, 479, 488, 360, 212, + 102, 517, 360, 462, 1699, -1232, 477, 112, 112, 477, + -24, 477, 102, -1232, 477, 477, 329, 360, 306, -1232, + -1232, -1232, 477, 112, 112, -1232, -1232, -24, 360, 212, + 477, 940, -1232, 477, 243, -1232, -1232, -1232, -1232, 477, + 108, -1232, 477, 192, -1232, 477, 25, -1232, -1232, 462, + -1232, -1232, 462, -1232, -1232, -1232, 477, 138, 1409, 360, + 462, -1232, -1232, 499, 1212, 360, -24, 498, 1047, 360, + -24, -1232, -87, -1232, -1232, 360, -1232, 360, -1232, -87, + -1232, 360, -87, -1232, -87, -1232, -87, 360, -1232, -1232, + -1232, 98, -1232, 287, 360, -1232, -1232, -1232, -1232, -1232, + -1232, -1232, -1232, -1232, -87, -1232, -1232, -1232, -1232, -87, + -87, -87, -1232, -87, -87, -87, -87, 360, -1232, -87, + 360, 360, 360, 360, -1232, -1232, -87, -87, 98, -1232, + -1232, -1232, -87, 98, 360, -87, -87, -87, -87, -1232, + -87, -1232, -87, 360, -87, 360, -87, -87, 360, -87, + 360, -87, 360, -87, 205, 427, -1232, 497, 360, -1232, + -1232, -1232, -1232, -87, -1232, -1232, -1232, -1232, -1232, -1232, + -1232, -1232, -1232, -1232, -1232, -87, 98, -87, 98, -1232, + -87, 98, -87, 98, -87, 98, -87, 98, -87, -1232, + 98, -87, -1232, -1232, -87, -1232, -1232, -1232, 98, -87, + -87, 98, -87, 98, -1232, -1232, -87, -1232, 98, -1232, + -1232, -87, 486, -1232, -1232, -1232, -1232, -1232, -1232, 117, + -1232, -24, 462, -1232, 398, 398, 398, 398, 78, 100, + 360, 78, 360, -1232, 499, -1232, -1232, -1232, -1232, -1232, + -1232, -24, -1232, -24, -1232, 78, 58, 360, 78, 360, + 416, 518, -1232, 398, -1232, 89, 360, -1232, 360, -1232, + 360, -1232, 360, -1232, 462, -1232, -1232, 462, 462, -1232, + 430, -1232, -1232, -1232, -1232, 466, 176, 566, 530, -1232, + -24, 547, -1232, -24, 425, -1232, 823, 281, -1232, 823, + 333, -1232, 387, -1232, 469, -1232, 1134, 360, -24, -1232, + -1232, -24, -1232, 823, 488, 360, 267, 47, -1232, -1232, + -1232, -87, -1232, -87, -1232, -1232, -1232, -1232, -87, -87, + -87, -87, -87, -87, -87, -1232, -87, -1232, -87, -1232, + -87, -87, -87, -87, -1232, -87, -87, -1232, -87, -1232, + -1232, -87, -87, -87, -87, -1232, -1232, -1232, -1232, -1232, + 465, 430, -1232, 497, 462, -1232, -87, -1232, -87, -1232, + -87, -1232, -87, -1232, -1232, 360, -87, -87, -87, -1232, + 360, -87, -87, -1232, -87, -87, -1232, -87, -1232, -1232, + -87, -1232, 360, -1232, -1232, -87, -87, -87, 98, -87, + -1232, -87, -87, 360, -1232, -1232, -1232, -1232, -1232, -1232, + 360, -87, -87, 360, 360, 360, 360, 360, 360, -1232, + -1232, 360, 103, 360, 761, 761, 360, -1232, 306, -1232, + -1232, 360, 746, 360, 360, 360, -1232, -1232, 462, -1232, + -1232, -1232, 360, -1232, 338, -1232, -1232, 425, -1232, 281, + -1232, -1232, -1232, 281, -1232, -1232, 823, -1232, 823, 387, + -1232, -1232, -1232, 1054, -1232, 810, -1232, 416, -24, -1232, + -87, 168, 499, -1232, -1232, -87, -87, -87, -87, -1232, + -1232, -87, -87, -87, -1232, -1232, -87, -87, -1232, -87, + -1232, -1232, -1232, -1232, -1232, -87, -1232, 98, -87, -1232, + -87, -1232, -1232, -1232, 681, -1232, 360, -87, -87, -87, + -1232, -87, -87, -87, -87, -1232, -87, -1232, -87, -1232, + -1232, 360, -87, 360, -87, -1232, -87, 498, 98, -1232, + -87, -1232, 623, 623, 623, 623, -1232, -1232, -1232, 360, + 360, -1232, -1232, -24, -1232, 623, 811, -1232, -1232, 199, + 535, 579, 281, -1232, -1232, -1232, -1232, 823, 372, 360, + -1232, -1232, -1232, 297, 360, 98, -24, 1415, 360, -1232, + -87, 98, -87, 98, -87, -87, 98, -1232, -1232, -87, + -87, 370, 811, -1232, -87, -87, -1232, -87, -1232, -1232, + -87, -1232, -87, -1232, -1232, -1232, -1232, -1232, -1232, -1232, + -1232, -87, -1232, 98, -1232, 267, -87, -1232, -87, -87, + -1232, 1348, -1232, -24, 1001, -1232, -24, -1232, 711, -1232, + -24, 761, 1104, -1232, -1232, 535, 579, 579, -1232, 823, + 360, -24, 360, 416, -1232, -1232, -1232, -1232, -1232, -1232, + -1232, -1232, -1232, -1232, -1232, -1232, -1232, 98, -1232, 98, + -87, -1232, -87, -1232, -87, -87, -87, -1232, -87, -87, + -87, -1232, -1232, -87, -87, 98, -87, -1232, -1232, -1232, + -1232, 360, -1232, -87, -87, -87, -24, -24, 1047, 2503, + -1232, -1232, 2115, -1232, 2716, 360, 1527, -1232, -1232, -24, + 579, -1232, 761, 360, 1340, 360, 360, -87, -87, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, - -1232, -1232, -1232, -1232, -75, -75, -75, -75, -75, 284, - -1232, -75, -75, -75, -75, -75, 284, -1232, -75, -1232, - -75, -1232, -75, -1232, -75, -1232, -1232, -75, 231, -1232, - -1232, 713, 284, 55, 284, 563, 563, 723, 723, -1232, - 741, 457, 563, 593, 593, -1232, 530, -1232, 284, -1232, - -1232, 282, -75, -1232, -1232, -75, -75, -1232, -75, 231, - -1232, -1232, -75, -75, -1232, -75, 231, -75, -1232, -1232, - -75, -75, -1232, -75, 231, -75, -1232, -75, -75, -1232, - -75, -75, -1232, -75, -75, -1232, -75, -1232, -75, -75, - -1232, -75, -1232, -75, -1232, 284, 284, -1232, -1232, 92, - -1232, 728, -1232, -1232, 741, -1232, 1192, 763, -1232, -1232, - -1232, 741, -1232, 1192, 763, -1232, -1232, -1232, 763, -1232, - -1232, 530, -1232, -1232, -1232, 530, -1232, -1232, -1232, -1232, - -75, -1232, -75, 284, -75, -75, -75, -75, -75, -75, - 284, -75, -75, -75, -75, -1232, -1232, -1232, -1232, 763, - -1232, 577, -1232, -1232, 763, -1232, -1232, -1232, -1232, -1232, - -1232, -75, 284, -75, -1232, -1232, -1232 + -1232, -1232, -1232, -1232, -1232, -1232, -87, -87, -87, -87, + -87, 360, -1232, -87, -87, -87, -87, -87, 360, -1232, + -87, -1232, -87, -1232, -87, -1232, -87, -1232, -1232, -87, + 98, -1232, -1232, 761, 360, 272, 360, 679, 679, 710, + 710, -1232, 870, 412, 679, 494, 494, -1232, 336, -1232, + 360, -1232, -1232, 267, -87, -1232, -1232, -87, -87, -1232, + -87, 98, -1232, -1232, -87, -87, -1232, -87, 98, -87, + -1232, -1232, -87, -87, -1232, -87, 98, -87, -1232, -87, + -87, -1232, -87, -87, -1232, -87, -87, -1232, -87, -1232, + -87, -87, -1232, -87, -1232, -87, -1232, 360, 360, -1232, + -1232, 74, -1232, 462, -1232, -1232, 870, -1232, 823, 475, + -1232, -1232, -1232, 870, -1232, 823, 475, -1232, -1232, -1232, + 475, -1232, -1232, 336, -1232, -1232, -1232, 336, -1232, -1232, + -1232, -1232, -87, -1232, -87, 360, -87, -87, -87, -87, + -87, -87, 360, -87, -87, -87, -87, -1232, -1232, -1232, + -1232, 475, -1232, 438, -1232, -1232, 475, -1232, -1232, -1232, + -1232, -1232, -1232, -87, 360, -87, -1232, -1232, -1232 }; /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. @@ -1092,190 +1092,190 @@ static const yytype_int16 yypact[] = means the default is an error. */ static const yytype_uint16 yydefact[] = { - 0, 419, 406, 395, 405, 161, 431, 454, 397, 482, - 485, 600, 644, 679, 682, 507, 500, 356, 559, 492, - 489, 497, 495, 611, 666, 396, 421, 432, 398, 420, - 483, 487, 486, 508, 493, 490, 498, 0, 4, 5, - 2, 0, 13, 346, 347, 0, 583, 385, 383, 384, - 386, 387, 0, 0, 3, 0, 12, 416, 0, 585, - 0, 11, 0, 587, 467, 468, 0, 14, 0, 589, - 0, 15, 0, 591, 0, 16, 0, 593, 0, 17, - 0, 584, 540, 538, 539, 541, 542, 586, 0, 588, - 590, 592, 594, 19, 18, 0, 7, 0, 8, 0, + 0, 419, 406, 395, 405, 161, 431, 454, 397, 483, + 486, 601, 645, 680, 683, 508, 501, 356, 560, 493, + 490, 498, 496, 612, 667, 396, 421, 432, 398, 420, + 484, 488, 487, 509, 494, 491, 499, 0, 4, 5, + 2, 0, 13, 346, 347, 0, 584, 385, 383, 384, + 386, 387, 0, 0, 3, 0, 12, 416, 0, 586, + 0, 11, 0, 588, 468, 469, 0, 14, 0, 590, + 0, 15, 0, 592, 0, 16, 0, 594, 0, 17, + 0, 585, 541, 539, 540, 542, 543, 587, 0, 589, + 591, 593, 595, 19, 18, 0, 7, 0, 8, 0, 9, 0, 10, 0, 6, 0, 1, 73, 74, 0, 0, 0, 0, 0, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 78, 162, 0, 357, 0, 394, 0, 0, 407, 0, 411, 412, 417, 0, 422, 0, 0, 455, 0, 0, 423, 0, 423, 0, 423, 0, - 502, 560, 0, 601, 0, 612, 626, 613, 627, 614, - 615, 629, 616, 617, 618, 619, 620, 621, 622, 623, - 624, 625, 0, 609, 0, 645, 0, 0, 0, 650, + 503, 561, 0, 602, 0, 613, 627, 614, 628, 615, + 616, 630, 617, 618, 619, 620, 621, 622, 623, 624, + 625, 626, 0, 610, 0, 646, 0, 0, 0, 651, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 75, 76, 608, 0, 0, 633, 635, - 0, 657, 659, 0, 667, 669, 0, 0, 40, 20, + 0, 0, 0, 75, 76, 609, 0, 0, 634, 636, + 0, 658, 660, 0, 668, 670, 0, 0, 40, 20, 37, 38, 39, 41, 42, 0, 163, 21, 22, 26, 0, 25, 35, 0, 164, 154, 361, 0, 0, 446, 447, 369, 400, 0, 0, 0, 0, 399, 0, 0, - 0, 0, 544, 547, 545, 548, 0, 0, 0, 0, + 0, 0, 545, 548, 546, 549, 0, 0, 0, 0, 408, 0, 413, 0, 423, 0, 433, 434, 435, 436, - 0, 0, 458, 457, 451, 0, 572, 472, 0, 0, - 0, 471, 0, 568, 569, 0, 428, 190, 424, 0, - 484, 575, 0, 0, 0, 491, 578, 0, 0, 0, - 496, 581, 0, 0, 0, 514, 510, 190, 190, 0, - 190, 0, 501, 562, 0, 0, 595, 0, 596, 603, - 604, 610, 0, 647, 0, 0, 0, 0, 0, 0, - 0, 652, 0, 0, 0, 34, 27, 0, 33, 23, + 0, 0, 458, 457, 451, 0, 573, 473, 0, 0, + 0, 472, 0, 569, 570, 0, 428, 190, 424, 0, + 485, 576, 0, 0, 0, 492, 579, 0, 0, 0, + 497, 582, 0, 0, 0, 515, 511, 190, 190, 0, + 190, 0, 502, 563, 0, 0, 596, 0, 597, 604, + 605, 611, 0, 648, 0, 0, 0, 0, 0, 0, + 0, 653, 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, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 425, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 506, 505, 0, 0, 503, - 0, 0, 0, 0, 0, 0, 634, 0, 0, 0, - 658, 0, 0, 668, 0, 0, 0, 649, 0, 29, + 0, 0, 0, 0, 0, 507, 506, 0, 0, 504, + 0, 0, 0, 0, 0, 0, 635, 0, 0, 0, + 659, 0, 0, 669, 0, 0, 0, 650, 0, 29, 31, 28, 36, 168, 171, 165, 166, 155, 158, 0, 160, 0, 153, 365, 0, 351, 0, 0, 348, 353, 362, 359, 0, 0, 371, 375, 0, 223, 393, 204, - 205, 206, 207, 0, 0, 0, 448, 0, 0, 521, + 205, 206, 207, 0, 0, 0, 448, 0, 0, 522, 0, 0, 0, 0, 0, 0, 0, 409, 402, 190, - 0, 0, 418, 0, 0, 0, 463, 190, 451, 0, + 0, 0, 418, 0, 0, 0, 464, 190, 451, 0, 450, 459, 190, 0, 0, 0, 0, 0, 0, 190, 190, 429, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 50, 511, 48, 512, 0, 190, 515, 0, - 0, 0, 597, 605, 0, 648, 0, 0, 524, 661, - 0, 0, 693, 80, 0, 0, 32, 0, 0, 0, + 0, 0, 50, 512, 48, 513, 0, 190, 516, 0, + 0, 0, 598, 606, 0, 649, 0, 0, 525, 662, + 0, 0, 694, 80, 0, 0, 32, 0, 0, 0, 0, 350, 355, 0, 354, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 388, 0, 0, 0, 0, 0, 0, 0, 390, 0, 0, 0, 0, 0, 415, 24, 410, 0, 0, 0, 452, 453, 0, 0, 0, - 0, 0, 469, 0, 0, 191, 426, 427, 488, 0, - 0, 494, 0, 0, 499, 0, 0, 44, 58, 0, - 45, 49, 0, 509, 504, 513, 0, 0, 0, 0, - 606, 602, 646, 0, 0, 0, 0, 0, 0, 0, - 0, 651, 156, 159, 169, 0, 172, 0, 367, 351, + 0, 0, 470, 0, 0, 191, 426, 427, 489, 0, + 0, 495, 0, 0, 500, 0, 0, 44, 58, 0, + 45, 49, 0, 510, 505, 514, 0, 0, 0, 0, + 607, 603, 647, 0, 0, 0, 0, 0, 0, 0, + 0, 652, 156, 159, 169, 0, 172, 0, 367, 351, 366, 0, 351, 363, 359, 358, 0, 0, 380, 381, 376, 0, 368, 372, 0, 224, 225, 226, 227, 228, 229, 230, 231, 232, 0, 233, 234, 235, 236, 0, - 0, 0, 392, 0, 552, 0, 552, 0, 522, 0, + 0, 0, 392, 0, 553, 0, 553, 0, 523, 0, 0, 0, 0, 0, 199, 198, 190, 190, 0, 401, - 197, 196, 190, 0, 0, 0, 438, 0, 438, 464, + 197, 196, 190, 0, 0, 0, 438, 0, 438, 465, 0, 456, 0, 0, 0, 0, 0, 190, 0, 190, - 0, 190, 0, 190, 48, 0, 59, 0, 0, 563, - 564, 565, 566, 0, 174, 100, 133, 136, 144, 148, - 98, 599, 82, 88, 89, 93, 0, 85, 0, 92, + 0, 190, 0, 190, 48, 0, 59, 0, 0, 564, + 565, 566, 567, 0, 174, 100, 133, 136, 144, 148, + 98, 600, 82, 88, 89, 93, 0, 85, 0, 92, 85, 0, 85, 0, 85, 0, 85, 0, 85, 84, - 0, 597, 582, 607, 637, 536, 656, 665, 0, 661, - 661, 0, 80, 0, 660, 525, 378, 680, 0, 81, - 681, 0, 0, 167, 170, 352, 364, 349, 360, 0, + 0, 598, 583, 608, 638, 537, 657, 666, 0, 662, + 662, 0, 80, 0, 661, 526, 378, 681, 0, 81, + 682, 0, 0, 167, 170, 352, 364, 349, 360, 0, 389, 0, 373, 370, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 543, 0, 546, 391, 549, 550, 404, + 0, 0, 0, 544, 0, 547, 391, 550, 551, 404, 403, 0, 414, 0, 430, 0, 0, 0, 0, 0, - 27, 0, 470, 0, 567, 0, 0, 573, 0, 576, - 0, 579, 0, 46, 0, 43, 68, 0, 0, 53, - 71, 55, 66, 67, 558, 0, 0, 0, 0, 91, + 27, 0, 471, 0, 568, 0, 0, 574, 0, 577, + 0, 580, 0, 46, 0, 43, 68, 0, 0, 53, + 71, 55, 66, 67, 559, 0, 0, 0, 0, 91, 0, 0, 117, 0, 0, 118, 0, 0, 119, 0, - 0, 120, 0, 83, 0, 598, 0, 0, 0, 662, - 663, 0, 664, 0, 0, 0, 0, 0, 683, 685, + 0, 120, 0, 83, 0, 599, 0, 0, 0, 663, + 664, 0, 665, 0, 0, 0, 0, 0, 684, 686, 157, 0, 382, 378, 374, 237, 238, 239, 190, 190, - 190, 190, 552, 190, 190, 551, 552, 556, 517, 202, + 190, 190, 553, 190, 190, 552, 553, 557, 518, 202, 0, 0, 438, 190, 449, 190, 190, 437, 438, 444, - 465, 461, 0, 190, 190, 570, 574, 577, 580, 52, + 466, 461, 0, 190, 190, 571, 575, 578, 581, 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, 654, 643, 637, 637, 80, 0, 80, - 636, 0, 0, 0, 379, 523, 673, 674, 671, 672, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 554, - 553, 0, 0, 0, 0, 0, 0, 442, 0, 439, + 0, 79, 0, 655, 644, 638, 638, 80, 0, 80, + 637, 0, 0, 0, 379, 524, 674, 675, 672, 673, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 555, + 554, 0, 0, 0, 0, 0, 0, 442, 0, 439, 441, 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, 638, 639, 0, 640, 0, 642, 27, 0, 655, - 0, 0, 0, 684, 377, 0, 0, 0, 0, 555, - 557, 190, 517, 517, 516, 203, 190, 190, 443, 190, - 445, 188, 186, 185, 187, 466, 0, 190, 460, 0, - 571, 64, 56, 0, 561, 0, 102, 103, 104, 105, - 85, 85, 85, 85, 138, 0, 146, 142, 151, 152, - 0, 80, 0, 0, 537, 378, 0, 0, 688, 689, - 687, 0, 0, 0, 0, 520, 518, 519, 0, 0, - 440, 0, 462, 0, 0, 63, 97, 0, 0, 0, - 0, 127, 128, 129, 130, 0, 0, 0, 147, 641, - 653, 0, 0, 0, 0, 0, 0, 243, 214, 0, - 209, 0, 80, 220, 0, 192, 189, 0, 474, 65, - 0, 61, 106, 107, 108, 109, 110, 111, 85, 139, - 0, 143, 141, 534, 529, 530, 531, 532, 533, 378, - 527, 0, 535, 0, 0, 692, 689, 689, 686, 0, - 213, 0, 0, 208, 0, 218, 0, 219, 0, 0, - 0, 473, 62, 0, 0, 0, 131, 0, 0, 0, - 0, 27, 691, 690, 183, 180, 179, 182, 200, 181, - 201, 217, 345, 175, 177, 0, 176, 0, 215, 244, - 0, 212, 209, 80, 0, 222, 220, 0, 190, 480, - 478, 80, 80, 0, 112, 113, 114, 115, 140, 0, - 526, 194, 675, 190, 0, 0, 0, 0, 211, 210, - 0, 221, 0, 0, 0, 475, 477, 0, 0, 135, - 0, 0, 0, 0, 0, 0, 194, 216, 303, 304, - 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, - 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, - 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, - 335, 336, 337, 338, 297, 246, 248, 250, 252, 0, - 245, 270, 277, 279, 281, 283, 0, 276, 293, 184, - 80, 481, 378, 116, 190, 528, 678, 80, 0, 670, - 694, 0, 0, 0, 0, 0, 0, 0, 0, 240, - 0, 0, 0, 0, 0, 242, 0, 476, 0, 195, - 677, 0, 190, 193, 344, 190, 190, 298, 190, 0, - 241, 340, 190, 190, 247, 190, 0, 190, 249, 342, - 190, 190, 251, 190, 0, 190, 253, 190, 190, 271, - 190, 190, 278, 190, 190, 280, 190, 282, 190, 190, - 284, 190, 294, 190, 479, 0, 0, 299, 302, 0, - 300, 0, 254, 261, 0, 258, 0, 0, 260, 262, - 269, 0, 266, 0, 0, 268, 272, 275, 0, 273, - 285, 0, 287, 288, 289, 0, 291, 292, 295, 296, - 675, 178, 190, 0, 190, 190, 0, 190, 190, 190, - 0, 190, 190, 190, 190, 676, 301, 343, 257, 0, - 255, 0, 259, 265, 0, 263, 341, 267, 274, 286, - 290, 190, 0, 190, 256, 339, 264 + 173, 639, 640, 0, 641, 0, 643, 27, 0, 656, + 0, 0, 0, 685, 377, 0, 0, 0, 0, 556, + 558, 190, 518, 518, 517, 203, 190, 190, 443, 190, + 445, 188, 186, 185, 187, 190, 467, 0, 190, 460, + 0, 572, 64, 56, 0, 562, 0, 102, 103, 104, + 105, 85, 85, 85, 85, 138, 0, 146, 142, 151, + 152, 0, 80, 0, 0, 538, 378, 0, 0, 689, + 690, 688, 0, 0, 0, 0, 521, 519, 520, 0, + 0, 440, 462, 0, 463, 0, 0, 63, 97, 0, + 0, 0, 0, 127, 128, 129, 130, 0, 0, 0, + 147, 642, 654, 0, 0, 0, 0, 0, 0, 243, + 214, 0, 209, 0, 80, 220, 0, 192, 189, 0, + 475, 65, 0, 61, 106, 107, 108, 109, 110, 111, + 85, 139, 0, 143, 141, 535, 530, 531, 532, 533, + 534, 378, 528, 0, 536, 0, 0, 693, 690, 690, + 687, 0, 213, 0, 0, 208, 0, 218, 0, 219, + 0, 0, 0, 474, 62, 0, 0, 0, 131, 0, + 0, 0, 0, 27, 692, 691, 183, 180, 179, 182, + 200, 181, 201, 217, 345, 175, 177, 0, 176, 0, + 215, 244, 0, 212, 209, 80, 0, 222, 220, 0, + 190, 481, 479, 80, 80, 0, 112, 113, 114, 115, + 140, 0, 527, 194, 676, 190, 0, 0, 0, 0, + 211, 210, 0, 221, 0, 0, 0, 476, 478, 0, + 0, 135, 0, 0, 0, 0, 0, 0, 194, 216, + 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, + 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, + 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, + 333, 334, 335, 336, 337, 338, 297, 246, 248, 250, + 252, 0, 245, 270, 277, 279, 281, 283, 0, 276, + 293, 184, 80, 482, 378, 116, 190, 529, 679, 80, + 0, 671, 695, 0, 0, 0, 0, 0, 0, 0, + 0, 240, 0, 0, 0, 0, 0, 242, 0, 477, + 0, 195, 678, 0, 190, 193, 344, 190, 190, 298, + 190, 0, 241, 340, 190, 190, 247, 190, 0, 190, + 249, 342, 190, 190, 251, 190, 0, 190, 253, 190, + 190, 271, 190, 190, 278, 190, 190, 280, 190, 282, + 190, 190, 284, 190, 294, 190, 480, 0, 0, 299, + 302, 0, 300, 0, 254, 261, 0, 258, 0, 0, + 260, 262, 269, 0, 266, 0, 0, 268, 272, 275, + 0, 273, 285, 0, 287, 288, 289, 0, 291, 292, + 295, 296, 676, 178, 190, 0, 190, 190, 0, 190, + 190, 190, 0, 190, 190, 190, 190, 677, 301, 343, + 257, 0, 255, 0, 259, 265, 0, 263, 341, 267, + 274, 286, 290, 190, 0, 190, 256, 339, 264 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int16 yypgoto[] = { - -1232, -1232, -1232, -222, -226, -189, -1232, 247, -195, 289, - -1232, -1232, -1232, -1232, -1232, -1232, -196, -342, -662, -56, - -783, -637, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -569, - -252, -1232, -1232, -1232, -849, -1232, -1232, -247, 1222, 1220, - -57, 1263, -1232, -708, -589, -607, -1232, -1232, -169, -1232, - -1232, -168, -1232, -1232, -1232, -167, -321, -1232, -1232, -791, - -1232, -1232, -1232, -1232, -1232, -788, -1232, -1232, -1232, -1232, - -655, -1232, -1232, -1232, 108, -1232, -1232, -1232, -1232, -1232, - 130, -1232, -1232, -503, -1232, -1232, -489, -1232, -1232, -1222, - -1232, -1232, -1232, -1232, -552, 1709, -427, -1231, -565, -1232, - -1232, -1232, -746, -909, -36, -1232, -516, -1232, -1232, -1232, - -1232, -518, -334, 99, -1232, -1232, -315, -1007, -385, -466, - -1008, -980, -1232, -942, -614, -1232, -1232, -1232, -1232, -600, - -1232, -1232, -1232, -1232, -606, -611, -1232, -583, -1232, -776, - -1232, -761, -1232, 711, -412, -190, 514, -417, 29, -245, - -310, 107, -1232, -1232, -1232, 193, -1232, -110, -1232, -77, - -1232, -1232, -1232, -1232, -1232, -1232, -835, -1232, -1232, -1232, - -1232, 635, 637, 638, 640, -283, 531, -1232, -1232, -91, - 41, -1232, -1232, -1232, -1232, -1232, -107, -1232, -1232, -1232, - -1232, 10, -1232, 502, -104, -1232, -1232, -1232, 642, -1232, - -1232, -1232, -620, -1232, -1232, -1232, 580, 584, 510, -174, - 2, 312, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -367, - -798, -966, -1232, -1232, 662, 671, -1232, 232, -1232, -411, - -1232, -1232, -1232, -182, -1232, 675, -1232, -178, -1232, 677, - -1232, -186, -1232, 679, -1232, -187, -1232, -1232, 414, -1232, - -1232, -1232, -1232, -1232, 969, -289, -1232, -1232, -379, -1232, - -1232, -785, -1232, -1232, -1232, -775, -1232, -1232, 687, -1232, - -1232, 625, -1232, 628, -1232, -1232, 230, -618, 234, 241, - 242, 699, -1232, -1232, -1232, -1232, -1232, 717, -1232, -1232, - -1232, -1232, 718, -1232, -1232, 719, -1232, -1232, 727, -1232, - -1232, 738, -188, -344, 109, -1232, -1232, -1232, -1232, -1232, - -1232, -1232, -1232, -1232, -1232, 842, -1232, 539, -179, -1232, - -119, -209, -1232, -1232, -86, -1232, 115, -1232, -1232, -1232, - -808, -1232, -1232, -1232, 549, 16, 887, -1232, -1232, 551, - -1083, -502, -1232, -988, 892, -1232, -1232, -1232, -49, -1232, - -375, -1232, -200 + -1232, -1232, -1232, -221, -226, -189, -1232, 266, -194, 293, + -1232, -1232, -1232, -1232, -1232, -1232, -196, -341, -654, -53, + -782, -642, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -563, + -250, -1232, -1232, -1232, -847, -1232, -1232, -237, 1251, 1249, + -57, 1948, -1232, -665, -567, -574, -1232, -1232, -157, -1232, + -1232, -156, -1232, -1232, -1232, -154, -306, -1232, -1232, -791, + -1232, -1232, -1232, -1232, -1232, -783, -1232, -1232, -1232, -1232, + -657, -1232, -1232, -1232, 110, -1232, -1232, -1232, -1232, -1232, + 143, -1232, -1232, -505, -1232, -1232, -473, -1232, -1232, -1231, + -1232, -1232, -1232, -1232, -557, 1794, -410, -1201, -544, -1232, + -1232, -1232, -748, -930, -37, -1232, -497, -1232, -1232, -1232, + -1232, -500, -334, 124, -1232, -1232, -290, -1018, -364, -446, + -1004, -578, -1232, -852, -597, -1232, -1232, -1232, -1232, -602, + -1232, -1232, -1232, -1232, -729, -588, -1232, -701, -1232, -556, + -1232, -724, -1232, 716, -416, -148, 519, -419, 36, -102, + -326, 101, -1232, -1232, -1232, 188, -1232, -117, -1232, -67, + -1232, -1232, -1232, -1232, -1232, -1232, -836, -1232, -1232, -1232, + -1232, 600, 604, 605, 607, -280, 663, -1232, -1232, -91, + 42, -1232, -1232, -1232, -1232, -1232, -107, -1232, -1232, -1232, + -1232, 10, -1232, 506, -105, -1232, -1232, -1232, 609, -1232, + -1232, -1232, -644, -1232, -1232, -1232, 546, 552, 527, -204, + 4, 277, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -367, + -794, -938, -1232, -1232, 627, 633, -1232, 197, -1232, -448, + -1232, -1232, -1232, -192, -1232, 640, -1232, -185, -1232, 641, + -1232, -186, -1232, 644, -1232, -187, -1232, -1232, 378, -1232, + -1232, -1232, -1232, -1232, 540, -406, -1232, -1232, -384, -1232, + -1232, -781, -1232, -1232, -1232, -796, -1232, -1232, 648, -1232, + -1232, 588, -1232, 590, -1232, -1232, 190, -624, 193, 194, + 195, 660, -1232, -1232, -1232, -1232, -1232, 671, -1232, -1232, + -1232, -1232, 672, -1232, -1232, 673, -1232, -1232, 674, -1232, + -1232, 675, -179, -349, 76, -1232, -1232, -1232, -1232, -1232, + -1232, -1232, -1232, -1232, -1232, 806, -1232, 478, -253, -1232, + -119, -209, -1232, -1232, -109, -1232, 81, -1232, -1232, -1232, + -814, -1232, -1232, -1232, 489, -64, 816, -1232, -1232, 484, + -1087, -552, -1232, -1001, 842, -1232, -1232, -1232, -96, -1232, + -458, -1232, -249 }; /* YYDEFGOTO[NTERM-NUM]. */ @@ -1284,18 +1284,18 @@ static const yytype_int16 yydefgoto[] = -1, 37, 38, 39, 235, 620, 237, 880, 238, 470, 239, 240, 419, 420, 241, 348, 242, 243, 894, 589, 503, 590, 504, 695, 890, 591, 809, 969, 592, 810, - 893, 1032, 1033, 1110, 811, 812, 813, 895, 109, 215, + 893, 1033, 1034, 1112, 811, 812, 813, 895, 109, 215, 382, 456, 922, 609, 749, 819, 712, 713, 714, 715, - 716, 717, 718, 905, 1035, 719, 720, 721, 910, 722, - 723, 914, 1045, 1120, 1199, 724, 1087, 725, 917, 1047, - 726, 727, 920, 1050, 489, 351, 41, 136, 245, 427, - 428, 429, 615, 430, 431, 617, 729, 730, 1172, 1173, - 1174, 1175, 1025, 1026, 874, 383, 667, 1176, 1221, 673, - 668, 1177, 870, 1016, 448, 449, 1143, 450, 1140, 451, - 452, 1147, 453, 649, 650, 651, 858, 1100, 1098, 1103, - 1101, 1180, 1269, 1324, 1332, 1270, 1339, 1276, 1342, 1347, - 1277, 1352, 1294, 1317, 1264, 1325, 1326, 1333, 1334, 1327, - 1319, 1178, 42, 252, 353, 534, 44, 354, 253, 138, + 716, 717, 718, 905, 1036, 719, 720, 721, 910, 722, + 723, 914, 1046, 1122, 1201, 724, 1089, 725, 917, 1048, + 726, 727, 920, 1051, 489, 351, 41, 136, 245, 427, + 428, 429, 615, 430, 431, 617, 729, 730, 1174, 1175, + 1176, 1177, 1026, 1027, 874, 383, 667, 1178, 1223, 673, + 668, 1179, 870, 1016, 448, 449, 1145, 450, 1142, 451, + 452, 1149, 453, 649, 650, 651, 858, 1102, 1100, 1105, + 1103, 1182, 1271, 1326, 1334, 1272, 1341, 1278, 1344, 1349, + 1279, 1354, 1296, 1319, 1266, 1327, 1328, 1335, 1336, 1329, + 1321, 1180, 42, 252, 353, 534, 44, 354, 253, 138, 247, 538, 248, 441, 624, 435, 436, 621, 619, 254, 255, 445, 446, 634, 542, 630, 845, 631, 853, 46, 47, 48, 49, 50, 51, 454, 140, 52, 53, 256, @@ -1303,11 +1303,11 @@ static const yytype_int16 yydefgoto[] = 56, 257, 58, 149, 203, 298, 299, 492, 59, 60, 275, 276, 787, 277, 278, 279, 258, 259, 457, 876, 936, 375, 62, 152, 284, 285, 482, 478, 963, 738, - 680, 881, 1027, 63, 64, 65, 290, 486, 1151, 1192, - 1193, 1282, 66, 67, 68, 69, 70, 71, 72, 73, + 680, 881, 1028, 63, 64, 65, 290, 486, 1153, 1194, + 1195, 1284, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 210, 80, 318, 319, 506, 320, 321, 509, 937, 953, 461, 659, 941, 520, - 746, 739, 1129, 1130, 1131, 740, 741, 1055, 81, 82, + 746, 739, 1131, 1132, 1133, 740, 741, 1056, 81, 82, 83, 260, 84, 261, 85, 86, 262, 770, 263, 264, 265, 87, 88, 162, 324, 325, 703, 89, 292, 293, 294, 295, 90, 303, 304, 91, 308, 309, 92, 313, @@ -1315,8 +1315,8 @@ static const yytype_int16 yydefgoto[] = 96, 182, 97, 183, 184, 938, 218, 219, 837, 99, 186, 334, 335, 516, 336, 191, 342, 343, 927, 928, 742, 743, 100, 221, 222, 605, 939, 102, 224, 225, - 940, 1223, 103, 748, 328, 105, 523, 848, 849, 1059, - 1096, 524, 1060 + 940, 1225, 103, 748, 328, 105, 523, 848, 849, 1060, + 1098, 524, 1061 }; /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If @@ -1324,638 +1324,654 @@ static const yytype_int16 yydefgoto[] = number is the opposite. If YYTABLE_NINF, syntax error. */ static const yytype_int16 yytable[] = { - 115, 270, 61, 236, 421, 344, 672, 479, 146, 711, - 57, 337, 187, 188, 339, 737, 347, 532, 943, 291, - 307, 312, 531, 697, 326, 613, 302, 421, 929, 45, - 906, 1053, 519, 907, 842, 808, 911, 871, 772, 345, - 931, 54, 434, 932, 970, 485, 1017, 190, 349, 918, - 1160, 925, 205, 1099, 207, 1099, 1104, 803, 789, 512, - 1, 926, 1316, 1, 19, 21, 1108, 518, 1093, 1168, - 1, 15, 5, 1323, 1323, 1331, 1331, 1314, 1338, 192, - 1323, 193, 464, 194, 195, 249, 196, 144, 114, 34, - 36, 5, 198, 199, 250, 200, 201, 202, 204, 202, - 206, 202, 208, 209, 267, 211, 1168, 212, 40, 5, - 33, 442, 251, 822, 106, 825, 17, 828, 266, 831, - 333, 833, 251, 10, 289, 316, 17, 216, 1392, 217, - 220, 223, 483, 226, 338, 1182, 26, 340, 1104, 26, - 29, 189, 1394, 29, 1170, 1397, 26, 144, 670, 1398, - 29, 422, 1401, 671, 15, 664, 1402, 189, 5, 665, - 282, 425, 5, 145, 1184, 5, 908, 1012, 1187, 912, - 370, 704, 915, 467, 31, 32, 476, 1013, 311, 333, - 134, 1170, 283, 1037, 1075, 1051, 1038, 1421, 350, 1040, - 352, -628, 1423, 33, 525, 1203, 484, 357, 249, 359, - 710, 502, 144, 362, 363, 735, 1048, 250, 513, 364, - 365, 366, 367, 5, 368, 326, 369, 202, 371, 994, - 1092, 996, 526, 145, 734, 1111, 1058, 374, 1355, 626, - 288, 968, 378, 379, 1288, 380, 485, 246, 891, 274, - 1188, 384, 706, 707, 948, 386, 387, 924, 951, 850, - 389, 390, 956, 966, 731, 392, 393, 627, 961, 682, - -630, 1152, 2, 398, 144, 708, 709, 401, 476, 661, - 403, 587, 4, 588, 447, 560, 5, 405, 145, 408, - 409, 411, 412, 414, 5, 415, 1112, 600, 2, 1113, - 1115, 973, 2, 704, 1158, 975, 1134, 735, 4, 978, - 980, 981, 4, 5, 984, 985, 7, 5, 987, 19, - 297, 1284, 10, 296, -51, 301, 588, 317, 246, 1039, - 1136, 12, 1041, 338, 1042, 1107, 340, 899, 1043, 903, - 459, -631, 903, 251, 34, 903, 315, 316, 903, 5, - 145, 903, 5, 1089, 246, 433, 707, 633, 704, -632, - 493, 704, 670, 496, 1328, 807, 499, 671, 476, 24, - 1345, 323, 5, 31, 32, 1194, 5, 443, 708, 709, - 527, 528, 341, 473, 463, 708, 709, 352, 533, 709, - 536, 1183, 1312, 664, 537, 539, 540, 665, 541, 1191, - 107, 108, 687, 694, 1145, 868, 696, 691, 546, 693, - 547, 548, 689, 549, 733, 551, 552, 762, 554, 555, - 326, 556, 558, 1201, 1287, 346, 562, 563, 564, 423, - 424, 374, 1114, 1116, 1117, 1118, 569, 570, -30, 755, - 573, 574, 757, 1081, 1082, 1083, 1084, 579, 580, 531, - 582, 583, 229, 585, 586, 213, 214, 1308, 421, 851, - 859, 860, 861, 596, 597, 598, 654, 656, 1225, 1226, - 603, 444, 604, 1021, 607, 532, 608, 1022, 1023, 1024, - 653, 655, 676, 678, 5, 1209, 7, 1321, 883, 1314, - 21, 882, 477, 1215, 1216, 306, 675, 677, 903, 459, - 903, 751, 490, 447, 903, 5, 5, 686, 1195, 1196, - 1197, 696, 329, 330, 704, 36, 1135, 705, 706, 707, - 652, 1156, 518, 657, 1189, 660, 522, 1318, 662, 663, - 423, 1335, 1335, 517, 1340, 1344, 674, 1349, 1349, 521, - 1353, 708, 709, 710, 134, 228, 229, 685, 230, 231, - 232, 233, 234, 688, 424, 5, 690, 5, 433, 692, - 1171, 807, 1314, 1181, 704, 752, 587, 1185, 706, 707, - 698, 1190, 533, 1283, 5, 533, 854, 537, 747, 759, - 1164, 805, 1307, 704, 1165, 1166, 1167, 705, 707, 1310, - 5, 708, 709, 1321, 670, 1314, 921, 764, 1395, 671, - 588, 903, 765, 766, 767, 1399, 768, 769, 771, 769, - 708, 709, 774, 1097, 1271, 1403, 1278, 709, 889, 1404, - 5, 696, 892, 884, 1329, 1314, 469, 1227, 785, 786, - 788, 786, 154, 790, 156, 791, 158, 793, 160, 795, - 233, 234, 1169, 1286, 1057, 418, 502, 913, 942, 804, - 916, 618, 971, 141, 967, 623, 815, 897, 150, 900, - 153, 901, 155, 1036, 157, 421, 159, 612, 816, 1121, - 818, 1292, 864, 821, 666, 824, 1208, 827, 1211, 830, - 684, 830, 628, 629, 598, 708, 709, 836, 1102, 875, - 1186, -59, 604, 604, 1336, 608, -59, -59, -59, 844, - 1343, 807, 246, 433, 847, 1164, 1097, 696, 892, 1165, - 1166, 1167, 1168, 1164, 1350, 5, 728, 1165, 1166, 1167, - 1168, 43, 728, 5, 704, 287, 728, 705, 706, 707, - 1348, 1348, 704, 1066, 1067, 705, 706, 707, 1057, 622, - 1164, 758, 807, 933, 1165, 1166, 1167, 855, 856, 857, - 5, 708, 709, 710, 1329, 1314, 991, 992, 1164, 708, - 709, 710, 1165, 1166, 1167, 839, 840, 1169, 5, 1015, - 1015, 1162, 1163, 1314, 165, 1169, 166, 167, 807, 168, - 1164, 169, 1031, 1052, 1165, 1166, 1167, 1170, 862, 280, - 5, 866, 1123, 281, 1019, 1170, 1124, 1125, 1126, 1127, - 566, 170, 1169, 502, 759, 872, 844, 1044, 878, 1046, - 171, 10, 683, 1280, 172, 769, 173, 1074, 174, 769, - 1169, 952, 507, 954, 955, 786, 175, 896, 958, 421, - 268, 786, 251, 269, 962, 791, 17, 699, 176, 134, - 228, 700, 1169, 230, 231, 232, 286, 696, 701, 702, - 835, 830, 98, 974, 1128, 830, 177, 178, 179, 977, - 979, 830, 31, 32, 983, 830, 180, 986, 830, 1422, - 988, 228, 229, 989, 230, 231, 232, 181, 836, 836, - 993, 458, 608, 406, 997, 998, 228, 863, 1109, 230, - 231, 232, 474, 475, 1001, 1002, 410, 101, 1405, 3, - 413, 488, 104, 1003, 873, 1137, 1119, 6, 495, 0, - 0, 498, 0, 0, 501, 0, 8, 0, 0, 0, - 0, 0, 511, 9, 696, 228, 11, 0, 230, 231, - 232, 233, 234, 805, 898, 806, 902, 0, 0, 902, - 0, 16, 902, 0, 0, 902, 0, 0, 902, 0, - 0, 0, 18, 1056, 728, 20, 0, 22, 1061, 1062, - 1063, 1064, 934, 0, 1015, 952, 952, 0, 25, 0, - 27, 0, 28, 0, 30, 0, 0, 0, 1198, 0, - 35, 0, 1073, 0, 0, 0, 0, 0, 0, 1077, - 1078, 1079, 1097, 1080, 830, 830, 830, 0, 1085, 476, - 1086, 5, 0, 0, 608, 0, 1091, 5, 844, 0, - 704, 0, 1095, 705, 706, 707, 704, 0, 0, 705, - 706, 707, 0, 0, 0, 0, 0, 0, 735, 0, - 0, 0, 923, 736, 0, 1015, 0, 708, 709, 710, - 0, 0, 0, 708, 709, 710, 0, 0, 0, 0, - 0, 1139, 0, 1142, 0, 608, 1146, 0, 0, 0, - 1149, 1150, 0, 0, 0, 1153, 1154, 0, 1155, 0, - 1011, 830, 0, 1157, 0, 0, 0, 0, 0, 5, - 0, 0, 844, 0, 0, 0, 0, 1161, 704, 1095, - 1095, 705, 706, 707, 0, 902, 0, 902, 0, 0, - 0, 902, 0, 1164, 0, 736, 1015, 1165, 1166, 1167, - 1168, 728, 0, 5, 0, 708, 709, 710, 0, 0, - 0, 0, 704, 0, 0, 705, 706, 707, 0, 0, - 0, 1206, 1189, 1207, 0, 1142, 608, 1210, 0, 1146, - 1212, 0, 0, 0, 1214, 608, 0, 1218, 0, 708, - 709, 710, 0, 0, 1220, 1222, 0, 0, 0, 0, - 476, 0, 0, 0, 0, 1169, 228, 229, 5, 230, - 231, 232, 233, 234, 0, 1393, 806, 704, 1291, 1220, - 705, 706, 707, 0, 0, 1170, 0, 1396, 0, 735, - 0, 0, 0, 0, 1400, 134, 228, 229, 902, 230, - 231, 232, 233, 234, 708, 709, 710, 0, 0, 0, - 0, 0, 0, 728, 0, 0, 0, 1293, 1295, 1296, - 1297, 1298, 0, 0, 1300, 1301, 1302, 1303, 1304, 476, - 0, 1306, 0, 608, 0, 844, 0, 5, 228, 0, - 608, 230, 231, 232, 233, 234, 704, 0, 806, 705, - 706, 707, 0, 0, 0, 0, 0, 728, 735, 0, - 728, 0, 0, 736, 728, 0, 0, 0, 728, 0, - 0, 1359, 0, 708, 709, 710, 0, 110, 1364, 0, - 1367, 0, 0, 0, 111, 112, 1371, 113, 1374, 0, - 116, 0, 117, 1378, 118, 0, 1381, 0, 119, 0, - 120, 1385, 121, 0, 122, 0, 123, 0, 124, 0, - 125, 0, 126, 0, 0, 0, 0, 0, 0, 0, - 127, 0, 0, 0, 728, 0, 0, 128, 0, 129, - 0, 130, 728, 131, 0, 132, 0, 133, 0, 0, - 728, 460, 462, 1222, 0, 465, 466, 0, 1409, 1411, - 228, 229, 1414, 230, 231, 232, 233, 234, 0, 487, - 0, 0, 0, 0, 0, 0, 494, 0, 0, 497, - 0, 0, 500, 0, 0, 0, 0, 0, 0, 197, - 510, 0, 135, 137, 139, 139, 142, 0, 0, 148, - 139, 151, 139, 148, 139, 148, 139, 148, 139, 148, - 161, 163, 0, 185, 185, 185, 0, 0, 0, 0, - 0, 1315, 0, 1322, 1322, 1330, 1330, 0, 1337, 1341, - 1322, 1346, 1346, 227, 1351, 0, 3, 0, 0, 0, - 0, 0, 0, 300, 6, 305, 0, 310, 0, 5, - 322, 0, 0, 8, 0, 0, 0, 0, 704, 0, - 9, 705, 706, 707, 0, 0, 0, 0, 0, 0, - 0, 0, 14, 0, 0, 244, 0, 0, 16, 0, - 272, 0, 0, 0, 0, 708, 709, 710, 0, 18, - 355, 0, 20, 0, 22, 356, 0, 358, 0, 0, - 360, 361, 0, 0, 0, 25, 5, 27, 0, 28, - 0, 30, 0, 0, 0, 704, 0, 35, 705, 706, - 707, 0, 372, 373, 0, 0, 0, 376, 0, 0, - 377, 0, 736, 0, 747, 0, 0, 381, 0, 0, - 0, 385, 708, 709, 710, 0, 388, 0, 0, 0, - 0, 391, 0, 0, 0, 0, 394, 0, 0, 0, - 0, 397, 0, 400, 0, 0, 0, 402, 0, 0, - 0, 0, 0, 0, 404, 0, 0, 407, 0, 0, - 0, 0, 0, 0, 417, 416, 0, 0, 0, 0, - 0, 432, 0, 438, 439, 635, 636, 637, 638, 639, - 640, 641, 642, 643, 644, 645, 646, 647, 648, 0, - 472, 0, 0, 0, 0, 480, 635, 636, 637, 638, - 639, 640, 641, 642, 643, 0, 0, 0, 0, 0, - 0, 0, 0, 426, 0, 0, 0, 0, 440, 137, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 481, - 137, 0, 0, 0, 0, 0, 0, 0, 491, 0, - 0, 529, 0, 530, 0, 0, 0, 0, 535, 0, - 505, 0, 0, 508, 0, 0, 0, 0, 543, 0, - 515, 0, 0, 0, 545, 544, 0, 0, 0, 3, - 0, 0, 0, 550, 553, 0, 5, 6, 0, 0, - 0, 561, 0, 0, 0, 704, 8, 0, 705, 706, - 707, 567, 0, 9, 0, 0, 572, 571, 0, 0, - 0, 0, 577, 578, 0, 14, 581, 0, 0, 584, - 0, 16, 708, 709, 710, 0, 593, 0, 0, 595, - 0, 0, 18, 0, 601, 20, 602, 22, 0, 0, - 0, 0, 606, 0, 0, 611, 610, 0, 25, 0, - 27, 0, 28, 0, 30, 0, 0, 0, 625, 0, - 35, 0, 632, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 669, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 681, 0, - 0, 0, 614, 616, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 658, 0, 0, 0, 0, 0, 732, - 0, 0, 0, 0, 0, 744, 0, 0, 0, 750, - 679, 0, 0, 0, 0, 753, 0, 754, 0, 0, - 0, 756, 0, 0, 0, 0, 0, 760, 0, 0, - 0, 0, 0, 761, 763, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 745, - 0, 0, 0, 185, 0, 0, 0, 773, 0, 0, - 775, 776, 777, 778, 0, 0, 0, 0, 0, 0, - 781, 0, 0, 0, 784, 783, 0, 0, 0, 0, - 0, 0, 0, 792, 0, 794, 0, 0, 797, 0, - 799, 0, 801, 0, 0, 0, 0, 0, 814, 0, + 115, 672, 270, 236, 61, 421, 344, 479, 146, 291, + 57, 337, 187, 188, 339, 532, 347, 943, 531, 302, + 307, 312, 929, 613, 190, 1017, 434, 519, 421, 697, + 906, 711, 772, 326, 789, 871, 45, 737, 907, 345, + 926, 911, 54, 808, 931, 485, 970, 932, 1162, 349, + 918, 205, 803, 207, 512, 925, 1095, 1110, 1101, 1054, + 1101, 1106, 106, 1, 144, 670, 1325, 1325, 1333, 1333, + 671, 1340, 518, 1325, 15, 5, 114, 842, 249, 192, + 2, 193, 1, 194, 195, 464, 196, 250, 1170, 144, + 4, 5, 198, 199, 1318, 200, 201, 202, 204, 202, + 206, 202, 208, 209, 267, 211, 144, 212, 144, 189, + 40, 338, 476, 33, 340, 251, 1, 5, 447, 17, + 5, 5, 2, 134, 10, 333, 1184, 216, 266, 217, + 220, 223, 4, 226, 289, 1396, 246, 433, 1399, 26, + 145, 735, 1400, 29, 1106, 1403, 822, 333, 825, 1404, + 828, 422, 831, 189, 833, 316, 1013, 249, 26, 282, + 1394, 425, 29, 1172, 908, 145, 250, 912, 251, 370, + 915, 1012, 17, 19, 467, 31, 32, 476, 246, 1052, + 1423, 283, 145, 1038, 145, 1425, 484, 1077, 350, -629, + 352, 1039, 26, 5, 1041, 525, 29, 357, 34, 359, + -631, 502, 704, 362, 363, 1059, 735, 1049, 513, 364, + 365, 366, 367, 626, 368, -632, 369, 202, 371, 734, + 1094, 1190, 526, 1290, 326, 1205, 1357, 374, 956, 1113, + 707, 710, 378, 379, 961, 380, 485, 288, 948, 968, + 274, 384, 951, 682, 891, 386, 387, 850, 966, 731, + 389, 390, 708, 709, 442, 392, 393, 107, 108, 21, + 627, 2, 994, 398, 996, 1154, 15, 401, 19, 924, + 403, 4, 661, 246, 301, 483, 560, 405, 10, 408, + 409, 411, 412, 414, 36, 415, 1170, 600, 1114, 5, + 311, 7, 1286, 34, 1316, 1160, 1115, 1117, 5, 251, + 338, 1138, 1136, 340, 1125, 33, 12, 704, 1126, 1127, + 1128, 1129, 297, 670, 587, 459, 588, 1040, 671, 317, + 1042, 5, 1043, 5, 973, 1109, 1044, 296, 975, 31, + 32, 5, 978, 980, 981, 709, 664, 984, 985, 323, + 665, 987, -633, 899, 24, 903, 5, 633, 903, 493, + 5, 903, 496, 5, 903, 499, 807, 903, 1316, 704, + -51, 1172, 588, 1314, 315, 316, 1130, 443, 706, 707, + 527, 528, 1196, 476, 463, 473, 341, 352, 533, 664, + 536, 5, 687, 665, 537, 539, 540, 1091, 541, 21, + 868, 708, 709, 694, 306, 689, 696, 691, 546, 693, + 547, 548, 346, 549, 733, 551, 552, 762, 554, 555, + 1289, 556, 558, 1203, 36, -30, 562, 563, 564, 326, + 1185, 374, 1116, 1118, 1119, 1120, 569, 570, 1193, 5, + 573, 574, 1323, 851, 1316, 531, 229, 579, 580, 1147, + 582, 583, 5, 585, 586, 670, 1330, 444, 1310, 421, + 671, 704, 1347, 596, 597, 598, 654, 656, 1227, 1228, + 603, 459, 604, 532, 607, 882, 608, 1083, 1084, 1085, + 1086, 755, 676, 678, 757, 859, 860, 861, 708, 709, + 653, 655, 1166, 1273, 477, 1280, 1167, 1168, 1169, 517, + 7, 751, 5, 447, 490, 521, 675, 677, 1197, 1198, + 1199, 696, 10, 883, 903, 5, 903, 686, 522, 652, + 903, 5, 657, 423, 660, 1331, 1316, 662, 663, 424, + 1211, 213, 214, 251, 518, 674, -59, 17, 1217, 1218, + 1137, -59, -59, -59, 134, 228, 685, 286, 230, 231, + 232, 433, 688, 747, 1171, 690, 1158, 5, 692, 855, + 856, 857, 807, 31, 32, 752, 704, 329, 330, 698, + 706, 707, 533, 1285, 5, 533, 854, 537, 1186, 759, + 233, 234, 1189, 704, 1173, 628, 629, 1183, 707, 246, + 433, 1187, 587, 708, 709, 1192, 805, 764, 708, 709, + 423, 424, 765, 766, 767, 705, 768, 769, 771, 769, + 708, 709, 774, 884, 1350, 1350, 1067, 1068, 889, 903, + 228, 696, 892, 230, 231, 232, 921, 1309, 785, 786, + 788, 786, 588, 790, 1312, 791, 154, 793, 156, 795, + 158, 1099, 160, 709, 1058, 469, 502, 913, 942, 418, + 916, 1229, 804, 618, 971, 228, 815, 623, 230, 231, + 232, 233, 234, 805, 967, 806, 421, 1288, 816, 897, + 818, 900, 864, 821, 901, 824, 666, 827, 1037, 830, + 612, 830, 991, 992, 598, 839, 840, 836, 1123, 875, + 1164, 1165, 604, 604, 1294, 608, 1166, 1210, 1213, 844, + 1167, 1168, 1169, 807, 847, 684, 5, 696, 892, 1323, + 1104, 1316, 1188, 1338, 1352, 134, 228, 229, 728, 230, + 231, 232, 233, 234, 728, 1345, 43, 1166, 728, 1099, + 287, 1167, 1168, 1169, 622, 758, 933, 5, 5, 165, + 1058, 1331, 1316, 166, 167, 807, 168, 704, 169, 1320, + 705, 706, 707, 1337, 1337, 280, 1342, 1346, 1171, 1351, + 1351, 281, 1355, 1021, 1019, 566, 170, 1022, 1023, 1024, + 1015, 1015, 171, 5, 708, 709, 710, 683, 1282, 172, + 173, 807, 1032, 174, 1053, 141, 507, 175, 862, 1171, + 150, 866, 153, 268, 155, 269, 157, 699, 159, 176, + 700, 701, 702, 502, 759, 872, 844, 1045, 878, 1047, + 177, 178, 179, 180, 181, 769, 98, 835, 1076, 769, + 1397, 952, 406, 954, 955, 786, 101, 1401, 958, 896, + 3, 786, 421, 413, 962, 791, 410, 1405, 6, 228, + 229, 1406, 230, 231, 232, 233, 234, 8, 696, 806, + 1407, 830, 104, 974, 9, 830, 1003, 11, 1139, 977, + 979, 830, 0, 0, 983, 830, 1424, 986, 830, 0, + 988, 0, 16, 989, 0, 0, 0, 0, 836, 836, + 993, 0, 608, 18, 997, 998, 20, 1166, 22, 863, + 1111, 1167, 1168, 1169, 1001, 1002, 0, 5, 458, 25, + 0, 27, 1316, 28, 0, 30, 873, 0, 1121, 474, + 475, 35, 460, 462, 0, 0, 465, 466, 488, 228, + 229, 0, 230, 231, 232, 495, 696, 0, 498, 0, + 487, 501, 0, 0, 0, 0, 898, 494, 902, 511, + 497, 902, 0, 500, 902, 0, 0, 902, 0, 1171, + 902, 510, 0, 1057, 0, 0, 728, 0, 1062, 1063, + 1064, 1065, 0, 0, 934, 952, 952, 1015, 0, 228, + 0, 0, 230, 231, 232, 233, 234, 0, 0, 806, + 1200, 228, 229, 1075, 230, 231, 232, 233, 234, 0, + 1079, 1080, 1081, 0, 1082, 830, 830, 830, 0, 1087, + 0, 1088, 0, 0, 0, 608, 0, 1093, 0, 844, + 0, 0, 0, 1097, 0, 0, 0, 0, 1166, 1099, + 0, 0, 1167, 1168, 1169, 1170, 0, 0, 5, 0, + 0, 0, 0, 0, 0, 0, 0, 704, 1015, 0, + 705, 706, 707, 635, 636, 637, 638, 639, 640, 641, + 642, 643, 0, 1141, 0, 1144, 0, 608, 1148, 0, + 0, 0, 1151, 1152, 708, 709, 710, 1155, 1156, 0, + 1157, 0, 1011, 830, 5, 1159, 0, 0, 0, 0, + 1171, 5, 1025, 704, 844, 0, 705, 706, 707, 1163, + 704, 1097, 1097, 705, 706, 707, 0, 902, 0, 902, + 1172, 0, 0, 902, 0, 0, 0, 736, 0, 1015, + 708, 709, 710, 728, 0, 0, 0, 708, 709, 710, + 0, 1166, 0, 0, 0, 1167, 1168, 1169, 1170, 0, + 0, 5, 0, 1208, 0, 1209, 0, 1144, 608, 1212, + 704, 1148, 1214, 705, 706, 707, 1216, 608, 0, 1220, + 1191, 0, 0, 476, 0, 0, 1222, 1224, 0, 0, + 0, 5, 0, 0, 0, 0, 0, 708, 709, 710, + 704, 0, 0, 705, 706, 707, 0, 1395, 0, 0, + 1293, 1222, 735, 1171, 0, 0, 923, 736, 0, 1398, + 0, 0, 0, 0, 0, 0, 1402, 708, 709, 710, + 0, 0, 902, 1172, 0, 134, 228, 229, 0, 230, + 231, 232, 233, 234, 0, 0, 0, 728, 0, 1295, + 1297, 1298, 1299, 1300, 0, 0, 1302, 1303, 1304, 1305, + 1306, 476, 0, 1308, 0, 608, 0, 844, 0, 5, + 0, 0, 608, 0, 0, 0, 0, 0, 704, 0, + 0, 705, 706, 707, 0, 0, 0, 0, 0, 0, + 735, 728, 0, 0, 728, 736, 0, 0, 728, 0, + 0, 0, 728, 1361, 0, 708, 709, 710, 0, 0, + 1366, 0, 1369, 0, 0, 0, 0, 0, 1373, 0, + 1376, 0, 0, 0, 0, 1380, 0, 0, 1383, 0, + 0, 0, 0, 1387, 0, 0, 110, 0, 0, 0, + 0, 0, 0, 111, 112, 0, 113, 0, 0, 116, + 0, 117, 0, 118, 0, 0, 0, 119, 728, 120, + 0, 121, 0, 122, 0, 123, 728, 124, 0, 125, + 0, 126, 0, 0, 728, 1224, 0, 0, 0, 127, + 1411, 1413, 0, 0, 1416, 0, 128, 0, 129, 0, + 130, 0, 131, 0, 132, 1166, 133, 5, 0, 1167, + 1168, 1169, 1170, 0, 0, 5, 704, 0, 0, 705, + 706, 707, 0, 0, 704, 0, 0, 705, 706, 707, + 0, 0, 0, 736, 0, 747, 0, 0, 0, 0, + 0, 0, 0, 708, 709, 710, 0, 0, 197, 0, + 0, 708, 709, 710, 0, 1317, 0, 1324, 1324, 1332, + 1332, 0, 1339, 1343, 1324, 1348, 1348, 1171, 1353, 3, + 0, 0, 0, 0, 476, 0, 5, 6, 0, 0, + 0, 0, 5, 0, 0, 704, 8, 1172, 705, 706, + 707, 704, 227, 9, 705, 706, 707, 0, 0, 3, + 0, 0, 300, 735, 305, 14, 310, 6, 0, 322, + 0, 16, 708, 709, 710, 0, 8, 0, 708, 709, + 710, 0, 18, 9, 0, 20, 0, 22, 0, 0, + 0, 0, 0, 0, 0, 14, 0, 0, 25, 0, + 27, 16, 28, 0, 30, 0, 0, 0, 0, 355, + 35, 0, 18, 0, 356, 20, 358, 22, 0, 360, + 361, 0, 0, 0, 0, 0, 0, 0, 25, 0, + 27, 0, 28, 0, 30, 0, 0, 0, 0, 0, + 35, 372, 373, 0, 0, 0, 376, 0, 0, 377, + 0, 0, 0, 0, 5, 0, 381, 0, 0, 0, + 385, 0, 0, 704, 0, 388, 705, 706, 707, 0, + 391, 0, 0, 1191, 0, 394, 0, 0, 0, 0, + 397, 0, 400, 0, 0, 0, 402, 0, 1, 2, + 708, 709, 710, 404, 3, 0, 407, 0, 0, 4, + 0, 5, 6, 417, 416, 0, 0, 0, 7, 0, + 432, 8, 438, 439, 0, 0, 0, 0, 9, 10, + 0, 11, 0, 12, 0, 0, 0, 0, 13, 472, + 14, 0, 0, 15, 480, 0, 16, 0, 0, 0, + 0, 0, 0, 0, 17, 0, 0, 18, 0, 19, + 20, 21, 22, 0, 0, 0, 0, 0, 0, 0, + 23, 24, 0, 25, 26, 27, 0, 28, 29, 30, + 31, 32, 33, 0, 34, 35, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 817, 0, - 820, 0, 0, 823, 0, 826, 0, 829, 0, 832, - 0, 0, 834, 0, 0, 0, 0, 0, 0, 0, - 838, 0, 0, 841, 0, 843, 0, 0, 0, 0, - 846, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 529, 0, 530, 0, 0, 0, 0, 535, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 543, 0, 0, + 0, 0, 0, 545, 544, 0, 0, 0, 0, 0, + 0, 0, 550, 553, 0, 0, 0, 0, 0, 0, + 561, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 567, 0, 0, 0, 0, 572, 571, 0, 0, 0, + 0, 577, 578, 0, 0, 581, 0, 0, 584, 0, + 0, 0, 0, 0, 0, 593, 0, 0, 595, 0, + 0, 0, 0, 601, 0, 602, 0, 0, 0, 0, + 0, 606, 0, 0, 611, 610, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 625, 0, 0, + 0, 632, 635, 636, 637, 638, 639, 640, 641, 642, + 643, 644, 645, 646, 647, 648, 669, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 681, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 865, 0, 867, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 877, 0, 879, - 0, 0, 0, 0, 0, 0, 885, 0, 886, 0, - 887, 0, 888, 0, 852, 0, 395, 396, 0, 399, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 869, 0, 869, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 930, 0, 0, - 0, 0, 0, 0, 0, 935, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 732, 0, + 0, 0, 0, 0, 744, 0, 0, 0, 750, 0, + 0, 0, 0, 0, 753, 0, 754, 0, 0, 0, + 756, 0, 0, 0, 0, 0, 760, 0, 0, 0, + 0, 0, 761, 763, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 904, 0, 0, 909, 0, 0, 0, - 0, 0, 0, 0, 0, 919, 0, 0, 0, 0, - 0, 679, 0, 0, 679, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 773, 0, 0, 775, + 776, 777, 778, 0, 0, 0, 0, 0, 0, 781, + 0, 0, 0, 784, 783, 0, 0, 0, 0, 0, + 0, 0, 792, 0, 794, 0, 0, 797, 0, 799, + 0, 801, 0, 0, 0, 0, 0, 814, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 976, 0, 0, 0, 0, - 982, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 990, 0, 0, 0, 0, 0, 0, 0, - 995, 0, 0, 999, 0, 0, 0, 0, 0, 0, - 1000, 0, 0, 1004, 1005, 1006, 1007, 1008, 1009, 0, - 0, 1010, 0, 1014, 0, 0, 1018, 0, 559, 0, - 0, 1020, 0, 1028, 1029, 1030, 565, 0, 0, 0, - 0, 568, 1034, 0, 0, 0, 0, 0, 575, 576, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1228, - 1229, 1230, 1231, 1232, 1233, 1234, 594, 1235, 1236, 1237, - 1238, 1239, 1240, 1241, 1242, 1243, 1244, 1245, 1246, 1247, - 1248, 1249, 1250, 1251, 1252, 1253, 1254, 1255, 1256, 1257, - 1258, 0, 0, 1259, 1260, 1261, 1262, 1263, 1071, 0, - 0, 0, 1049, 0, 0, 1076, 0, 0, 0, 0, - 0, 1054, 0, 0, 0, 0, 0, 0, 0, 0, - 1088, 0, 1090, 0, 0, 0, 0, 0, 0, 1094, - 0, 0, 0, 0, 0, 0, 0, 0, 1105, 1106, + 0, 0, 0, 0, 0, 0, 0, 817, 0, 820, + 0, 0, 823, 0, 826, 0, 829, 0, 832, 0, + 0, 834, 0, 0, 0, 0, 0, 0, 0, 838, + 0, 0, 841, 0, 843, 0, 0, 0, 0, 846, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1122, 0, 0, - 0, 0, 1132, 0, 0, 1133, 1138, 0, 0, 0, - 0, 1141, 0, 1144, 0, 0, 1148, 0, 0, 0, - 0, 0, 0, 0, 869, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 865, + 0, 867, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 877, 0, 879, 0, + 0, 0, 0, 0, 0, 885, 0, 886, 0, 887, + 0, 888, 0, 0, 0, 0, 0, 135, 137, 139, + 139, 142, 0, 0, 148, 139, 151, 139, 148, 139, + 148, 139, 148, 139, 148, 161, 163, 0, 185, 185, + 185, 0, 0, 0, 0, 0, 930, 0, 0, 0, + 0, 0, 0, 0, 935, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1159, 0, 0, 0, 679, 0, 0, + 0, 395, 396, 0, 399, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 779, 780, 0, 1200, 0, - 1202, 782, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 796, 1204, 798, 1205, - 800, 0, 802, 0, 1179, 0, 0, 1179, 0, 0, - 0, 1179, 0, 0, 0, 1217, 0, 0, 0, 1219, - 0, 0, 869, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1279, 0, 0, 0, 0, 0, 0, - 0, 1285, 0, 1289, 1290, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 869, 869, 0, + 244, 0, 0, 0, 0, 272, 0, 0, 0, 0, + 0, 0, 0, 0, 976, 0, 0, 0, 0, 982, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1281, 0, 0, 0, 0, 0, 0, 0, 0, 1299, - 0, 0, 0, 0, 0, 0, 1305, 0, 0, 0, + 0, 990, 0, 0, 0, 0, 0, 0, 0, 995, + 0, 0, 999, 0, 0, 0, 0, 0, 0, 1000, + 0, 0, 1004, 1005, 1006, 1007, 1008, 1009, 0, 0, + 1010, 0, 1014, 0, 0, 1018, 0, 0, 0, 0, + 1020, 0, 1029, 1030, 1031, 0, 0, 0, 0, 0, + 0, 1035, 1267, 1230, 1231, 1232, 1233, 1234, 1235, 1236, + 1268, 1237, 1238, 1239, 1240, 1241, 1242, 1243, 1244, 1245, + 1246, 1247, 1248, 1249, 1250, 1251, 1252, 1253, 1254, 1255, + 1256, 1257, 1258, 1259, 1260, 1269, 1270, 1261, 1262, 1263, + 1264, 1265, 0, 559, 0, 0, 0, 0, 0, 0, + 0, 565, 0, 0, 0, 0, 568, 0, 1073, 0, + 0, 0, 0, 575, 576, 1078, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 426, 0, + 1090, 594, 1092, 440, 137, 0, 0, 0, 0, 1096, + 0, 0, 0, 0, 0, 0, 0, 0, 1107, 1108, + 0, 0, 0, 0, 481, 137, 0, 0, 0, 0, + 0, 0, 0, 491, 0, 0, 0, 0, 1124, 0, + 0, 0, 0, 1134, 0, 505, 1135, 1140, 508, 0, + 0, 0, 1143, 0, 1146, 515, 0, 1150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1311, 0, 1313, 0, 1320, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1354, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1361, 0, 0, 0, 0, 0, 0, 1366, 0, - 0, 0, 0, 0, 0, 0, 1373, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 944, 945, 946, - 947, 0, 949, 950, 0, 1390, 1391, 1, 2, 0, - 0, 0, 957, 3, 959, 960, 0, 0, 4, 0, - 5, 6, 964, 965, 0, 0, 0, 7, 0, 0, - 8, 0, 0, 0, 0, 972, 0, 9, 10, 0, - 11, 0, 12, 1407, 0, 0, 0, 13, 0, 14, - 1416, 0, 15, 0, 0, 16, 0, 0, 0, 0, - 0, 0, 0, 17, 0, 0, 18, 0, 19, 20, - 21, 22, 1425, 0, 0, 0, 0, 0, 0, 23, - 24, 0, 25, 26, 27, 0, 28, 29, 30, 31, - 32, 33, 0, 34, 35, 36, 1265, 1228, 1229, 1230, - 1231, 1232, 1233, 1234, 1266, 1235, 1236, 1237, 1238, 1239, - 1240, 1241, 1242, 1243, 1244, 1245, 1246, 1247, 1248, 1249, - 1250, 1251, 1252, 1253, 1254, 1255, 1256, 1257, 1258, 1267, - 1268, 1259, 1260, 1261, 1262, 1263, 0, 0, 0, 0, + 0, 0, 0, 0, 1161, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1065, 0, 0, 0, 0, 1068, 1069, 0, 1070, 0, - 0, 0, 0, 0, 0, 0, 1072, 1272, 1228, 1229, - 1230, 1231, 1232, 1233, 1234, 1273, 1235, 1236, 1237, 1238, - 1239, 1240, 1241, 1242, 1243, 1244, 1245, 1246, 1247, 1248, - 1249, 1250, 1251, 1252, 1253, 1254, 1255, 1256, 1257, 1258, - 1274, 1275, 1259, 1260, 1261, 1262, 1263, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1202, + 0, 1204, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1206, 0, + 1207, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1219, 0, 0, 0, + 1221, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 779, 780, 0, 0, 1281, 0, 782, 0, 0, 0, + 0, 0, 1287, 0, 1291, 1292, 0, 614, 616, 0, + 0, 796, 0, 798, 0, 800, 0, 802, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 658, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 679, 0, 0, 0, 0, + 1301, 0, 0, 0, 0, 0, 0, 1307, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1313, 0, 1315, 0, 1322, 0, 0, 0, 0, + 0, 0, 0, 0, 745, 0, 0, 0, 185, 1356, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1363, 0, 0, 0, 0, 0, 0, 1368, + 0, 0, 0, 0, 0, 0, 0, 1375, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1392, 1393, 0, 0, + 0, 1230, 1231, 1232, 1233, 1234, 1235, 1236, 0, 1237, + 1238, 1239, 1240, 1241, 1242, 1243, 1244, 1245, 1246, 1247, + 1248, 1249, 1250, 1251, 1252, 1253, 1254, 1255, 1256, 1257, + 1258, 1259, 1260, 0, 1409, 1261, 1262, 1263, 1264, 1265, + 0, 1418, 944, 945, 946, 947, 0, 949, 950, 0, + 0, 0, 0, 0, 0, 0, 0, 957, 0, 959, + 960, 0, 0, 1427, 0, 0, 0, 964, 965, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 972, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 852, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 869, + 0, 869, 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, 904, 0, + 0, 909, 0, 0, 0, 0, 0, 0, 0, 0, + 919, 0, 0, 0, 0, 0, 679, 0, 0, 679, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1066, 0, 0, 0, 0, + 1069, 1070, 0, 1071, 0, 0, 0, 0, 0, 1072, + 0, 0, 1074, 1274, 1230, 1231, 1232, 1233, 1234, 1235, + 1236, 1275, 1237, 1238, 1239, 1240, 1241, 1242, 1243, 1244, + 1245, 1246, 1247, 1248, 1249, 1250, 1251, 1252, 1253, 1254, + 1255, 1256, 1257, 1258, 1259, 1260, 1276, 1277, 1261, 1262, + 1263, 1264, 1265, 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, 1213, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1224, 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, 0, 0, 0, 1050, 0, 0, + 0, 0, 0, 0, 0, 0, 1055, 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, 1215, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1226, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1309, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 869, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1356, 0, 0, 1357, 1358, 0, 1360, 0, 0, - 0, 1362, 1363, 0, 1365, 0, 1368, 0, 0, 1369, - 1370, 0, 1372, 0, 1375, 0, 1376, 1377, 0, 1379, - 1380, 0, 1382, 1383, 0, 1384, 0, 1386, 1387, 0, - 1388, 0, 1389, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 679, 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, 1406, 0, 1408, 1410, 0, 1412, 1413, 1415, 0, - 1417, 1418, 1419, 1420, 0, 0, 0, 0, 0, 0, + 1311, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1181, 0, 0, 1181, 0, 0, 0, 1181, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1358, 869, + 0, 1359, 1360, 0, 1362, 0, 0, 0, 1364, 1365, + 0, 1367, 0, 1370, 0, 0, 1371, 1372, 0, 1374, + 0, 1377, 0, 1378, 1379, 0, 1381, 1382, 0, 1384, + 1385, 0, 1386, 0, 1388, 1389, 0, 1390, 0, 1391, + 0, 0, 0, 0, 869, 869, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1424, 0, 1426 + 0, 0, 0, 0, 0, 0, 0, 0, 1408, 0, + 1410, 1412, 0, 1414, 1415, 1417, 0, 1419, 1420, 1421, + 1422, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1426, 0, 1428 }; static const yytype_int16 yycheck[] = { - 57, 196, 0, 192, 346, 227, 558, 374, 115, 598, - 0, 220, 131, 132, 223, 604, 242, 434, 853, 201, - 206, 208, 434, 592, 212, 528, 204, 369, 836, 0, - 821, 997, 411, 821, 742, 697, 824, 783, 656, 235, - 838, 0, 352, 841, 893, 379, 955, 133, 243, 832, - 1133, 836, 156, 1061, 158, 1063, 1064, 694, 678, 403, - 4, 836, 1293, 4, 65, 67, 1073, 25, 1056, 14, - 4, 49, 17, 1295, 1296, 1297, 1298, 22, 1300, 136, - 1302, 138, 365, 140, 141, 19, 143, 6, 163, 90, - 92, 17, 149, 150, 28, 152, 153, 154, 155, 156, - 157, 158, 159, 160, 195, 162, 14, 164, 0, 17, - 88, 356, 56, 720, 0, 722, 60, 724, 195, 726, - 78, 728, 56, 35, 201, 51, 60, 184, 1359, 186, - 187, 188, 377, 190, 220, 1142, 80, 223, 1146, 80, - 84, 40, 1364, 84, 89, 1367, 80, 6, 7, 1371, - 84, 347, 1374, 12, 49, 7, 1378, 40, 17, 11, - 3, 350, 17, 82, 1144, 17, 821, 952, 1148, 824, - 274, 26, 827, 368, 86, 87, 9, 952, 73, 78, - 147, 89, 25, 974, 1033, 993, 974, 1409, 245, 977, - 247, 163, 1414, 88, 416, 1161, 378, 254, 19, 256, - 55, 397, 6, 260, 261, 38, 989, 28, 404, 266, - 267, 268, 269, 17, 271, 403, 273, 274, 275, 927, - 1055, 929, 418, 82, 603, 1074, 1001, 284, 1311, 539, - 201, 893, 289, 290, 1222, 292, 570, 61, 807, 198, - 1149, 298, 30, 31, 862, 302, 303, 836, 866, 752, - 307, 308, 872, 890, 598, 312, 313, 540, 878, 569, - 163, 1110, 5, 320, 6, 53, 54, 324, 9, 552, - 327, 155, 15, 157, 16, 470, 17, 334, 82, 336, - 337, 338, 339, 340, 17, 342, 1077, 513, 5, 1077, - 1078, 898, 5, 26, 1129, 902, 1094, 38, 15, 906, - 907, 908, 15, 17, 911, 912, 24, 17, 915, 65, - 202, 1220, 35, 23, 155, 71, 157, 209, 61, 974, - 1095, 39, 977, 409, 979, 1071, 412, 816, 983, 818, - 48, 163, 821, 56, 90, 824, 50, 51, 827, 17, - 82, 830, 17, 1051, 61, 62, 31, 543, 26, 163, - 386, 26, 7, 389, 1296, 697, 392, 12, 9, 77, - 1302, 64, 17, 86, 87, 1153, 17, 357, 53, 54, - 427, 428, 41, 371, 364, 53, 54, 434, 435, 54, - 437, 1142, 1291, 7, 441, 442, 443, 11, 445, 1150, - 159, 160, 574, 589, 1102, 774, 592, 583, 455, 586, - 457, 458, 580, 460, 600, 462, 463, 633, 465, 466, - 598, 468, 469, 1159, 1222, 150, 473, 474, 475, 32, - 33, 478, 1077, 1078, 1079, 1080, 483, 484, 150, 619, - 487, 488, 622, 1040, 1041, 1042, 1043, 494, 495, 851, - 497, 498, 149, 500, 501, 161, 162, 1282, 790, 759, - 765, 766, 767, 510, 511, 512, 547, 548, 1204, 1205, - 517, 57, 519, 7, 521, 882, 523, 11, 12, 13, - 547, 548, 563, 564, 17, 1183, 24, 20, 793, 22, - 67, 791, 374, 1191, 1192, 72, 563, 564, 977, 48, - 979, 610, 384, 16, 983, 17, 17, 574, 1153, 1154, - 1155, 697, 74, 75, 26, 92, 1095, 29, 30, 31, - 546, 1118, 25, 549, 36, 551, 47, 1293, 554, 555, - 32, 1297, 1298, 408, 1300, 1301, 562, 1303, 1304, 414, - 1306, 53, 54, 55, 147, 148, 149, 573, 151, 152, - 153, 154, 155, 579, 33, 17, 582, 17, 62, 585, - 1139, 893, 22, 1142, 26, 612, 155, 1146, 30, 31, - 596, 1150, 619, 1218, 17, 622, 762, 624, 45, 626, - 7, 156, 1280, 26, 11, 12, 13, 29, 31, 1287, - 17, 53, 54, 20, 7, 22, 147, 644, 1364, 12, - 157, 1080, 649, 650, 651, 1371, 653, 654, 655, 656, - 53, 54, 659, 8, 1210, 1381, 1212, 54, 804, 1385, - 17, 807, 808, 795, 21, 22, 369, 1206, 675, 676, - 677, 678, 120, 680, 122, 682, 124, 684, 126, 686, - 154, 155, 69, 1222, 1001, 346, 832, 826, 847, 695, - 829, 533, 894, 112, 891, 537, 703, 816, 117, 817, - 119, 818, 121, 974, 123, 997, 125, 527, 715, 1086, - 717, 1226, 769, 720, 556, 722, 1182, 724, 1186, 726, - 571, 728, 58, 59, 731, 53, 54, 734, 1063, 786, - 1146, 156, 739, 740, 1298, 742, 161, 162, 163, 746, - 1301, 1033, 61, 62, 751, 7, 8, 893, 894, 11, - 12, 13, 14, 7, 1304, 17, 598, 11, 12, 13, - 14, 0, 604, 17, 26, 201, 608, 29, 30, 31, - 1303, 1304, 26, 1012, 1013, 29, 30, 31, 1095, 536, - 7, 624, 1074, 843, 11, 12, 13, 151, 152, 153, - 17, 53, 54, 55, 21, 22, 925, 926, 7, 53, - 54, 55, 11, 12, 13, 739, 740, 69, 17, 954, - 955, 1136, 1137, 22, 129, 69, 129, 129, 1110, 129, - 7, 129, 968, 995, 11, 12, 13, 89, 768, 199, - 17, 771, 7, 199, 958, 89, 11, 12, 13, 14, - 478, 129, 69, 989, 851, 785, 853, 986, 788, 988, - 129, 35, 570, 1214, 129, 862, 129, 1033, 129, 866, - 69, 868, 398, 870, 871, 872, 129, 815, 875, 1161, - 195, 878, 56, 195, 881, 882, 60, 597, 129, 147, - 148, 597, 69, 151, 152, 153, 70, 1033, 597, 597, - 731, 898, 0, 900, 69, 902, 129, 129, 129, 906, - 907, 908, 86, 87, 911, 912, 129, 914, 915, 1411, - 917, 148, 149, 920, 151, 152, 153, 129, 925, 926, - 927, 361, 929, 334, 931, 932, 148, 769, 1074, 151, - 152, 153, 372, 373, 941, 942, 337, 0, 1390, 10, - 339, 381, 0, 942, 786, 1095, 1085, 18, 388, -1, - -1, 391, -1, -1, 394, -1, 27, -1, -1, -1, - -1, -1, 402, 34, 1110, 148, 37, -1, 151, 152, - 153, 154, 155, 156, 816, 158, 818, -1, -1, 821, - -1, 52, 824, -1, -1, 827, -1, -1, 830, -1, - -1, -1, 63, 1000, 836, 66, -1, 68, 1005, 1006, - 1007, 1008, 844, -1, 1149, 1012, 1013, -1, 79, -1, - 81, -1, 83, -1, 85, -1, -1, -1, 1157, -1, - 91, -1, 1029, -1, -1, -1, -1, -1, -1, 1036, - 1037, 1038, 8, 1040, 1041, 1042, 1043, -1, 1045, 9, - 1047, 17, -1, -1, 1051, -1, 1053, 17, 1055, -1, - 26, -1, 1059, 29, 30, 31, 26, -1, -1, 29, - 30, 31, -1, -1, -1, -1, -1, -1, 38, -1, - -1, -1, 42, 43, -1, 1220, -1, 53, 54, 55, - -1, -1, -1, 53, 54, 55, -1, -1, -1, -1, - -1, 1098, -1, 1100, -1, 1102, 1103, -1, -1, -1, - 1107, 1108, -1, -1, -1, 1112, 1113, -1, 1115, -1, - 952, 1118, -1, 1120, -1, -1, -1, -1, -1, 17, - -1, -1, 1129, -1, -1, -1, -1, 1134, 26, 1136, - 1137, 29, 30, 31, -1, 977, -1, 979, -1, -1, - -1, 983, -1, 7, -1, 43, 1291, 11, 12, 13, - 14, 993, -1, 17, -1, 53, 54, 55, -1, -1, - -1, -1, 26, -1, -1, 29, 30, 31, -1, -1, - -1, 1178, 36, 1180, -1, 1182, 1183, 1184, -1, 1186, - 1187, -1, -1, -1, 1191, 1192, -1, 1194, -1, 53, - 54, 55, -1, -1, 1201, 1202, -1, -1, -1, -1, - 9, -1, -1, -1, -1, 69, 148, 149, 17, 151, - 152, 153, 154, 155, -1, 1361, 158, 26, 1225, 1226, - 29, 30, 31, -1, -1, 89, -1, 1366, -1, 38, - -1, -1, -1, -1, 1373, 147, 148, 149, 1080, 151, - 152, 153, 154, 155, 53, 54, 55, -1, -1, -1, - -1, -1, -1, 1095, -1, -1, -1, 1264, 1265, 1266, - 1267, 1268, -1, -1, 1271, 1272, 1273, 1274, 1275, 9, - -1, 1278, -1, 1280, -1, 1282, -1, 17, 148, -1, - 1287, 151, 152, 153, 154, 155, 26, -1, 158, 29, - 30, 31, -1, -1, -1, -1, -1, 1139, 38, -1, - 1142, -1, -1, 43, 1146, -1, -1, -1, 1150, -1, - -1, 1318, -1, 53, 54, 55, -1, 45, 1325, -1, - 1327, -1, -1, -1, 52, 53, 1333, 55, 1335, -1, - 58, -1, 60, 1340, 62, -1, 1343, -1, 66, -1, - 68, 1348, 70, -1, 72, -1, 74, -1, 76, -1, - 78, -1, 80, -1, -1, -1, -1, -1, -1, -1, - 88, -1, -1, -1, 1206, -1, -1, 95, -1, 97, - -1, 99, 1214, 101, -1, 103, -1, 105, -1, -1, - 1222, 362, 363, 1390, -1, 366, 367, -1, 1395, 1396, - 148, 149, 1399, 151, 152, 153, 154, 155, -1, 380, - -1, -1, -1, -1, -1, -1, 387, -1, -1, 390, - -1, -1, 393, -1, -1, -1, -1, -1, -1, 147, - 401, -1, 109, 110, 111, 112, 113, -1, -1, 116, - 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, - 127, 128, -1, 130, 131, 132, -1, -1, -1, -1, - -1, 1293, -1, 1295, 1296, 1297, 1298, -1, 1300, 1301, - 1302, 1303, 1304, 191, 1306, -1, 10, -1, -1, -1, - -1, -1, -1, 203, 18, 205, -1, 207, -1, 17, - 210, -1, -1, 27, -1, -1, -1, -1, 26, -1, - 34, 29, 30, 31, -1, -1, -1, -1, -1, -1, - -1, -1, 46, -1, -1, 192, -1, -1, 52, -1, - 197, -1, -1, -1, -1, 53, 54, 55, -1, 63, - 248, -1, 66, -1, 68, 253, -1, 255, -1, -1, - 258, 259, -1, -1, -1, 79, 17, 81, -1, 83, - -1, 85, -1, -1, -1, 26, -1, 91, 29, 30, - 31, -1, 280, 281, -1, -1, -1, 285, -1, -1, - 288, -1, 43, -1, 45, -1, -1, 295, -1, -1, - -1, 299, 53, 54, 55, -1, 304, -1, -1, -1, - -1, 309, -1, -1, -1, -1, 314, -1, -1, -1, - -1, 319, -1, 321, -1, -1, -1, 325, -1, -1, - -1, -1, -1, -1, 332, -1, -1, 335, -1, -1, - -1, -1, -1, -1, 344, 343, -1, -1, -1, -1, - -1, 351, -1, 353, 354, 93, 94, 95, 96, 97, - 98, 99, 100, 101, 102, 103, 104, 105, 106, -1, - 370, -1, -1, -1, -1, 375, 93, 94, 95, 96, - 97, 98, 99, 100, 101, -1, -1, -1, -1, -1, - -1, -1, -1, 350, -1, -1, -1, -1, 355, 356, + 57, 558, 196, 192, 0, 346, 227, 374, 115, 201, + 0, 220, 131, 132, 223, 434, 242, 853, 434, 204, + 206, 208, 836, 528, 133, 955, 352, 411, 369, 592, + 821, 598, 656, 212, 678, 783, 0, 604, 821, 235, + 836, 824, 0, 697, 838, 379, 893, 841, 1135, 243, + 832, 156, 694, 158, 403, 836, 1057, 1075, 1062, 997, + 1064, 1065, 0, 4, 6, 7, 1297, 1298, 1299, 1300, + 12, 1302, 25, 1304, 49, 17, 163, 742, 19, 136, + 5, 138, 4, 140, 141, 365, 143, 28, 14, 6, + 15, 17, 149, 150, 1295, 152, 153, 154, 155, 156, + 157, 158, 159, 160, 195, 162, 6, 164, 6, 40, + 0, 220, 9, 88, 223, 56, 4, 17, 16, 60, + 17, 17, 5, 147, 35, 78, 1144, 184, 195, 186, + 187, 188, 15, 190, 201, 1366, 61, 62, 1369, 80, + 82, 38, 1373, 84, 1148, 1376, 720, 78, 722, 1380, + 724, 347, 726, 40, 728, 51, 952, 19, 80, 3, + 1361, 350, 84, 89, 821, 82, 28, 824, 56, 274, + 827, 952, 60, 65, 368, 86, 87, 9, 61, 993, + 1411, 25, 82, 974, 82, 1416, 378, 1034, 245, 163, + 247, 974, 80, 17, 977, 416, 84, 254, 90, 256, + 163, 397, 26, 260, 261, 1001, 38, 989, 404, 266, + 267, 268, 269, 539, 271, 163, 273, 274, 275, 603, + 1056, 1151, 418, 1224, 403, 1163, 1313, 284, 872, 1076, + 31, 55, 289, 290, 878, 292, 570, 201, 862, 893, + 198, 298, 866, 569, 807, 302, 303, 752, 890, 598, + 307, 308, 53, 54, 356, 312, 313, 159, 160, 67, + 540, 5, 927, 320, 929, 1112, 49, 324, 65, 836, + 327, 15, 552, 61, 71, 377, 470, 334, 35, 336, + 337, 338, 339, 340, 92, 342, 14, 513, 1079, 17, + 73, 24, 1222, 90, 22, 1131, 1079, 1080, 17, 56, + 409, 1097, 1096, 412, 7, 88, 39, 26, 11, 12, + 13, 14, 202, 7, 155, 48, 157, 974, 12, 209, + 977, 17, 979, 17, 898, 1073, 983, 23, 902, 86, + 87, 17, 906, 907, 908, 54, 7, 911, 912, 64, + 11, 915, 163, 816, 77, 818, 17, 543, 821, 386, + 17, 824, 389, 17, 827, 392, 697, 830, 22, 26, + 155, 89, 157, 1293, 50, 51, 69, 357, 30, 31, + 427, 428, 1155, 9, 364, 371, 41, 434, 435, 7, + 437, 17, 574, 11, 441, 442, 443, 1052, 445, 67, + 774, 53, 54, 589, 72, 580, 592, 583, 455, 586, + 457, 458, 150, 460, 600, 462, 463, 633, 465, 466, + 1224, 468, 469, 1161, 92, 150, 473, 474, 475, 598, + 1144, 478, 1079, 1080, 1081, 1082, 483, 484, 1152, 17, + 487, 488, 20, 759, 22, 851, 149, 494, 495, 1104, + 497, 498, 17, 500, 501, 7, 1298, 57, 1284, 790, + 12, 26, 1304, 510, 511, 512, 547, 548, 1206, 1207, + 517, 48, 519, 882, 521, 791, 523, 1041, 1042, 1043, + 1044, 619, 563, 564, 622, 765, 766, 767, 53, 54, + 547, 548, 7, 1212, 374, 1214, 11, 12, 13, 408, + 24, 610, 17, 16, 384, 414, 563, 564, 1155, 1156, + 1157, 697, 35, 793, 977, 17, 979, 574, 47, 546, + 983, 17, 549, 32, 551, 21, 22, 554, 555, 33, + 1185, 161, 162, 56, 25, 562, 156, 60, 1193, 1194, + 1097, 161, 162, 163, 147, 148, 573, 70, 151, 152, + 153, 62, 579, 45, 69, 582, 1120, 17, 585, 151, + 152, 153, 893, 86, 87, 612, 26, 74, 75, 596, + 30, 31, 619, 1220, 17, 622, 762, 624, 1146, 626, + 154, 155, 1150, 26, 1141, 58, 59, 1144, 31, 61, + 62, 1148, 155, 53, 54, 1152, 156, 644, 53, 54, + 32, 33, 649, 650, 651, 29, 653, 654, 655, 656, + 53, 54, 659, 795, 1305, 1306, 1012, 1013, 804, 1082, + 148, 807, 808, 151, 152, 153, 147, 1282, 675, 676, + 677, 678, 157, 680, 1289, 682, 120, 684, 122, 686, + 124, 8, 126, 54, 1001, 369, 832, 826, 847, 346, + 829, 1208, 695, 533, 894, 148, 703, 537, 151, 152, + 153, 154, 155, 156, 891, 158, 997, 1224, 715, 816, + 717, 817, 769, 720, 818, 722, 556, 724, 974, 726, + 527, 728, 925, 926, 731, 739, 740, 734, 1088, 786, + 1138, 1139, 739, 740, 1228, 742, 7, 1184, 1188, 746, + 11, 12, 13, 1034, 751, 571, 17, 893, 894, 20, + 1064, 22, 1148, 1300, 1306, 147, 148, 149, 598, 151, + 152, 153, 154, 155, 604, 1303, 0, 7, 608, 8, + 201, 11, 12, 13, 536, 624, 843, 17, 17, 129, + 1097, 21, 22, 129, 129, 1076, 129, 26, 129, 1295, + 29, 30, 31, 1299, 1300, 199, 1302, 1303, 69, 1305, + 1306, 199, 1308, 7, 958, 478, 129, 11, 12, 13, + 954, 955, 129, 17, 53, 54, 55, 570, 1216, 129, + 129, 1112, 968, 129, 995, 112, 398, 129, 768, 69, + 117, 771, 119, 195, 121, 195, 123, 597, 125, 129, + 597, 597, 597, 989, 851, 785, 853, 986, 788, 988, + 129, 129, 129, 129, 129, 862, 0, 731, 1034, 866, + 1366, 868, 334, 870, 871, 872, 0, 1373, 875, 815, + 10, 878, 1163, 339, 881, 882, 337, 1383, 18, 148, + 149, 1387, 151, 152, 153, 154, 155, 27, 1034, 158, + 1392, 898, 0, 900, 34, 902, 942, 37, 1097, 906, + 907, 908, -1, -1, 911, 912, 1413, 914, 915, -1, + 917, -1, 52, 920, -1, -1, -1, -1, 925, 926, + 927, -1, 929, 63, 931, 932, 66, 7, 68, 769, + 1076, 11, 12, 13, 941, 942, -1, 17, 361, 79, + -1, 81, 22, 83, -1, 85, 786, -1, 1087, 372, + 373, 91, 362, 363, -1, -1, 366, 367, 381, 148, + 149, -1, 151, 152, 153, 388, 1112, -1, 391, -1, + 380, 394, -1, -1, -1, -1, 816, 387, 818, 402, + 390, 821, -1, 393, 824, -1, -1, 827, -1, 69, + 830, 401, -1, 1000, -1, -1, 836, -1, 1005, 1006, + 1007, 1008, -1, -1, 844, 1012, 1013, 1151, -1, 148, + -1, -1, 151, 152, 153, 154, 155, -1, -1, 158, + 1159, 148, 149, 1030, 151, 152, 153, 154, 155, -1, + 1037, 1038, 1039, -1, 1041, 1042, 1043, 1044, -1, 1046, + -1, 1048, -1, -1, -1, 1052, -1, 1054, -1, 1056, + -1, -1, -1, 1060, -1, -1, -1, -1, 7, 8, + -1, -1, 11, 12, 13, 14, -1, -1, 17, -1, + -1, -1, -1, -1, -1, -1, -1, 26, 1222, -1, + 29, 30, 31, 93, 94, 95, 96, 97, 98, 99, + 100, 101, -1, 1100, -1, 1102, -1, 1104, 1105, -1, + -1, -1, 1109, 1110, 53, 54, 55, 1114, 1115, -1, + 1117, -1, 952, 1120, 17, 1122, -1, -1, -1, -1, + 69, 17, 962, 26, 1131, -1, 29, 30, 31, 1136, + 26, 1138, 1139, 29, 30, 31, -1, 977, -1, 979, + 89, -1, -1, 983, -1, -1, -1, 43, -1, 1293, + 53, 54, 55, 993, -1, -1, -1, 53, 54, 55, + -1, 7, -1, -1, -1, 11, 12, 13, 14, -1, + -1, 17, -1, 1180, -1, 1182, -1, 1184, 1185, 1186, + 26, 1188, 1189, 29, 30, 31, 1193, 1194, -1, 1196, + 36, -1, -1, 9, -1, -1, 1203, 1204, -1, -1, + -1, 17, -1, -1, -1, -1, -1, 53, 54, 55, + 26, -1, -1, 29, 30, 31, -1, 1363, -1, -1, + 1227, 1228, 38, 69, -1, -1, 42, 43, -1, 1368, + -1, -1, -1, -1, -1, -1, 1375, 53, 54, 55, + -1, -1, 1082, 89, -1, 147, 148, 149, -1, 151, + 152, 153, 154, 155, -1, -1, -1, 1097, -1, 1266, + 1267, 1268, 1269, 1270, -1, -1, 1273, 1274, 1275, 1276, + 1277, 9, -1, 1280, -1, 1282, -1, 1284, -1, 17, + -1, -1, 1289, -1, -1, -1, -1, -1, 26, -1, + -1, 29, 30, 31, -1, -1, -1, -1, -1, -1, + 38, 1141, -1, -1, 1144, 43, -1, -1, 1148, -1, + -1, -1, 1152, 1320, -1, 53, 54, 55, -1, -1, + 1327, -1, 1329, -1, -1, -1, -1, -1, 1335, -1, + 1337, -1, -1, -1, -1, 1342, -1, -1, 1345, -1, + -1, -1, -1, 1350, -1, -1, 45, -1, -1, -1, + -1, -1, -1, 52, 53, -1, 55, -1, -1, 58, + -1, 60, -1, 62, -1, -1, -1, 66, 1208, 68, + -1, 70, -1, 72, -1, 74, 1216, 76, -1, 78, + -1, 80, -1, -1, 1224, 1392, -1, -1, -1, 88, + 1397, 1398, -1, -1, 1401, -1, 95, -1, 97, -1, + 99, -1, 101, -1, 103, 7, 105, 17, -1, 11, + 12, 13, 14, -1, -1, 17, 26, -1, -1, 29, + 30, 31, -1, -1, 26, -1, -1, 29, 30, 31, + -1, -1, -1, 43, -1, 45, -1, -1, -1, -1, + -1, -1, -1, 53, 54, 55, -1, -1, 147, -1, + -1, 53, 54, 55, -1, 1295, -1, 1297, 1298, 1299, + 1300, -1, 1302, 1303, 1304, 1305, 1306, 69, 1308, 10, + -1, -1, -1, -1, 9, -1, 17, 18, -1, -1, + -1, -1, 17, -1, -1, 26, 27, 89, 29, 30, + 31, 26, 191, 34, 29, 30, 31, -1, -1, 10, + -1, -1, 203, 38, 205, 46, 207, 18, -1, 210, + -1, 52, 53, 54, 55, -1, 27, -1, 53, 54, + 55, -1, 63, 34, -1, 66, -1, 68, -1, -1, + -1, -1, -1, -1, -1, 46, -1, -1, 79, -1, + 81, 52, 83, -1, 85, -1, -1, -1, -1, 248, + 91, -1, 63, -1, 253, 66, 255, 68, -1, 258, + 259, -1, -1, -1, -1, -1, -1, -1, 79, -1, + 81, -1, 83, -1, 85, -1, -1, -1, -1, -1, + 91, 280, 281, -1, -1, -1, 285, -1, -1, 288, + -1, -1, -1, -1, 17, -1, 295, -1, -1, -1, + 299, -1, -1, 26, -1, 304, 29, 30, 31, -1, + 309, -1, -1, 36, -1, 314, -1, -1, -1, -1, + 319, -1, 321, -1, -1, -1, 325, -1, 4, 5, + 53, 54, 55, 332, 10, -1, 335, -1, -1, 15, + -1, 17, 18, 344, 343, -1, -1, -1, 24, -1, + 351, 27, 353, 354, -1, -1, -1, -1, 34, 35, + -1, 37, -1, 39, -1, -1, -1, -1, 44, 370, + 46, -1, -1, 49, 375, -1, 52, -1, -1, -1, + -1, -1, -1, -1, 60, -1, -1, 63, -1, 65, + 66, 67, 68, -1, -1, -1, -1, -1, -1, -1, + 76, 77, -1, 79, 80, 81, -1, 83, 84, 85, + 86, 87, 88, -1, 90, 91, 92, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 376, - 377, -1, -1, -1, -1, -1, -1, -1, 385, -1, - -1, 429, -1, 431, -1, -1, -1, -1, 436, -1, - 397, -1, -1, 400, -1, -1, -1, -1, 446, -1, - 407, -1, -1, -1, 454, 453, -1, -1, -1, 10, - -1, -1, -1, 461, 464, -1, 17, 18, -1, -1, - -1, 471, -1, -1, -1, 26, 27, -1, 29, 30, - 31, 479, -1, 34, -1, -1, 486, 485, -1, -1, - -1, -1, 492, 493, -1, 46, 496, -1, -1, 499, - -1, 52, 53, 54, 55, -1, 506, -1, -1, 509, - -1, -1, 63, -1, 514, 66, 516, 68, -1, -1, - -1, -1, 520, -1, -1, 525, 524, -1, 79, -1, - 81, -1, 83, -1, 85, -1, -1, -1, 538, -1, - 91, -1, 542, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 557, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 568, -1, - -1, -1, 529, 530, -1, -1, -1, -1, -1, -1, + 429, -1, 431, -1, -1, -1, -1, 436, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 446, -1, -1, + -1, -1, -1, 454, 453, -1, -1, -1, -1, -1, + -1, -1, 461, 464, -1, -1, -1, -1, -1, -1, + 471, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 479, -1, -1, -1, -1, 486, 485, -1, -1, -1, + -1, 492, 493, -1, -1, 496, -1, -1, 499, -1, + -1, -1, -1, -1, -1, 506, -1, -1, 509, -1, + -1, -1, -1, 514, -1, 516, -1, -1, -1, -1, + -1, 520, -1, -1, 525, 524, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 538, -1, -1, + -1, 542, 93, 94, 95, 96, 97, 98, 99, 100, + 101, 102, 103, 104, 105, 106, 557, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 568, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 550, -1, -1, -1, -1, -1, 599, - -1, -1, -1, -1, -1, 605, -1, -1, -1, 609, - 567, -1, -1, -1, -1, 615, -1, 617, -1, -1, - -1, 621, -1, -1, -1, -1, -1, 627, -1, -1, - -1, -1, -1, 631, 634, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 606, - -1, -1, -1, 610, -1, -1, -1, 657, -1, -1, - 660, 661, 662, 663, -1, -1, -1, -1, -1, -1, - 668, -1, -1, -1, 674, 673, -1, -1, -1, -1, - -1, -1, -1, 683, -1, 685, -1, -1, 688, -1, - 690, -1, 692, -1, -1, -1, -1, -1, 698, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 716, -1, - 718, -1, -1, 721, -1, 723, -1, 725, -1, 727, - -1, -1, 730, -1, -1, -1, -1, -1, -1, -1, - 738, -1, -1, 741, -1, 743, -1, -1, -1, -1, - 748, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 599, -1, + -1, -1, -1, -1, 605, -1, -1, -1, 609, -1, + -1, -1, -1, -1, 615, -1, 617, -1, -1, -1, + 621, -1, -1, -1, -1, -1, 627, -1, -1, -1, + -1, -1, 631, 634, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 770, -1, 772, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 787, -1, 789, - -1, -1, -1, -1, -1, -1, 796, -1, 798, -1, - 800, -1, 802, -1, 761, -1, 317, 318, -1, 320, + -1, -1, -1, -1, -1, -1, 657, -1, -1, 660, + 661, 662, 663, -1, -1, -1, -1, -1, -1, 668, + -1, -1, -1, 674, 673, -1, -1, -1, -1, -1, + -1, -1, 683, -1, 685, -1, -1, 688, -1, 690, + -1, 692, -1, -1, -1, -1, -1, 698, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 781, -1, 783, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 837, -1, -1, - -1, -1, -1, -1, -1, 845, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 716, -1, 718, + -1, -1, 721, -1, 723, -1, 725, -1, 727, -1, + -1, 730, -1, -1, -1, -1, -1, -1, -1, 738, + -1, -1, 741, -1, 743, -1, -1, -1, -1, 748, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 820, -1, -1, 823, -1, -1, -1, - -1, -1, -1, -1, -1, 832, -1, -1, -1, -1, - -1, 838, -1, -1, 841, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 770, + -1, 772, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 787, -1, 789, -1, + -1, -1, -1, -1, -1, 796, -1, 798, -1, 800, + -1, 802, -1, -1, -1, -1, -1, 109, 110, 111, + 112, 113, -1, -1, 116, 117, 118, 119, 120, 121, + 122, 123, 124, 125, 126, 127, 128, -1, 130, 131, + 132, -1, -1, -1, -1, -1, 837, -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, 905, -1, -1, -1, -1, - 910, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 922, -1, -1, -1, -1, -1, -1, -1, - 928, -1, -1, 933, -1, -1, -1, -1, -1, -1, - 940, -1, -1, 943, 944, 945, 946, 947, 948, -1, - -1, 951, -1, 953, -1, -1, 956, -1, 469, -1, - -1, 961, -1, 963, 964, 965, 477, -1, -1, -1, - -1, 482, 972, -1, -1, -1, -1, -1, 489, 490, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 108, - 109, 110, 111, 112, 113, 114, 507, 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, 1026, -1, - -1, -1, 989, -1, -1, 1035, -1, -1, -1, -1, - -1, 998, -1, -1, -1, -1, -1, -1, -1, -1, - 1050, -1, 1052, -1, -1, -1, -1, -1, -1, 1057, - -1, -1, -1, -1, -1, -1, -1, -1, 1068, 1069, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 1087, -1, -1, - -1, -1, 1092, -1, -1, 1093, 1096, -1, -1, -1, - -1, 1099, -1, 1101, -1, -1, 1104, -1, -1, -1, - -1, -1, -1, -1, 1071, -1, -1, -1, -1, -1, + -1, 317, 318, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 1131, -1, -1, -1, 1094, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 666, 667, -1, 1158, -1, - 1160, 672, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 687, 1175, 689, 1177, - 691, -1, 693, -1, 1141, -1, -1, 1144, -1, -1, - -1, 1148, -1, -1, -1, 1193, -1, -1, -1, 1199, - -1, -1, 1159, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 1213, -1, -1, -1, -1, -1, -1, - -1, 1221, -1, 1223, 1224, -1, -1, -1, -1, -1, + 192, -1, -1, -1, -1, 197, -1, -1, -1, -1, + -1, -1, -1, -1, 905, -1, -1, -1, -1, 910, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 1204, 1205, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 1217, -1, -1, -1, -1, -1, -1, -1, -1, 1269, - -1, -1, -1, -1, -1, -1, 1276, -1, -1, -1, + -1, 922, -1, -1, -1, -1, -1, -1, -1, 928, + -1, -1, 933, -1, -1, -1, -1, -1, -1, 940, + -1, -1, 943, 944, 945, 946, 947, 948, -1, -1, + 951, -1, 953, -1, -1, 956, -1, -1, -1, -1, + 961, -1, 963, 964, 965, -1, -1, -1, -1, -1, + -1, 972, 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, 469, -1, -1, -1, -1, -1, -1, + -1, 477, -1, -1, -1, -1, 482, -1, 1027, -1, + -1, -1, -1, 489, 490, 1036, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 350, -1, + 1051, 507, 1053, 355, 356, -1, -1, -1, -1, 1058, + -1, -1, -1, -1, -1, -1, -1, -1, 1069, 1070, + -1, -1, -1, -1, 376, 377, -1, -1, -1, -1, + -1, -1, -1, 385, -1, -1, -1, -1, 1089, -1, + -1, -1, -1, 1094, -1, 397, 1095, 1098, 400, -1, + -1, -1, 1101, -1, 1103, 407, -1, 1106, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 1288, -1, 1292, -1, 1294, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 1308, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 1319, -1, -1, -1, -1, -1, -1, 1326, -1, - -1, -1, -1, -1, -1, -1, 1334, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 858, 859, 860, - 861, -1, 863, 864, -1, 1355, 1356, 4, 5, -1, - -1, -1, 873, 10, 875, 876, -1, -1, 15, -1, - 17, 18, 883, 884, -1, -1, -1, 24, -1, -1, - 27, -1, -1, -1, -1, 896, -1, 34, 35, -1, - 37, -1, 39, 1393, -1, -1, -1, 44, -1, 46, - 1400, -1, 49, -1, -1, 52, -1, -1, -1, -1, - -1, -1, -1, 60, -1, -1, 63, -1, 65, 66, - 67, 68, 1422, -1, -1, -1, -1, -1, -1, 76, - 77, -1, 79, 80, 81, -1, 83, 84, 85, 86, - 87, 88, -1, 90, 91, 92, 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, 1133, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 1011, -1, -1, -1, -1, 1016, 1017, -1, 1019, -1, - -1, -1, -1, -1, -1, -1, 1027, 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, 1160, + -1, 1162, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 1177, -1, + 1179, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 1195, -1, -1, -1, + 1201, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 666, 667, -1, -1, 1215, -1, 672, -1, -1, -1, + -1, -1, 1223, -1, 1225, 1226, -1, 529, 530, -1, + -1, 687, -1, 689, -1, 691, -1, 693, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 550, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 567, -1, -1, -1, -1, + 1271, -1, -1, -1, -1, -1, -1, 1278, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 1290, -1, 1294, -1, 1296, -1, -1, -1, -1, + -1, -1, -1, -1, 606, -1, -1, -1, 610, 1310, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 1321, -1, -1, -1, -1, -1, -1, 1328, + -1, -1, -1, -1, -1, -1, -1, 1336, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 1357, 1358, -1, -1, + -1, 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, 1395, 142, 143, 144, 145, 146, + -1, 1402, 858, 859, 860, 861, -1, 863, 864, -1, + -1, -1, -1, -1, -1, -1, -1, 873, -1, 875, + 876, -1, -1, 1424, -1, -1, -1, 883, 884, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 896, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 761, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 781, + -1, 783, -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, -1, 820, -1, + -1, 823, -1, -1, -1, -1, -1, -1, -1, -1, + 832, -1, -1, -1, -1, -1, 838, -1, -1, 841, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 1011, -1, -1, -1, -1, + 1016, 1017, -1, 1019, -1, -1, -1, -1, -1, 1025, + -1, -1, 1028, 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, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 1188, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 1203, -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, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 989, -1, -1, + -1, -1, -1, -1, -1, -1, 998, -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, -1, -1, 1190, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 1205, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 1284, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 1073, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 1312, -1, -1, 1315, 1316, -1, 1318, -1, -1, - -1, 1322, 1323, -1, 1325, -1, 1327, -1, -1, 1330, - 1331, -1, 1333, -1, 1335, -1, 1337, 1338, -1, 1340, - 1341, -1, 1343, 1344, -1, 1346, -1, 1348, 1349, -1, - 1351, -1, 1353, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 1096, -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, - -1, 1392, -1, 1394, 1395, -1, 1397, 1398, 1399, -1, - 1401, 1402, 1403, 1404, -1, -1, -1, -1, -1, -1, + 1286, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 1143, -1, -1, 1146, -1, -1, -1, 1150, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 1314, 1161, + -1, 1317, 1318, -1, 1320, -1, -1, -1, 1324, 1325, + -1, 1327, -1, 1329, -1, -1, 1332, 1333, -1, 1335, + -1, 1337, -1, 1339, 1340, -1, 1342, 1343, -1, 1345, + 1346, -1, 1348, -1, 1350, 1351, -1, 1353, -1, 1355, + -1, -1, -1, -1, 1206, 1207, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 1219, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 1421, -1, 1423 + -1, -1, -1, -1, -1, -1, -1, -1, 1394, -1, + 1396, 1397, -1, 1399, 1400, 1401, -1, 1403, 1404, 1405, + 1406, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 1423, -1, 1425 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing @@ -2064,47 +2080,47 @@ static const yytype_uint16 yystos[] = 203, 482, 482, 204, 207, 202, 207, 204, 204, 203, 203, 204, 204, 512, 203, 203, 203, 203, 203, 203, 203, 238, 425, 429, 203, 172, 267, 267, 203, 373, - 203, 7, 11, 12, 13, 256, 257, 386, 203, 203, - 203, 180, 195, 196, 203, 218, 220, 223, 229, 234, - 229, 234, 234, 234, 169, 226, 169, 233, 184, 205, - 237, 494, 167, 385, 205, 431, 204, 383, 429, 513, - 516, 204, 204, 204, 204, 259, 419, 419, 259, 259, - 259, 202, 259, 204, 168, 198, 203, 204, 204, 204, - 204, 209, 209, 209, 209, 204, 204, 230, 203, 207, - 203, 204, 330, 507, 202, 204, 514, 8, 282, 284, - 281, 284, 282, 283, 284, 203, 203, 266, 281, 180, - 197, 198, 223, 229, 234, 229, 234, 234, 234, 169, - 227, 260, 203, 7, 11, 12, 13, 14, 69, 426, - 427, 428, 203, 202, 384, 208, 429, 516, 203, 204, - 272, 202, 204, 270, 202, 207, 204, 275, 202, 204, - 204, 392, 198, 204, 204, 204, 209, 204, 330, 202, - 504, 204, 514, 514, 7, 11, 12, 13, 14, 69, - 89, 208, 252, 253, 254, 255, 261, 265, 305, 205, - 285, 208, 281, 305, 285, 208, 283, 285, 267, 36, - 208, 305, 393, 394, 229, 234, 234, 234, 169, 228, - 203, 266, 203, 385, 202, 202, 204, 204, 270, 207, - 204, 275, 204, 259, 204, 207, 207, 202, 204, 203, - 204, 262, 204, 505, 259, 266, 266, 208, 108, 109, - 110, 111, 112, 113, 114, 116, 117, 118, 119, 120, - 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, - 131, 132, 133, 134, 135, 136, 137, 138, 139, 142, - 143, 144, 145, 146, 298, 107, 115, 140, 141, 286, - 289, 298, 107, 115, 140, 141, 291, 294, 298, 203, - 393, 205, 395, 234, 267, 203, 208, 494, 507, 203, - 203, 204, 262, 204, 296, 204, 204, 204, 204, 203, - 204, 204, 204, 204, 204, 203, 204, 207, 330, 259, - 207, 202, 267, 203, 22, 238, 261, 297, 303, 304, - 203, 20, 238, 253, 287, 299, 300, 303, 287, 21, - 238, 253, 288, 301, 302, 303, 288, 238, 253, 290, - 303, 238, 292, 299, 303, 287, 238, 293, 301, 303, - 293, 238, 295, 303, 203, 504, 259, 259, 259, 204, - 259, 202, 259, 259, 204, 259, 202, 204, 259, 259, - 259, 204, 259, 202, 204, 259, 259, 259, 204, 259, - 259, 204, 259, 259, 259, 204, 259, 259, 259, 259, - 203, 203, 261, 180, 253, 303, 169, 253, 253, 303, - 169, 253, 253, 303, 303, 505, 259, 203, 259, 204, - 259, 204, 259, 259, 204, 259, 203, 259, 259, 259, - 259, 253, 258, 253, 259, 203, 259 + 203, 7, 11, 12, 13, 238, 256, 257, 386, 203, + 203, 203, 180, 195, 196, 203, 218, 220, 223, 229, + 234, 229, 234, 234, 234, 169, 226, 169, 233, 184, + 205, 237, 494, 167, 385, 205, 431, 204, 383, 429, + 513, 516, 204, 204, 204, 204, 259, 419, 419, 259, + 259, 259, 259, 202, 259, 204, 168, 198, 203, 204, + 204, 204, 204, 209, 209, 209, 209, 204, 204, 230, + 203, 207, 203, 204, 330, 507, 202, 204, 514, 8, + 282, 284, 281, 284, 282, 283, 284, 203, 203, 266, + 281, 180, 197, 198, 223, 229, 234, 229, 234, 234, + 234, 169, 227, 260, 203, 7, 11, 12, 13, 14, + 69, 426, 427, 428, 203, 202, 384, 208, 429, 516, + 203, 204, 272, 202, 204, 270, 202, 207, 204, 275, + 202, 204, 204, 392, 198, 204, 204, 204, 209, 204, + 330, 202, 504, 204, 514, 514, 7, 11, 12, 13, + 14, 69, 89, 208, 252, 253, 254, 255, 261, 265, + 305, 205, 285, 208, 281, 305, 285, 208, 283, 285, + 267, 36, 208, 305, 393, 394, 229, 234, 234, 234, + 169, 228, 203, 266, 203, 385, 202, 202, 204, 204, + 270, 207, 204, 275, 204, 259, 204, 207, 207, 202, + 204, 203, 204, 262, 204, 505, 259, 266, 266, 208, + 108, 109, 110, 111, 112, 113, 114, 116, 117, 118, + 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, + 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, + 139, 142, 143, 144, 145, 146, 298, 107, 115, 140, + 141, 286, 289, 298, 107, 115, 140, 141, 291, 294, + 298, 203, 393, 205, 395, 234, 267, 203, 208, 494, + 507, 203, 203, 204, 262, 204, 296, 204, 204, 204, + 204, 203, 204, 204, 204, 204, 204, 203, 204, 207, + 330, 259, 207, 202, 267, 203, 22, 238, 261, 297, + 303, 304, 203, 20, 238, 253, 287, 299, 300, 303, + 287, 21, 238, 253, 288, 301, 302, 303, 288, 238, + 253, 290, 303, 238, 292, 299, 303, 287, 238, 293, + 301, 303, 293, 238, 295, 303, 203, 504, 259, 259, + 259, 204, 259, 202, 259, 259, 204, 259, 202, 204, + 259, 259, 259, 204, 259, 202, 204, 259, 259, 259, + 204, 259, 259, 204, 259, 259, 259, 204, 259, 259, + 259, 259, 203, 203, 261, 180, 253, 303, 169, 253, + 253, 303, 169, 253, 253, 303, 303, 505, 259, 203, + 259, 204, 259, 204, 259, 259, 204, 259, 203, 259, + 259, 259, 259, 253, 258, 253, 259, 203, 259 }; /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ @@ -2156,30 +2172,30 @@ static const yytype_uint16 yyr1[] = 362, 363, 363, 364, 364, 364, 364, 365, 366, 366, 366, 366, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 375, 375, 376, 377, 378, 379, 379, 380, - 381, 382, 382, 383, 384, 385, 386, 387, 387, 388, - 389, 390, 390, 391, 392, 392, 392, 392, 392, 393, - 394, 395, 396, 396, 397, 398, 398, 398, 399, 400, - 400, 401, 402, 402, 403, 404, 405, 406, 406, 407, - 408, 409, 410, 410, 410, 410, 410, 411, 411, 412, - 413, 414, 414, 415, 416, 417, 418, 419, 419, 419, - 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, - 428, 428, 428, 428, 428, 429, 430, 431, 432, 432, - 432, 433, 433, 434, 435, 435, 436, 437, 437, 438, - 439, 440, 441, 441, 441, 442, 443, 444, 445, 446, - 447, 448, 449, 450, 450, 450, 450, 451, 452, 452, - 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, - 463, 464, 465, 466, 466, 466, 466, 466, 466, 466, - 466, 466, 466, 466, 466, 467, 467, 468, 468, 468, - 469, 470, 471, 472, 472, 473, 473, 473, 474, 475, - 475, 476, 477, 477, 477, 477, 477, 477, 477, 477, - 477, 477, 477, 477, 477, 477, 478, 478, 478, 478, - 478, 478, 478, 479, 480, 480, 481, 482, 482, 482, - 482, 482, 482, 482, 483, 484, 485, 486, 487, 488, - 489, 490, 491, 492, 493, 494, 495, 496, 497, 497, - 498, 499, 499, 499, 499, 499, 500, 501, 502, 502, - 503, 504, 504, 504, 504, 505, 505, 505, 505, 506, - 507, 508, 509, 510, 511, 511, 512, 513, 513, 514, - 514, 514, 514, 515, 516 + 381, 382, 382, 382, 383, 384, 385, 386, 387, 387, + 388, 389, 390, 390, 391, 392, 392, 392, 392, 392, + 393, 394, 395, 396, 396, 397, 398, 398, 398, 399, + 400, 400, 401, 402, 402, 403, 404, 405, 406, 406, + 407, 408, 409, 410, 410, 410, 410, 410, 411, 411, + 412, 413, 414, 414, 415, 416, 417, 418, 419, 419, + 419, 419, 420, 421, 422, 423, 424, 425, 426, 427, + 428, 428, 428, 428, 428, 428, 429, 430, 431, 432, + 432, 432, 433, 433, 434, 435, 435, 436, 437, 437, + 438, 439, 440, 441, 441, 441, 442, 443, 444, 445, + 446, 447, 448, 449, 450, 450, 450, 450, 451, 452, + 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, + 462, 463, 464, 465, 466, 466, 466, 466, 466, 466, + 466, 466, 466, 466, 466, 466, 467, 467, 468, 468, + 468, 469, 470, 471, 472, 472, 473, 473, 473, 474, + 475, 475, 476, 477, 477, 477, 477, 477, 477, 477, + 477, 477, 477, 477, 477, 477, 477, 478, 478, 478, + 478, 478, 478, 478, 479, 480, 480, 481, 482, 482, + 482, 482, 482, 482, 482, 483, 484, 485, 486, 487, + 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, + 497, 498, 499, 499, 499, 499, 499, 500, 501, 502, + 502, 503, 504, 504, 504, 504, 505, 505, 505, 505, + 506, 507, 508, 509, 510, 511, 511, 512, 513, 513, + 514, 514, 514, 514, 515, 516 }; /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */ @@ -2231,30 +2247,30 @@ static const yytype_uint8 yyr2[] = 10, 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, + 7, 0, 3, 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, 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 + 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_grammar.y b/src/wkt2_grammar.y index 4f30b5b2..fc2e8bf0 100644 --- a/src/wkt2_grammar.y +++ b/src/wkt2_grammar.y @@ -1073,6 +1073,7 @@ map_projection_parameter: parameter_keyword left_delimiter parameter_name right_delimiter opt_separator_param_unit_identifier_list: + | wkt_separator identifier opt_separator_identifier_list | wkt_separator map_projection_parameter_unit opt_separator_identifier_list parameter_keyword: T_PARAMETER diff --git a/test/unit/test_io.cpp b/test/unit/test_io.cpp index 3d8df998..dff8ec45 100644 --- a/test/unit/test_io.cpp +++ b/test/unit/test_io.cpp @@ -1658,16 +1658,21 @@ TEST(wkt_parse, wkt2_projected) { " ID[\"EPSG\",9122]],\n" " ID[\"EPSG\",8801]],\n" " PARAMETER[\"Longitude of natural origin\",3,\n" - " ANGLEUNIT[\"degree\",0.0174532925199433,\n" - " ID[\"EPSG\",9122]],\n" + // Volontary omit LENGTHUNIT to check the WKT grammar accepts + // Check that we default to degree + //" ANGLEUNIT[\"degree\",0.0174532925199433,\n" + //" ID[\"EPSG\",9122]],\n" " ID[\"EPSG\",8802]],\n" " PARAMETER[\"Scale factor at natural origin\",0.9996,\n" - " SCALEUNIT[\"unity\",1,\n" - " ID[\"EPSG\",9201]],\n" + // Check that we default to unity + //" SCALEUNIT[\"unity\",1,\n" + //" ID[\"EPSG\",9201]],\n" " ID[\"EPSG\",8805]],\n" " PARAMETER[\"False easting\",500000,\n" - " LENGTHUNIT[\"metre\",1,\n" - " ID[\"EPSG\",9001]],\n" + // Volontary omit LENGTHUNIT to check the WKT grammar accepts + // Check that we default to metre + //" LENGTHUNIT[\"metre\",1,\n" + //" ID[\"EPSG\",9001]],\n" " ID[\"EPSG\",8806]],\n" " PARAMETER[\"False northing\",0,\n" " LENGTHUNIT[\"metre\",1,\n" -- cgit v1.2.3 From 7eda8aacb65ca0a14eddb5721b24bdcf89d36a4e Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Tue, 17 Nov 2020 16:15:50 +0100 Subject: github actions: update to conda-incubator/setup-miniconda@v2 to be compatible with latest github action security fix constraints --- .github/workflows/conda.yml | 2 +- .github/workflows/doc_build.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/conda.yml b/.github/workflows/conda.yml index 80828772..296754f1 100644 --- a/.github/workflows/conda.yml +++ b/.github/workflows/conda.yml @@ -20,7 +20,7 @@ jobs: steps: - uses: actions/checkout@v2 - - uses: goanpeca/setup-miniconda@v1 + - uses: conda-incubator/setup-miniconda@v2 with: channels: conda-forge auto-update-conda: true diff --git a/.github/workflows/doc_build.yml b/.github/workflows/doc_build.yml index fa4546b2..52bf2b63 100644 --- a/.github/workflows/doc_build.yml +++ b/.github/workflows/doc_build.yml @@ -11,7 +11,7 @@ jobs: steps: - name: Checkout uses: actions/checkout@v2 - - uses: goanpeca/setup-miniconda@v1 + - uses: conda-incubator/setup-miniconda@v2 with: channels: conda-forge auto-update-conda: true -- cgit v1.2.3 From c560b7957664c32e2465e8425abaccc5a6b2607d Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Tue, 17 Nov 2020 12:39:48 +0100 Subject: cs2cs, cct, proj and geod: fflush(stdout) after each line to emit each result as soon as it is produced This is needed when working with pipes, when stdout is not an interactive terminal, and thus the behaviour is to have it buffered as a regular file, whereas with an interactive terminal, each newline character causes an implicit flush. --- src/apps/cct.cpp | 2 ++ src/apps/cs2cs.cpp | 1 + src/apps/geod.cpp | 1 + src/apps/proj.cpp | 3 +++ 4 files changed, 7 insertions(+) diff --git a/src/apps/cct.cpp b/src/apps/cct.cpp index c482efc2..fa75267a 100644 --- a/src/apps/cct.cpp +++ b/src/apps/cct.cpp @@ -470,6 +470,8 @@ int main(int argc, char **argv) { decimals_distances, point.xyzt.z, point.xyzt.t, comment_delimiter, comment ); + if( fout == stdout ) + fflush(stdout); } proj_destroy(P); diff --git a/src/apps/cs2cs.cpp b/src/apps/cs2cs.cpp index 58c164c9..1a33d444 100644 --- a/src/apps/cs2cs.cpp +++ b/src/apps/cs2cs.cpp @@ -217,6 +217,7 @@ static void process(FILE *fid) printf("%s", s); else printf("\n"); + fflush(stdout); } } diff --git a/src/apps/geod.cpp b/src/apps/geod.cpp index 919430ca..35a8e826 100644 --- a/src/apps/geod.cpp +++ b/src/apps/geod.cpp @@ -124,6 +124,7 @@ process(FILE *fid) { (void)fputs(rtodms(pline, al21, 0, 0), stdout); } (void)fputs(s, stdout); + fflush(stdout); } } diff --git a/src/apps/proj.cpp b/src/apps/proj.cpp index 0bf98b3a..c9bd8950 100644 --- a/src/apps/proj.cpp +++ b/src/apps/proj.cpp @@ -171,6 +171,7 @@ static void process(FILE *fid) { (void)fputs("\t<* * * * * *>", stdout); } (void)fputs(bin_in ? "\n" : s, stdout); + fflush(stdout); } } @@ -286,6 +287,8 @@ static void vprocess(FILE *fid) { (void)fputs(proj_rtodms(pline, facs.meridian_convergence, 0, 0), stdout); (void)printf(" [ %.8f ]\n", facs.meridian_convergence * RAD_TO_DEG); (void)printf("Max-min (Tissot axis a-b) scale error: %.5f %.5f\n\n", facs.tissot_semimajor, facs.tissot_semiminor); + + fflush(stdout); } } -- cgit v1.2.3 From 0476db2b05b9232b7c579901cf8a873ef34ae62f Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Wed, 18 Nov 2020 17:19:41 +0100 Subject: Database: update to EPSG v10.007 --- data/sql/alias_name.sql | 17 ++++++++++------- data/sql/conversion.sql | 2 ++ data/sql/customizations.sql | 6 ------ data/sql/extent.sql | 5 +++-- data/sql/geodetic_crs.sql | 8 ++++++-- data/sql/geodetic_datum.sql | 4 ++-- data/sql/grid_transformation.sql | 10 +++++++++- data/sql/helmert_transformation.sql | 16 ++++++++++------ data/sql/metadata.sql | 4 ++-- data/sql/projected_crs.sql | 2 ++ data/sql/scope.sql | 1 + data/sql/supersession.sql | 2 ++ data/sql/vertical_crs.sql | 4 ++-- scripts/build_db.py | 5 +++++ 14 files changed, 56 insertions(+), 30 deletions(-) diff --git a/data/sql/alias_name.sql b/data/sql/alias_name.sql index 88826f25..6dcb36c1 100644 --- a/data/sql/alias_name.sql +++ b/data/sql/alias_name.sql @@ -609,6 +609,8 @@ INSERT INTO "alias_name" VALUES('vertical_datum','EPSG','1130','JGD2000 (vertica INSERT INTO "alias_name" VALUES('vertical_datum','EPSG','1129','JSLD72','EPSG'); INSERT INTO "alias_name" VALUES('geodetic_datum','EPSG','1132','RDN2008','EPSG'); INSERT INTO "alias_name" VALUES('vertical_datum','EPSG','1288','BI','EPSG'); +INSERT INTO "alias_name" VALUES('geodetic_datum','EPSG','6258','European Terrestrial Reference System 1989','EPSG'); +INSERT INTO "alias_name" VALUES('geodetic_datum','EPSG','6326','World Geodetic System 1984','EPSG'); INSERT INTO "alias_name" VALUES('projected_crs','EPSG','21100','Genuk / NEIEZ','EPSG'); INSERT INTO "alias_name" VALUES('projected_crs','EPSG','2140','NAD83(CSRS98) / SCoPQ zone 3','EPSG'); INSERT INTO "alias_name" VALUES('projected_crs','EPSG','2141','NAD83(CSRS98) / SCoPQ zone 4','EPSG'); @@ -720,7 +722,6 @@ INSERT INTO "alias_name" VALUES('vertical_crs','EPSG','5701','Newlyn height','EP INSERT INTO "alias_name" VALUES('vertical_crs','EPSG','5702','National Geodetic Vertical Datum of 1929 height (ftUS)','EPSG'); INSERT INTO "alias_name" VALUES('vertical_crs','EPSG','5703','North American Vertical Datum of 1988 height (m)','EPSG'); INSERT INTO "alias_name" VALUES('vertical_crs','EPSG','5709','Normaal Amsterdams Peil height','EPSG'); -INSERT INTO "alias_name" VALUES('vertical_crs','EPSG','5711','Australian Height Datum height','EPSG'); INSERT INTO "alias_name" VALUES('vertical_crs','EPSG','5712','Australian Height Datum (Tasmania) height','EPSG'); INSERT INTO "alias_name" VALUES('vertical_crs','EPSG','5713','Canadian Geodetic Vertical Datum of 1928 height','EPSG'); INSERT INTO "alias_name" VALUES('vertical_crs','EPSG','5714','mean sea level height','EPSG'); @@ -4244,8 +4245,6 @@ INSERT INTO "alias_name" VALUES('projected_crs','EPSG','3088','NAD83 / KY1Z (m)' INSERT INTO "alias_name" VALUES('geodetic_crs','EPSG','9379','726','EPSG'); INSERT INTO "alias_name" VALUES('projected_crs','EPSG','3857','WGS 84 / Popular Visualisation Pseudo-Mercator','EPSG'); INSERT INTO "alias_name" VALUES('geodetic_crs','EPSG','9379','IGb14 - LatLonEHt','EPSG'); -INSERT INTO "alias_name" VALUES('geodetic_crs','EPSG','9380','725','EPSG'); -INSERT INTO "alias_name" VALUES('geodetic_crs','EPSG','9380','IGb14 - LatLon','EPSG'); INSERT INTO "alias_name" VALUES('vertical_crs','EPSG','3886','National Elevation Network height','EPSG'); INSERT INTO "alias_name" VALUES('projected_crs','EPSG','3893','ED50 / Iraq Nat. Grid','EPSG'); INSERT INTO "alias_name" VALUES('geodetic_crs','EPSG','4743','Karbala 1979 (Polservice)','EPSG'); @@ -5086,8 +5085,6 @@ INSERT INTO "alias_name" VALUES('projected_crs','EPSG','8383','NCRS Las Vegas (m INSERT INTO "alias_name" VALUES('projected_crs','EPSG','8387','NCRS Las Vegas high (ftUS)','EPSG'); INSERT INTO "alias_name" VALUES('projected_crs','EPSG','8433','Macao 1920 Grid System','EPSG'); INSERT INTO "alias_name" VALUES('projected_crs','EPSG','5514','S-JTSK [JTSK] / Krovak East North','EPSG'); -INSERT INTO "alias_name" VALUES('vertical_crs','EPSG','5711','AHD71 height','EPSG'); -INSERT INTO "alias_name" VALUES('vertical_crs','EPSG','5711','AHD-TAS83 height','EPSG'); INSERT INTO "alias_name" VALUES('projected_crs','EPSG','4414','GGN93 / Guam Map Grid','EPSG'); INSERT INTO "alias_name" VALUES('projected_crs','EPSG','4414','Guam Geodetic Network 1993 / Guam Map Grid','EPSG'); INSERT INTO "alias_name" VALUES('projected_crs','EPSG','4414','NAD83 / Guam Map Grid','EPSG'); @@ -5608,8 +5605,6 @@ INSERT INTO "alias_name" VALUES('geodetic_crs','EPSG','4202','298','EPSG'); INSERT INTO "alias_name" VALUES('geodetic_crs','EPSG','4202','AGD66 - LatLon','EPSG'); INSERT INTO "alias_name" VALUES('geodetic_crs','EPSG','4203','350','EPSG'); INSERT INTO "alias_name" VALUES('geodetic_crs','EPSG','4203','AGD84 - LatLon','EPSG'); -INSERT INTO "alias_name" VALUES('vertical_crs','EPSG','5711','339','EPSG'); -INSERT INTO "alias_name" VALUES('vertical_crs','EPSG','5711','AHD - NOHt','EPSG'); INSERT INTO "alias_name" VALUES('geodetic_crs','EPSG','7844','284','EPSG'); INSERT INTO "alias_name" VALUES('geodetic_crs','EPSG','7844','GDA2020 - LatLon','EPSG'); INSERT INTO "alias_name" VALUES('geodetic_crs','EPSG','7843','329','EPSG'); @@ -7194,3 +7189,11 @@ INSERT INTO "alias_name" VALUES('projected_crs','EPSG','6708','RDN2008 / TM33',' INSERT INTO "alias_name" VALUES('projected_crs','EPSG','6709','RDN2008 / TM34','EPSG'); INSERT INTO "alias_name" VALUES('projected_crs','EPSG','2062','Madrid (Madrid) / Spain LCC','EPSG'); INSERT INTO "alias_name" VALUES('projected_crs','EPSG','2062','Madrid - LCC','EPSG'); +INSERT INTO "alias_name" VALUES('geodetic_crs','EPSG','9380','725','EPSG'); +INSERT INTO "alias_name" VALUES('geodetic_crs','EPSG','9380','IGb14 - LatLon','EPSG'); +INSERT INTO "alias_name" VALUES('vertical_crs','EPSG','5711','Australian Height Datum height','EPSG'); +INSERT INTO "alias_name" VALUES('vertical_crs','EPSG','5711','AHD71 height','EPSG'); +INSERT INTO "alias_name" VALUES('vertical_crs','EPSG','5711','AHD-TAS83 height','EPSG'); +INSERT INTO "alias_name" VALUES('vertical_crs','EPSG','5711','339','EPSG'); +INSERT INTO "alias_name" VALUES('vertical_crs','EPSG','5711','AHD - NOHt','EPSG'); +INSERT INTO "alias_name" VALUES('projected_crs','EPSG','9498','CABA-P07','EPSG'); diff --git a/data/sql/conversion.sql b/data/sql/conversion.sql index e515f198..76a4bfc1 100644 --- a/data/sql/conversion.sql +++ b/data/sql/conversion.sql @@ -1734,6 +1734,8 @@ INSERT INTO "conversion" VALUES('EPSG','9385','AbInvA96_2020-TM','In conjunction INSERT INTO "usage" VALUES('EPSG','14062','conversion','EPSG','9385','EPSG','4589','EPSG','1196'); INSERT INTO "conversion" VALUES('EPSG','9455','GBK19-TM','In conjunction with transformation ETRS89 to GBK19-IRF (1) (code 9454), emulates the TPEN11 Snake projection.','EPSG','9807','Transverse Mercator','EPSG','8801','Latitude of natural origin',55.45,'EPSG','9110','EPSG','8802','Longitude of natural origin',-4.21,'EPSG','9110','EPSG','8805','Scale factor at natural origin',1.0,'EPSG','9201','EPSG','8806','False easting',93720.394,'EPSG','9001','EPSG','8807','False northing',113870.493,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0); INSERT INTO "usage" VALUES('EPSG','14130','conversion','EPSG','9455','EPSG','4607','EPSG','1141'); +INSERT INTO "conversion" VALUES('EPSG','9497','Gauss-Kruger CABA 2019','Projection created in 2017 for the purpose of modernizing the city''s cadastre and linking it to modern reference frames. Origin approximates the 1919 origin of the cross of the main tower of the San José de Flores church ("0 de Flores" plane grid).','EPSG','9807','Transverse Mercator','EPSG','8801','Latitude of natural origin',-34.374536,'EPSG','9110','EPSG','8802','Longitude of natural origin',-58.274791,'EPSG','9110','EPSG','8805','Scale factor at natural origin',1.0,'EPSG','9201','EPSG','8806','False easting',20000.0,'EPSG','9001','EPSG','8807','False northing',70000.0,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0); +INSERT INTO "usage" VALUES('EPSG','14242','conversion','EPSG','9497','EPSG','4610','EPSG','1056'); INSERT INTO "conversion" VALUES('EPSG','10101','Alabama CS27 East zone','','EPSG','9807','Transverse Mercator','EPSG','8801','Latitude of natural origin',30.3,'EPSG','9110','EPSG','8802','Longitude of natural origin',-85.5,'EPSG','9110','EPSG','8805','Scale factor at natural origin',0.99996,'EPSG','9201','EPSG','8806','False easting',500000.0,'EPSG','9003','EPSG','8807','False northing',0.0,'EPSG','9003',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0); INSERT INTO "usage" VALUES('EPSG','11101','conversion','EPSG','10101','EPSG','2154','EPSG','1142'); INSERT INTO "conversion" VALUES('EPSG','10102','Alabama CS27 West zone','','EPSG','9807','Transverse Mercator','EPSG','8801','Latitude of natural origin',30.0,'EPSG','9110','EPSG','8802','Longitude of natural origin',-87.3,'EPSG','9110','EPSG','8805','Scale factor at natural origin',0.999933333,'EPSG','9201','EPSG','8806','False easting',500000.0,'EPSG','9003','EPSG','8807','False northing',0.0,'EPSG','9003',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0); diff --git a/data/sql/customizations.sql b/data/sql/customizations.sql index beaaf8fd..c53a324d 100644 --- a/data/sql/customizations.sql +++ b/data/sql/customizations.sql @@ -274,12 +274,6 @@ INSERT INTO "alias_name" VALUES('geodetic_datum','EPSG','6277','OSGB36','PROJ'); -- to the EPSG:4326 CRS, as this is a common use case (https://github.com/OSGeo/PROJ/issues/2216) INSERT INTO "alias_name" VALUES('geodetic_crs','EPSG','4326','WGS84','PROJ'); ----- Aliases from old datum names to new datum ensemble names ----- - --- Those have been reported to IOGP and will hopefully be integrated in a later EPSG release -INSERT INTO "alias_name" VALUES('geodetic_datum','EPSG','6326','World Geodetic System 1984','PROJ'); -INSERT INTO "alias_name" VALUES('geodetic_datum','EPSG','6258','European Terrestrial Reference System 1989','PROJ'); - ---- PROJ unit short names ----- -- Linear units diff --git a/data/sql/extent.sql b/data/sql/extent.sql index d82a8ff9..1c94827d 100644 --- a/data/sql/extent.sql +++ b/data/sql/extent.sql @@ -2442,7 +2442,7 @@ INSERT INTO "extent" VALUES('EPSG','3462','Mexico - offshore GoM - Campeche area INSERT INTO "extent" VALUES('EPSG','3463','World - 86°S to 86°N','World between 86°S and 86°N.',-86.0,86.0,-180.0,180.0,0); INSERT INTO "extent" VALUES('EPSG','3464','World - N hemisphere - 12°E to 18°E - by country and WGS 72BE','Between 12°E and 18°E, northern hemisphere between equator and 84°N, onshore and offshore. Chad - west of 18°E.',0.0,84.0,12.0,18.0,0); INSERT INTO "extent" VALUES('EPSG','3465','World - N hemisphere - 18°E to 24°E - by country and WGS 72BE','Between 12°E and 18°E, northern hemisphere between equator and 84°N, onshore and offshore. Chad - east of 18°E.',0.0,84.0,18.0,24.0,0); -INSERT INTO "extent" VALUES('EPSG','3466','China - Ordos - 108°E to 108.5°E and 37.75°N to 38.25°N','China - Ordos basin.',35.0,39.0,107.0,110.01,0); +INSERT INTO "extent" VALUES('EPSG','3466','China - Ordos basin','China - Ordos basin.',35.0,39.0,107.0,110.007,0); INSERT INTO "extent" VALUES('EPSG','3467','North America - Great Lakes basin','Canada and United States (USA) - Great Lakes basin.',40.99,50.74,-93.17,-74.47,0); INSERT INTO "extent" VALUES('EPSG','3468','North America - Great Lakes basin and St Lawrence Seaway','Canada and United States (USA) - Great Lakes basin and St Lawrence Seaway.',40.99,52.22,-93.17,-54.75,0); INSERT INTO "extent" VALUES('EPSG','3469','China - offshore - Yellow Sea','China - offshore - Huang Hai (Yellow Sea).',31.23,37.4,119.23,125.06,0); @@ -3518,7 +3518,7 @@ INSERT INTO "extent" VALUES('EPSG','4539','Angola - east of 18°E','Angola - eas INSERT INTO "extent" VALUES('EPSG','4540','Africa - South Africa, Lesotho and Eswatini.','Eswatini (Swaziland); Lesotho; South Africa - onshore and offshore.',-50.32,-22.13,13.33,42.85,0); INSERT INTO "extent" VALUES('EPSG','4541','Vietnam - Dien Bien and Lai Chau','Vietnam - Dien Bien and Lai Chau provinces.',20.89,22.82,102.14,103.99,0); INSERT INTO "extent" VALUES('EPSG','4542','Kosovo','Kosovo.',41.85,43.25,19.97,21.8,0); -INSERT INTO "extent" VALUES('EPSG','4543','Serbia','Serbia including Vojvodinja.',42.23,46.19,18.81,23.01,0); +INSERT INTO "extent" VALUES('EPSG','4543','Serbia','Serbia including Vojvodina.',42.232494354248,46.18111038208,18.81702041626,23.004997253418,0); INSERT INTO "extent" VALUES('EPSG','4544','North America - Canada, US (Conus+AK), PRVI','North America - onshore and offshore: Canada - Alberta; British Columbia; Manitoba; New Brunswick; Newfoundland and Labrador; Northwest Territories; Nova Scotia; Nunavut; Ontario; Prince Edward Island; Quebec; Saskatchewan; Yukon. Puerto Rico. United States (USA) - Alabama; Alaska; Arizona; Arkansas; California; Colorado; Connecticut; Delaware; Florida; Georgia; Idaho; Illinois; Indiana; Iowa; Kansas; Kentucky; Louisiana; Maine; Maryland; Massachusetts; Michigan; Minnesota; Mississippi; Missouri; Montana; Nebraska; Nevada; New Hampshire; New Jersey; New Mexico; New York; North Carolina; North Dakota; Ohio; Oklahoma; Oregon; Pennsylvania; Rhode Island; South Carolina; South Dakota; Tennessee; Texas; Utah; Vermont; Virginia; Washington; West Virginia; Wisconsin; Wyoming. US Virgin Islands.',14.92,86.46,167.65,-47.74,0); INSERT INTO "extent" VALUES('EPSG','4545','Vietnam - Ca Mau and Kien Giang','Vietnam - Ca Mau and Kien Giang provinces.',8.33,10.55,103.4,105.54,0); INSERT INTO "extent" VALUES('EPSG','4546','Vietnam - An Giang, Lao Cai, Nghe An, Phu Tho, Yen Bai','Vietnam - An Giang, Lao Cai, Nghe An, Phu Tho and Yen Bai provinces.',10.18,22.85,103.53,105.86,0); @@ -3585,3 +3585,4 @@ INSERT INTO "extent" VALUES('EPSG','4606','Europe - British Isles - UK and Irela INSERT INTO "extent" VALUES('EPSG','4607','UK - Glasgow to Kilmarnock','UK - on or related to the rail route from Glasgow via Barrhead to Kilmarnock and the branch to East Kilbride.',55.55,55.95,-4.65,-4.05,0); INSERT INTO "extent" VALUES('EPSG','4608','Europe - EVRF2019','Europe - onshore - Andorra; Austria; Belarus; Belgium; Bosnia and Herzegovina; Bulgaria; Croatia; Czechia; Denmark; Estonia; Finland; France - mainland; Germany; Gibraltar, Hungary; Italy - mainland and Sicily; Latvia; Liechtenstein; Lithuania; Luxembourg; Netherlands; North Macedonia; Norway; Poland; Portugal - mainland; Romania; Russia – west of approximately 60°E; San Marino; Slovakia; Slovenia; Spain - mainland; Sweden; Switzerland; United Kingdom (UK) - Great Britain mainland; Ukraine; Vatican City State.',35.95,77.07,-9.56,69.15,0); INSERT INTO "extent" VALUES('EPSG','4609','Europe - ETRF EVRF2019','Europe - onshore - Andorra; Austria; Belgium; Bosnia and Herzegovina; Bulgaria; Croatia; Czechia; Denmark; Estonia; Finland; France - mainland; Germany; Gibraltar, Hungary; Italy - mainland and Sicily; Latvia; Liechtenstein; Lithuania; Luxembourg; Netherlands; North Macedonia; Norway; Poland; Portugal - mainland; Romania; San Marino; Slovakia; Slovenia; Spain - mainland; Sweden; Switzerland; United Kingdom (UK) - Great Britain mainland; Vatican City State.',35.95,71.21,-9.56,31.59,0); +INSERT INTO "extent" VALUES('EPSG','4610','Argentina - Buenos Aires city','Argentina - autonomous city of Buenos Aires.',-34.705314975913,-34.506992229796,-58.531465195974,-58.29240989685,0); diff --git a/data/sql/geodetic_crs.sql b/data/sql/geodetic_crs.sql index d2aecc13..545e8c91 100644 --- a/data/sql/geodetic_crs.sql +++ b/data/sql/geodetic_crs.sql @@ -2090,8 +2090,8 @@ INSERT INTO "geodetic_crs" VALUES('EPSG','9378','IGb14',NULL,'geocentric','EPSG' INSERT INTO "usage" VALUES('EPSG','13999','geodetic_crs','EPSG','9378','EPSG','2830','EPSG','1027'); INSERT INTO "geodetic_crs" VALUES('EPSG','9379','IGb14',NULL,'geographic 3D','EPSG','6423','EPSG','1272',NULL,0); INSERT INTO "usage" VALUES('EPSG','14000','geodetic_crs','EPSG','9379','EPSG','1262','EPSG','1027'); -INSERT INTO "geodetic_crs" VALUES('EPSG','9380','IGb14',NULL,'geographic 2D','EPSG','6422','EPSG','1191',NULL,0); -INSERT INTO "usage" VALUES('EPSG','14001','geodetic_crs','EPSG','9380','EPSG','1262','EPSG','1027'); +INSERT INTO "geodetic_crs" VALUES('EPSG','9380','IGb14',NULL,'geographic 2D','EPSG','6422','EPSG','1272',NULL,0); +INSERT INTO "usage" VALUES('EPSG','14213','geodetic_crs','EPSG','9380','EPSG','1262','EPSG','1027'); INSERT INTO "geodetic_crs" VALUES('EPSG','9384','AbInvA96_2020-IRF',NULL,'geographic 2D','EPSG','6422','EPSG','1273',NULL,0); INSERT INTO "usage" VALUES('EPSG','14028','geodetic_crs','EPSG','9384','EPSG','4589','EPSG','1196'); INSERT INTO "geodetic_crs" VALUES('EPSG','9403','PN68',NULL,'geographic 2D','EPSG','6422','EPSG','1286',NULL,0); @@ -2104,3 +2104,7 @@ INSERT INTO "geodetic_crs" VALUES('EPSG','9469','SRGI2013',NULL,'geographic 3D', INSERT INTO "usage" VALUES('EPSG','14151','geodetic_crs','EPSG','9469','EPSG','1122','EPSG','1027'); INSERT INTO "geodetic_crs" VALUES('EPSG','9470','SRGI2013',NULL,'geographic 2D','EPSG','6422','EPSG','1293',NULL,0); INSERT INTO "usage" VALUES('EPSG','14152','geodetic_crs','EPSG','9470','EPSG','1122','EPSG','1183'); +INSERT INTO "geodetic_crs" VALUES('EPSG','9474','PZ-90.02',NULL,'geographic 2D','EPSG','6422','EPSG','1157',NULL,0); +INSERT INTO "usage" VALUES('EPSG','14195','geodetic_crs','EPSG','9474','EPSG','1262','EPSG','1183'); +INSERT INTO "geodetic_crs" VALUES('EPSG','9475','PZ-90.11',NULL,'geographic 2D','EPSG','6422','EPSG','1158',NULL,0); +INSERT INTO "usage" VALUES('EPSG','14194','geodetic_crs','EPSG','9475','EPSG','1262','EPSG','1183'); diff --git a/data/sql/geodetic_datum.sql b/data/sql/geodetic_datum.sql index 5ccc5410..47b4c498 100644 --- a/data/sql/geodetic_datum.sql +++ b/data/sql/geodetic_datum.sql @@ -1177,6 +1177,6 @@ INSERT INTO "usage" VALUES('EPSG','13848','geodetic_datum','EPSG','6903','EPSG', INSERT INTO "geodetic_datum" VALUES('EPSG','6904','Lisbon 1890 (Lisbon)',NULL,'EPSG','7004','EPSG','8902','1937-01-01',NULL,NULL,0); INSERT INTO "usage" VALUES('EPSG','13849','geodetic_datum','EPSG','6904','EPSG','1294','EPSG','1153'); INSERT INTO "geodetic_datum" VALUES('EPSG','6258','European Terrestrial Reference System 1989 ensemble',NULL,'EPSG','7019','EPSG','8901',NULL,NULL,0.1,0); -INSERT INTO "usage" VALUES('EPSG','13599','geodetic_datum','EPSG','6258','EPSG','1298','EPSG','1026'); +INSERT INTO "usage" VALUES('EPSG','14235','geodetic_datum','EPSG','6258','EPSG','1298','EPSG','1026'); INSERT INTO "geodetic_datum" VALUES('EPSG','6326','World Geodetic System 1984 ensemble',NULL,'EPSG','7030','EPSG','8901',NULL,NULL,2.0,0); -INSERT INTO "usage" VALUES('EPSG','13661','geodetic_datum','EPSG','6326','EPSG','1262','EPSG','1245'); +INSERT INTO "usage" VALUES('EPSG','14343','geodetic_datum','EPSG','6326','EPSG','1262','EPSG','1245'); diff --git a/data/sql/grid_transformation.sql b/data/sql/grid_transformation.sql index 80b310f8..5bd59179 100644 --- a/data/sql/grid_transformation.sql +++ b/data/sql/grid_transformation.sql @@ -277,7 +277,7 @@ INSERT INTO "usage" VALUES('EPSG','8673','grid_transformation','EPSG','1752','EP INSERT INTO "grid_transformation" VALUES('EPSG','1803','AGD66 to GDA94 (11)','Replaces AGD66 to GDA94 variants 6, 7 and 10 (codes 1506 1507 1596). Input expects longitudes to be positive west; EPSG GeogCRS AGD66 (code 4202) and GDA94 (code 4283) both have longitudes positive east. May be used as tfm to WGS 84 - see code 15786.','EPSG','9615','NTv2','EPSG','4202','EPSG','4283',0.1,'EPSG','8656','Latitude and longitude difference file','A66 National (13.09.01).gsb',NULL,NULL,NULL,NULL,NULL,NULL,'ICSM-Aus 0.1m',0); INSERT INTO "usage" VALUES('EPSG','8724','grid_transformation','EPSG','1803','EPSG','2575','EPSG','1031'); INSERT INTO "grid_transformation" VALUES('EPSG','1804','AGD84 to GDA94 (5)','Replaces AGD84 to GDA94 (4) (code 1593) which itself replaced variant 3 (code 1559). Input expects longitudes to be + west; EPSG GeogCRS AGD84 (code 4203) and GDA94 (code 4283) both have longitudes positive east. May be used as tfm to WGS 84 - see 15785','EPSG','9615','NTv2','EPSG','4203','EPSG','4283',0.1,'EPSG','8656','Latitude and longitude difference file','National 84 (02.07.01).gsb',NULL,NULL,NULL,NULL,NULL,NULL,'Auslig-Aus 0.1m',0); -INSERT INTO "usage" VALUES('EPSG','8725','grid_transformation','EPSG','1804','EPSG','2576','EPSG','1031'); +INSERT INTO "usage" VALUES('EPSG','14199','grid_transformation','EPSG','1804','EPSG','2576','EPSG','1031'); INSERT INTO "grid_transformation" VALUES('EPSG','1841','ATS77 to NAD83(CSRS) (1)','Introduced in 1999. Can be taken as an approximate transformation ATS77 to WGS 84 - see code 1688.','EPSG','9615','NTv2','EPSG','4122','EPSG','4617',1.5,'EPSG','8656','Latitude and longitude difference file','NB7783v2.gsb',NULL,NULL,NULL,NULL,NULL,NULL,'GIC-Can NB',1); INSERT INTO "usage" VALUES('EPSG','8762','grid_transformation','EPSG','1841','EPSG','1447','EPSG','1231'); INSERT INTO "grid_transformation" VALUES('EPSG','1843','NAD83 to NAD83(CSRS) (1)','Uses NT method which expects longitudes positive west; EPSG GeogCRSs NAD83 (code 4269) and NAD83(CSRS) (code 4617) have longitudes positive east. Can be taken as an approximate transformation NAD83 to WGS 84 - see code 1696.','EPSG','9615','NTv2','EPSG','4269','EPSG','4617',1.5,'EPSG','8656','Latitude and longitude difference file','NAD83-98.gsb',NULL,NULL,NULL,NULL,NULL,NULL,'SGQ-Can QC',1); @@ -826,6 +826,14 @@ INSERT INTO "grid_transformation" VALUES('EPSG','9466','GDA2020 to GDA2020 + AHD INSERT INTO "usage" VALUES('EPSG','14146','grid_transformation','EPSG','9466','EPSG','4493','EPSG','1133'); INSERT INTO "grid_transformation" VALUES('EPSG','9467','GDA94 to GDA94 + AHD height (1)','Reversible alternative to GDA94 to AHD height (1) (code 5656). Uses AUSGeoid09 model which uses bi-cubic interpolation; bi-linear interpolation of the grid file will give results agreeing to within 1cm 99.97% of the time.','EPSG','1083','Geog3D to Geog2D+Vertical (AUSGeoid v2)','EPSG','4939','EPSG','9464',0.15,'EPSG','8666','Geoid (height correction) model file','AUSGeoid09_V1.01.gsb',NULL,NULL,NULL,NULL,'EPSG','4283','GA-Aus09',0); INSERT INTO "usage" VALUES('EPSG','14147','grid_transformation','EPSG','9467','EPSG','4493','EPSG','1133'); +INSERT INTO "grid_transformation" VALUES('EPSG','9483','Canada velocity grid v7','','EPSG','1070','Point motion by grid (Canada NTv2_Vel)','EPSG','8254','EPSG','8254',0.01,'EPSG','1050','Point motion velocity grid file','cvg70.cvb',NULL,NULL,NULL,NULL,NULL,NULL,'NRC-Can cvg7.0',0); +INSERT INTO "usage" VALUES('EPSG','14214','grid_transformation','EPSG','9483','EPSG','1061','EPSG','1131'); +INSERT INTO "grid_transformation" VALUES('EPSG','9484','ETRS89 to NN54 height (1)','','EPSG','9665','Geographic3D to GravityRelatedHeight (gtx)','EPSG','4937','EPSG','5776',0.02,'EPSG','8666','Geoid (height correction) model file','href2008a.gtx',NULL,NULL,NULL,NULL,NULL,NULL,'SK-Nor 2008',0); +INSERT INTO "usage" VALUES('EPSG','14215','grid_transformation','EPSG','9484','EPSG','1352','EPSG','1133'); +INSERT INTO "grid_transformation" VALUES('EPSG','9485','ETRS89 to NN2000 height (1)','','EPSG','9665','Geographic3D to GravityRelatedHeight (gtx)','EPSG','4937','EPSG','5941',0.02,'EPSG','8666','Geoid (height correction) model file','HREF2018B_NN2000_EUREF89.gtx',NULL,NULL,NULL,NULL,NULL,NULL,'SK-Nor 2018',0); +INSERT INTO "usage" VALUES('EPSG','14216','grid_transformation','EPSG','9485','EPSG','1352','EPSG','1133'); +INSERT INTO "grid_transformation" VALUES('EPSG','9496','MGI 1901 to SRB-ETRS89 (9)','','EPSG','9615','NTv2','EPSG','3906','EPSG','8685',0.03,'EPSG','8656','Latitude and longitude difference file','MGI1901_TO_SRBETRS89_NTv2.gsb',NULL,NULL,NULL,NULL,NULL,NULL,'RGZ-Srb 0.1m 2020',0); +INSERT INTO "usage" VALUES('EPSG','14226','grid_transformation','EPSG','9496','EPSG','4543','EPSG','1185'); INSERT INTO "grid_transformation" VALUES('EPSG','10000','RGF93 to NGF-IGN69 height (1)','May be used for transformations from WGS 84 to NGF-IGN69 height. Accuracy at each 0.1 deg x 0.1 degree grid node is given within the geoid model file.','EPSG','9664','Geographic3D to GravityRelatedHeight (IGN1997)','EPSG','4965','EPSG','5720',0.5,'EPSG','8666','Geoid (height correction) model file','ggf97a.txt',NULL,NULL,NULL,NULL,NULL,NULL,'IGN Fra',0); INSERT INTO "usage" VALUES('EPSG','11001','grid_transformation','EPSG','10000','EPSG','1326','EPSG','1133'); INSERT INTO "grid_transformation" VALUES('EPSG','10001','ETRS89 to NGF-IGN69 height (1)','Parameter values taken from RGF93 to NGF-IGN69 height (1) (code 10000) assuming that RGF93 is equivalent to ETRS89 within the accuracy of the transformation. Accuracy at each 0.1 deg x 0.1 degree grid node is given within the geoid model file.','EPSG','9664','Geographic3D to GravityRelatedHeight (IGN1997)','EPSG','4937','EPSG','5720',0.5,'EPSG','8666','Geoid (height correction) model file','ggf97a.txt',NULL,NULL,NULL,NULL,NULL,NULL,'IGN Fra',0); diff --git a/data/sql/helmert_transformation.sql b/data/sql/helmert_transformation.sql index b3238817..ff7e9a42 100644 --- a/data/sql/helmert_transformation.sql +++ b/data/sql/helmert_transformation.sql @@ -416,7 +416,7 @@ INSERT INTO "usage" VALUES('EPSG','8199','helmert_transformation','EPSG','1278', INSERT INTO "helmert_transformation" VALUES('EPSG','1279','AGD84 to GDA94 (1)','Derived at 327 stations. May be taken as approximate transformation AGD84 to WGS 84 - see code 15789. For higher accuracy use AGD84 to GDA94 (2) (code 1280). Note: AGD84 officially adopted only in Queensland, South Australia and Western Australia.','EPSG','9603','Geocentric translations (geog2D domain)','EPSG','4203','EPSG','4283',5.0,-128.5,-53.0,153.4,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'Auslig-Aus 5m',0); INSERT INTO "usage" VALUES('EPSG','8200','helmert_transformation','EPSG','1279','EPSG','2576','EPSG','1045'); INSERT INTO "helmert_transformation" VALUES('EPSG','1280','AGD84 to GDA94 (2)','Replaces AGD84 to WGS 84 (2) (code 1236). May be taken as approximate transformation AGD84 to WGS 84 - see code 1669. Note: although applicable nationwide, AGD84 officially adopted only in Queensland, South Australia and Western Australia.','EPSG','9607','Coordinate Frame rotation (geog2D domain)','EPSG','4203','EPSG','4283',1.0,-117.763,-51.51,139.061,'EPSG','9001',-0.292,-0.443,-0.277,'EPSG','9104',-0.191,'EPSG','9202',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'Auslig-Aus 1m',0); -INSERT INTO "usage" VALUES('EPSG','8201','helmert_transformation','EPSG','1280','EPSG','2576','EPSG','1041'); +INSERT INTO "usage" VALUES('EPSG','14198','helmert_transformation','EPSG','1280','EPSG','2576','EPSG','1041'); INSERT INTO "helmert_transformation" VALUES('EPSG','1281','Pulkovo 1995 to WGS 84 (1)','Derived through concatenation of Pulkovo 1995 to PZ-90 (1) (tfm code 1257) and PZ-90 to WGS 84 (2) (tfm code 1244). Mandated for use in Russia by GOST R 51794-2001, but this has been superseded by GOST R 51794-2008. Replaced by tfm code 5043.','EPSG','9607','Coordinate Frame rotation (geog2D domain)','EPSG','4200','EPSG','4326',1.0,24.82,-131.21,-82.66,'EPSG','9001',0.0,0.0,-0.16,'EPSG','9104',-0.12,'EPSG','9202',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'GOST-Rus',0); INSERT INTO "usage" VALUES('EPSG','8202','helmert_transformation','EPSG','1281','EPSG','1198','EPSG','1041'); INSERT INTO "helmert_transformation" VALUES('EPSG','1282','Samboja to WGS 84 (1)','Datum shift derived through ITRF93.','EPSG','9603','Geocentric translations (geog2D domain)','EPSG','4125','EPSG','4326',NULL,-404.78,685.68,45.47,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'TOT-Idn Mah',1); @@ -2036,8 +2036,8 @@ INSERT INTO "helmert_transformation" VALUES('EPSG','8270','Saint Pierre et Mique INSERT INTO "usage" VALUES('EPSG','10463','helmert_transformation','EPSG','8270','EPSG','3299','EPSG','1041'); INSERT INTO "helmert_transformation" VALUES('EPSG','8365','ETRS89 to S-JTSK [JTSK03] (1)','Derived at 684 points with known S-JTSK and ETRS89 (ETRF2000 realization) coordinates. Scale parameter was constrained to be zero. UGKK consider this transformation to not be reversible at the 1mm accuracy level: for reverse see transformation code 8367.','EPSG','9607','Coordinate Frame rotation (geog2D domain)','EPSG','4258','EPSG','8351',0.001,-485.014055,-169.473618,-483.842943,'EPSG','9001',7.78625453,4.39770887,4.10248899,'EPSG','9104',0.0,'EPSG','9202',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'UGKK-Svk',0); INSERT INTO "usage" VALUES('EPSG','10512','helmert_transformation','EPSG','8365','EPSG','1211','EPSG','1115'); -INSERT INTO "helmert_transformation" VALUES('EPSG','8366','ITRF2014 to ETRF2014 (1)','Scale difference in ppb and scale difference rate in ppb/yr where 1/billion = 1E-9 or nm/m. See ITRF2014 to ETRF2014 (2) (code 8407) for an exactly equivalent transformation but with the transformation''s parameter values at epoch 2010.00.','EPSG','1053','Time-dependent Position Vector tfm (geocentric)','EPSG','7789','EPSG','8401',0.0,0.0,0.0,0.0,'EPSG','1025',0.0,0.0,0.0,'EPSG','1031',0.0,'EPSG','1028',0.0,0.0,0.0,'EPSG','1027',0.085,0.531,-0.77,'EPSG','1032',0.0,'EPSG','1030',1989.0,'EPSG','1029',NULL,NULL,NULL,NULL,NULL,'EUREF-Eur',0); -INSERT INTO "usage" VALUES('EPSG','10513','helmert_transformation','EPSG','8366','EPSG','1298','EPSG','1129'); +INSERT INTO "helmert_transformation" VALUES('EPSG','8366','ITRF2014 to ETRF2014 (1)','Scale difference in ppb and scale difference rate in ppb/yr where 1/billion = 1E-9 or nm/m. See ITRF2014 to ETRF2014 (2) (code 8880) for an exactly equivalent transformation but with the transformation''s parameter values at epoch 2010.00.','EPSG','1053','Time-dependent Position Vector tfm (geocentric)','EPSG','7789','EPSG','8401',0.0,0.0,0.0,0.0,'EPSG','1025',0.0,0.0,0.0,'EPSG','1031',0.0,'EPSG','1028',0.0,0.0,0.0,'EPSG','1027',0.085,0.531,-0.77,'EPSG','1032',0.0,'EPSG','1030',1989.0,'EPSG','1029',NULL,NULL,NULL,NULL,NULL,'EUREF-Eur',0); +INSERT INTO "usage" VALUES('EPSG','14203','helmert_transformation','EPSG','8366','EPSG','1298','EPSG','1129'); INSERT INTO "helmert_transformation" VALUES('EPSG','8367','S-JTSK [JTSK03] to ETRS89 (1)','Derived at 684 points. At the 1mm accuracy level this transformation is not reversible: for reverse see transformation code 8365. May be taken as approximate transformation to WGS 84 - see code 8368.','EPSG','9607','Coordinate Frame rotation (geog2D domain)','EPSG','8351','EPSG','4258',0.001,485.021,169.465,483.839,'EPSG','9001',-7.786342,-4.397554,-4.102655,'EPSG','9104',0.0,'EPSG','9202',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'UGKK-Svk',0); INSERT INTO "usage" VALUES('EPSG','10514','helmert_transformation','EPSG','8367','EPSG','1211','EPSG','1027'); INSERT INTO "helmert_transformation" VALUES('EPSG','8368','S-JTSK [JTSK03] to WGS 84 (1)','Parameter values taken from S-JTSK [JTSK03] to ETRS89 (1) (code 8367) assuming that ETRS89 (ETRF2000 realization) is coincident with WGS 84 within the accuracy of the transformation. Within the 1m accuracy of this transformation, it is reversible.','EPSG','9607','Coordinate Frame rotation (geog2D domain)','EPSG','8351','EPSG','4326',1.0,485.021,169.465,483.839,'EPSG','9001',-7.786342,-4.397554,-4.102655,'EPSG','9104',0.0,'EPSG','9202',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'UGKK-Svk',0); @@ -2172,8 +2172,8 @@ INSERT INTO "helmert_transformation" VALUES('EPSG','8878','ITRF90 to ETRF2014 (1 INSERT INTO "usage" VALUES('EPSG','10820','helmert_transformation','EPSG','8878','EPSG','1298','EPSG','1027'); INSERT INTO "helmert_transformation" VALUES('EPSG','8879','ITRF89 to ETRF2014 (1)','Scale difference in ppb and scale difference rate in ppb/yr where 1/billion = 1E-9 or nm/m.','EPSG','1053','Time-dependent Position Vector tfm (geocentric)','EPSG','4911','EPSG','8401',0.0,-30.4,-35.5,130.8,'EPSG','1025',1.785,11.151,-16.43,'EPSG','1031',-8.19,'EPSG','1028',-0.1,0.5,3.3,'EPSG','1027',0.085,0.531,-0.79,'EPSG','1032',-0.12,'EPSG','1030',2010.0,'EPSG','1029',NULL,NULL,NULL,NULL,NULL,'EUREF-Eur 2014',0); INSERT INTO "usage" VALUES('EPSG','10821','helmert_transformation','EPSG','8879','EPSG','1298','EPSG','1027'); -INSERT INTO "helmert_transformation" VALUES('EPSG','8880','ITRF2014 to ETRF2014 (2)','Scale difference in ppb and scale difference rate in ppb/yr where 1/billion = 1E-9. See ITRF2014 to ETRF2014 (1) (code 8366) for transformation which defines ETRF2014. Transformation 8407 is equivalent to 8366 but with parameter values at epoch 2010.00.','EPSG','1053','Time-dependent Position Vector tfm (geocentric)','EPSG','7789','EPSG','8401',0.0,0.0,0.0,0.0,'EPSG','1025',1.785,11.151,-16.17,'EPSG','1031',0.0,'EPSG','1028',0.0,0.0,0.0,'EPSG','1027',0.085,0.531,-0.77,'EPSG','1032',0.0,'EPSG','1030',2010.0,'EPSG','1029',NULL,NULL,NULL,NULL,NULL,'EUREF-Eur 2014',0); -INSERT INTO "usage" VALUES('EPSG','10822','helmert_transformation','EPSG','8880','EPSG','1298','EPSG','1027'); +INSERT INTO "helmert_transformation" VALUES('EPSG','8880','ITRF2014 to ETRF2014 (2)','Scale difference in ppb and scale difference rate in ppb/yr where 1/billion = 1E-9. See ITRF2014 to ETRF2014 (1) (code 8366) for transformation which defines ETRF2014. Transformation 8880 is equivalent to 8366 but with parameter values at epoch 2010.00.','EPSG','1053','Time-dependent Position Vector tfm (geocentric)','EPSG','7789','EPSG','8401',0.0,0.0,0.0,0.0,'EPSG','1025',1.785,11.151,-16.17,'EPSG','1031',0.0,'EPSG','1028',0.0,0.0,0.0,'EPSG','1027',0.085,0.531,-0.77,'EPSG','1032',0.0,'EPSG','1030',2010.0,'EPSG','1029',NULL,NULL,NULL,NULL,NULL,'EUREF-Eur 2014',0); +INSERT INTO "usage" VALUES('EPSG','14204','helmert_transformation','EPSG','8880','EPSG','1298','EPSG','1027'); INSERT INTO "helmert_transformation" VALUES('EPSG','8882','Camacupa 2015 to WGS 84 (11)','Used by CIDDEMA for delimitation of Angola''s EEZ boundary. Derived by Univ. of Lisbon using 38 REPANGOL points. Average horizontal error 1m, vertical 3m; max radial error 6m. Application offshore differs from Camacupa 1948 to WGS 84 by approx 25m.','EPSG','9607','Coordinate Frame rotation (geog2D domain)','EPSG','8694','EPSG','4326',3.0,-93.799,-132.737,-219.073,'EPSG','9001',1.844,-0.648,6.37,'EPSG','9104',-0.169,'EPSG','9202',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'CIDDEMA-Ago',0); INSERT INTO "usage" VALUES('EPSG','10823','helmert_transformation','EPSG','8882','EPSG','1029','EPSG','1053'); INSERT INTO "helmert_transformation" VALUES('EPSG','8883','Camacupa 1948 to RSAO13 (1)','Parameter values taken from Camacupa 1948 to WGS 84 (7) (code 1324) assuming that RSAO13 is coincident with WGS 84 within the accuracy of the transformation.','EPSG','9603','Geocentric translations (geog2D domain)','EPSG','4220','EPSG','8699',3.0,-48.0,-345.0,-231.0,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'ELF-Ago B15',0); @@ -2406,6 +2406,10 @@ INSERT INTO "helmert_transformation" VALUES('EPSG','9460','ITRF2014 to ATRF2014 INSERT INTO "usage" VALUES('EPSG','14140','helmert_transformation','EPSG','9460','EPSG','4177','EPSG','1268'); INSERT INTO "helmert_transformation" VALUES('EPSG','9472','DGN95 to SRGI2013 (1)','Derived at 533 stations. Mean residual 0.218m. Note: information source gives rotations given in radians.','EPSG','9607','Coordinate Frame rotation (geog2D domain)','EPSG','4755','EPSG','9470',0.2,-0.2773,0.0534,0.4819,'EPSG','9001',0.0935,-0.0286,0.00969,'EPSG','9109',-0.028,'EPSG','9202',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'SRGI-Idn',0); INSERT INTO "usage" VALUES('EPSG','14154','helmert_transformation','EPSG','9472','EPSG','1122','EPSG','1026'); +INSERT INTO "helmert_transformation" VALUES('EPSG','9486','MGI 1901 to WGS 84 (15)','Parameter values from MGI 1901 to ETRS89 (8) (code 9495). Assumes SRB-ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.','EPSG','9607','Coordinate Frame rotation (geog2D domain)','EPSG','3906','EPSG','4326',1.0,577.84843,165.45019,390.43652,'EPSG','9001',-4.93131,0.96052,13.05072,'EPSG','9104',7.86546,'EPSG','9202',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'IOGP-Srb 2020',0); +INSERT INTO "usage" VALUES('EPSG','14220','helmert_transformation','EPSG','9486','EPSG','4543','EPSG','1041'); +INSERT INTO "helmert_transformation" VALUES('EPSG','9495','MGI 1901 to SRB-ETRS89 (8)','','EPSG','9607','Coordinate Frame rotation (geog2D domain)','EPSG','3906','EPSG','8685',0.46,577.84843,165.45019,390.43652,'EPSG','9001',-4.93131,0.96052,13.05072,'EPSG','9104',7.86546,'EPSG','9202',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'RGZ-Srb 0.5m 2020',0); +INSERT INTO "usage" VALUES('EPSG','14227','helmert_transformation','EPSG','9495','EPSG','4543','EPSG','1153'); INSERT INTO "helmert_transformation" VALUES('EPSG','10085','Trinidad 1903 to WGS 84 (2)','Parameter values provided to EOG by Trinidad Ministry of Energy and Energy Industries. Used by EOG offshore Trinidad (including Pelican, Kiskadee and Ibis fields) since 1996.','EPSG','9603','Geocentric translations (geog2D domain)','EPSG','4302','EPSG','4326',3.0,-61.0,285.2,471.6,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'EOG-Tto Trin',0); INSERT INTO "usage" VALUES('EPSG','11086','helmert_transformation','EPSG','10085','EPSG','1339','EPSG','1136'); INSERT INTO "helmert_transformation" VALUES('EPSG','10086','JAD69 to WGS 72 (1)','Derived in 1977 through Transit observations at 2 stations by US DMA.','EPSG','9603','Geocentric translations (geog2D domain)','EPSG','4242','EPSG','4322',15.0,48.0,208.0,382.0,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'SD-Jam',0); @@ -2896,7 +2900,7 @@ INSERT INTO "usage" VALUES('EPSG','11987','helmert_transformation','EPSG','15977 INSERT INTO "helmert_transformation" VALUES('EPSG','15978','NAD27 to WGS 84 (88)','','EPSG','9607','Coordinate Frame rotation (geog2D domain)','EPSG','4267','EPSG','4326',1.0,2.478,149.752,197.726,'EPSG','9001',-0.526,-0.498,0.501,'EPSG','9104',0.685,'EPSG','9202',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'ONHG-Cub',0); INSERT INTO "usage" VALUES('EPSG','11988','helmert_transformation','EPSG','15978','EPSG','1077','EPSG','1041'); INSERT INTO "helmert_transformation" VALUES('EPSG','15979','AGD66 to GDA94 (12)','Use only offshore: onshore, tfms 1458 (ACT), 1594 (Tas), 1460 (NSW and Vic) and 1595 (NT) are more accurate.May be used as a tfm to WGS 84 - see code 15980.','EPSG','9607','Coordinate Frame rotation (geog2D domain)','EPSG','4202','EPSG','4283',3.0,-117.808,-51.536,137.784,'EPSG','9001',-0.303,-0.446,-0.234,'EPSG','9104',-0.29,'EPSG','9202',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'ICSM-Aus off',0); -INSERT INTO "usage" VALUES('EPSG','11989','helmert_transformation','EPSG','15979','EPSG','3559','EPSG','1043'); +INSERT INTO "usage" VALUES('EPSG','14200','helmert_transformation','EPSG','15979','EPSG','3559','EPSG','1043'); INSERT INTO "helmert_transformation" VALUES('EPSG','15980','AGD66 to WGS 84 (18)','Parameter values from AGD66 to GDA94 (12) (code 15979). Assumes GDA94 and WGS 84 can be considered the same to within the accuracy of the transformation. Use only offshore: onshore tfms 1665-68 for ACT, NSW/Vic, Tas and NT respectively are more accurate.','EPSG','9607','Coordinate Frame rotation (geog2D domain)','EPSG','4202','EPSG','4326',3.0,-117.808,-51.536,137.784,'EPSG','9001',-0.303,-0.446,-0.234,'EPSG','9104',-0.29,'EPSG','9202',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'EPSG-Aus off',0); INSERT INTO "usage" VALUES('EPSG','11990','helmert_transformation','EPSG','15980','EPSG','3559','EPSG','1043'); INSERT INTO "helmert_transformation" VALUES('EPSG','15981','MGI to Slovenia 1996 (1)','Info source also gives a separate reverse tfm with slightly different parameter values. Given the tfm accuracy these differences are not significant and this tfm can be considered reversible. May be taken as approximate tfm MGI to WGS 84 (see code 15982)','EPSG','9607','Coordinate Frame rotation (geog2D domain)','EPSG','4312','EPSG','4765',1.0,409.545,72.164,486.872,'EPSG','9001',-3.085957,-5.46911,11.020289,'EPSG','9104',17.919665,'EPSG','9202',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'GuRS-Svn',1); diff --git a/data/sql/metadata.sql b/data/sql/metadata.sql index 8db35745..3c21636c 100644 --- a/data/sql/metadata.sql +++ b/data/sql/metadata.sql @@ -1,2 +1,2 @@ -INSERT INTO "metadata" VALUES('EPSG.VERSION', 'v10.003'); -INSERT INTO "metadata" VALUES('EPSG.DATE', '2020-10-05'); +INSERT INTO "metadata" VALUES('EPSG.VERSION', 'v10.007'); +INSERT INTO "metadata" VALUES('EPSG.DATE', '2020-11-18'); diff --git a/data/sql/projected_crs.sql b/data/sql/projected_crs.sql index ea7c9b71..a2adb443 100644 --- a/data/sql/projected_crs.sql +++ b/data/sql/projected_crs.sql @@ -7302,6 +7302,8 @@ INSERT INTO "projected_crs" VALUES('EPSG','9493','SRGI2013 / UTM zone 53S',NULL, INSERT INTO "usage" VALUES('EPSG','14171','projected_crs','EPSG','9493','EPSG','1662','EPSG','1266'); INSERT INTO "projected_crs" VALUES('EPSG','9494','SRGI2013 / UTM zone 54S',NULL,'EPSG','4400','EPSG','9470','EPSG','16154',NULL,0); INSERT INTO "usage" VALUES('EPSG','14172','projected_crs','EPSG','9494','EPSG','1663','EPSG','1266'); +INSERT INTO "projected_crs" VALUES('EPSG','9498','POSGAR 2007 / CABA 2019',NULL,'EPSG','4500','EPSG','5340','EPSG','9497',NULL,0); +INSERT INTO "usage" VALUES('EPSG','14243','projected_crs','EPSG','9498','EPSG','4610','EPSG','1056'); INSERT INTO "projected_crs" VALUES('EPSG','20004','Pulkovo 1995 / Gauss-Kruger zone 4',NULL,'EPSG','4530','EPSG','4200','EPSG','16204',NULL,0); INSERT INTO "usage" VALUES('EPSG','6177','projected_crs','EPSG','20004','EPSG','1763','EPSG','1211'); INSERT INTO "projected_crs" VALUES('EPSG','20005','Pulkovo 1995 / Gauss-Kruger zone 5',NULL,'EPSG','4530','EPSG','4200','EPSG','16205',NULL,0); diff --git a/data/sql/scope.sql b/data/sql/scope.sql index 993057f7..9f314f37 100644 --- a/data/sql/scope.sql +++ b/data/sql/scope.sql @@ -107,6 +107,7 @@ INSERT INTO "scope" VALUES('EPSG','1127','Geodesy. Defines ETRF2000.',0); INSERT INTO "scope" VALUES('EPSG','1128','Geodesy. Defines ETRF2005.',0); INSERT INTO "scope" VALUES('EPSG','1129','Geodesy. Defines ETRF2014.',0); INSERT INTO "scope" VALUES('EPSG','1130','EEZ delimitation.',0); +INSERT INTO "scope" VALUES('EPSG','1131','Change of coordinate epoch for points referenced to NAD83(CSRS)v7.',0); INSERT INTO "scope" VALUES('EPSG','1132','Derivation of approximate gravity-related heights from GNSS observations.',0); INSERT INTO "scope" VALUES('EPSG','1133','Derivation of gravity-related heights from GNSS observations.',0); INSERT INTO "scope" VALUES('EPSG','1134','Description of the use or purpose of the CRS.',0); diff --git a/data/sql/supersession.sql b/data/sql/supersession.sql index 0ed78ad6..8148c911 100644 --- a/data/sql/supersession.sql +++ b/data/sql/supersession.sql @@ -246,3 +246,5 @@ INSERT INTO "supersession" VALUES('grid_transformation','EPSG','9168','grid_tran INSERT INTO "supersession" VALUES('grid_transformation','EPSG','9169','grid_transformation','EPSG','9174','EPSG',0); INSERT INTO "supersession" VALUES('grid_transformation','EPSG','15932','grid_transformation','EPSG','9409','EPSG',1); INSERT INTO "supersession" VALUES('grid_transformation','EPSG','15932','grid_transformation','EPSG','9408','EPSG',1); +INSERT INTO "supersession" VALUES('helmert_transformation','EPSG','7675','helmert_transformation','EPSG','9495','EPSG',0); +INSERT INTO "supersession" VALUES('helmert_transformation','EPSG','7676','helmert_transformation','EPSG','9486','EPSG',1); diff --git a/data/sql/vertical_crs.sql b/data/sql/vertical_crs.sql index 0a30c44f..ab265193 100644 --- a/data/sql/vertical_crs.sql +++ b/data/sql/vertical_crs.sql @@ -85,7 +85,7 @@ INSERT INTO "usage" VALUES('EPSG','4152','vertical_crs','EPSG','5709','EPSG','11 INSERT INTO "vertical_crs" VALUES('EPSG','5710','Ostend height',NULL,'EPSG','6499','EPSG','5110',0); INSERT INTO "usage" VALUES('EPSG','4153','vertical_crs','EPSG','5710','EPSG','1347','EPSG','1179'); INSERT INTO "vertical_crs" VALUES('EPSG','5711','AHD height',NULL,'EPSG','6499','EPSG','5111',0); -INSERT INTO "usage" VALUES('EPSG','4154','vertical_crs','EPSG','5711','EPSG','4493','EPSG','1263'); +INSERT INTO "usage" VALUES('EPSG','14230','vertical_crs','EPSG','5711','EPSG','4493','EPSG','1263'); INSERT INTO "vertical_crs" VALUES('EPSG','5712','AHD (Tasmania) height',NULL,'EPSG','6499','EPSG','5112',0); INSERT INTO "usage" VALUES('EPSG','4155','vertical_crs','EPSG','5712','EPSG','2947','EPSG','1179'); INSERT INTO "vertical_crs" VALUES('EPSG','5713','CGVD28 height',NULL,'EPSG','6499','EPSG','5114',0); @@ -481,6 +481,6 @@ INSERT INTO "usage" VALUES('EPSG','14041','vertical_crs','EPSG','9402','EPSG','4 INSERT INTO "vertical_crs" VALUES('EPSG','9451','BI height',NULL,'EPSG','6499','EPSG','1288',0); INSERT INTO "usage" VALUES('EPSG','14087','vertical_crs','EPSG','9451','EPSG','4606','EPSG','1026'); INSERT INTO "vertical_crs" VALUES('EPSG','9458','AVWS height',NULL,'EPSG','6499','EPSG','1292',0); -INSERT INTO "usage" VALUES('EPSG','14138','vertical_crs','EPSG','9458','EPSG','4177','EPSG','1264'); +INSERT INTO "usage" VALUES('EPSG','14231','vertical_crs','EPSG','9458','EPSG','4177','EPSG','1264'); INSERT INTO "vertical_crs" VALUES('EPSG','9471','INAGeoid2020 height',NULL,'EPSG','6499','EPSG','1294',0); INSERT INTO "usage" VALUES('EPSG','14153','vertical_crs','EPSG','9471','EPSG','1122','EPSG','1178'); diff --git a/scripts/build_db.py b/scripts/build_db.py index 63636a71..af304424 100755 --- a/scripts/build_db.py +++ b/scripts/build_db.py @@ -401,6 +401,9 @@ def fill_helmert_transformation(proj_db_cursor): assert param_code[6] == 8611 assert param_uom_code[3] == param_uom_code[4] assert param_uom_code[3] == param_uom_code[5] + for i in range(7): + assert param_uom_code[i] is not None + if n_params == 8: # Time-specific transformation assert param_code[7] == 1049, (code, name, param_code[7]) param_value[14] = param_value[7] @@ -438,6 +441,8 @@ def fill_helmert_transformation(proj_db_cursor): assert param_uom_code[7] == param_uom_code[9] assert param_uom_code[10] == param_uom_code[11] assert param_uom_code[10] == param_uom_code[12] + for i in range(15): + assert param_uom_code[i] is not None, (code, name, i, param_name[i]) arg = (EPSG_AUTHORITY, code, name, remarks, -- cgit v1.2.3 From 2cbf659bfcdffe12a4e7e397553c886566b2e949 Mon Sep 17 00:00:00 2001 From: "J.H. van de Water" Date: Thu, 19 Nov 2020 10:52:29 +0100 Subject: Replace line feed in input line by null character As result of a modification in logging (adding a line feed), many changes had to be made in different places of cct.cpp. However, one missed the line feed in input to cct. As result of missing this, the output from cct showed a superfluous empty line after each output line, but only if the corresponding input line ended with comment. Replacing the LF in the "comment" string (present if the input line ended with comment) by a null character ('\0') solves this issue. Modification in logging? https://github.com/OSGeo/PROJ/commit/37da5e243191c04607597f6b8a77acfa017a5c99 ( cct: revise end-of-line handling in logging, and always output debug ) See also: https://github.com/OSGeo/PROJ/issues/1677 ( cct outputs excessive whitespace comments are included in input data ) --- src/apps/cct.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/apps/cct.cpp b/src/apps/cct.cpp index fa75267a..b0e15e62 100644 --- a/src/apps/cct.cpp +++ b/src/apps/cct.cpp @@ -450,6 +450,11 @@ int main(int argc, char **argv) { colmax = MAX(colmax, columns_xyzt[i]); comment = column(buf, colmax+1); } + /* remove the line feed from comment, as logger() above, invoked + by print() below (output), will add one */ + size_t len = strlen(comment); + if (len >= 1) + comment[len - 1] = '\0'; comment_delimiter = (comment && *comment) ? whitespace : blank_comment; /* Time to print the result */ -- cgit v1.2.3 From 9419b42ade1f1d35a61c05f0f7ce9aab2eeff3c7 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Sun, 1 Nov 2020 13:34:32 +0100 Subject: Remove proj_api.h Removes proj_api.h from the public API. The contents of the header file has been moved to proj_internal.h verbatim and any references to proj_api.h has been changed to proj_internal.h. The documentation of proj_api.h has been removed. The only exception to this is the API migration guides which still mention the old API. Fixes #837 --- docs/source/development/index.rst | 5 +- docs/source/development/reference/deprecated.rst | 270 ----------------------- docs/source/development/reference/index.rst | 1 - src/Makefile.am | 2 +- src/apps/emess.cpp | 2 +- src/iso19111/datum.cpp | 1 - src/iso19111/factory.cpp | 1 - src/iso19111/io.cpp | 1 - src/lib_proj.cmake | 1 - src/mutex.cpp | 5 - src/proj.h | 4 - src/proj_api.h | 227 ------------------- src/proj_internal.h | 163 +++++++++++++- src/projections/calcofi.cpp | 1 - src/tests/multistresstest.cpp | 2 +- src/tests/test228.cpp | 2 +- test/fuzzers/standard_fuzzer.cpp | 2 +- test/unit/pj_transform_test.cpp | 1 - 18 files changed, 164 insertions(+), 527 deletions(-) delete mode 100644 docs/source/development/reference/deprecated.rst delete mode 100644 src/proj_api.h diff --git a/docs/source/development/index.rst b/docs/source/development/index.rst index 85c10c6d..f985279f 100644 --- a/docs/source/development/index.rst +++ b/docs/source/development/index.rst @@ -39,9 +39,8 @@ are maintained in a `separate git repository - - main(int argc, char **argv) { - projPJ pj_merc, pj_latlong; - double x, y; - - if (!(pj_merc = pj_init_plus("+proj=merc +ellps=clrk66 +lat_ts=33")) ) - exit(1); - if (!(pj_latlong = pj_init_plus("+proj=latlong +ellps=clrk66")) ) - exit(1); - while (scanf("%lf %lf", &x, &y) == 2) { - x *= DEG_TO_RAD; - y *= DEG_TO_RAD; - p = pj_transform(pj_latlong, pj_merc, 1, 1, &x, &y, NULL ); - printf("%.2f\t%.2f\n", x, y); - } - exit(0); - } - - -For this program, an input of ``-16 20.25`` would give a result of -``-1495284.21 1920596.79``. - -API Functions -------------- - -pj_transform -============ - -:: - - int pj_transform( projPJ srcdefn, - projPJ dstdefn, - long point_count, - int point_offset, - double *x, - double *y, - double *z ); - - -Transform the x/y/z points from the source coordinate system to the -destination coordinate system. - -``srcdefn``: source (input) coordinate system. - -``dstdefn``: destination (output) coordinate system. - -``point_count``: the number of points to be processed (the size of the -x/y/z arrays). - -``point_offset``: the step size from value to value (measured in -doubles) within the x/y/z arrays - normally 1 for a packed array. May be -used to operate on xyz interleaved point arrays. - -``x``/``y``/``z``: The array of X, Y and Z coordinate values passed as -input, and modified in place for output. The Z may optionally be NULL. - -``return``: The return is zero on success, or a PROJ.4 error code. - -The ``pj_transform()`` function transforms the passed in list of points -from the source coordinate system to the destination coordinate system. -Note that geographic locations need to be passed in radians, not decimal -degrees, and will be returned similarly. The ``z`` array may be passed -as NULL if Z values are not available. - -If there is an overall failure, an error code will be returned from the -function. If individual points fail to transform - for instance due to -being over the horizon - then those x/y/z values will be set to -``HUGE_VAL`` on return. Input values that are ``HUGE_VAL`` will not be -transformed. - - -pj_init_plus -============ - -:: - - projPJ pj_init_plus(const char *definition); - -This function converts a string representation of a coordinate system -definition into a projPJ object suitable for use with other API -functions. On failure the function will return NULL and set pj_errno. -The definition should be of the general form -``+proj=tmerc +lon_0 +datum=WGS84``. Refer to PROJ.4 documentation and -the :ref:`transformation` notes for additional detail. - -Coordinate system objects allocated with ``pj_init_plus()`` should be -deallocated with ``pj_free()``. - - -pj_free -======= - -:: - - void pj_free( projPJ pj ); - -Frees all resources associated with pj. - - -pj_is_latlong -============= - -:: - - int pj_is_latlong( projPJ pj ); - -Returns TRUE if the passed coordinate system is geographic -(``proj=latlong``). - - -pj_is_geocent -============= - -:: - - int pj_is_geocent( projPJ pj );`` - -Returns TRUE if the coordinate system is geocentric (``proj=geocent``). - -pj_get_def -========== - -:: - - char *pj_get_def( projPJ pj, int options);`` - -Returns the PROJ.4 initialization string suitable for use with -``pj_init_plus()`` that would produce this coordinate system, but with -the definition expanded as much as possible (for instance ``+init=`` and -``+datum=`` definitions). - -pj_latlong_from_proj -==================== - -:: - - projPJ pj_latlong_from_proj( projPJ pj_in );`` - -Returns a new coordinate system definition which is the geographic -coordinate (lat/long) system underlying ``pj_in``. - -pj_set_finder -============== - -:: - - void pj_set_finder( const char *(*new_finder)(const char *) );`` - -Install a custom function for finding init and grid shift files. - -pj_set_searchpath -================= - -:: - - void pj_set_searchpath ( int count, const char **path );`` - -Set a list of directories to search for init and grid shift files. - - -pj_deallocate_grids -=================== - -:: - - void pj_deallocate_grids( void );`` - -Frees all resources associated with loaded and cached datum shift grids. - - -pj_strerrno -=========== - -:: - - char *pj_strerrno( int );`` - -Returns the error text associated with the passed in error code. - -pj_get_errno_ref -================ - -:: - - int *pj_get_errno_ref( void );`` - -Returns a pointer to the global pj\_errno error variable. - -pj_get_release -============== - -:: - - const char *pj_get_release( void );`` - -Returns an internal string describing the release version. - -Obsolete Functions -~~~~~~~~~~~~~~~~~~ - -``XY pj_fwd( LP lp, PJ *P );`` - -``LP pj_inv( XY xy, PJ *P );`` - -``projPJ pj_init(int argc, char **argv);`` - -.. _more info: pj_transform - diff --git a/docs/source/development/reference/index.rst b/docs/source/development/reference/index.rst index 1d39b1d0..caa893c3 100644 --- a/docs/source/development/reference/index.rst +++ b/docs/source/development/reference/index.rst @@ -10,4 +10,3 @@ Reference datatypes functions cpp/index.rst - deprecated diff --git a/src/Makefile.am b/src/Makefile.am index 5b36c8bd..62bff403 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -9,7 +9,7 @@ AM_CPPFLAGS = -DPROJ_LIB=\"$(pkgdatadir)\" \ -DMUTEX_@MUTEX_SETTING@ -I$(top_srcdir)/include @SQLITE3_CFLAGS@ @TIFF_CFLAGS@ @TIFF_ENABLED_FLAGS@ @CURL_CFLAGS@ @CURL_ENABLED_FLAGS@ AM_CXXFLAGS = @CXX_WFLAGS@ @FLTO_FLAG@ -include_HEADERS = proj.h proj_experimental.h proj_constants.h proj_api.h geodesic.h \ +include_HEADERS = proj.h proj_experimental.h proj_constants.h geodesic.h \ proj_symbol_rename.h EXTRA_DIST = bin_cct.cmake bin_gie.cmake bin_cs2cs.cmake \ diff --git a/src/apps/emess.cpp b/src/apps/emess.cpp index 53018ba8..138cbf01 100644 --- a/src/apps/emess.cpp +++ b/src/apps/emess.cpp @@ -19,7 +19,7 @@ #include #include -#include "proj_api.h" +#include "proj_internal.h" #include "proj_config.h" #define EMESS_ROUTINE #include "emess.h" diff --git a/src/iso19111/datum.cpp b/src/iso19111/datum.cpp index e29f6319..28dbc462 100644 --- a/src/iso19111/datum.cpp +++ b/src/iso19111/datum.cpp @@ -43,7 +43,6 @@ // clang-format off #include "proj.h" #include "proj_internal.h" -#include "proj_api.h" // clang-format on #include "proj_json_streaming_writer.hpp" diff --git a/src/iso19111/factory.cpp b/src/iso19111/factory.cpp index 0ccfefc1..03fd5267 100644 --- a/src/iso19111/factory.cpp +++ b/src/iso19111/factory.cpp @@ -65,7 +65,6 @@ // clang-format off #include "proj.h" #include "proj_internal.h" -#include "proj_api.h" // clang-format on #include diff --git a/src/iso19111/io.cpp b/src/iso19111/io.cpp index 623ad6f9..8c815f36 100644 --- a/src/iso19111/io.cpp +++ b/src/iso19111/io.cpp @@ -70,7 +70,6 @@ // clang-format off #include "proj.h" #include "proj_internal.h" -#include "proj_api.h" // clang-format on using namespace NS_PROJ::common; diff --git a/src/lib_proj.cmake b/src/lib_proj.cmake index 67bc1f4e..95417004 100644 --- a/src/lib_proj.cmake +++ b/src/lib_proj.cmake @@ -275,7 +275,6 @@ set(SRC_LIBPROJ_CORE ) set(HEADERS_LIBPROJ - proj_api.h proj.h proj_experimental.h proj_constants.h diff --git a/src/mutex.cpp b/src/mutex.cpp index da415e55..2cc4d0a1 100644 --- a/src/mutex.cpp +++ b/src/mutex.cpp @@ -34,11 +34,6 @@ #ifndef _WIN32 #include "proj_config.h" #include "proj_internal.h" -#else -#ifndef ACCEPT_USE_OF_DEPRECATED_PROJ_API_H -#define ACCEPT_USE_OF_DEPRECATED_PROJ_API_H -#endif -#include "proj_api.h" #endif /* on win32 we always use win32 mutexes, even if pthreads are available */ diff --git a/src/proj.h b/src/proj.h index 4185ddbf..0597db26 100644 --- a/src/proj.h +++ b/src/proj.h @@ -119,10 +119,6 @@ #include /* For size_t */ -#ifdef PROJ_API_H -#error proj.h must be included before proj_api.h -#endif - #ifdef PROJ_RENAME_SYMBOLS #include "proj_symbol_rename.h" #endif diff --git a/src/proj_api.h b/src/proj_api.h deleted file mode 100644 index a26088ca..00000000 --- a/src/proj_api.h +++ /dev/null @@ -1,227 +0,0 @@ -/****************************************************************************** - * Project: PROJ.4 - * Purpose: Public (application) include file for PROJ.4 API, and constants. - * Author: Frank Warmerdam, - * - ****************************************************************************** - * Copyright (c) 2001, Frank Warmerdam - * - * 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. - *****************************************************************************/ - -/* - * This version number should be updated with every release! - * - * This file is expected to be removed from the PROJ distribution - * when a few minor-version releases has been made. - * - */ - -#ifndef ACCEPT_USE_OF_DEPRECATED_PROJ_API_H -#error 'To use the proj_api.h you must define the macro ACCEPT_USE_OF_DEPRECATED_PROJ_API_H' -#endif - -#ifndef PJ_VERSION -#define PJ_VERSION 800 -#endif - -#ifdef PROJ_RENAME_SYMBOLS -#include "proj_symbol_rename.h" -#endif - - -/* If we're not asked for PJ_VERSION only, give them everything */ -#ifndef PROJ_API_INCLUDED_FOR_PJ_VERSION_ONLY -/* General projections header file */ -#ifndef PROJ_API_H -#define PROJ_API_H - -/* standard inclusions */ -#include -#include -#include - -#ifndef PROJ_DLL -#ifdef PROJ_MSVC_DLL_EXPORT -#define PROJ_DLL __declspec(dllexport) -#elif defined(PROJ_MSVC_DLL_IMPORT) -#define PROJ_DLL __declspec(dllimport) -#elif defined(__GNUC__) -#define PROJ_DLL __attribute__ ((visibility("default"))) -#else -#define PROJ_DLL -#endif -#endif - -#ifdef __cplusplus -extern "C" { -#endif - - -/* pj_init() and similar functions can be used with a non-C locale */ -/* Can be detected too at runtime if the symbol pj_atof exists */ -#define PJ_LOCALE_SAFE 1 - -#define RAD_TO_DEG 57.295779513082321 -#define DEG_TO_RAD .017453292519943296 - - -#if defined(PROJ_H) -#define PROJ_API_H_NOT_INVOKED_AS_PRIMARY_API -#endif - - - -extern char const PROJ_DLL pj_release[]; /* global release id string */ -PROJ_DLL extern int pj_errno; /* global error return code */ - -#ifndef PROJ_INTERNAL_H -/* replaced by enum proj_log_level in proj_internal.h */ -#define PJ_LOG_NONE 0 -#define PJ_LOG_ERROR 1 -#define PJ_LOG_DEBUG_MAJOR 2 -#define PJ_LOG_DEBUG_MINOR 3 -#endif - -#ifdef PROJ_API_H_NOT_INVOKED_AS_PRIMARY_API - /* These make the function declarations below conform with classic proj */ - typedef PJ *projPJ; /* projPJ is a pointer to PJ */ - typedef struct projCtx_t *projCtx; /* projCtx is a pointer to projCtx_t */ -# define projXY PJ_XY -# define projLP PJ_LP -# define projXYZ PJ_XYZ -# define projLPZ PJ_LPZ - -#else - /* i.e. proj_api invoked as primary API */ - typedef struct { double u, v; } projUV; - typedef struct { double u, v, w; } projUVW; - typedef void *projPJ; - #define projXY projUV - #define projLP projUV - #define projXYZ projUVW - #define projLPZ projUVW - typedef void *projCtx; -#endif - - -/* If included *after* proj.h finishes, we have alternative names */ -/* file reading api, like stdio */ -typedef int *PAFile; -typedef struct projFileAPI_t { - PAFile (*FOpen)(projCtx ctx, const char *filename, const char *access); - size_t (*FRead)(void *buffer, size_t size, size_t nmemb, PAFile file); - int (*FSeek)(PAFile file, long offset, int whence); - long (*FTell)(PAFile file); - void (*FClose)(PAFile); -} projFileAPI; - - - -/* procedure prototypes */ - -projCtx PROJ_DLL pj_get_default_ctx(void); -projCtx PROJ_DLL pj_get_ctx( projPJ ); - -projXY PROJ_DLL pj_fwd(projLP, projPJ); -projLP PROJ_DLL pj_inv(projXY, projPJ); - -projXYZ PROJ_DLL pj_fwd3d(projLPZ, projPJ); -projLPZ PROJ_DLL pj_inv3d(projXYZ, projPJ); - - -int PROJ_DLL pj_transform( projPJ src, projPJ dst, long point_count, int point_offset, - double *x, double *y, double *z ); -int PROJ_DLL pj_datum_transform( projPJ src, projPJ dst, long point_count, int point_offset, - double *x, double *y, double *z ); -int PROJ_DLL pj_geocentric_to_geodetic( double a, double es, - long point_count, int point_offset, - double *x, double *y, double *z ); -int PROJ_DLL pj_geodetic_to_geocentric( double a, double es, - long point_count, int point_offset, - double *x, double *y, double *z ); -int PROJ_DLL pj_compare_datums( projPJ srcdefn, projPJ dstdefn ); -int PROJ_DLL pj_apply_gridshift( projCtx, const char *, int, - long point_count, int point_offset, - double *x, double *y, double *z ); -void PROJ_DLL pj_deallocate_grids(void); -void PROJ_DLL pj_clear_initcache(void); -int PROJ_DLL pj_is_latlong(projPJ); -int PROJ_DLL pj_is_geocent(projPJ); -void PROJ_DLL pj_get_spheroid_defn(projPJ defn, double *major_axis, double *eccentricity_squared); -void PROJ_DLL pj_pr_list(projPJ); -void PROJ_DLL pj_free(projPJ); -void PROJ_DLL pj_set_finder( const char *(*)(const char *) ); -void PROJ_DLL pj_set_searchpath ( int count, const char **path ); -projPJ PROJ_DLL pj_init(int, char **); -projPJ PROJ_DLL pj_init_plus(const char *); -projPJ PROJ_DLL pj_init_ctx( projCtx, int, char ** ); -projPJ PROJ_DLL pj_init_plus_ctx( projCtx, const char * ); -char PROJ_DLL *pj_get_def(projPJ, int); -projPJ PROJ_DLL pj_latlong_from_proj( projPJ ); -int PROJ_DLL pj_has_inverse(projPJ); - - -void PROJ_DLL *pj_malloc(size_t); -void PROJ_DLL pj_dalloc(void *); -void PROJ_DLL *pj_calloc (size_t n, size_t size); -void PROJ_DLL *pj_dealloc (void *ptr); -char PROJ_DLL *pj_strdup(const char *str); -char PROJ_DLL *pj_strerrno(int); -int PROJ_DLL *pj_get_errno_ref(void); -const char PROJ_DLL *pj_get_release(void); -void PROJ_DLL pj_acquire_lock(void); -void PROJ_DLL pj_release_lock(void); -void PROJ_DLL pj_cleanup_lock(void); - -void PROJ_DLL pj_set_ctx( projPJ, projCtx ); -projCtx PROJ_DLL pj_ctx_alloc(void); -void PROJ_DLL pj_ctx_free( projCtx ); -int PROJ_DLL pj_ctx_get_errno( projCtx ); -void PROJ_DLL pj_ctx_set_errno( projCtx, int ); -void PROJ_DLL pj_ctx_set_debug( projCtx, int ); -void PROJ_DLL pj_ctx_set_logger( projCtx, void (*)(void *, int, const char *) ); -void PROJ_DLL pj_ctx_set_app_data( projCtx, void * ); -void PROJ_DLL *pj_ctx_get_app_data( projCtx ); -void PROJ_DLL pj_ctx_set_fileapi( projCtx, projFileAPI *); -projFileAPI PROJ_DLL *pj_ctx_get_fileapi( projCtx ); - -void PROJ_DLL pj_log( projCtx ctx, int level, const char *fmt, ... ); -void PROJ_DLL pj_stderr_logger( void *, int, const char * ); - -/* file api */ -projFileAPI PROJ_DLL *pj_get_default_fileapi(void); - -PAFile PROJ_DLL pj_ctx_fopen(projCtx ctx, const char *filename, const char *access); -size_t PROJ_DLL pj_ctx_fread(projCtx ctx, void *buffer, size_t size, size_t nmemb, PAFile file); -int PROJ_DLL pj_ctx_fseek(projCtx ctx, PAFile file, long offset, int whence); -long PROJ_DLL pj_ctx_ftell(projCtx ctx, PAFile file); -void PROJ_DLL pj_ctx_fclose(projCtx ctx, PAFile file); -char PROJ_DLL *pj_ctx_fgets(projCtx ctx, char *line, int size, PAFile file); - -PAFile PROJ_DLL pj_open_lib(projCtx, const char *, const char *); -int PROJ_DLL pj_find_file(projCtx ctx, const char *short_filename, - char* out_full_filename, size_t out_full_filename_size); - -#ifdef __cplusplus -} -#endif - -#endif /* ndef PROJ_API_H */ -#endif /* ndef PROJ_API_INCLUDED_FOR_PJ_VERSION_ONLY */ diff --git a/src/proj_internal.h b/src/proj_internal.h index 203765a3..5a075088 100644 --- a/src/proj_internal.h +++ b/src/proj_internal.h @@ -66,10 +66,6 @@ #include "proj.h" -#ifdef PROJ_API_H -#error proj_internal.h must be included before proj_api.h -#endif - #ifdef PROJ_RENAME_SYMBOLS #include "proj_symbol_rename.h" #endif @@ -910,7 +906,162 @@ void pj_clear_vgridshift_knowngrids_cache(); PJ_LP pj_generic_inverse_2d(PJ_XY xy, PJ *P, PJ_LP lpInitial); -/* classic public API */ -#include "proj_api.h" + + + +/*****************************************************************************/ +/* */ +/* proj_api.h */ +/* */ +/* The rest of this header file includes what used to be "proj_api.h" */ +/* */ +/*****************************************************************************/ + +/* pj_init() and similar functions can be used with a non-C locale */ +/* Can be detected too at runtime if the symbol pj_atof exists */ +#define PJ_LOCALE_SAFE 1 + +#define RAD_TO_DEG 57.295779513082321 +#define DEG_TO_RAD .017453292519943296 + + +#if defined(PROJ_H) +#define PROJ_API_H_NOT_INVOKED_AS_PRIMARY_API +#endif + + + +extern char const PROJ_DLL pj_release[]; /* global release id string */ +PROJ_DLL extern int pj_errno; /* global error return code */ + +#ifndef PROJ_INTERNAL_H +/* replaced by enum proj_log_level in proj_internal.h */ +#define PJ_LOG_NONE 0 +#define PJ_LOG_ERROR 1 +#define PJ_LOG_DEBUG_MAJOR 2 +#define PJ_LOG_DEBUG_MINOR 3 +#endif + +#ifdef PROJ_API_H_NOT_INVOKED_AS_PRIMARY_API + /* These make the function declarations below conform with classic proj */ + typedef PJ *projPJ; /* projPJ is a pointer to PJ */ + typedef struct projCtx_t *projCtx; /* projCtx is a pointer to projCtx_t */ +# define projXY PJ_XY +# define projLP PJ_LP +# define projXYZ PJ_XYZ +# define projLPZ PJ_LPZ + +#else + /* i.e. proj_api invoked as primary API */ + typedef struct { double u, v; } projUV; + typedef struct { double u, v, w; } projUVW; + typedef void *projPJ; + #define projXY projUV + #define projLP projUV + #define projXYZ projUVW + #define projLPZ projUVW + typedef void *projCtx; +#endif + + +/* If included *after* proj.h finishes, we have alternative names */ +/* file reading api, like stdio */ +typedef int *PAFile; +typedef struct projFileAPI_t { + PAFile (*FOpen)(projCtx ctx, const char *filename, const char *access); + size_t (*FRead)(void *buffer, size_t size, size_t nmemb, PAFile file); + int (*FSeek)(PAFile file, long offset, int whence); + long (*FTell)(PAFile file); + void (*FClose)(PAFile); +} projFileAPI; + + + +/* procedure prototypes */ + +projCtx PROJ_DLL pj_get_default_ctx(void); +projCtx PROJ_DLL pj_get_ctx( projPJ ); + +projXY PROJ_DLL pj_fwd(projLP, projPJ); +projLP PROJ_DLL pj_inv(projXY, projPJ); + +projXYZ PROJ_DLL pj_fwd3d(projLPZ, projPJ); +projLPZ PROJ_DLL pj_inv3d(projXYZ, projPJ); + + +int PROJ_DLL pj_transform( projPJ src, projPJ dst, long point_count, int point_offset, + double *x, double *y, double *z ); +int PROJ_DLL pj_datum_transform( projPJ src, projPJ dst, long point_count, int point_offset, + double *x, double *y, double *z ); +int PROJ_DLL pj_geocentric_to_geodetic( double a, double es, + long point_count, int point_offset, + double *x, double *y, double *z ); +int PROJ_DLL pj_geodetic_to_geocentric( double a, double es, + long point_count, int point_offset, + double *x, double *y, double *z ); +int PROJ_DLL pj_compare_datums( projPJ srcdefn, projPJ dstdefn ); +int PROJ_DLL pj_apply_gridshift( projCtx, const char *, int, + long point_count, int point_offset, + double *x, double *y, double *z ); +void PROJ_DLL pj_deallocate_grids(void); +void PROJ_DLL pj_clear_initcache(void); +int PROJ_DLL pj_is_latlong(projPJ); +int PROJ_DLL pj_is_geocent(projPJ); +void PROJ_DLL pj_get_spheroid_defn(projPJ defn, double *major_axis, double *eccentricity_squared); +void PROJ_DLL pj_pr_list(projPJ); +void PROJ_DLL pj_free(projPJ); +void PROJ_DLL pj_set_finder( const char *(*)(const char *) ); +void PROJ_DLL pj_set_searchpath ( int count, const char **path ); +projPJ PROJ_DLL pj_init(int, char **); +projPJ PROJ_DLL pj_init_plus(const char *); +projPJ PROJ_DLL pj_init_ctx( projCtx, int, char ** ); +projPJ PROJ_DLL pj_init_plus_ctx( projCtx, const char * ); +char PROJ_DLL *pj_get_def(projPJ, int); +projPJ PROJ_DLL pj_latlong_from_proj( projPJ ); +int PROJ_DLL pj_has_inverse(projPJ); + + +void PROJ_DLL *pj_malloc(size_t); +void PROJ_DLL pj_dalloc(void *); +void PROJ_DLL *pj_calloc (size_t n, size_t size); +void PROJ_DLL *pj_dealloc (void *ptr); +char PROJ_DLL *pj_strdup(const char *str); +char PROJ_DLL *pj_strerrno(int); +int PROJ_DLL *pj_get_errno_ref(void); +const char PROJ_DLL *pj_get_release(void); +void PROJ_DLL pj_acquire_lock(void); +void PROJ_DLL pj_release_lock(void); +void PROJ_DLL pj_cleanup_lock(void); + +void PROJ_DLL pj_set_ctx( projPJ, projCtx ); +projCtx PROJ_DLL pj_ctx_alloc(void); +void PROJ_DLL pj_ctx_free( projCtx ); +int PROJ_DLL pj_ctx_get_errno( projCtx ); +void PROJ_DLL pj_ctx_set_errno( projCtx, int ); +void PROJ_DLL pj_ctx_set_debug( projCtx, int ); +void PROJ_DLL pj_ctx_set_logger( projCtx, void (*)(void *, int, const char *) ); +void PROJ_DLL pj_ctx_set_app_data( projCtx, void * ); +void PROJ_DLL *pj_ctx_get_app_data( projCtx ); +void PROJ_DLL pj_ctx_set_fileapi( projCtx, projFileAPI *); +projFileAPI PROJ_DLL *pj_ctx_get_fileapi( projCtx ); + +void PROJ_DLL pj_log( projCtx ctx, int level, const char *fmt, ... ); +void PROJ_DLL pj_stderr_logger( void *, int, const char * ); + +/* file api */ +projFileAPI PROJ_DLL *pj_get_default_fileapi(void); + +PAFile PROJ_DLL pj_ctx_fopen(projCtx ctx, const char *filename, const char *access); +size_t PROJ_DLL pj_ctx_fread(projCtx ctx, void *buffer, size_t size, size_t nmemb, PAFile file); +int PROJ_DLL pj_ctx_fseek(projCtx ctx, PAFile file, long offset, int whence); +long PROJ_DLL pj_ctx_ftell(projCtx ctx, PAFile file); +void PROJ_DLL pj_ctx_fclose(projCtx ctx, PAFile file); +char PROJ_DLL *pj_ctx_fgets(projCtx ctx, char *line, int size, PAFile file); + +PAFile PROJ_DLL pj_open_lib(projCtx, const char *, const char *); +int PROJ_DLL pj_find_file(projCtx ctx, const char *short_filename, + char* out_full_filename, size_t out_full_filename_size); + + #endif /* ndef PROJ_INTERNAL_H */ diff --git a/src/projections/calcofi.cpp b/src/projections/calcofi.cpp index 57c12dde..d1e96de8 100644 --- a/src/projections/calcofi.cpp +++ b/src/projections/calcofi.cpp @@ -4,7 +4,6 @@ #include "proj.h" #include "proj_internal.h" -#include "proj_api.h" PROJ_HEAD(calcofi, "Cal Coop Ocean Fish Invest Lines/Stations") "\n\tCyl, Sph&Ell"; diff --git a/src/tests/multistresstest.cpp b/src/tests/multistresstest.cpp index 33d2d738..6af35979 100644 --- a/src/tests/multistresstest.cpp +++ b/src/tests/multistresstest.cpp @@ -34,7 +34,7 @@ #define ACCEPT_USE_OF_DEPRECATED_PROJ_API_H #endif -#include "proj_api.h" +#include "proj_internal.h" #ifdef _WIN32 #include diff --git a/src/tests/test228.cpp b/src/tests/test228.cpp index 8ae17c87..b27ebf2f 100644 --- a/src/tests/test228.cpp +++ b/src/tests/test228.cpp @@ -30,7 +30,7 @@ #define ACCEPT_USE_OF_DEPRECATED_PROJ_API_H #endif -#include "proj_api.h" +#include "proj_internal.h" #include /* for printf declaration */ diff --git a/test/fuzzers/standard_fuzzer.cpp b/test/fuzzers/standard_fuzzer.cpp index 468e8cbb..552ac781 100644 --- a/test/fuzzers/standard_fuzzer.cpp +++ b/test/fuzzers/standard_fuzzer.cpp @@ -36,7 +36,7 @@ #define ACCEPT_USE_OF_DEPRECATED_PROJ_API_H #include "proj.h" -#include "proj_api.h" +#include "proj_internal.h" /* Standalone build: g++ -g -std=c++11 standard_fuzzer.cpp -o standard_fuzzer -fvisibility=hidden -DSTANDALONE ../../src/.libs/libproj.a -lpthread -lsqlite3 -I../../src -I../../include diff --git a/test/unit/pj_transform_test.cpp b/test/unit/pj_transform_test.cpp index ddb054f0..5f390541 100644 --- a/test/unit/pj_transform_test.cpp +++ b/test/unit/pj_transform_test.cpp @@ -35,7 +35,6 @@ // clang-format off #include #include "proj_internal.h" -#include // clang-format on namespace { -- cgit v1.2.3 From 9e50c8c0e207191c4c7bb6883f7ad485df04fc2c Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Sun, 1 Nov 2020 14:56:17 +0100 Subject: Remove ACCEPT_USE_OF_DEPRECATED_PROJ_API_H macro --- src/apps/emess.cpp | 4 ---- src/proj_internal.h | 4 ---- src/tests/multistresstest.cpp | 4 ---- src/tests/test228.cpp | 4 ---- test/fuzzers/standard_fuzzer.cpp | 1 - test/unit/pj_transform_test.cpp | 2 -- 6 files changed, 19 deletions(-) diff --git a/src/apps/emess.cpp b/src/apps/emess.cpp index 138cbf01..5a50cd25 100644 --- a/src/apps/emess.cpp +++ b/src/apps/emess.cpp @@ -9,10 +9,6 @@ # endif #endif -#ifndef ACCEPT_USE_OF_DEPRECATED_PROJ_API_H -#define ACCEPT_USE_OF_DEPRECATED_PROJ_API_H -#endif - #include #include #include diff --git a/src/proj_internal.h b/src/proj_internal.h index 5a075088..e0cc5170 100644 --- a/src/proj_internal.h +++ b/src/proj_internal.h @@ -33,10 +33,6 @@ #error "proj_internal.h can only be included from a C++ file" #endif -#ifndef ACCEPT_USE_OF_DEPRECATED_PROJ_API_H -#define ACCEPT_USE_OF_DEPRECATED_PROJ_API_H -#endif - #ifdef _MSC_VER # ifndef _CRT_SECURE_NO_DEPRECATE # define _CRT_SECURE_NO_DEPRECATE diff --git a/src/tests/multistresstest.cpp b/src/tests/multistresstest.cpp index 6af35979..51720fbd 100644 --- a/src/tests/multistresstest.cpp +++ b/src/tests/multistresstest.cpp @@ -30,10 +30,6 @@ #include #include -#ifndef ACCEPT_USE_OF_DEPRECATED_PROJ_API_H -#define ACCEPT_USE_OF_DEPRECATED_PROJ_API_H -#endif - #include "proj_internal.h" #ifdef _WIN32 diff --git a/src/tests/test228.cpp b/src/tests/test228.cpp index b27ebf2f..bffb8e79 100644 --- a/src/tests/test228.cpp +++ b/src/tests/test228.cpp @@ -26,10 +26,6 @@ * DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#ifndef ACCEPT_USE_OF_DEPRECATED_PROJ_API_H -#define ACCEPT_USE_OF_DEPRECATED_PROJ_API_H -#endif - #include "proj_internal.h" #include /* for printf declaration */ diff --git a/test/fuzzers/standard_fuzzer.cpp b/test/fuzzers/standard_fuzzer.cpp index 552ac781..ab30200b 100644 --- a/test/fuzzers/standard_fuzzer.cpp +++ b/test/fuzzers/standard_fuzzer.cpp @@ -34,7 +34,6 @@ #include #include -#define ACCEPT_USE_OF_DEPRECATED_PROJ_API_H #include "proj.h" #include "proj_internal.h" diff --git a/test/unit/pj_transform_test.cpp b/test/unit/pj_transform_test.cpp index 5f390541..6f02ec5a 100644 --- a/test/unit/pj_transform_test.cpp +++ b/test/unit/pj_transform_test.cpp @@ -26,8 +26,6 @@ * DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#define ACCEPT_USE_OF_DEPRECATED_PROJ_API_H - #include "gtest_include.h" #include -- cgit v1.2.3 From eb82aa83f2530e5e4df420ab64476b947bdc7f5d Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Sat, 14 Nov 2020 11:04:02 +0100 Subject: Raise error when ACCEPT_USE_OF_DEPRECATED_PROJ_API_H is defined --- scripts/cppcheck.sh | 2 +- src/proj.h | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/scripts/cppcheck.sh b/scripts/cppcheck.sh index 1cfd61b5..4e76db94 100755 --- a/scripts/cppcheck.sh +++ b/scripts/cppcheck.sh @@ -22,7 +22,7 @@ for dirname in ${TOPDIR}/src; do echo "Running cppcheck on $dirname... (can be long)" if ! cppcheck --inline-suppr --template='{file}:{line},{severity},{id},{message}' \ --enable=all --inconclusive --std=posix \ - -DCPPCHECK -D__cplusplus=201103L -DACCEPT_USE_OF_DEPRECATED_PROJ_API_H -DNAN \ + -DCPPCHECK -D__cplusplus=201103L -DNAN \ -I${TOPDIR}/src -I${TOPDIR}/include \ "$dirname" \ -j 8 >>${LOG_FILE} 2>&1 ; then diff --git a/src/proj.h b/src/proj.h index 0597db26..e2c47a17 100644 --- a/src/proj.h +++ b/src/proj.h @@ -119,6 +119,10 @@ #include /* For size_t */ +#ifdef ACCEPT_USE_OF_DEPRECATED_PROJ_API_H + #error "The proj_api.h header has been removed from PROJ with version 8.0.0" +#endif + #ifdef PROJ_RENAME_SYMBOLS #include "proj_symbol_rename.h" #endif -- cgit v1.2.3 From e2dd223c5601b387cd622b88583e857b03e9fade Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Sat, 14 Nov 2020 11:28:36 +0100 Subject: Remove src/transform.cpp and related tests --- src/Makefile.am | 2 +- src/lib_proj.cmake | 1 - src/malloc.cpp | 1 - src/proj_internal.h | 12 - src/transform.cpp | 1850 --------------------------------------- test/unit/CMakeLists.txt | 11 - test/unit/Makefile.am | 10 +- test/unit/pj_transform_test.cpp | 737 ---------------- 8 files changed, 3 insertions(+), 2621 deletions(-) delete mode 100644 src/transform.cpp delete mode 100644 test/unit/pj_transform_test.cpp diff --git a/src/Makefile.am b/src/Makefile.am index 62bff403..edfd05ef 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -220,7 +220,7 @@ libproj_la_SOURCES = \ generic_inverse.cpp \ quadtree.hpp \ \ - datums.cpp datum_set.cpp transform.cpp \ + datums.cpp datum_set.cpp \ utils.cpp \ mutex.cpp initcache.cpp geodesic.c \ strtod.cpp \ diff --git a/src/lib_proj.cmake b/src/lib_proj.cmake index 95417004..b0f9a6ba 100644 --- a/src/lib_proj.cmake +++ b/src/lib_proj.cmake @@ -246,7 +246,6 @@ set(SRC_LIBPROJ_CORE rtodms.cpp strerrno.cpp strtod.cpp - transform.cpp tsfn.cpp units.cpp utils.cpp diff --git a/src/malloc.cpp b/src/malloc.cpp index c8de6630..eb64023f 100644 --- a/src/malloc.cpp +++ b/src/malloc.cpp @@ -262,7 +262,6 @@ PJ *pj_default_destructor (PJ *P, int errlev) { /* Destructor */ void proj_cleanup() { /*****************************************************************************/ pj_clear_initcache(); - pj_deallocate_grids(); FileManager::clearMemoryCache(); pj_clear_hgridshift_knowngrids_cache(); pj_clear_vgridshift_knowngrids_cache(); diff --git a/src/proj_internal.h b/src/proj_internal.h index e0cc5170..062f240b 100644 --- a/src/proj_internal.h +++ b/src/proj_internal.h @@ -985,21 +985,9 @@ projXYZ PROJ_DLL pj_fwd3d(projLPZ, projPJ); projLPZ PROJ_DLL pj_inv3d(projXYZ, projPJ); -int PROJ_DLL pj_transform( projPJ src, projPJ dst, long point_count, int point_offset, - double *x, double *y, double *z ); -int PROJ_DLL pj_datum_transform( projPJ src, projPJ dst, long point_count, int point_offset, - double *x, double *y, double *z ); -int PROJ_DLL pj_geocentric_to_geodetic( double a, double es, - long point_count, int point_offset, - double *x, double *y, double *z ); -int PROJ_DLL pj_geodetic_to_geocentric( double a, double es, - long point_count, int point_offset, - double *x, double *y, double *z ); -int PROJ_DLL pj_compare_datums( projPJ srcdefn, projPJ dstdefn ); int PROJ_DLL pj_apply_gridshift( projCtx, const char *, int, long point_count, int point_offset, double *x, double *y, double *z ); -void PROJ_DLL pj_deallocate_grids(void); void PROJ_DLL pj_clear_initcache(void); int PROJ_DLL pj_is_latlong(projPJ); int PROJ_DLL pj_is_geocent(projPJ); diff --git a/src/transform.cpp b/src/transform.cpp deleted file mode 100644 index cff89232..00000000 --- a/src/transform.cpp +++ /dev/null @@ -1,1850 +0,0 @@ -/****************************************************************************** - * Project: PROJ.4 - * Purpose: Perform overall coordinate system to coordinate system - * transformations (pj_transform() function) including reprojection - * and datum shifting. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 2000, Frank Warmerdam - * - * 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 -#include -#include - -#include "proj.h" -#include "proj_internal.h" -#include "grids.hpp" - -using namespace NS_PROJ; - - -/////////////////////////////////////////////////////////////////////////////// -/// From older geocent.h -/////////////////////////////////////////////////////////////////////////////// - - -/***************************************************************************/ -/* RSC IDENTIFIER: GEOCENTRIC - * - * ABSTRACT - * - * This component provides conversions between Geodetic coordinates (latitude, - * longitude in radians and height in meters) and Geocentric coordinates - * (X, Y, Z) in meters. - * - * ERROR HANDLING - * - * This component checks parameters for valid values. If an invalid value - * is found, the error code is combined with the current error code using - * the bitwise or. This combining allows multiple error codes to be - * returned. The possible error codes are: - * - * GEOCENT_NO_ERROR : No errors occurred in function - * GEOCENT_LAT_ERROR : Latitude out of valid range - * (-90 to 90 degrees) - * GEOCENT_LON_ERROR : Longitude out of valid range - * (-180 to 360 degrees) - * GEOCENT_A_ERROR : Semi-major axis less than or equal to zero - * GEOCENT_B_ERROR : Semi-minor axis less than or equal to zero - * GEOCENT_A_LESS_B_ERROR : Semi-major axis less than semi-minor axis - * - * - * REUSE NOTES - * - * GEOCENTRIC is intended for reuse by any application that performs - * coordinate conversions between geodetic coordinates and geocentric - * coordinates. - * - * - * REFERENCES - * - * An Improved Algorithm for Geocentric to Geodetic Coordinate Conversion, - * Ralph Toms, February 1996 UCRL-JC-123138. - * - * Further information on GEOCENTRIC can be found in the Reuse Manual. - * - * GEOCENTRIC originated from : U.S. Army Topographic Engineering Center - * Geospatial Information Division - * 7701 Telegraph Road - * Alexandria, VA 22310-3864 - * - * LICENSES - * - * None apply to this component. - * - * RESTRICTIONS - * - * GEOCENTRIC has no restrictions. - * - * ENVIRONMENT - * - * GEOCENTRIC was tested and certified in the following environments: - * - * 1. Solaris 2.5 with GCC version 2.8.1 - * 2. Windows 95 with MS Visual C++ version 6 - * - * MODIFICATIONS - * - * Date Description - * ---- ----------- - * - * - */ - - -/***************************************************************************/ -/* - * DEFINES - */ -#define GEOCENT_NO_ERROR 0x0000 -#define GEOCENT_LAT_ERROR 0x0001 -#define GEOCENT_LON_ERROR 0x0002 -#define GEOCENT_A_ERROR 0x0004 -#define GEOCENT_B_ERROR 0x0008 -#define GEOCENT_A_LESS_B_ERROR 0x0010 - - -/***************************************************************************/ -/* - * FUNCTION PROTOTYPES - */ - -/* ensure proper linkage to c++ programs */ -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct -{ - double Geocent_a; /* Semi-major axis of ellipsoid in meters */ - double Geocent_b; /* Semi-minor axis of ellipsoid */ - double Geocent_a2; /* Square of semi-major axis */ - double Geocent_b2; /* Square of semi-minor axis */ - double Geocent_e2; /* Eccentricity squared */ - double Geocent_ep2; /* 2nd eccentricity squared */ -} GeocentricInfo; - -void pj_Init_Geocentric( GeocentricInfo *gi ); -long pj_Set_Geocentric_Parameters( GeocentricInfo *gi, - double a, - double b); - -/* - * The function Set_Geocentric_Parameters receives the ellipsoid parameters - * as inputs and sets the corresponding state variables. - * - * a : Semi-major axis, in meters. (input) - * b : Semi-minor axis, in meters. (input) - */ - - -void pj_Get_Geocentric_Parameters ( GeocentricInfo *gi, - double *a, - double *b); - -/* - * The function Get_Geocentric_Parameters returns the ellipsoid parameters - * to be used in geocentric coordinate conversions. - * - * a : Semi-major axis, in meters. (output) - * b : Semi-minor axis, in meters. (output) - */ - - -long pj_Convert_Geodetic_To_Geocentric ( GeocentricInfo *gi, - double Latitude, - double Longitude, - double Height, - double *X, - double *Y, - double *Z); -/* - * The function Convert_Geodetic_To_Geocentric converts geodetic coordinates - * (latitude, longitude, and height) to geocentric coordinates (X, Y, Z), - * according to the current ellipsoid parameters. - * - * Latitude : Geodetic latitude in radians (input) - * Longitude : Geodetic longitude in radians (input) - * Height : Geodetic height, in meters (input) - * X : Calculated Geocentric X coordinate, in meters. (output) - * Y : Calculated Geocentric Y coordinate, in meters. (output) - * Z : Calculated Geocentric Z coordinate, in meters. (output) - * - */ - - -void pj_Convert_Geocentric_To_Geodetic (GeocentricInfo *gi, - double X, - double Y, - double Z, - double *Latitude, - double *Longitude, - double *Height); -/* - * The function Convert_Geocentric_To_Geodetic converts geocentric - * coordinates (X, Y, Z) to geodetic coordinates (latitude, longitude, - * and height), according to the current ellipsoid parameters. - * - * X : Geocentric X coordinate, in meters. (input) - * Y : Geocentric Y coordinate, in meters. (input) - * Z : Geocentric Z coordinate, in meters. (input) - * Latitude : Calculated latitude value in radians. (output) - * Longitude : Calculated longitude value in radians. (output) - * Height : Calculated height value, in meters. (output) - */ - - -#ifdef __cplusplus -} -#endif - - -/////////////////////////////////////////////////////////////////////////////// -/// From older geocent.cpp -/////////////////////////////////////////////////////////////////////////////// - - -/***************************************************************************/ -/* RSC IDENTIFIER: GEOCENTRIC - * - * ABSTRACT - * - * This component provides conversions between Geodetic coordinates (latitude, - * longitude in radians and height in meters) and Geocentric coordinates - * (X, Y, Z) in meters. - * - * ERROR HANDLING - * - * This component checks parameters for valid values. If an invalid value - * is found, the error code is combined with the current error code using - * the bitwise or. This combining allows multiple error codes to be - * returned. The possible error codes are: - * - * GEOCENT_NO_ERROR : No errors occurred in function - * GEOCENT_LAT_ERROR : Latitude out of valid range - * (-90 to 90 degrees) - * GEOCENT_LON_ERROR : Longitude out of valid range - * (-180 to 360 degrees) - * GEOCENT_A_ERROR : Semi-major axis lessthan or equal to zero - * GEOCENT_B_ERROR : Semi-minor axis lessthan or equal to zero - * GEOCENT_A_LESS_B_ERROR : Semi-major axis less than semi-minor axis - * - * - * REUSE NOTES - * - * GEOCENTRIC is intended for reuse by any application that performs - * coordinate conversions between geodetic coordinates and geocentric - * coordinates. - * - * - * REFERENCES - * - * An Improved Algorithm for Geocentric to Geodetic Coordinate Conversion, - * Ralph Toms, February 1996 UCRL-JC-123138. - * - * Further information on GEOCENTRIC can be found in the Reuse Manual. - * - * GEOCENTRIC originated from : U.S. Army Topographic Engineering Center - * Geospatial Information Division - * 7701 Telegraph Road - * Alexandria, VA 22310-3864 - * - * LICENSES - * - * None apply to this component. - * - * RESTRICTIONS - * - * GEOCENTRIC has no restrictions. - * - * ENVIRONMENT - * - * GEOCENTRIC was tested and certified in the following environments: - * - * 1. Solaris 2.5 with GCC version 2.8.1 - * 2. Windows 95 with MS Visual C++ version 6 - * - * MODIFICATIONS - * - * Date Description - * ---- ----------- - * 25-02-97 Original Code - * - */ - - -/***************************************************************************/ -/* - * INCLUDES - */ -#include -//#include "geocent.h" -/* - * math.h - is needed for calls to sin, cos, tan and sqrt. - * geocent.h - is needed for Error codes and prototype error checking. - */ - - -/***************************************************************************/ -/* - * DEFINES - */ -#define PI 3.14159265358979323e0 -#define PI_OVER_2 (PI / 2.0e0) -#define FALSE 0 -#define TRUE 1 -#define COS_67P5 0.38268343236508977 /* cosine of 67.5 degrees */ -#define AD_C 1.0026000 /* Toms region 1 constant */ - - -/***************************************************************************/ -/* - * FUNCTIONS - */ - - -long pj_Set_Geocentric_Parameters (GeocentricInfo *gi, double a, double b) - -{ /* BEGIN Set_Geocentric_Parameters */ -/* - * The function Set_Geocentric_Parameters receives the ellipsoid parameters - * as inputs and sets the corresponding state variables. - * - * a : Semi-major axis, in meters. (input) - * b : Semi-minor axis, in meters. (input) - */ - long Error_Code = GEOCENT_NO_ERROR; - - if (a <= 0.0) - Error_Code |= GEOCENT_A_ERROR; - if (b <= 0.0) - Error_Code |= GEOCENT_B_ERROR; - if (a < b) - Error_Code |= GEOCENT_A_LESS_B_ERROR; - if (!Error_Code) - { - gi->Geocent_a = a; - gi->Geocent_b = b; - gi->Geocent_a2 = a * a; - gi->Geocent_b2 = b * b; - gi->Geocent_e2 = (gi->Geocent_a2 - gi->Geocent_b2) / gi->Geocent_a2; - gi->Geocent_ep2 = (gi->Geocent_a2 - gi->Geocent_b2) / gi->Geocent_b2; - } - return (Error_Code); -} /* END OF Set_Geocentric_Parameters */ - - -void pj_Get_Geocentric_Parameters (GeocentricInfo *gi, - double *a, - double *b) -{ /* BEGIN Get_Geocentric_Parameters */ -/* - * The function Get_Geocentric_Parameters returns the ellipsoid parameters - * to be used in geocentric coordinate conversions. - * - * a : Semi-major axis, in meters. (output) - * b : Semi-minor axis, in meters. (output) - */ - - *a = gi->Geocent_a; - *b = gi->Geocent_b; -} /* END OF Get_Geocentric_Parameters */ - - -long pj_Convert_Geodetic_To_Geocentric (GeocentricInfo *gi, - double Latitude, - double Longitude, - double Height, - double *X, - double *Y, - double *Z) -{ /* BEGIN Convert_Geodetic_To_Geocentric */ -/* - * The function Convert_Geodetic_To_Geocentric converts geodetic coordinates - * (latitude, longitude, and height) to geocentric coordinates (X, Y, Z), - * according to the current ellipsoid parameters. - * - * Latitude : Geodetic latitude in radians (input) - * Longitude : Geodetic longitude in radians (input) - * Height : Geodetic height, in meters (input) - * X : Calculated Geocentric X coordinate, in meters (output) - * Y : Calculated Geocentric Y coordinate, in meters (output) - * Z : Calculated Geocentric Z coordinate, in meters (output) - * - */ - long Error_Code = GEOCENT_NO_ERROR; - double Rn; /* Earth radius at location */ - double Sin_Lat; /* sin(Latitude) */ - double Sin2_Lat; /* Square of sin(Latitude) */ - double Cos_Lat; /* cos(Latitude) */ - - /* - ** Don't blow up if Latitude is just a little out of the value - ** range as it may just be a rounding issue. Also removed longitude - ** test, it should be wrapped by cos() and sin(). NFW for PROJ.4, Sep/2001. - */ - if( Latitude < -PI_OVER_2 && Latitude > -1.001 * PI_OVER_2 ) - Latitude = -PI_OVER_2; - else if( Latitude > PI_OVER_2 && Latitude < 1.001 * PI_OVER_2 ) - Latitude = PI_OVER_2; - else if ((Latitude < -PI_OVER_2) || (Latitude > PI_OVER_2)) - { /* Latitude out of range */ - Error_Code |= GEOCENT_LAT_ERROR; - } - - if (!Error_Code) - { /* no errors */ - if (Longitude > PI) - Longitude -= (2*PI); - Sin_Lat = sin(Latitude); - Cos_Lat = cos(Latitude); - Sin2_Lat = Sin_Lat * Sin_Lat; - Rn = gi->Geocent_a / (sqrt(1.0e0 - gi->Geocent_e2 * Sin2_Lat)); - *X = (Rn + Height) * Cos_Lat * cos(Longitude); - *Y = (Rn + Height) * Cos_Lat * sin(Longitude); - *Z = ((Rn * (1 - gi->Geocent_e2)) + Height) * Sin_Lat; - - } - return (Error_Code); -} /* END OF Convert_Geodetic_To_Geocentric */ - -/* - * The function Convert_Geocentric_To_Geodetic converts geocentric - * coordinates (X, Y, Z) to geodetic coordinates (latitude, longitude, - * and height), according to the current ellipsoid parameters. - * - * X : Geocentric X coordinate, in meters. (input) - * Y : Geocentric Y coordinate, in meters. (input) - * Z : Geocentric Z coordinate, in meters. (input) - * Latitude : Calculated latitude value in radians. (output) - * Longitude : Calculated longitude value in radians. (output) - * Height : Calculated height value, in meters. (output) - */ - -#define USE_ITERATIVE_METHOD - -void pj_Convert_Geocentric_To_Geodetic (GeocentricInfo *gi, - double X, - double Y, - double Z, - double *Latitude, - double *Longitude, - double *Height) -{ /* BEGIN Convert_Geocentric_To_Geodetic */ -#if !defined(USE_ITERATIVE_METHOD) -/* - * The method used here is derived from 'An Improved Algorithm for - * Geocentric to Geodetic Coordinate Conversion', by Ralph Toms, Feb 1996 - */ - -/* Note: Variable names follow the notation used in Toms, Feb 1996 */ - - double W; /* distance from Z axis */ - double W2; /* square of distance from Z axis */ - double T0; /* initial estimate of vertical component */ - double T1; /* corrected estimate of vertical component */ - double S0; /* initial estimate of horizontal component */ - double S1; /* corrected estimate of horizontal component */ - double Sin_B0; /* sin(B0), B0 is estimate of Bowring aux variable */ - double Sin3_B0; /* cube of sin(B0) */ - double Cos_B0; /* cos(B0) */ - double Sin_p1; /* sin(phi1), phi1 is estimated latitude */ - double Cos_p1; /* cos(phi1) */ - double Rn; /* Earth radius at location */ - double Sum; /* numerator of cos(phi1) */ - int At_Pole; /* indicates location is in polar region */ - - At_Pole = FALSE; - if (X != 0.0) - { - *Longitude = atan2(Y,X); - } - else - { - if (Y > 0) - { - *Longitude = PI_OVER_2; - } - else if (Y < 0) - { - *Longitude = -PI_OVER_2; - } - else - { - At_Pole = TRUE; - *Longitude = 0.0; - if (Z > 0.0) - { /* north pole */ - *Latitude = PI_OVER_2; - } - else if (Z < 0.0) - { /* south pole */ - *Latitude = -PI_OVER_2; - } - else - { /* center of earth */ - *Latitude = PI_OVER_2; - *Height = -Geocent_b; - return; - } - } - } - W2 = X*X + Y*Y; - W = sqrt(W2); - T0 = Z * AD_C; - S0 = sqrt(T0 * T0 + W2); - Sin_B0 = T0 / S0; - Cos_B0 = W / S0; - Sin3_B0 = Sin_B0 * Sin_B0 * Sin_B0; - T1 = Z + gi->Geocent_b * gi->Geocent_ep2 * Sin3_B0; - Sum = W - gi->Geocent_a * gi->Geocent_e2 * Cos_B0 * Cos_B0 * Cos_B0; - S1 = sqrt(T1*T1 + Sum * Sum); - Sin_p1 = T1 / S1; - Cos_p1 = Sum / S1; - Rn = gi->Geocent_a / sqrt(1.0 - gi->Geocent_e2 * Sin_p1 * Sin_p1); - if (Cos_p1 >= COS_67P5) - { - *Height = W / Cos_p1 - Rn; - } - else if (Cos_p1 <= -COS_67P5) - { - *Height = W / -Cos_p1 - Rn; - } - else - { - *Height = Z / Sin_p1 + Rn * (gi->Geocent_e2 - 1.0); - } - if (At_Pole == FALSE) - { - *Latitude = atan(Sin_p1 / Cos_p1); - } -#else /* defined(USE_ITERATIVE_METHOD) */ -/* -* Reference... -* ============ -* Wenzel, H.-G.(1985): Hochauflösende Kugelfunktionsmodelle für -* das Gravitationspotential der Erde. Wiss. Arb. Univ. Hannover -* Nr. 137, p. 130-131. - -* Programmed by GGA- Leibniz-Institute of Applied Geophysics -* Stilleweg 2 -* D-30655 Hannover -* Federal Republic of Germany -* Internet: www.gga-hannover.de -* -* Hannover, March 1999, April 2004. -* see also: comments in statements -* remarks: -* Mathematically exact and because of symmetry of rotation-ellipsoid, -* each point (X,Y,Z) has at least two solutions (Latitude1,Longitude1,Height1) and -* (Latitude2,Longitude2,Height2). Is point=(0.,0.,Z) (P=0.), so you get even -* four solutions, every two symmetrical to the semi-minor axis. -* Here Height1 and Height2 have at least a difference in order of -* radius of curvature (e.g. (0,0,b)=> (90.,0.,0.) or (-90.,0.,-2b); -* (a+100.)*(sqrt(2.)/2.,sqrt(2.)/2.,0.) => (0.,45.,100.) or -* (0.,225.,-(2a+100.))). -* The algorithm always computes (Latitude,Longitude) with smallest |Height|. -* For normal computations, that means |Height|<10000.m, algorithm normally -* converges after to 2-3 steps!!! -* But if |Height| has the amount of length of ellipsoid's axis -* (e.g. -6300000.m), algorithm needs about 15 steps. -*/ - -/* local definitions and variables */ -/* end-criterium of loop, accuracy of sin(Latitude) */ -#define genau 1.E-12 -#define genau2 (genau*genau) -#define maxiter 30 - - double P; /* distance between semi-minor axis and location */ - double RR; /* distance between center and location */ - double CT; /* sin of geocentric latitude */ - double ST; /* cos of geocentric latitude */ - double RX; - double RK; - double RN; /* Earth radius at location */ - double CPHI0; /* cos of start or old geodetic latitude in iterations */ - double SPHI0; /* sin of start or old geodetic latitude in iterations */ - double CPHI; /* cos of searched geodetic latitude */ - double SPHI; /* sin of searched geodetic latitude */ - double SDPHI; /* end-criterium: addition-theorem of sin(Latitude(iter)-Latitude(iter-1)) */ - int iter; /* # of continuous iteration, max. 30 is always enough (s.a.) */ - - P = sqrt(X*X+Y*Y); - RR = sqrt(X*X+Y*Y+Z*Z); - -/* special cases for latitude and longitude */ - if (P/gi->Geocent_a < genau) { - -/* special case, if P=0. (X=0., Y=0.) */ - *Longitude = 0.; - -/* if (X,Y,Z)=(0.,0.,0.) then Height becomes semi-minor axis - * of ellipsoid (=center of mass), Latitude becomes PI/2 */ - if (RR/gi->Geocent_a < genau) { - *Latitude = PI_OVER_2; - *Height = -gi->Geocent_b; - return ; - - } - } - else { -/* ellipsoidal (geodetic) longitude - * interval: -PI < Longitude <= +PI */ - *Longitude=atan2(Y,X); - } - -/* -------------------------------------------------------------- - * Following iterative algorithm was developed by - * "Institut für Erdmessung", University of Hannover, July 1988. - * Internet: www.ife.uni-hannover.de - * Iterative computation of CPHI,SPHI and Height. - * Iteration of CPHI and SPHI to 10**-12 radian resp. - * 2*10**-7 arcsec. - * -------------------------------------------------------------- - */ - CT = Z/RR; - ST = P/RR; - { - const double denominator = 1.0-gi->Geocent_e2*(2.0-gi->Geocent_e2)*ST*ST; - if( denominator == 0 ) - { - *Latitude = HUGE_VAL; - *Longitude = HUGE_VAL; - *Height = HUGE_VAL; - return; - } - RX = 1.0/sqrt(denominator); - } - CPHI0 = ST*(1.0-gi->Geocent_e2)*RX; - SPHI0 = CT*RX; - iter = 0; - -/* loop to find sin(Latitude) resp. Latitude - * until |sin(Latitude(iter)-Latitude(iter-1))| < genau */ - do - { - iter++; - RN = gi->Geocent_a/sqrt(1.0-gi->Geocent_e2*SPHI0*SPHI0); - -/* ellipsoidal (geodetic) height */ - *Height = P*CPHI0+Z*SPHI0-RN*(1.0-gi->Geocent_e2*SPHI0*SPHI0); - - /* avoid zero division */ - if (RN+*Height==0.0) { - *Latitude = 0.0; - return; - } - RK = gi->Geocent_e2*RN/(RN+*Height); - { - const double denominator = 1.0-RK*(2.0-RK)*ST*ST; - if( denominator == 0 ) - { - *Latitude = HUGE_VAL; - *Longitude = HUGE_VAL; - *Height = HUGE_VAL; - return; - } - RX = 1.0/sqrt(denominator); - } - CPHI = ST*(1.0-RK)*RX; - SPHI = CT*RX; - SDPHI = SPHI*CPHI0-CPHI*SPHI0; - CPHI0 = CPHI; - SPHI0 = SPHI; - } - while (SDPHI*SDPHI > genau2 && iter < maxiter); - -/* ellipsoidal (geodetic) latitude */ - *Latitude=atan2(SPHI, fabs(CPHI)); - -#endif /* defined(USE_ITERATIVE_METHOD) */ -} /* END OF Convert_Geocentric_To_Geodetic */ - - -/////////////////////////////////////////////////////////////////////////////// -/// Main of transform.cpp -/////////////////////////////////////////////////////////////////////////////// - - -static int adjust_axis( projCtx ctx, const char *axis, int denormalize_flag, - long point_count, int point_offset, - double *x, double *y, double *z ); - -#ifndef SRS_WGS84_SEMIMAJOR -#define SRS_WGS84_SEMIMAJOR 6378137.0 -#endif - -#ifndef SRS_WGS84_ESQUARED -#define SRS_WGS84_ESQUARED 0.0066943799901413165 -#endif - -#define Dx_BF (defn->datum_params[0]) -#define Dy_BF (defn->datum_params[1]) -#define Dz_BF (defn->datum_params[2]) -#define Rx_BF (defn->datum_params[3]) -#define Ry_BF (defn->datum_params[4]) -#define Rz_BF (defn->datum_params[5]) -#define M_BF (defn->datum_params[6]) - -/* -** This table is intended to indicate for any given error code -** whether that error will occur for all locations (ie. -** it is a problem with the coordinate system as a whole) in which case the -** value would be 0, or if the problem is with the point being transformed -** in which case the value is 1. -** -** At some point we might want to move this array in with the error message -** list or something, but while experimenting with it this should be fine. -** -** -** NOTE (2017-10-01): Non-transient errors really should have resulted in a -** PJ==0 during initialization, and hence should be handled at the level -** before calling pj_transform. The only obvious example of the contrary -** appears to be the PJD_ERR_GRID_AREA case, which may also be taken to -** mean "no grids available" -** -** -*/ - -static const int transient_error[70] = { - /* 0 1 2 3 4 5 6 7 8 9 */ - /* 0 to 9 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 10 to 19 */ 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, - /* 20 to 29 */ 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, - /* 30 to 39 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 40 to 49 */ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, - /* 50 to 59 */ 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, - /* 60 to 69 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}; - - -/* -------------------------------------------------------------------- */ -/* Read transient_error[] in a safe way. */ -/* -------------------------------------------------------------------- */ -static int get_transient_error_value(int pos_index) -{ - const int array_size = - (int)(sizeof(transient_error) / sizeof(transient_error[0])); - if( pos_index < 0 || pos_index >= array_size ) { - return 0; - } - return transient_error[pos_index]; -} - - -/* -------------------------------------------------------------------- */ -/* Transform unusual input coordinate axis orientation to */ -/* standard form if needed. */ -/* -------------------------------------------------------------------- */ -static int adjust_axes (PJ *P, PJ_DIRECTION dir, long n, int dist, double *x, double *y, double *z) { - /* Nothing to do? */ - if (0==strcmp(P->axis,"enu")) - return 0; - - return adjust_axis( P->ctx, P->axis, - dir==PJ_FWD ? 1: 0, n, dist, x, y, z ); -} - - - -/* ----------------------------------------------------------------------- */ -/* Transform geographic (lat/long) source coordinates to */ -/* cartesian ("geocentric"), if needed */ -/* ----------------------------------------------------------------------- */ -static int geographic_to_cartesian (PJ *P, PJ_DIRECTION dir, long n, int dist, double *x, double *y, double *z) { - int res; - long i; - double fac = P->to_meter; - - /* Nothing to do? */ - if (!P->is_geocent) - return 0; - - if ( z == nullptr ) { - pj_ctx_set_errno( pj_get_ctx(P), PJD_ERR_GEOCENTRIC); - return PJD_ERR_GEOCENTRIC; - } - - if (PJ_FWD==dir) { - fac = P->fr_meter; - res = pj_geodetic_to_geocentric( P->a_orig, P->es_orig, n, dist, x, y, z ); - if (res) - return res; - } - - if (fac != 1.0) { - for( i = 0; i < n; i++ ) { - if( x[dist*i] != HUGE_VAL ) { - x[dist*i] *= fac; - y[dist*i] *= fac; - z[dist*i] *= fac; - } - } - } - - if (PJ_FWD==dir) - return 0; - return pj_geocentric_to_geodetic( - P->a_orig, P->es_orig, - n, dist, - x, y, z - ); -} - - - - - - - - - - -/* -------------------------------------------------------------------- */ -/* Transform destination points to projection coordinates, if */ -/* desired. */ -/* */ -/* Ought to fold this into projected_to_geographic */ -/* -------------------------------------------------------------------- */ -static int geographic_to_projected (PJ *P, long n, int dist, double *x, double *y, double *z) { - long i; - - /* Nothing to do? */ - if (P->is_latlong && !P->geoc && P->vto_meter == 1.0) - return 0; - if (P->is_geocent) - return 0; - - if(P->fwd3d != nullptr && !(z == nullptr && P->is_latlong)) - { - /* Three dimensions must be defined */ - if ( z == nullptr) - { - pj_ctx_set_errno( pj_get_ctx(P), PJD_ERR_GEOCENTRIC); - return PJD_ERR_GEOCENTRIC; - } - - for( i = 0; i < n; i++ ) - { - PJ_XYZ projected_loc; - PJ_LPZ geodetic_loc; - - geodetic_loc.lam = x[dist*i]; - geodetic_loc.phi = y[dist*i]; - geodetic_loc.z = z[dist*i]; - - if (geodetic_loc.lam == HUGE_VAL) - continue; - - proj_errno_reset( P ); - projected_loc = pj_fwd3d( geodetic_loc, P); - if( P->ctx->last_errno != 0 ) - { - if( (P->ctx->last_errno != EDOM - && P->ctx->last_errno != ERANGE) - && (P->ctx->last_errno > 0 - || P->ctx->last_errno < -44 || n == 1 - || get_transient_error_value(-P->ctx->last_errno) == 0 ) ) - { - return P->ctx->last_errno; - } - else - { - projected_loc.x = HUGE_VAL; - projected_loc.y = HUGE_VAL; - projected_loc.z = HUGE_VAL; - } - } - - x[dist*i] = projected_loc.x; - y[dist*i] = projected_loc.y; - z[dist*i] = projected_loc.z; - } - return 0; - } - - // Ugly hack. See https://github.com/OSGeo/PROJ/issues/1782 - if( P->right == PJ_IO_UNITS_WHATEVER && P->descr && - strncmp(P->descr, "General Oblique Transformation", - strlen("General Oblique Transformation")) == 0 ) - { - P->right = PJ_IO_UNITS_PROJECTED; - } - - for( i = 0; i ctx->last_errno != 0 ) - { - if( (P->ctx->last_errno != EDOM - && P->ctx->last_errno != ERANGE) - && (P->ctx->last_errno > 0 - || P->ctx->last_errno < -44 || n == 1 - || get_transient_error_value(-P->ctx->last_errno) == 0 ) ) - { - return P->ctx->last_errno; - } - else - { - projected_loc.x = HUGE_VAL; - projected_loc.y = HUGE_VAL; - } - } - - x[dist*i] = projected_loc.x; - y[dist*i] = projected_loc.y; - } - return 0; -} - - - - - -/* ----------------------------------------------------------------------- */ -/* Transform projected source coordinates to lat/long, if needed */ -/* ----------------------------------------------------------------------- */ -static int projected_to_geographic (PJ *P, long n, int dist, double *x, double *y, double *z) { - long i; - - /* Nothing to do? */ - if (P->is_latlong && !P->geoc && P->vto_meter == 1.0) - return 0; - if (P->is_geocent) - return 0; - - /* Check first if projection is invertible. */ - if( (P->inv3d == nullptr) && (P->inv == nullptr)) - { - pj_ctx_set_errno(pj_get_ctx(P), PJD_ERR_NON_CONV_INV_MERI_DIST); - pj_log( pj_get_ctx(P), PJ_LOG_ERROR, - "pj_transform(): source projection not invertable" ); - return PJD_ERR_NON_CONV_INV_MERI_DIST; - } - - /* If invertible - First try inv3d if defined */ - if (P->inv3d != nullptr && !(z == nullptr && P->is_latlong)) - { - /* Three dimensions must be defined */ - if ( z == nullptr) - { - pj_ctx_set_errno( pj_get_ctx(P), PJD_ERR_GEOCENTRIC); - return PJD_ERR_GEOCENTRIC; - } - - for (i=0; i < n; i++) - { - PJ_XYZ projected_loc; - PJ_LPZ geodetic_loc; - - projected_loc.x = x[dist*i]; - projected_loc.y = y[dist*i]; - projected_loc.z = z[dist*i]; - - if (projected_loc.x == HUGE_VAL) - continue; - - proj_errno_reset( P ); - geodetic_loc = pj_inv3d(projected_loc, P); - if( P->ctx->last_errno != 0 ) - { - if( (P->ctx->last_errno != EDOM - && P->ctx->last_errno != ERANGE) - && (P->ctx->last_errno > 0 - || P->ctx->last_errno < -44 || n == 1 - || get_transient_error_value(-P->ctx->last_errno) == 0 ) ) - { - return P->ctx->last_errno; - } - else - { - geodetic_loc.lam = HUGE_VAL; - geodetic_loc.phi = HUGE_VAL; - geodetic_loc.z = HUGE_VAL; - } - } - - x[dist*i] = geodetic_loc.lam; - y[dist*i] = geodetic_loc.phi; - z[dist*i] = geodetic_loc.z; - - } - return 0; - } - - // Ugly hack. See https://github.com/OSGeo/PROJ/issues/1782 - if( P->right == PJ_IO_UNITS_WHATEVER && P->descr && - strncmp(P->descr, "General Oblique Transformation", - strlen("General Oblique Transformation")) == 0 ) - { - P->right = PJ_IO_UNITS_PROJECTED; - } - - /* Fallback to the original PROJ.4 API 2d inversion - inv */ - for( i = 0; i < n; i++ ) { - PJ_XY projected_loc; - PJ_LP geodetic_loc; - - projected_loc.x = x[dist*i]; - projected_loc.y = y[dist*i]; - - if( projected_loc.x == HUGE_VAL ) - continue; - - proj_errno_reset( P ); - geodetic_loc = pj_inv( projected_loc, P ); - if( P->ctx->last_errno != 0 ) - { - if( (P->ctx->last_errno != EDOM - && P->ctx->last_errno != ERANGE) - && (P->ctx->last_errno > 0 - || P->ctx->last_errno < -44 || n == 1 - || get_transient_error_value(-P->ctx->last_errno) == 0 ) ) - { - return P->ctx->last_errno; - } - else - { - geodetic_loc.lam = HUGE_VAL; - geodetic_loc.phi = HUGE_VAL; - } - } - - x[dist*i] = geodetic_loc.lam; - y[dist*i] = geodetic_loc.phi; - } - return 0; -} - - - -/* -------------------------------------------------------------------- */ -/* Adjust for the prime meridian if needed. */ -/* -------------------------------------------------------------------- */ -static int prime_meridian (PJ *P, PJ_DIRECTION dir, long n, int dist, double *x) { - int i; - double pm = P->from_greenwich; - - /* Nothing to do? */ - if (pm==0.0) - return 0; - if (!(P->is_geocent || P->is_latlong)) - return 0; - - if (dir==PJ_FWD) - pm = -pm; - - for (i = 0; i < n; i++) - if (x[dist*i] != HUGE_VAL) - x[dist*i] += pm; - - return 0; -} - - - -/* -------------------------------------------------------------------- */ -/* Adjust for vertical scale factor if needed */ -/* -------------------------------------------------------------------- */ -static int height_unit (PJ *P, PJ_DIRECTION dir, long n, int dist, double *z) { - int i; - double fac = P->vto_meter; - - if (PJ_FWD==dir) - fac = P->vfr_meter; - - /* Nothing to do? */ - if (fac==1.0) - return 0; - if (nullptr==z) - return 0; - if (P->is_latlong) - return 0; /* done in pj_inv3d() / pj_fwd3d() */ - - for (i = 0; i < n; i++) - if (z[dist*i] != HUGE_VAL ) - z[dist*i] *= fac; - - return 0; -} - - -/************************************************************************/ -/* pj_apply_vgridshift() */ -/* */ -/* This implementation takes uses the gridlist from a coordinate */ -/* system definition. If the gridlist has not yet been */ -/* populated in the coordinate system definition we set it up */ -/* now. */ -/************************************************************************/ -static int pj_apply_vgridshift( PJ *defn, - int inverse, - long point_count, int point_offset, - double *x, double *y, double *z ) - -{ - if( defn->vgrids_legacy == nullptr ) - { - defn->vgrids_legacy = new ListOfVGrids; - auto vgrids = pj_vgrid_init(defn, "geoidgrids"); - if( vgrids.empty() ) - return 0; - *static_cast(defn->vgrids_legacy) = std::move(vgrids); - } - if( static_cast(defn->vgrids_legacy)->empty() ) - { - return 0; - } - - for( int i = 0; i < point_count; i++ ) - { - double value; - long io = i * point_offset; - PJ_LP input; - - input.phi = y[io]; - input.lam = x[io]; - - value = pj_vgrid_value(defn, *static_cast(defn->vgrids_legacy), input, 1.0); - - if( inverse ) - z[io] -= value; - else - z[io] += value; - - if( value == HUGE_VAL ) - { - std::string gridlist; - - proj_log_debug(defn, - "pj_apply_vgridshift(): failed to find a grid shift table for\n" - " location (%.7fdW,%.7fdN)", - x[io] * RAD_TO_DEG, - y[io] * RAD_TO_DEG ); - - for( const auto& gridset: *static_cast(defn->vgrids_legacy) ) - { - if( gridlist.empty() ) - gridlist += " tried: "; - else - gridlist += ','; - gridlist += gridset->name(); - } - - proj_log_debug(defn, "%s", gridlist.c_str()); - pj_ctx_set_errno( defn->ctx, PJD_ERR_GRID_AREA ); - - return PJD_ERR_GRID_AREA; - } - } - - return 0; -} - - -/* -------------------------------------------------------------------- */ -/* Transform to ellipsoidal heights if needed */ -/* -------------------------------------------------------------------- */ -static int geometric_to_orthometric (PJ *P, PJ_DIRECTION dir, long n, int dist, double *x, double *y, double *z) { - int err; - if (0==P->has_geoid_vgrids) - return 0; - if (z==nullptr) - return PJD_ERR_GEOCENTRIC; - err = pj_apply_vgridshift (P, dir==PJ_FWD ? 1 : 0, n, dist, x, y, z ); - if (err) - return pj_ctx_get_errno(P->ctx); - return 0; -} - - - -/* -------------------------------------------------------------------- */ -/* Convert datums if needed, and possible. */ -/* -------------------------------------------------------------------- */ -static int datum_transform (PJ *P, PJ *Q, long n, int dist, double *x, double *y, double *z) { - if (0==pj_datum_transform (P, Q, n, dist, x, y, z)) - return 0; - if (P->ctx->last_errno) - return P->ctx->last_errno; - return Q->ctx->last_errno; -} - - - - - -/* -------------------------------------------------------------------- */ -/* If a wrapping center other than 0 is provided, rewrap around */ -/* the suggested center (for latlong coordinate systems only). */ -/* -------------------------------------------------------------------- */ -static int long_wrap (PJ *P, long n, int dist, double *x) { - long i; - - /* Nothing to do? */ - if (P->is_geocent) - return 0; - if (!P->is_long_wrap_set) - return 0; - if (!P->is_latlong) - return 0; - - for (i = 0; i < n; i++ ) { - double val = x[dist*i]; - if (val == HUGE_VAL) - continue; - - /* Get fast in ] -2 PI, 2 PI [ range */ - val = fmod(val, M_TWOPI); - while( val < P->long_wrap_center - M_PI ) - val += M_TWOPI; - while( val > P->long_wrap_center + M_PI ) - val -= M_TWOPI; - x[dist*i] = val; - } - return 0; -} - - - -/************************************************************************/ -/* pj_transform() */ -/* */ -/* Currently this function doesn't recognise if two projections */ -/* are identical (to short circuit reprojection) because it is */ -/* difficult to compare PJ structures (since there are some */ -/* projection specific components). */ -/************************************************************************/ - -int pj_transform( - PJ *src, PJ *dst, - long point_count, int point_offset, - double *x, double *y, double *z -){ - int err; - - src->ctx->last_errno = 0; - dst->ctx->last_errno = 0; - - if( point_offset == 0 ) - point_offset = 1; - - /* Bring input to "normal form": longitude, latitude, ellipsoidal height */ - - err = adjust_axes (src, PJ_INV, point_count, point_offset, x, y, z); - if (err) - return err; - err = geographic_to_cartesian (src, PJ_INV, point_count, point_offset, x, y, z); - if (err) - return err; - err = projected_to_geographic (src, point_count, point_offset, x, y, z); - if (err) - return err; - err = prime_meridian (src, PJ_INV, point_count, point_offset, x); - if (err) - return err; - err = height_unit (src, PJ_INV, point_count, point_offset, z); - if (err) - return err; - err = geometric_to_orthometric (src, PJ_INV, point_count, point_offset, x, y, z); - if (err) - return err; - - /* At the center of the process we do the datum shift (if needed) */ - - err = datum_transform(src, dst, point_count, point_offset, x, y, z ); - if (err) - return err; - - /* Now get out on the other side: Bring "normal form" to output form */ - - err = geometric_to_orthometric (dst, PJ_FWD, point_count, point_offset, x, y, z); - if (err) - return err; - err = height_unit (dst, PJ_FWD, point_count, point_offset, z); - if (err) - return err; - err = prime_meridian (dst, PJ_FWD, point_count, point_offset, x); - if (err) - return err; - err = geographic_to_cartesian (dst, PJ_FWD, point_count, point_offset, x, y, z); - if (err) - return err; - err = geographic_to_projected (dst, point_count, point_offset, x, y, z); - if (err) - return err; - err = long_wrap (dst, point_count, point_offset, x); - if (err) - return err; - err = adjust_axes (dst, PJ_FWD, point_count, point_offset, x, y, z); - if (err) - return err; - - return 0; -} - - - -/************************************************************************/ -/* pj_geodetic_to_geocentric() */ -/************************************************************************/ - -int pj_geodetic_to_geocentric( double a, double es, - long point_count, int point_offset, - double *x, double *y, double *z ) - -{ - double b; - int i; - GeocentricInfo gi; - int ret_errno = 0; - - if( es == 0.0 ) - b = a; - else - b = a * sqrt(1-es); - - if( pj_Set_Geocentric_Parameters( &gi, a, b ) != 0 ) - { - return PJD_ERR_GEOCENTRIC; - } - - for( i = 0; i < point_count; i++ ) - { - long io = i * point_offset; - - if( x[io] == HUGE_VAL ) - continue; - - if( pj_Convert_Geodetic_To_Geocentric( &gi, y[io], x[io], z[io], - x+io, y+io, z+io ) != 0 ) - { - ret_errno = PJD_ERR_LAT_OR_LON_EXCEED_LIMIT; - x[io] = y[io] = HUGE_VAL; - /* but keep processing points! */ - } - } - - return ret_errno; -} - -/************************************************************************/ -/* pj_geocentric_to_geodetic() */ -/************************************************************************/ - -int pj_geocentric_to_geodetic( double a, double es, - long point_count, int point_offset, - double *x, double *y, double *z ) - -{ - double b; - int i; - GeocentricInfo gi; - - if( es == 0.0 ) - b = a; - else - b = a * sqrt(1-es); - - if( pj_Set_Geocentric_Parameters( &gi, a, b ) != 0 ) - { - return PJD_ERR_GEOCENTRIC; - } - - for( i = 0; i < point_count; i++ ) - { - long io = i * point_offset; - - if( x[io] == HUGE_VAL ) - continue; - - pj_Convert_Geocentric_To_Geodetic( &gi, x[io], y[io], z[io], - y+io, x+io, z+io ); - } - - return 0; -} - -/************************************************************************/ -/* pj_compare_datums() */ -/* */ -/* Returns TRUE if the two datums are identical, otherwise */ -/* FALSE. */ -/************************************************************************/ - -int pj_compare_datums( PJ *srcdefn, PJ *dstdefn ) - -{ - if( srcdefn->datum_type != dstdefn->datum_type ) - { - return 0; - } - else if( srcdefn->a_orig != dstdefn->a_orig - || ABS(srcdefn->es_orig - dstdefn->es_orig) > 0.000000000050 ) - { - /* the tolerance for es is to ensure that GRS80 and WGS84 are - considered identical */ - return 0; - } - else if( srcdefn->datum_type == PJD_3PARAM ) - { - return (srcdefn->datum_params[0] == dstdefn->datum_params[0] - && srcdefn->datum_params[1] == dstdefn->datum_params[1] - && srcdefn->datum_params[2] == dstdefn->datum_params[2]); - } - else if( srcdefn->datum_type == PJD_7PARAM ) - { - return (srcdefn->datum_params[0] == dstdefn->datum_params[0] - && srcdefn->datum_params[1] == dstdefn->datum_params[1] - && srcdefn->datum_params[2] == dstdefn->datum_params[2] - && srcdefn->datum_params[3] == dstdefn->datum_params[3] - && srcdefn->datum_params[4] == dstdefn->datum_params[4] - && srcdefn->datum_params[5] == dstdefn->datum_params[5] - && srcdefn->datum_params[6] == dstdefn->datum_params[6]); - } - else if( srcdefn->datum_type == PJD_GRIDSHIFT ) - { - const char* srcnadgrids = - pj_param(srcdefn->ctx, srcdefn->params,"snadgrids").s; - const char* dstnadgrids = - pj_param(dstdefn->ctx, dstdefn->params,"snadgrids").s; - return srcnadgrids != nullptr && dstnadgrids != nullptr && - strcmp( srcnadgrids, dstnadgrids ) == 0; - } - else - return 1; -} - -/************************************************************************/ -/* pj_geocentic_to_wgs84() */ -/************************************************************************/ - -static -int pj_geocentric_to_wgs84( PJ *defn, - long point_count, int point_offset, - double *x, double *y, double *z ) - -{ - int i; - - if( defn->datum_type == PJD_3PARAM ) - { - for( i = 0; i < point_count; i++ ) - { - long io = i * point_offset; - - if( x[io] == HUGE_VAL ) - continue; - - x[io] = x[io] + Dx_BF; - y[io] = y[io] + Dy_BF; - z[io] = z[io] + Dz_BF; - } - } - else if( defn->datum_type == PJD_7PARAM ) - { - for( i = 0; i < point_count; i++ ) - { - long io = i * point_offset; - double x_out, y_out, z_out; - - if( x[io] == HUGE_VAL ) - continue; - - x_out = M_BF*( x[io] - Rz_BF*y[io] + Ry_BF*z[io]) + Dx_BF; - y_out = M_BF*( Rz_BF*x[io] + y[io] - Rx_BF*z[io]) + Dy_BF; - z_out = M_BF*(-Ry_BF*x[io] + Rx_BF*y[io] + z[io]) + Dz_BF; - - x[io] = x_out; - y[io] = y_out; - z[io] = z_out; - } - } - - return 0; -} - -/************************************************************************/ -/* pj_geocentic_from_wgs84() */ -/************************************************************************/ - -static -int pj_geocentric_from_wgs84( PJ *defn, - long point_count, int point_offset, - double *x, double *y, double *z ) - -{ - int i; - - if( defn->datum_type == PJD_3PARAM ) - { - for( i = 0; i < point_count; i++ ) - { - long io = i * point_offset; - - if( x[io] == HUGE_VAL ) - continue; - - x[io] = x[io] - Dx_BF; - y[io] = y[io] - Dy_BF; - z[io] = z[io] - Dz_BF; - } - } - else if( defn->datum_type == PJD_7PARAM ) - { - for( i = 0; i < point_count; i++ ) - { - long io = i * point_offset; - double x_tmp, y_tmp, z_tmp; - - if( x[io] == HUGE_VAL ) - continue; - - x_tmp = (x[io] - Dx_BF) / M_BF; - y_tmp = (y[io] - Dy_BF) / M_BF; - z_tmp = (z[io] - Dz_BF) / M_BF; - - x[io] = x_tmp + Rz_BF*y_tmp - Ry_BF*z_tmp; - y[io] = -Rz_BF*x_tmp + y_tmp + Rx_BF*z_tmp; - z[io] = Ry_BF*x_tmp - Rx_BF*y_tmp + z_tmp; - } - } - - return 0; -} - - -/************************************************************************/ -/* pj_apply_gridshift_2() */ -/* */ -/* This implementation uses the gridlist from a coordinate */ -/* system definition. If the gridlist has not yet been */ -/* populated in the coordinate system definition we set it up */ -/* now. */ -/************************************************************************/ -static -int pj_apply_gridshift_2( PJ *defn, int inverse, - long point_count, int point_offset, - double *x, double *y, double * /*z*/ ) - -{ - if( defn->hgrids_legacy == nullptr ) - { - defn->hgrids_legacy = new ListOfHGrids; - auto hgrids = pj_hgrid_init(defn, "nadgrids"); - if( hgrids.empty() ) - return 0; - *static_cast(defn->hgrids_legacy) = std::move(hgrids); - } - if( static_cast(defn->hgrids_legacy)->empty() ) - { - return 0; - } - - for( long i = 0; i < point_count; i++ ) - { - PJ_LP input; - - long io = i * point_offset; - input.phi = y[io]; - input.lam = x[io]; - - auto output = pj_hgrid_apply(defn->ctx, *static_cast(defn->hgrids_legacy), input, inverse ? PJ_INV : PJ_FWD); - - if ( output.lam != HUGE_VAL ) - { - y[io] = output.phi; - x[io] = output.lam; - } - else - { - if( defn->ctx->debug_level >= PJ_LOG_DEBUG_MAJOR ) - { - pj_log( defn->ctx, PJ_LOG_DEBUG_MAJOR, - "pj_apply_gridshift(): failed to find a grid shift table for\n" - " location (%.7fdW,%.7fdN)", - x[io] * RAD_TO_DEG, - y[io] * RAD_TO_DEG ); - } - } - } - - return 0; -} - - -/************************************************************************/ -/* pj_datum_transform() */ -/* */ -/* The input should be long/lat/z coordinates in radians in the */ -/* source datum, and the output should be long/lat/z */ -/* coordinates in radians in the destination datum. */ -/************************************************************************/ - -int pj_datum_transform( PJ *src, PJ *dst, - long point_count, int point_offset, - double *x, double *y, double *z ) - -{ - double src_a, src_es, dst_a, dst_es; - int z_is_temp = FALSE; - -/* -------------------------------------------------------------------- */ -/* We cannot do any meaningful datum transformation if either */ -/* the source or destination are of an unknown datum type */ -/* (ie. only a +ellps declaration, no +datum). This is new */ -/* behavior for PROJ 4.6.0. */ -/* -------------------------------------------------------------------- */ - if( src->datum_type == PJD_UNKNOWN - || dst->datum_type == PJD_UNKNOWN ) - return 0; - -/* -------------------------------------------------------------------- */ -/* Short cut if the datums are identical. */ -/* -------------------------------------------------------------------- */ - if( pj_compare_datums( src, dst ) ) - return 0; - - src_a = src->a_orig; - src_es = src->es_orig; - - dst_a = dst->a_orig; - dst_es = dst->es_orig; - -/* -------------------------------------------------------------------- */ -/* Create a temporary Z array if one is not provided. */ -/* -------------------------------------------------------------------- */ - if( z == nullptr ) - { - size_t bytes = sizeof(double) * point_count * point_offset; - z = (double *) pj_malloc(bytes); - memset( z, 0, bytes ); - z_is_temp = TRUE; - } - -#define CHECK_RETURN(defn) {if( defn->ctx->last_errno != 0 && (defn->ctx->last_errno > 0 || get_transient_error_value(-defn->ctx->last_errno) == 0) ) { if( z_is_temp ) pj_dalloc(z); return defn->ctx->last_errno; }} - -/* -------------------------------------------------------------------- */ -/* If this datum requires grid shifts, then apply it to geodetic */ -/* coordinates. */ -/* -------------------------------------------------------------------- */ - if( src->datum_type == PJD_GRIDSHIFT ) - { - pj_apply_gridshift_2( src, 0, point_count, point_offset, x, y, z ); - CHECK_RETURN(src); - - src_a = SRS_WGS84_SEMIMAJOR; - src_es = SRS_WGS84_ESQUARED; - } - - if( dst->datum_type == PJD_GRIDSHIFT ) - { - dst_a = SRS_WGS84_SEMIMAJOR; - dst_es = SRS_WGS84_ESQUARED; - } - -/* ==================================================================== */ -/* Do we need to go through geocentric coordinates? */ -/* ==================================================================== */ - if( src_es != dst_es || src_a != dst_a - || src->datum_type == PJD_3PARAM - || src->datum_type == PJD_7PARAM - || dst->datum_type == PJD_3PARAM - || dst->datum_type == PJD_7PARAM) - { -/* -------------------------------------------------------------------- */ -/* Convert to geocentric coordinates. */ -/* -------------------------------------------------------------------- */ - src->ctx->last_errno = - pj_geodetic_to_geocentric( src_a, src_es, - point_count, point_offset, x, y, z ); - CHECK_RETURN(src); - -/* -------------------------------------------------------------------- */ -/* Convert between datums. */ -/* -------------------------------------------------------------------- */ - if( src->datum_type == PJD_3PARAM - || src->datum_type == PJD_7PARAM ) - { - pj_geocentric_to_wgs84( src, point_count, point_offset,x,y,z); - CHECK_RETURN(src); - } - - if( dst->datum_type == PJD_3PARAM - || dst->datum_type == PJD_7PARAM ) - { - pj_geocentric_from_wgs84( dst, point_count,point_offset,x,y,z); - CHECK_RETURN(dst); - } - -/* -------------------------------------------------------------------- */ -/* Convert back to geodetic coordinates. */ -/* -------------------------------------------------------------------- */ - dst->ctx->last_errno = - pj_geocentric_to_geodetic( dst_a, dst_es, - point_count, point_offset, x, y, z ); - CHECK_RETURN(dst); - } - -/* -------------------------------------------------------------------- */ -/* Apply grid shift to destination if required. */ -/* -------------------------------------------------------------------- */ - if( dst->datum_type == PJD_GRIDSHIFT ) - { - pj_apply_gridshift_2( dst, 1, point_count, point_offset, x, y, z ); - CHECK_RETURN(dst); - } - - if( z_is_temp ) - pj_dalloc( z ); - - return 0; -} - -/************************************************************************/ -/* adjust_axis() */ -/* */ -/* Normalize or de-normalized the x/y/z axes. The normal form */ -/* is "enu" (easting, northing, up). */ -/************************************************************************/ -static int adjust_axis( projCtx ctx, - const char *axis, int denormalize_flag, - long point_count, int point_offset, - double *x, double *y, double *z ) - -{ - double x_in, y_in, z_in = 0.0; - int i, i_axis; - - if( !denormalize_flag ) - { - for( i = 0; i < point_count; i++ ) - { - x_in = x[point_offset*i]; - y_in = y[point_offset*i]; - if( z ) - z_in = z[point_offset*i]; - - for( i_axis = 0; i_axis < 3; i_axis++ ) - { - double value; - - if( i_axis == 0 ) - value = x_in; - else if( i_axis == 1 ) - value = y_in; - else - value = z_in; - - switch( axis[i_axis] ) - { - case 'e': - x[point_offset*i] = value; - break; - case 'w': - x[point_offset*i] = -value; - break; - case 'n': - y[point_offset*i] = value; - break; - case 's': - y[point_offset*i] = -value; - break; - case 'u': - if( z ) - z[point_offset*i] = value; - break; - case 'd': - if( z ) - z[point_offset*i] = -value; - break; - default: - pj_ctx_set_errno( ctx, PJD_ERR_AXIS ); - return PJD_ERR_AXIS; - } - } /* i_axis */ - } /* i (point) */ - } - - else /* denormalize */ - { - for( i = 0; i < point_count; i++ ) - { - x_in = x[point_offset*i]; - y_in = y[point_offset*i]; - if( z ) - z_in = z[point_offset*i]; - - for( i_axis = 0; i_axis < 3; i_axis++ ) - { - double *target; - - if( i_axis == 2 && z == nullptr ) - continue; - - if( i_axis == 0 ) - target = x; - else if( i_axis == 1 ) - target = y; - else - target = z; - - switch( axis[i_axis] ) - { - case 'e': - target[point_offset*i] = x_in; break; - case 'w': - target[point_offset*i] = -x_in; break; - case 'n': - target[point_offset*i] = y_in; break; - case 's': - target[point_offset*i] = -y_in; break; - case 'u': - target[point_offset*i] = z_in; break; - case 'd': - target[point_offset*i] = -z_in; break; - default: - pj_ctx_set_errno( ctx, PJD_ERR_AXIS ); - return PJD_ERR_AXIS; - } - } /* i_axis */ - } /* i (point) */ - } - - return 0; -} -// --------------------------------------------------------------------------- - -void pj_deallocate_grids() -{ -} diff --git a/test/unit/CMakeLists.txt b/test/unit/CMakeLists.txt index 2c0c19a9..3924f47d 100644 --- a/test/unit/CMakeLists.txt +++ b/test/unit/CMakeLists.txt @@ -69,17 +69,6 @@ set(PROJ_TEST_ENVIRONMENT "PROJ_SOURCE_DATA=${PROJ_SOURCE_DIR}/data" ) -add_executable(proj_pj_transform_test - main.cpp - pj_transform_test.cpp) -target_link_libraries(proj_pj_transform_test - GTest::gtest - ${PROJ_LIBRARIES}) -add_test(NAME proj_pj_transform_test COMMAND proj_pj_transform_test) -set_property(TEST proj_pj_transform_test - PROPERTY ENVIRONMENT ${PROJ_TEST_ENVIRONMENT}) - - add_executable(proj_errno_string_test main.cpp proj_errno_string_test.cpp) diff --git a/test/unit/Makefile.am b/test/unit/Makefile.am index 483cb0bd..4e931c2b 100644 --- a/test/unit/Makefile.am +++ b/test/unit/Makefile.am @@ -9,8 +9,7 @@ AM_CXXFLAGS = @CXX_WFLAGS@ @NO_ZERO_AS_NULL_POINTER_CONSTANT_FLAG@ PROJ_LIB ?= ../../data/for_tests -noinst_PROGRAMS = pj_transform_test -noinst_PROGRAMS += pj_phi2_test +noinst_PROGRAMS = pj_phi2_test noinst_PROGRAMS += proj_errno_string_test noinst_PROGRAMS += proj_angular_io_test noinst_PROGRAMS += proj_context_test @@ -21,11 +20,6 @@ noinst_PROGRAMS += test_network noinst_PROGRAMS += test_defmodel noinst_PROGRAMS += test_tinshift -pj_transform_test_SOURCES = pj_transform_test.cpp main.cpp -pj_transform_test_LDADD = ../../src/libproj.la @GTEST_LIBS@ - -pj_transform_test-check: pj_transform_test - PROJ_SKIP_READ_USER_WRITABLE_DIRECTORY=YES PROJ_LIB=$(PROJ_LIB) ./pj_transform_test pj_phi2_test_SOURCES = pj_phi2_test.cpp main.cpp pj_phi2_test_LDADD = ../../src/libproj.la @GTEST_LIBS@ @@ -84,6 +78,6 @@ test_tinshift_LDADD = ../../src/libproj.la @GTEST_LIBS@ test_tinshift-check: test_tinshift PROJ_LIB=$(PROJ_LIB) ./test_tinshift -check-local: pj_transform_test-check pj_phi2_test-check proj_errno_string_test-check \ +check-local: pj_phi2_test-check proj_errno_string_test-check \ proj_angular_io_test-check proj_context_test-check test_cpp_api-check \ gie_self_tests-check test_network-check test_defmodel-check test_tinshift-check diff --git a/test/unit/pj_transform_test.cpp b/test/unit/pj_transform_test.cpp deleted file mode 100644 index 6f02ec5a..00000000 --- a/test/unit/pj_transform_test.cpp +++ /dev/null @@ -1,737 +0,0 @@ -/****************************************************************************** - * - * Project: PROJ - * Purpose: Test pj_transform() legacy interface - * Author: Even Rouault - * - ****************************************************************************** - * Copyright (c) 2018, Even Rouault - * - * 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 "gtest_include.h" -#include - -// PROJ include order is sensitive -// clang-format off -#include -#include "proj_internal.h" -// clang-format on - -namespace { - -// --------------------------------------------------------------------------- - -TEST(pj_transform_test, longlat_to_longlat) { - auto src = pj_init_plus("+proj=longlat +datum=WGS84"); - auto dst = pj_init_plus("+proj=longlat +datum=WGS84"); - double x = 2 * DEG_TO_RAD; - double y = 49 * DEG_TO_RAD; - EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, nullptr), 0); - EXPECT_EQ(x, 2 * DEG_TO_RAD); - EXPECT_EQ(y, 49 * DEG_TO_RAD); - - x = 182 * DEG_TO_RAD; - EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, nullptr), 0); - EXPECT_EQ(x, 182 * DEG_TO_RAD); - EXPECT_EQ(y, 49 * DEG_TO_RAD); - - pj_free(src); - pj_free(dst); -} - -// --------------------------------------------------------------------------- - -TEST(pj_transform_test, longlat_to_proj) { - auto src = pj_init_plus("+proj=longlat +datum=WGS84"); - auto dst = pj_init_plus("+proj=utm +zone=31 +datum=WGS84"); - double x = 3 * DEG_TO_RAD; - double y = 0 * DEG_TO_RAD; - EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, nullptr), 0); - EXPECT_NEAR(x, 500000, 1e-8); - EXPECT_NEAR(y, 0, 1e-8); - pj_free(src); - pj_free(dst); -} - -// --------------------------------------------------------------------------- - -TEST(pj_transform_test, longlat_to_proj_tometer) { - auto src = pj_init_plus("+proj=longlat +datum=WGS84"); - auto dst = pj_init_plus("+proj=utm +zone=31 +datum=WGS84 +to_meter=1000"); - double x = 3 * DEG_TO_RAD; - double y = 0 * DEG_TO_RAD; - EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, nullptr), 0); - EXPECT_NEAR(x, 500, 1e-8); - EXPECT_NEAR(y, 0, 1e-8); - pj_free(src); - pj_free(dst); -} - -// --------------------------------------------------------------------------- - -TEST(pj_transform_test, proj_to_longlat) { - auto src = pj_init_plus("+proj=utm +zone=31 +datum=WGS84"); - auto dst = pj_init_plus("+proj=longlat +datum=WGS84"); - double x = 500000; - double y = 0; - EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, nullptr), 0); - EXPECT_NEAR(x, 3 * DEG_TO_RAD, 1e-12); - EXPECT_NEAR(y, 0 * DEG_TO_RAD, 1e-12); - pj_free(src); - pj_free(dst); -} - -// --------------------------------------------------------------------------- - -TEST(pj_transform_test, proj_to_proj) { - auto src = pj_init_plus("+proj=utm +zone=31 +datum=WGS84"); - auto dst = pj_init_plus("+proj=utm +zone=31 +datum=WGS84"); - double x = 500000; - double y = 0; - EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, nullptr), 0); - EXPECT_NEAR(x, 500000, 1e-8); - EXPECT_NEAR(y, 0, 1e-8); - pj_free(src); - pj_free(dst); -} - -// --------------------------------------------------------------------------- - -TEST(pj_transform_test, longlat_to_geocent) { - auto src = pj_init_plus("+proj=longlat +R=2"); - auto dst = pj_init_plus("+proj=geocent +R=2"); - double x = 0; - double y = 0; - double z = 0; - EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, &z), 0); - EXPECT_NEAR(x, 2, 1e-8); - EXPECT_NEAR(y, 0, 1e-8); - EXPECT_NEAR(z, 0, 1e-8); - - x = 90 * DEG_TO_RAD; - y = 0; - z = 0; - EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, &z), 0); - EXPECT_NEAR(x, 0, 1e-8); - EXPECT_NEAR(y, 2, 1e-8); - EXPECT_NEAR(z, 0, 1e-8); - - x = 0; - y = 90 * DEG_TO_RAD; - z = 0.1; - EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, &z), 0); - EXPECT_NEAR(x, 0, 1e-8); - EXPECT_NEAR(y, 0, 1e-8); - EXPECT_NEAR(z, 2 + 0.1, 1e-8); - - pj_free(src); - pj_free(dst); -} - -// --------------------------------------------------------------------------- - -TEST(pj_transform_test, longlat_to_geocent_to_meter) { - auto src = pj_init_plus("+proj=longlat +R=2"); - auto dst = pj_init_plus("+proj=geocent +R=2 +to_meter=1000"); - double x = 0; - double y = 0; - double z = 0; - EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, &z), 0); - EXPECT_NEAR(x, 2e-3, 1e-8); - EXPECT_NEAR(y, 0, 1e-8); - EXPECT_NEAR(z, 0, 1e-8); - pj_free(src); - pj_free(dst); -} - -// --------------------------------------------------------------------------- - -TEST(pj_transform_test, geocent_to_longlat) { - auto src = pj_init_plus("+proj=geocent +R=2"); - auto dst = pj_init_plus("+proj=longlat +R=2"); - double x = 0; - double y = 2; - double z = 0; - EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, &z), 0); - EXPECT_NEAR(x, 90 * DEG_TO_RAD, 1e-12) << x / DEG_TO_RAD; - EXPECT_NEAR(y, 0, 1e-12) << y / DEG_TO_RAD; - EXPECT_NEAR(z, 0, 1e-12); - - pj_free(src); - pj_free(dst); -} - -// --------------------------------------------------------------------------- - -TEST(pj_transform_test, geocent_to_meter_to_longlat) { - auto src = pj_init_plus("+proj=geocent +to_meter=1000 +R=2"); - auto dst = pj_init_plus("+proj=longlat +R=2"); - double x = 0; - double y = 2e-3; - double z = 0; - EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, &z), 0); - EXPECT_NEAR(x, 90 * DEG_TO_RAD, 1e-12) << x / DEG_TO_RAD; - EXPECT_NEAR(y, 0, 1e-12) << y / DEG_TO_RAD; - EXPECT_NEAR(z, 0, 1e-12); - pj_free(src); - pj_free(dst); -} - -// --------------------------------------------------------------------------- - -TEST(pj_transform_test, pm) { - auto src = pj_init_plus("+proj=longlat +pm=3 +datum=WGS84"); - auto dst = pj_init_plus("+proj=longlat +pm=1 +datum=WGS84"); - double x = 2 * DEG_TO_RAD; - double y = 49 * DEG_TO_RAD; - EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, nullptr), 0); - EXPECT_NEAR(x, (2 + 3 - 1) * DEG_TO_RAD, 1e-12) << x / DEG_TO_RAD; - EXPECT_EQ(y, 49 * DEG_TO_RAD) << y / DEG_TO_RAD; - pj_free(src); - pj_free(dst); -} - -// --------------------------------------------------------------------------- - -TEST(pj_transform_test, longlat_geoc_to_longlat) { - auto src = pj_init_plus("+proj=longlat +geoc +datum=WGS84"); - auto dst = pj_init_plus("+proj=longlat +datum=WGS84"); - double x = 2 * DEG_TO_RAD; - double y = 49 * DEG_TO_RAD; - EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, nullptr), 0); - EXPECT_NEAR(x, 2 * DEG_TO_RAD, 1e-12) << x / DEG_TO_RAD; - EXPECT_NEAR(y, 48.809360314691766 * DEG_TO_RAD, 1e-12) << y / DEG_TO_RAD; - pj_free(src); - pj_free(dst); -} - -// --------------------------------------------------------------------------- - -TEST(pj_transform_test, longlat_to_longlat_geoc) { - auto src = pj_init_plus("+proj=longlat +datum=WGS84"); - auto dst = pj_init_plus("+proj=longlat +geoc +datum=WGS84"); - double x = 2 * DEG_TO_RAD; - double y = 48.809360314691766 * DEG_TO_RAD; - EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, nullptr), 0); - EXPECT_NEAR(x, 2 * DEG_TO_RAD, 1e-12) << x / DEG_TO_RAD; - EXPECT_NEAR(y, 49 * DEG_TO_RAD, 1e-12) << y / DEG_TO_RAD; - pj_free(src); - pj_free(dst); -} - -// --------------------------------------------------------------------------- - -TEST(pj_transform_test, ellps_to_ellps_noop) { - auto src = pj_init_plus("+proj=longlat +ellps=clrk66"); - auto dst = pj_init_plus("+proj=longlat +ellps=WGS84"); - double x = 2 * DEG_TO_RAD; - double y = 49 * DEG_TO_RAD; - EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, nullptr), 0); - EXPECT_NEAR(x, 2 * DEG_TO_RAD, 1e-12) << x / DEG_TO_RAD; - EXPECT_NEAR(y, 49 * DEG_TO_RAD, 1e-12) << y / DEG_TO_RAD; - pj_free(src); - pj_free(dst); -} - -// --------------------------------------------------------------------------- - -TEST(pj_transform_test, towgs84_3param_noop) { - auto src = pj_init_plus("+proj=longlat +ellps=WGS84 +towgs84=1,2,3"); - auto dst = pj_init_plus("+proj=longlat +ellps=WGS84 +towgs84=1,2,3"); - double x = 2 * DEG_TO_RAD; - double y = 49 * DEG_TO_RAD; - double z = 10; - EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, &z), 0); - EXPECT_NEAR(x, 2 * DEG_TO_RAD, 1e-12) << x / DEG_TO_RAD; - EXPECT_NEAR(y, 49 * DEG_TO_RAD, 1e-12) << y / DEG_TO_RAD; - EXPECT_NEAR(z, 10, 1e-8); - pj_free(src); - pj_free(dst); -} - -// --------------------------------------------------------------------------- - -TEST(pj_transform_test, towgs84_7param_noop) { - auto src = - pj_init_plus("+proj=longlat +ellps=WGS84 +towgs84=1,2,3,4,5,6,7"); - auto dst = - pj_init_plus("+proj=longlat +ellps=WGS84 +towgs84=1,2,3,4,5,6,7"); - double x = 2 * DEG_TO_RAD; - double y = 49 * DEG_TO_RAD; - double z = 10; - EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, &z), 0); - EXPECT_NEAR(x, 2 * DEG_TO_RAD, 1e-12) << x / DEG_TO_RAD; - EXPECT_NEAR(y, 49 * DEG_TO_RAD, 1e-12) << y / DEG_TO_RAD; - EXPECT_NEAR(z, 10, 1e-8); - pj_free(src); - pj_free(dst); -} - -// --------------------------------------------------------------------------- - -TEST(pj_transform_test, longlat_towgs84_3param_to_datum) { - auto src = pj_init_plus("+proj=longlat +ellps=WGS84 +towgs84=0,1,0"); - auto dst = pj_init_plus("+proj=longlat +datum=WGS84"); - double x = 90 * DEG_TO_RAD; - double y = 0 * DEG_TO_RAD; - double z = 10; - EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, &z), 0); - EXPECT_NEAR(x, 90 * DEG_TO_RAD, 1e-12) << x / DEG_TO_RAD; - EXPECT_NEAR(y, 0 * DEG_TO_RAD, 1e-12) << y / DEG_TO_RAD; - EXPECT_NEAR(z, 10 + 1, 1e-8); - pj_free(src); - pj_free(dst); -} - -// --------------------------------------------------------------------------- - -TEST(pj_transform_test, longlat_towgs84_3param_to_datum_no_z) { - auto src = pj_init_plus("+proj=longlat +ellps=WGS84 +towgs84=0,1,0"); - auto dst = pj_init_plus("+proj=longlat +datum=WGS84"); - double x = 90 * DEG_TO_RAD; - double y = 0 * DEG_TO_RAD; - EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, nullptr), 0); - EXPECT_NEAR(x, 90 * DEG_TO_RAD, 1e-12) << x / DEG_TO_RAD; - EXPECT_NEAR(y, 0 * DEG_TO_RAD, 1e-12) << y / DEG_TO_RAD; - pj_free(src); - pj_free(dst); -} - -// --------------------------------------------------------------------------- - -TEST(pj_transform_test, longlat_towgs84_7param_to_datum) { - auto src = - pj_init_plus("+proj=longlat +ellps=WGS84 +towgs84=0,1,0,0,0,0,0.5"); - auto dst = pj_init_plus("+proj=longlat +datum=WGS84"); - double x = 90 * DEG_TO_RAD; - double y = 0 * DEG_TO_RAD; - double z = 10; - EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, &z), 0); - EXPECT_NEAR(x, 90 * DEG_TO_RAD, 1e-12) << x / DEG_TO_RAD; - EXPECT_NEAR(y, 0 * DEG_TO_RAD, 1e-12) << y / DEG_TO_RAD; - EXPECT_NEAR(z, 14.189073500223458, 1e-8); - pj_free(src); - pj_free(dst); -} - -// --------------------------------------------------------------------------- - -TEST(pj_transform_test, datum_to_longlat_towgs84_3param) { - auto src = pj_init_plus("+proj=longlat +datum=WGS84"); - auto dst = pj_init_plus("+proj=longlat +ellps=WGS84 +towgs84=0,1,0"); - double x = 90 * DEG_TO_RAD; - double y = 0 * DEG_TO_RAD; - double z = 10 + 1; - EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, &z), 0); - EXPECT_NEAR(x, 90 * DEG_TO_RAD, 1e-12) << x / DEG_TO_RAD; - EXPECT_NEAR(y, 0 * DEG_TO_RAD, 1e-12) << y / DEG_TO_RAD; - EXPECT_NEAR(z, 10, 1e-8); - pj_free(src); - pj_free(dst); -} - -// --------------------------------------------------------------------------- - -TEST(pj_transform_test, datum_to_longlat_towgs84_7param) { - auto src = pj_init_plus("+proj=longlat +datum=WGS84"); - auto dst = - pj_init_plus("+proj=longlat +ellps=WGS84 +towgs84=0,1,0,0,0,0,0.5"); - double x = 90 * DEG_TO_RAD; - double y = 0 * DEG_TO_RAD; - double z = 14.189073500223458; - EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, &z), 0); - EXPECT_NEAR(x, 90 * DEG_TO_RAD, 1e-12) << x / DEG_TO_RAD; - EXPECT_NEAR(y, 0 * DEG_TO_RAD, 1e-12) << y / DEG_TO_RAD; - EXPECT_NEAR(z, 10, 1e-8); - pj_free(src); - pj_free(dst); -} - -// --------------------------------------------------------------------------- - -TEST(pj_transform_test, ellps_grs80_towgs84_to_datum_wgs84) { - auto src = pj_init_plus("+proj=longlat +ellps=GRS80 +towgs84=0,0,0"); - auto dst = pj_init_plus("+proj=longlat +datum=WGS84"); - double x = 2 * DEG_TO_RAD; - double y = 49 * DEG_TO_RAD; - double z = 10; - EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, &z), 0); - EXPECT_NEAR(x, 2 * DEG_TO_RAD, 1e-15) << x / DEG_TO_RAD; - EXPECT_NEAR(y, 49 * DEG_TO_RAD, 1e-15) << y / DEG_TO_RAD; - EXPECT_NEAR(z, 10, 1e-8); - pj_free(src); - pj_free(dst); -} - -// --------------------------------------------------------------------------- - -TEST(pj_transform_test, longlat_nadgrids_to_datum) { - auto src = pj_init_plus("+proj=longlat +ellps=clrk66 +nadgrids=conus"); - auto dst = pj_init_plus("+proj=longlat +datum=NAD83"); - double x = -100 * DEG_TO_RAD; - double y = 40 * DEG_TO_RAD; - double z = 10; - int ret = pj_transform(src, dst, 1, 0, &x, &y, &z); - EXPECT_TRUE(ret == 0 || ret == PJD_ERR_FAILED_TO_LOAD_GRID); - if (ret == 0) { - EXPECT_NEAR(x, -100.00040583667015 * DEG_TO_RAD, 1e-12) - << x / DEG_TO_RAD; - EXPECT_NEAR(y, 40.000005895651363 * DEG_TO_RAD, 1e-12) - << y / DEG_TO_RAD; - EXPECT_NEAR(z, 10.000043224543333, 1e-8); - } - pj_free(src); - pj_free(dst); -} - -// --------------------------------------------------------------------------- - -TEST(pj_transform_test, nadgrids_noop) { - auto src = pj_init_plus("+proj=longlat +ellps=clrk66 +nadgrids=conus"); - auto dst = pj_init_plus("+proj=longlat +ellps=clrk66 +nadgrids=conus"); - double x = -100 * DEG_TO_RAD; - double y = 40 * DEG_TO_RAD; - double z = 10; - int ret = pj_transform(src, dst, 1, 0, &x, &y, &z); - EXPECT_TRUE(ret == 0); - if (ret == 0) { - EXPECT_NEAR(x, -100 * DEG_TO_RAD, 1e-15) << x / DEG_TO_RAD; - EXPECT_NEAR(y, 40 * DEG_TO_RAD, 1e-15) << y / DEG_TO_RAD; - EXPECT_NEAR(z, 10, 1e-8); - } - pj_free(src); - pj_free(dst); -} - -// --------------------------------------------------------------------------- - -TEST(pj_transform_test, datum_to_longlat_nadgrids) { - auto src = pj_init_plus("+proj=longlat +datum=NAD83"); - auto dst = pj_init_plus("+proj=longlat +ellps=clrk66 +nadgrids=conus"); - double x = -100.00040583667015 * DEG_TO_RAD; - double y = 40.000005895651363 * DEG_TO_RAD; - double z = 10.000043224543333; - int ret = pj_transform(src, dst, 1, 0, &x, &y, &z); - EXPECT_TRUE(ret == 0 || ret == PJD_ERR_FAILED_TO_LOAD_GRID); - if (ret == 0) { - EXPECT_NEAR(x, -100 * DEG_TO_RAD, 1e-12) << x / DEG_TO_RAD; - EXPECT_NEAR(y, 40 * DEG_TO_RAD, 1e-12) << y / DEG_TO_RAD; - EXPECT_NEAR(z, 10, 1e-8); - } - pj_free(src); - pj_free(dst); -} - -// --------------------------------------------------------------------------- - -TEST(pj_transform_test, long_wrap) { - auto src = pj_init_plus("+proj=longlat +datum=WGS84"); - auto dst = pj_init_plus("+proj=longlat +datum=WGS84 +lon_wrap=180"); - double x = -1 * DEG_TO_RAD; - double y = 0 * DEG_TO_RAD; - EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, nullptr), 0); - EXPECT_NEAR(x, 359 * DEG_TO_RAD, 1e-12) << x / DEG_TO_RAD; - EXPECT_NEAR(y, 0 * DEG_TO_RAD, 1e-12) << y / DEG_TO_RAD; - pj_free(src); - pj_free(dst); -} - -// --------------------------------------------------------------------------- - -TEST(pj_transform_test, src_vto_meter) { - auto src = pj_init_plus("+proj=longlat +datum=WGS84 +vto_meter=1000"); - auto dst = pj_init_plus("+proj=longlat +datum=WGS84"); - double x = 2 * DEG_TO_RAD; - double y = 49 * DEG_TO_RAD; - double z = 1; - EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, &z), 0); - EXPECT_NEAR(x, 2 * DEG_TO_RAD, 1e-12) << x / DEG_TO_RAD; - EXPECT_NEAR(y, 49 * DEG_TO_RAD, 1e-12) << y / DEG_TO_RAD; - EXPECT_NEAR(z, 1000, 1e-8); - pj_free(src); - pj_free(dst); -} - -// --------------------------------------------------------------------------- - -TEST(pj_transform_test, dest_vto_meter) { - auto src = pj_init_plus("+proj=longlat +datum=WGS84"); - auto dst = pj_init_plus("+proj=longlat +datum=WGS84 +vto_meter=1000"); - double x = 2 * DEG_TO_RAD; - double y = 49 * DEG_TO_RAD; - double z = 1000; - EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, &z), 0); - EXPECT_NEAR(x, 2 * DEG_TO_RAD, 1e-12) << x / DEG_TO_RAD; - EXPECT_NEAR(y, 49 * DEG_TO_RAD, 1e-12) << y / DEG_TO_RAD; - EXPECT_NEAR(z, 1, 1e-8); - pj_free(src); - pj_free(dst); -} - -// --------------------------------------------------------------------------- - -TEST(pj_transform_test, src_axis_neu_with_z) { - auto src = pj_init_plus("+proj=longlat +datum=WGS84 +axis=neu"); - auto dst = pj_init_plus("+proj=longlat +datum=WGS84"); - double x = 49 * DEG_TO_RAD; - double y = 2 * DEG_TO_RAD; - double z = 1; - EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, &z), 0); - EXPECT_NEAR(x, 2 * DEG_TO_RAD, 1e-12) << x / DEG_TO_RAD; - EXPECT_NEAR(y, 49 * DEG_TO_RAD, 1e-12) << y / DEG_TO_RAD; - EXPECT_NEAR(z, 1, 1e-8); - pj_free(src); - pj_free(dst); -} - -// --------------------------------------------------------------------------- - -TEST(pj_transform_test, src_axis_neu_without_z) { - auto src = pj_init_plus("+proj=longlat +datum=WGS84 +axis=neu"); - auto dst = pj_init_plus("+proj=longlat +datum=WGS84"); - double x = 49 * DEG_TO_RAD; - double y = 2 * DEG_TO_RAD; - EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, nullptr), 0); - EXPECT_NEAR(x, 2 * DEG_TO_RAD, 1e-12) << x / DEG_TO_RAD; - EXPECT_NEAR(y, 49 * DEG_TO_RAD, 1e-12) << y / DEG_TO_RAD; - pj_free(src); - pj_free(dst); -} - -// --------------------------------------------------------------------------- - -TEST(pj_transform_test, src_axis_swd) { - auto src = pj_init_plus("+proj=longlat +datum=WGS84 +axis=swd"); - auto dst = pj_init_plus("+proj=longlat +datum=WGS84"); - double x = 49 * DEG_TO_RAD; - double y = 2 * DEG_TO_RAD; - double z = -1; - EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, &z), 0); - EXPECT_NEAR(x, -2 * DEG_TO_RAD, 1e-12) << x / DEG_TO_RAD; - EXPECT_NEAR(y, -49 * DEG_TO_RAD, 1e-12) << y / DEG_TO_RAD; - EXPECT_NEAR(z, 1, 1e-8); - pj_free(src); - pj_free(dst); -} - -// --------------------------------------------------------------------------- - -TEST(pj_transform_test, dst_axis_neu) { - auto src = pj_init_plus("+proj=longlat +datum=WGS84"); - auto dst = pj_init_plus("+proj=longlat +datum=WGS84 +axis=neu"); - double x = 2 * DEG_TO_RAD; - double y = 49 * DEG_TO_RAD; - double z = 1; - EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, &z), 0); - EXPECT_NEAR(x, 49 * DEG_TO_RAD, 1e-12) << x / DEG_TO_RAD; - EXPECT_NEAR(y, 2 * DEG_TO_RAD, 1e-12) << y / DEG_TO_RAD; - EXPECT_NEAR(z, 1, 1e-8); - pj_free(src); - pj_free(dst); -} -// --------------------------------------------------------------------------- - -TEST(pj_transform_test, dst_axis_swd) { - auto src = pj_init_plus("+proj=longlat +datum=WGS84"); - auto dst = pj_init_plus("+proj=longlat +datum=WGS84 +axis=swd"); - double x = 2 * DEG_TO_RAD; - double y = 49 * DEG_TO_RAD; - double z = 1; - EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, &z), 0); - EXPECT_NEAR(x, -49 * DEG_TO_RAD, 1e-12) << x / DEG_TO_RAD; - EXPECT_NEAR(y, -2 * DEG_TO_RAD, 1e-12) << y / DEG_TO_RAD; - EXPECT_NEAR(z, -1, 1e-8); - pj_free(src); - pj_free(dst); -} - -// --------------------------------------------------------------------------- - -TEST(pj_transform_test, init_epsg) { - auto src = pj_init_plus("+init=epsg:4326"); - ASSERT_TRUE(src != nullptr); - auto dst = pj_init_plus("+init=epsg:32631"); - ASSERT_TRUE(dst != nullptr); - double x = 3 * DEG_TO_RAD; - double y = 0 * DEG_TO_RAD; - EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, nullptr), 0); - EXPECT_NEAR(x, 500000, 1e-8); - EXPECT_NEAR(y, 0, 1e-8); - pj_free(src); - pj_free(dst); -} - -// --------------------------------------------------------------------------- - -TEST(proj_api_h, pj_set_searchpath) { - - const char *path = "/i_do/not/exit"; - pj_set_searchpath(1, &path); - { - auto info = proj_info(); - EXPECT_EQ(info.path_count, 1U); - ASSERT_NE(info.paths, nullptr); - ASSERT_NE(info.paths[0], nullptr); - EXPECT_EQ(std::string(info.paths[0]), path); - } - - pj_set_searchpath(0, nullptr); - { - auto info = proj_info(); - EXPECT_EQ(info.path_count, 0U); - EXPECT_EQ(info.paths, nullptr); - } -} - -// --------------------------------------------------------------------------- - -TEST(proj_api_h, pj_set_finder) { - - const auto myfinder = [](const char *) -> const char * { return nullptr; }; - pj_set_finder(myfinder); - - pj_set_finder(nullptr); -} - -// --------------------------------------------------------------------------- - -TEST(proj_api_h, default_fileapi) { - auto ctx = pj_ctx_alloc(); - auto fid = pj_open_lib(ctx, "proj.db", "rb"); - ASSERT_NE(fid, nullptr); - char header[6]; - ASSERT_EQ(pj_ctx_fread(ctx, header, 1, 6, fid), 6U); - ASSERT_TRUE(memcmp(header, "SQLite", 6) == 0); - ASSERT_EQ(pj_ctx_ftell(ctx, fid), 6); - ASSERT_EQ(pj_ctx_fseek(ctx, fid, 0, SEEK_SET), 0); - ASSERT_EQ(pj_ctx_ftell(ctx, fid), 0); - pj_ctx_fclose(ctx, fid); - pj_ctx_free(ctx); -} - -// --------------------------------------------------------------------------- - -TEST(pj_transform_test, ob_tran_to_meter_as_dest) { - auto src = pj_init_plus( - "+ellps=WGS84 +a=57.29577951308232 +proj=eqc +lon_0=0.0 +no_defs"); - auto dst = pj_init_plus("+ellps=WGS84 +proj=ob_tran +o_proj=latlon " - "+o_lon_p=0.0 +o_lat_p=90.0 +lon_0=360.0 " - "+to_meter=0.0174532925199433 +no_defs"); - double x = 2 * DEG_TO_RAD; - double y = 49 * DEG_TO_RAD; - EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, nullptr), 0); - EXPECT_NEAR(x, 2 * DEG_TO_RAD, 1e-12) << x / DEG_TO_RAD; - EXPECT_NEAR(y, 49 * DEG_TO_RAD, 1e-12) << y / DEG_TO_RAD; - pj_free(src); - pj_free(dst); -} - -// --------------------------------------------------------------------------- - -struct Spy { - bool gotInMyFOpen = false; - bool gotInMyFRead = false; - bool gotInMyFSeek = false; - bool gotInMyFTell = false; - bool gotInMyFClose = false; -}; - -struct MyFile { - FILE *fp; - Spy *spy; -}; - -static PAFile myFOpen(projCtx ctx, const char *filename, const char *access) { - FILE *fp = fopen(filename, access); - if (!fp) - return nullptr; - MyFile *myF = new MyFile; - myF->spy = (Spy *)pj_ctx_get_app_data(ctx); - myF->spy->gotInMyFOpen = true; - myF->fp = fp; - return reinterpret_cast(myF); -} - -static size_t myFRead(void *buffer, size_t size, size_t nmemb, PAFile file) { - MyFile *myF = reinterpret_cast(file); - myF->spy->gotInMyFRead = true; - return fread(buffer, size, nmemb, myF->fp); -} - -static int myFSeek(PAFile file, long offset, int whence) { - MyFile *myF = reinterpret_cast(file); - myF->spy->gotInMyFSeek = true; - return fseek(myF->fp, offset, whence); -} - -static long myFTell(PAFile file) { - MyFile *myF = reinterpret_cast(file); - myF->spy->gotInMyFTell = true; - return ftell(myF->fp); -} - -static void myFClose(PAFile file) { - MyFile *myF = reinterpret_cast(file); - myF->spy->gotInMyFClose = true; - fclose(myF->fp); - delete myF; -} - -TEST(proj_api_h, custom_fileapi) { - auto ctx = pj_ctx_alloc(); - Spy spy; - pj_ctx_set_app_data(ctx, &spy); - projFileAPI myAPI = {myFOpen, myFRead, myFSeek, myFTell, myFClose}; - pj_ctx_set_fileapi(ctx, &myAPI); - EXPECT_EQ(pj_ctx_get_fileapi(ctx), &myAPI); - auto fid = pj_open_lib(ctx, "proj.db", "rb"); - ASSERT_NE(fid, nullptr); - char header[6]; - ASSERT_EQ(pj_ctx_fread(ctx, header, 1, 6, fid), 6U); - ASSERT_TRUE(memcmp(header, "SQLite", 6) == 0); - ASSERT_EQ(pj_ctx_ftell(ctx, fid), 6); - ASSERT_EQ(pj_ctx_fseek(ctx, fid, 0, SEEK_SET), 0); - ASSERT_EQ(pj_ctx_ftell(ctx, fid), 0); - pj_ctx_fclose(ctx, fid); - pj_ctx_free(ctx); - EXPECT_TRUE(spy.gotInMyFOpen); - EXPECT_TRUE(spy.gotInMyFRead); - EXPECT_TRUE(spy.gotInMyFSeek); - EXPECT_TRUE(spy.gotInMyFTell); - EXPECT_TRUE(spy.gotInMyFClose); -} - -TEST(pj_transform_test, ob_tran_to_meter_as_srouce) { - auto src = pj_init_plus("+ellps=WGS84 +proj=ob_tran +o_proj=latlon " - "+o_lon_p=0.0 +o_lat_p=90.0 +lon_0=360.0 " - "+to_meter=0.0174532925199433 +no_defs"); - auto dst = pj_init_plus( - "+ellps=WGS84 +a=57.29577951308232 +proj=eqc +lon_0=0.0 +no_defs"); - double x = 2 * DEG_TO_RAD; - double y = 49 * DEG_TO_RAD; - EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, nullptr), 0); - EXPECT_NEAR(x, 2 * DEG_TO_RAD, 1e-12) << x / DEG_TO_RAD; - EXPECT_NEAR(y, 49 * DEG_TO_RAD, 1e-12) << y / DEG_TO_RAD; - pj_free(src); - pj_free(dst); -} - -} // namespace -- cgit v1.2.3 From aa46197d66ce70ece382bf955326c46b13f35864 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Sat, 14 Nov 2020 22:55:31 +0100 Subject: Weed out proj_api.h datatypes and replace them with their proj.h counterparts --- src/aasincos.cpp | 4 +- src/ctx.cpp | 55 +++++++------- src/datum_set.cpp | 2 +- src/dmstor.cpp | 2 +- src/ell_set.cpp | 2 +- src/fileapi.cpp | 22 +++--- src/filemanager.cpp | 16 ++-- src/gauss.cpp | 4 +- src/grids.cpp | 4 +- src/init.cpp | 6 +- src/internal.cpp | 2 +- src/iso19111/datum.cpp | 2 +- src/log.cpp | 6 +- src/mlfn.cpp | 2 +- src/mlfn.hpp | 2 +- src/param.cpp | 2 +- src/phi2.cpp | 4 +- src/proj.h | 6 +- src/proj_internal.h | 155 ++++++++++++++++----------------------- src/proj_mdist.cpp | 2 +- src/projections/chamb.cpp | 4 +- src/tests/multistresstest.cpp | 14 ++-- src/tests/test228.cpp | 6 +- src/utils.cpp | 2 +- test/fuzzers/standard_fuzzer.cpp | 4 +- test/unit/pj_phi2_test.cpp | 2 +- 26 files changed, 153 insertions(+), 179 deletions(-) diff --git a/src/aasincos.cpp b/src/aasincos.cpp index 398a8cfc..c3229d39 100644 --- a/src/aasincos.cpp +++ b/src/aasincos.cpp @@ -9,7 +9,7 @@ #define ATOL 1e-50 double -aasin(projCtx ctx,double v) { +aasin(PJ_CONTEXT *ctx,double v) { double av; if ((av = fabs(v)) >= 1.) { @@ -21,7 +21,7 @@ aasin(projCtx ctx,double v) { } double -aacos(projCtx ctx, double v) { +aacos(PJ_CONTEXT *ctx, double v) { double av; if ((av = fabs(v)) >= 1.) { diff --git a/src/ctx.cpp b/src/ctx.cpp index 6dbe0de5..24d3773b 100644 --- a/src/ctx.cpp +++ b/src/ctx.cpp @@ -1,6 +1,6 @@ /****************************************************************************** * Project: PROJ.4 - * Purpose: Implementation of the projCtx thread context object. + * Purpose: Implementation of the PJ_CONTEXT thread context object. * Author: Frank Warmerdam, warmerdam@pobox.com * ****************************************************************************** @@ -43,7 +43,7 @@ /* pj_get_ctx() */ /************************************************************************/ -projCtx pj_get_ctx( projPJ pj ) +PJ_CONTEXT* pj_get_ctx( PJ *pj ) { if (nullptr==pj) @@ -59,7 +59,7 @@ projCtx pj_get_ctx( projPJ pj ) /* Note we do not deallocate the old context! */ /************************************************************************/ -void pj_set_ctx( projPJ pj, projCtx ctx ) +void pj_set_ctx( PJ *pj, PJ_CONTEXT *ctx ) { if (pj==nullptr) @@ -86,7 +86,7 @@ void pj_set_ctx( projPJ pj, projCtx ctx ) * the user may want to assign another thread-specific context to the * object. */ -void proj_assign_context( PJ* pj, PJ_CONTEXT* ctx ) +void proj_assign_context( PJ* pj, PJ_CONTEXT *ctx ) { pj_set_ctx( pj, ctx ); } @@ -95,9 +95,9 @@ void proj_assign_context( PJ* pj, PJ_CONTEXT* ctx ) /* createDefault() */ /************************************************************************/ -projCtx_t projCtx_t::createDefault() +pj_ctx pj_ctx::createDefault() { - projCtx_t ctx; + pj_ctx ctx; ctx.debug_level = PJ_LOG_NONE; ctx.logger = pj_stderr_logger; ctx.fileapi_legacy = pj_get_default_fileapi(); @@ -117,7 +117,7 @@ projCtx_t projCtx_t::createDefault() /* get_cpp_context() */ /**************************************************************************/ -projCppContext* projCtx_t::get_cpp_context() +projCppContext* pj_ctx::get_cpp_context() { if (cpp_context == nullptr) { cpp_context = new projCppContext(this); @@ -125,12 +125,11 @@ projCppContext* projCtx_t::get_cpp_context() return cpp_context; } - /**************************************************************************/ /* safeAutoCloseDbIfNeeded() */ /**************************************************************************/ -void projCtx_t::safeAutoCloseDbIfNeeded() +void pj_ctx::safeAutoCloseDbIfNeeded() { if (cpp_context) { cpp_context->autoCloseDbIfNeeded(); @@ -141,7 +140,7 @@ void projCtx_t::safeAutoCloseDbIfNeeded() /* set_search_paths() */ /************************************************************************/ -void projCtx_t::set_search_paths(const std::vector& search_paths_in ) +void pj_ctx::set_search_paths(const std::vector& search_paths_in ) { search_paths = search_paths_in; delete[] c_compat_paths; @@ -158,16 +157,16 @@ void projCtx_t::set_search_paths(const std::vector& search_paths_in /* set_ca_bundle_path() */ /**************************************************************************/ -void projCtx_t::set_ca_bundle_path(const std::string& ca_bundle_path_in) +void pj_ctx::set_ca_bundle_path(const std::string& ca_bundle_path_in) { ca_bundle_path = ca_bundle_path_in; } /************************************************************************/ -/* projCtx_t(const projCtx_t& other) */ +/* pj_ctx(const pj_ctx& other) */ /************************************************************************/ -projCtx_t::projCtx_t(const projCtx_t& other) : +pj_ctx::pj_ctx(const pj_ctx& other) : debug_level(other.debug_level), logger(other.logger), logger_app_data(other.logger_app_data), @@ -197,19 +196,19 @@ projCtx_t::projCtx_t(const projCtx_t& other) : /* pj_get_default_ctx() */ /************************************************************************/ -projCtx pj_get_default_ctx() +PJ_CONTEXT* pj_get_default_ctx() { // C++11 rules guarantee a thread-safe instantiation. - static projCtx_t default_context(projCtx_t::createDefault()); + static pj_ctx default_context(pj_ctx::createDefault()); return &default_context; } /************************************************************************/ -/* ~projCtx_t() */ +/* ~pj_ctx() */ /************************************************************************/ -projCtx_t::~projCtx_t() +pj_ctx::~pj_ctx() { delete[] c_compat_paths; proj_context_delete_cpp_context(cpp_context); @@ -219,10 +218,10 @@ projCtx_t::~projCtx_t() /* pj_ctx_alloc() */ /************************************************************************/ -projCtx pj_ctx_alloc() +PJ_CONTEXT* pj_ctx_alloc() { - return new (std::nothrow) projCtx_t(*pj_get_default_ctx()); + return new (std::nothrow) pj_ctx(*pj_get_default_ctx()); } /************************************************************************/ @@ -230,19 +229,19 @@ projCtx pj_ctx_alloc() /* Create a new context based on a custom context */ /************************************************************************/ -PJ_CONTEXT *proj_context_clone (PJ_CONTEXT *ctx) +PJ_CONTEXT* proj_context_clone (PJ_CONTEXT *ctx) { if (nullptr==ctx) return pj_ctx_alloc (); - return new (std::nothrow) projCtx_t(*ctx); + return new (std::nothrow) pj_ctx(*ctx); } /************************************************************************/ /* pj_ctx_free() */ /************************************************************************/ -void pj_ctx_free( projCtx ctx ) +void pj_ctx_free( PJ_CONTEXT *ctx ) { delete ctx; @@ -252,7 +251,7 @@ void pj_ctx_free( projCtx ctx ) /* pj_ctx_get_errno() */ /************************************************************************/ -int pj_ctx_get_errno( projCtx ctx ) +int pj_ctx_get_errno( PJ_CONTEXT *ctx ) { if (nullptr==ctx) @@ -266,7 +265,7 @@ int pj_ctx_get_errno( projCtx ctx ) /* Also sets the global errno */ /************************************************************************/ -void pj_ctx_set_errno( projCtx ctx, int new_errno ) +void pj_ctx_set_errno( PJ_CONTEXT *ctx, int new_errno ) { ctx->last_errno = new_errno; @@ -280,7 +279,7 @@ void pj_ctx_set_errno( projCtx ctx, int new_errno ) /* pj_ctx_set_debug() */ /************************************************************************/ -void pj_ctx_set_debug( projCtx ctx, int new_debug ) +void pj_ctx_set_debug( PJ_CONTEXT *ctx, int new_debug ) { if (nullptr==ctx) @@ -292,7 +291,7 @@ void pj_ctx_set_debug( projCtx ctx, int new_debug ) /* pj_ctx_set_logger() */ /************************************************************************/ -void pj_ctx_set_logger( projCtx ctx, void (*new_logger)(void*,int,const char*) ) +void pj_ctx_set_logger( PJ_CONTEXT *ctx, void (*new_logger)(void*,int,const char*) ) { if (nullptr==ctx) @@ -304,7 +303,7 @@ void pj_ctx_set_logger( projCtx ctx, void (*new_logger)(void*,int,const char*) ) /* pj_ctx_set_app_data() */ /************************************************************************/ -void pj_ctx_set_app_data( projCtx ctx, void *new_app_data ) +void pj_ctx_set_app_data( PJ_CONTEXT *ctx, void *new_app_data ) { if (nullptr==ctx) @@ -316,7 +315,7 @@ void pj_ctx_set_app_data( projCtx ctx, void *new_app_data ) /* pj_ctx_get_app_data() */ /************************************************************************/ -void *pj_ctx_get_app_data( projCtx ctx ) +void *pj_ctx_get_app_data( PJ_CONTEXT *ctx ) { if (nullptr==ctx) diff --git a/src/datum_set.cpp b/src/datum_set.cpp index 15d51613..cc6f3dbe 100644 --- a/src/datum_set.cpp +++ b/src/datum_set.cpp @@ -38,7 +38,7 @@ /* pj_datum_set() */ /************************************************************************/ -int pj_datum_set(projCtx ctx, paralist *pl, PJ *projdef) +int pj_datum_set(PJ_CONTEXT *ctx, paralist *pl, PJ *projdef) { const char *name, *towgs84, *nadgrids; diff --git a/src/dmstor.cpp b/src/dmstor.cpp index 3ba66030..e72d9930 100644 --- a/src/dmstor.cpp +++ b/src/dmstor.cpp @@ -26,7 +26,7 @@ dmstor(const char *is, char **rs) { } double -dmstor_ctx(projCtx ctx, const char *is, char **rs) { +dmstor_ctx(PJ_CONTEXT *ctx, const char *is, char **rs) { int sign, n, nl; char *s, work[MAX_WORK]; const char* p; diff --git a/src/ell_set.cpp b/src/ell_set.cpp index ddd507ac..ec3e03eb 100644 --- a/src/ell_set.cpp +++ b/src/ell_set.cpp @@ -609,7 +609,7 @@ int pj_ell_set (PJ_CONTEXT *ctx, paralist *pl, double *a, double *es) { /**************************************************************************************/ -int pj_ell_set (projCtx ctx, paralist *pl, double *a, double *es) { +int pj_ell_set (PJ_CONTEXT *ctx, paralist *pl, double *a, double *es) { /*************************************************************************************** Initialize ellipsoidal parameters: This is the original ellipsoid setup function by Gerald Evenden - significantly more compact than pj_ellipsoid and diff --git a/src/fileapi.cpp b/src/fileapi.cpp index 70be2502..0af83926 100644 --- a/src/fileapi.cpp +++ b/src/fileapi.cpp @@ -36,7 +36,7 @@ #include "proj_internal.h" #include "filemanager.hpp" -static PAFile stdio_fopen(projCtx ctx, const char *filename, +static PAFile stdio_fopen(PJ_CONTEXT *ctx, const char *filename, const char *access); static size_t stdio_fread(void *buffer, size_t size, size_t nmemb, PAFile file); @@ -53,7 +53,7 @@ static projFileAPI default_fileapi = { }; typedef struct { - projCtx ctx; + PJ_CONTEXT *ctx; FILE *fp; } stdio_pafile; @@ -70,7 +70,7 @@ projFileAPI *pj_get_default_fileapi(void) /* stdio_fopen() */ /************************************************************************/ -static PAFile stdio_fopen(projCtx ctx, const char *filename, +static PAFile stdio_fopen(PJ_CONTEXT *ctx, const char *filename, const char *access) { stdio_pafile *pafile; @@ -140,7 +140,7 @@ static void stdio_fclose(PAFile file) /* Open a file using the provided file io hooks. */ /************************************************************************/ -PAFile pj_ctx_fopen(projCtx ctx, const char *filename, const char *access) +PAFile pj_ctx_fopen(PJ_CONTEXT *ctx, const char *filename, const char *access) { return ctx->fileapi_legacy->FOpen(ctx, filename, access); } @@ -148,7 +148,7 @@ PAFile pj_ctx_fopen(projCtx ctx, const char *filename, const char *access) /************************************************************************/ /* pj_ctx_fread() */ /************************************************************************/ -size_t pj_ctx_fread(projCtx ctx, void *buffer, size_t size, size_t nmemb, PAFile file) +size_t pj_ctx_fread(PJ_CONTEXT *ctx, void *buffer, size_t size, size_t nmemb, PAFile file) { return ctx->fileapi_legacy->FRead(buffer, size, nmemb, file); } @@ -156,7 +156,7 @@ size_t pj_ctx_fread(projCtx ctx, void *buffer, size_t size, size_t nmemb, PAFile /************************************************************************/ /* pj_ctx_fseek() */ /************************************************************************/ -int pj_ctx_fseek(projCtx ctx, PAFile file, long offset, int whence) +int pj_ctx_fseek(PJ_CONTEXT *ctx, PAFile file, long offset, int whence) { return ctx->fileapi_legacy->FSeek(file, offset, whence); } @@ -164,7 +164,7 @@ int pj_ctx_fseek(projCtx ctx, PAFile file, long offset, int whence) /************************************************************************/ /* pj_ctx_ftell() */ /************************************************************************/ -long pj_ctx_ftell(projCtx ctx, PAFile file) +long pj_ctx_ftell(PJ_CONTEXT *ctx, PAFile file) { return ctx->fileapi_legacy->FTell(file); } @@ -172,7 +172,7 @@ long pj_ctx_ftell(projCtx ctx, PAFile file) /************************************************************************/ /* pj_ctx_fclose() */ /************************************************************************/ -void pj_ctx_fclose(projCtx ctx, PAFile file) +void pj_ctx_fclose(PJ_CONTEXT *ctx, PAFile file) { ctx->fileapi_legacy->FClose(file); } @@ -185,7 +185,7 @@ void pj_ctx_fclose(projCtx ctx, PAFile file) /* taken. */ /************************************************************************/ -char *pj_ctx_fgets(projCtx ctx, char *line, int size, PAFile file) +char *pj_ctx_fgets(PJ_CONTEXT *ctx, char *line, int size, PAFile file) { long start = pj_ctx_ftell(ctx, file); size_t bytes_read; @@ -218,7 +218,7 @@ char *pj_ctx_fgets(projCtx ctx, char *line, int size, PAFile file) /* pj_ctx_set_fileapi() */ /************************************************************************/ -void pj_ctx_set_fileapi( projCtx ctx, projFileAPI *fileapi ) +void pj_ctx_set_fileapi( PJ_CONTEXT *ctx, projFileAPI *fileapi ) { if (nullptr==ctx) @@ -230,7 +230,7 @@ void pj_ctx_set_fileapi( projCtx ctx, projFileAPI *fileapi ) /* pj_ctx_get_fileapi() */ /************************************************************************/ -projFileAPI *pj_ctx_get_fileapi( projCtx ctx ) +projFileAPI *pj_ctx_get_fileapi( PJ_CONTEXT *ctx ) { if (nullptr==ctx) diff --git a/src/filemanager.cpp b/src/filemanager.cpp index e6a9ed95..37dc920e 100644 --- a/src/filemanager.cpp +++ b/src/filemanager.cpp @@ -1445,8 +1445,8 @@ static bool dontReadUserWritableDirectory() { } static void * -pj_open_lib_internal(projCtx ctx, const char *name, const char *mode, - void *(*open_file)(projCtx, const char *, const char *), +pj_open_lib_internal(PJ_CONTEXT *ctx, const char *name, const char *mode, + void *(*open_file)(PJ_CONTEXT *, const char *, const char *), char *out_full_filename, size_t out_full_filename_size) { try { std::string fname; @@ -1617,7 +1617,7 @@ std::vector pj_get_default_searchpaths(PJ_CONTEXT *ctx) { /* pj_open_file_with_manager() */ /************************************************************************/ -static void *pj_open_file_with_manager(projCtx ctx, const char *name, +static void *pj_open_file_with_manager(PJ_CONTEXT *ctx, const char *name, const char * /* mode */) { return NS_PROJ::FileManager::open(ctx, name, NS_PROJ::FileAccess::READ_ONLY) .release(); @@ -1639,7 +1639,7 @@ static NS_PROJ::io::DatabaseContextPtr getDBcontext(PJ_CONTEXT *ctx) { /************************************************************************/ std::unique_ptr -NS_PROJ::FileManager::open_resource_file(projCtx ctx, const char *name) { +NS_PROJ::FileManager::open_resource_file(PJ_CONTEXT *ctx, const char *name) { if (ctx == nullptr) { ctx = pj_get_default_ctx(); @@ -1735,13 +1735,13 @@ NS_PROJ::FileManager::open_resource_file(projCtx ctx, const char *name) { #ifndef REMOVE_LEGACY_SUPPORT // Used by following legacy function -static void *pj_ctx_fopen_adapter(projCtx ctx, const char *name, +static void *pj_ctx_fopen_adapter(PJ_CONTEXT *ctx, const char *name, const char *mode) { return pj_ctx_fopen(ctx, name, mode); } // Legacy function -PAFile pj_open_lib(projCtx ctx, const char *name, const char *mode) { +PAFile pj_open_lib(PJ_CONTEXT *ctx, const char *name, const char *mode) { return (PAFile)pj_open_lib_internal(ctx, name, mode, pj_ctx_fopen_adapter, nullptr, 0); } @@ -1764,7 +1764,7 @@ PAFile pj_open_lib(projCtx ctx, const char *name, const char *mode) { * @param out_full_filename_size size of out_full_filename. * @return 1 if the file was found, 0 otherwise. */ -int pj_find_file(projCtx ctx, const char *short_filename, +int pj_find_file(PJ_CONTEXT *ctx, const char *short_filename, char *out_full_filename, size_t out_full_filename_size) { auto file = std::unique_ptr( reinterpret_cast(pj_open_lib_internal( @@ -1812,7 +1812,7 @@ static std::string trim(const std::string &s) { /* pj_load_ini() */ /************************************************************************/ -void pj_load_ini(projCtx ctx) { +void pj_load_ini(PJ_CONTEXT *ctx) { if (ctx->iniFileLoaded) return; diff --git a/src/gauss.cpp b/src/gauss.cpp index a34a8f5b..54dff5a8 100644 --- a/src/gauss.cpp +++ b/src/gauss.cpp @@ -81,7 +81,7 @@ void *pj_gauss_ini(double e, double phi0, double *chi, double *rc) { return ((void *)en); } -PJ_LP pj_gauss(projCtx ctx, PJ_LP elp, const void *data) { +PJ_LP pj_gauss(PJ_CONTEXT *ctx, PJ_LP elp, const void *data) { const struct GAUSS *en = (const struct GAUSS *)data; PJ_LP slp; (void) ctx; @@ -93,7 +93,7 @@ PJ_LP pj_gauss(projCtx ctx, PJ_LP elp, const void *data) { return(slp); } -PJ_LP pj_inv_gauss(projCtx ctx, PJ_LP slp, const void *data) { +PJ_LP pj_inv_gauss(PJ_CONTEXT *ctx, PJ_LP slp, const void *data) { const struct GAUSS *en = (const struct GAUSS *)data; PJ_LP elp; double num; diff --git a/src/grids.cpp b/src/grids.cpp index 8065813a..8c1bc4cc 100644 --- a/src/grids.cpp +++ b/src/grids.cpp @@ -2948,7 +2948,7 @@ static PJ_LP pj_hgrid_interpolate(PJ_LP t, const HorizontalShiftGrid *grid, #define MAX_ITERATIONS 10 #define TOL 1e-12 -static PJ_LP pj_hgrid_apply_internal(projCtx ctx, PJ_LP in, +static PJ_LP pj_hgrid_apply_internal(PJ_CONTEXT *ctx, PJ_LP in, PJ_DIRECTION direction, const HorizontalShiftGrid *grid, HorizontalShiftGridSet *gridset, @@ -3452,7 +3452,7 @@ NS_PROJ_END /* it to honour our public api. */ /************************************************************************/ -int pj_apply_gridshift(projCtx ctx, const char *nadgrids, int inverse, +int pj_apply_gridshift(PJ_CONTEXT *ctx, const char *nadgrids, int inverse, long point_count, int point_offset, double *x, double *y, double * /*z */) diff --git a/src/init.cpp b/src/init.cpp index 101fc8ad..a42bf963 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -415,7 +415,7 @@ pj_init_plus( const char *definition ) } PJ * -pj_init_plus_ctx( projCtx ctx, const char *definition ) +pj_init_plus_ctx( PJ_CONTEXT *ctx, const char *definition ) { #define MAX_ARG 200 char *argv[MAX_ARG]; @@ -511,7 +511,7 @@ static PJ_CONSTRUCTOR locate_constructor (const char *name) { PJ * -pj_init_ctx(projCtx ctx, int argc, char **argv) { +pj_init_ctx(PJ_CONTEXT *ctx, int argc, char **argv) { /* Legacy interface: allow init=epsg:XXXX syntax by default */ int allow_init_epsg = proj_context_get_use_proj4_init_rules(ctx, TRUE); return pj_init_ctx_with_allow_init_epsg(ctx, argc, argv, allow_init_epsg); @@ -519,7 +519,7 @@ pj_init_ctx(projCtx ctx, int argc, char **argv) { PJ * -pj_init_ctx_with_allow_init_epsg(projCtx ctx, int argc, char **argv, int allow_init_epsg) { +pj_init_ctx_with_allow_init_epsg(PJ_CONTEXT *ctx, int argc, char **argv, int allow_init_epsg) { const char *s; char *name; PJ_CONSTRUCTOR proj; diff --git a/src/internal.cpp b/src/internal.cpp index 91994077..32dc1bba 100644 --- a/src/internal.cpp +++ b/src/internal.cpp @@ -417,7 +417,7 @@ to that context. /* logging */ /* pj_vlog resides in pj_log.c and relates to pj_log as vsprintf relates to sprintf */ -void pj_vlog( projCtx ctx, int level, const char *fmt, va_list args ); +void pj_vlog( PJ_CONTEXT *ctx, int level, const char *fmt, va_list args ); /***************************************************************************************/ diff --git a/src/iso19111/datum.cpp b/src/iso19111/datum.cpp index 28dbc462..4d7e78d3 100644 --- a/src/iso19111/datum.cpp +++ b/src/iso19111/datum.cpp @@ -417,7 +417,7 @@ std::string PrimeMeridian::getPROJStringWellKnownName(const common::Angle &angle) { const double valRad = angle.getSIValue(); std::string projPMName; - projCtx ctxt = pj_ctx_alloc(); + PJ_CONTEXT *ctxt = pj_ctx_alloc(); auto proj_pm = proj_list_prime_meridians(); for (int i = 0; proj_pm[i].id != nullptr; ++i) { double valRefRad = dmstor_ctx(ctxt, proj_pm[i].defn, nullptr); diff --git a/src/log.cpp b/src/log.cpp index 3cc10cfd..c343e65b 100644 --- a/src/log.cpp +++ b/src/log.cpp @@ -48,9 +48,9 @@ void pj_stderr_logger( void *app_data, int level, const char *msg ) /************************************************************************/ /* pj_vlog() */ /************************************************************************/ -void pj_vlog( projCtx ctx, int level, const char *fmt, va_list args ); +void pj_vlog( PJ_CONTEXT *ctx, int level, const char *fmt, va_list args ); /* Workhorse for the log functions - relates to pj_log as vsprintf relates to sprintf */ -void pj_vlog( projCtx ctx, int level, const char *fmt, va_list args ) +void pj_vlog( PJ_CONTEXT *ctx, int level, const char *fmt, va_list args ) { char *msg_buf; @@ -84,7 +84,7 @@ void pj_vlog( projCtx ctx, int level, const char *fmt, va_list args ) /* pj_log() */ /************************************************************************/ -void pj_log( projCtx ctx, int level, const char *fmt, ... ) +void pj_log( PJ_CONTEXT *ctx, int level, const char *fmt, ... ) { va_list args; diff --git a/src/mlfn.cpp b/src/mlfn.cpp index 80f9163b..d4037897 100644 --- a/src/mlfn.cpp +++ b/src/mlfn.cpp @@ -45,7 +45,7 @@ pj_mlfn(double phi, double sphi, double cphi, const double *en) { } double -pj_inv_mlfn(projCtx ctx, double arg, double es, const double *en) { +pj_inv_mlfn(PJ_CONTEXT *ctx, double arg, double es, const double *en) { double sinphi_ignored; double cosphi_ignored; return inline_pj_inv_mlfn(ctx, arg, es, en, &sinphi_ignored, &cosphi_ignored); diff --git a/src/mlfn.hpp b/src/mlfn.hpp index 26a2959f..e7138c63 100644 --- a/src/mlfn.hpp +++ b/src/mlfn.hpp @@ -15,7 +15,7 @@ inline static double inline_pj_mlfn(double phi, double sphi, double cphi, const } inline static double -inline_pj_inv_mlfn(projCtx ctx, double arg, double es, const double *en, +inline_pj_inv_mlfn(PJ_CONTEXT *ctx, double arg, double es, const double *en, double* sinphi, double* cosphi) { const double k = 1./(1.-es); constexpr double INV_MLFN_EPS = 1e-11; diff --git a/src/param.cpp b/src/param.cpp index 289faca3..9a3888e1 100644 --- a/src/param.cpp +++ b/src/param.cpp @@ -151,7 +151,7 @@ paralist *pj_param_exists (paralist *list, const char *parameter) { /* */ /************************************************************************/ -PROJVALUE pj_param (projCtx ctx, paralist *pl, const char *opt) { +PROJVALUE pj_param (PJ_CONTEXT *ctx, paralist *pl, const char *opt) { int type; unsigned l; diff --git a/src/phi2.cpp b/src/phi2.cpp index 1c48d67f..214d1058 100644 --- a/src/phi2.cpp +++ b/src/phi2.cpp @@ -7,7 +7,7 @@ #include "proj.h" #include "proj_internal.h" -double pj_sinhpsi2tanphi(projCtx ctx, const double taup, const double e) { +double pj_sinhpsi2tanphi(PJ_CONTEXT *ctx, const double taup, const double e) { /**************************************************************************** * Convert tau' = sinh(psi) = tan(chi) to tau = tan(phi). The code is taken * from GeographicLib::Math::tauf(taup, e). @@ -108,7 +108,7 @@ double pj_sinhpsi2tanphi(projCtx ctx, const double taup, const double e) { } /*****************************************************************************/ -double pj_phi2(projCtx ctx, const double ts0, const double e) { +double pj_phi2(PJ_CONTEXT *ctx, const double ts0, const double e) { /**************************************************************************** * Determine latitude angle phi-2. * Inputs: diff --git a/src/proj.h b/src/proj.h index e2c47a17..d4defc47 100644 --- a/src/proj.h +++ b/src/proj.h @@ -340,9 +340,9 @@ typedef enum PJ_LOG_LEVEL { typedef void (*PJ_LOG_FUNCTION)(void *, int, const char *); -/* The context type - properly namespaced synonym for projCtx */ -struct projCtx_t; -typedef struct projCtx_t PJ_CONTEXT; +/* The context type - properly namespaced synonym for pj_ctx */ +struct pj_ctx; +typedef struct pj_ctx PJ_CONTEXT; /* A P I */ diff --git a/src/proj_internal.h b/src/proj_internal.h index 062f240b..273c1efd 100644 --- a/src/proj_internal.h +++ b/src/proj_internal.h @@ -240,8 +240,6 @@ struct PJ_AREA { double north_lat_degree; }; -struct projCtx_t; -typedef struct projCtx_t projCtx_t; /***************************************************************************** @@ -352,7 +350,7 @@ struct PJconsts { **************************************************************************************/ - projCtx_t *ctx = nullptr; + PJ_CONTEXT *ctx = nullptr; const char *descr = nullptr; /* From pj_list.h or individual PJ_*.c file */ paralist *params = nullptr; /* Parameter list */ char *def_full = nullptr; /* Full textual definition (usually 0 - set by proj_pj_info) */ @@ -393,7 +391,7 @@ struct PJconsts { PJ_OPERATOR inv4d = nullptr; PJ_DESTRUCTOR destructor = nullptr; - void (*reassign_context)(PJ*, projCtx_t *) = nullptr; + void (*reassign_context)(PJ*, PJ_CONTEXT*) = nullptr; /************************************************************************************* @@ -708,7 +706,7 @@ struct projFileApiCallbackAndData }; /* proj thread context */ -struct projCtx_t { +struct pj_ctx{ int last_errno = 0; int debug_level = 0; void (*logger)(void *, int, const char *) = nullptr; @@ -745,18 +743,18 @@ struct projCtx_t { int pipelineInitRecursiongCounter = 0; // to avoid potential infinite recursion in pipeline.cpp - projCtx_t() = default; - projCtx_t(const projCtx_t&); - ~projCtx_t(); + pj_ctx() = default; + pj_ctx(const pj_ctx&); + ~pj_ctx(); - projCtx_t& operator= (const projCtx_t&) = delete; + pj_ctx& operator= (const pj_ctx&) = delete; projCppContext* get_cpp_context(); void safeAutoCloseDbIfNeeded(); void set_search_paths(const std::vector& search_paths_in); void set_ca_bundle_path(const std::string& ca_bundle_path_in); - static projCtx_t createDefault(); + static pj_ctx createDefault(); }; /* Generate pj_list external or make list from include file */ @@ -804,41 +802,41 @@ PJ *pj_projection_specific_setup_##name (PJ *P) /* procedure prototypes */ double PROJ_DLL dmstor(const char *, char **); -double dmstor_ctx(projCtx_t *ctx, const char *, char **); +double dmstor_ctx(PJ_CONTEXT *ctx, const char *, char **); void PROJ_DLL set_rtodms(int, int); char PROJ_DLL *rtodms(char *, double, int, int); double PROJ_DLL adjlon(double); -double aacos(projCtx_t *,double); -double aasin(projCtx_t *,double); +double aacos(PJ_CONTEXT *,double); +double aasin(PJ_CONTEXT *,double); double asqrt(double); double aatan2(double, double); -PROJVALUE PROJ_DLL pj_param(projCtx_t *ctx, paralist *, const char *); +PROJVALUE PROJ_DLL pj_param(PJ_CONTEXT *ctx, paralist *, const char *); paralist PROJ_DLL *pj_param_exists (paralist *list, const char *parameter); paralist PROJ_DLL *pj_mkparam(const char *); paralist *pj_mkparam_ws (const char *str, const char **next_str); -int PROJ_DLL pj_ell_set(projCtx_t *ctx, paralist *, double *, double *); -int pj_datum_set(projCtx_t *,paralist *, PJ *); +int PROJ_DLL pj_ell_set(PJ_CONTEXT *ctx, paralist *, double *, double *); +int pj_datum_set(PJ_CONTEXT *,paralist *, PJ *); int pj_angular_units_set(paralist *, PJ *); paralist *pj_clone_paralist( const paralist* ); paralist *pj_search_initcache( const char *filekey ); void pj_insert_initcache( const char *filekey, const paralist *list); -paralist *pj_expand_init(projCtx_t *ctx, paralist *init); +paralist *pj_expand_init(PJ_CONTEXT *ctx, paralist *init); -void *pj_dealloc_params (projCtx_t *ctx, paralist *start, int errlev); +void *pj_dealloc_params (PJ_CONTEXT *ctx, paralist *start, int errlev); double *pj_enfn(double); double pj_mlfn(double, double, double, const double *); -double pj_inv_mlfn(projCtx_t *, double, double, const double *); +double pj_inv_mlfn(PJ_CONTEXT *, double, double, const double *); double pj_qsfn(double, double, double); double pj_tsfn(double, double, double); double pj_msfn(double, double, double); -double PROJ_DLL pj_phi2(projCtx_t *, const double, const double); -double pj_sinhpsi2tanphi(projCtx_t *, const double, const double); +double PROJ_DLL pj_phi2(PJ_CONTEXT *, const double, const double); +double pj_sinhpsi2tanphi(PJ_CONTEXT *, const double, const double); double pj_qsfn_(double, PJ *); double *pj_authset(double); double pj_authlat(double, double *); @@ -851,10 +849,10 @@ int pj_factors(PJ_LP, const PJ *, double, struct FACTORS *); void *proj_mdist_ini(double); double proj_mdist(double, double, double, const void *); -double proj_inv_mdist(projCtx_t *ctx, double, const void *); +double proj_inv_mdist(PJ_CONTEXT *ctx, double, const void *); void *pj_gauss_ini(double, double, double *,double *); -PJ_LP pj_gauss(projCtx_t *, PJ_LP, const void *); -PJ_LP pj_inv_gauss(projCtx_t *, PJ_LP, const void *); +PJ_LP pj_gauss(PJ_CONTEXT *, PJ_LP, const void *); +PJ_LP pj_inv_gauss(PJ_CONTEXT *, PJ_LP, const void *); struct PJ_DATUMS PROJ_DLL *pj_get_datums_ref( void ); @@ -865,7 +863,7 @@ double PROJ_DLL pj_atof( const char* nptr ); double pj_strtod( const char *nptr, char **endptr ); void pj_freeup_plain (PJ *P); -PJ* pj_init_ctx_with_allow_init_epsg( projCtx_t *ctx, int argc, char **argv, int allow_init_epsg ); +PJ* pj_init_ctx_with_allow_init_epsg( PJ_CONTEXT *ctx, int argc, char **argv, int allow_init_epsg ); std::string PROJ_DLL pj_add_type_crs_if_needed(const std::string& str); std::string pj_double_quote_string_param_if_needed(const std::string& str); @@ -921,10 +919,6 @@ PJ_LP pj_generic_inverse_2d(PJ_XY xy, PJ *P, PJ_LP lpInitial); #define DEG_TO_RAD .017453292519943296 -#if defined(PROJ_H) -#define PROJ_API_H_NOT_INVOKED_AS_PRIMARY_API -#endif - extern char const PROJ_DLL pj_release[]; /* global release id string */ @@ -938,33 +932,12 @@ PROJ_DLL extern int pj_errno; /* global error return code */ #define PJ_LOG_DEBUG_MINOR 3 #endif -#ifdef PROJ_API_H_NOT_INVOKED_AS_PRIMARY_API - /* These make the function declarations below conform with classic proj */ - typedef PJ *projPJ; /* projPJ is a pointer to PJ */ - typedef struct projCtx_t *projCtx; /* projCtx is a pointer to projCtx_t */ -# define projXY PJ_XY -# define projLP PJ_LP -# define projXYZ PJ_XYZ -# define projLPZ PJ_LPZ - -#else - /* i.e. proj_api invoked as primary API */ - typedef struct { double u, v; } projUV; - typedef struct { double u, v, w; } projUVW; - typedef void *projPJ; - #define projXY projUV - #define projLP projUV - #define projXYZ projUVW - #define projLPZ projUVW - typedef void *projCtx; -#endif - /* If included *after* proj.h finishes, we have alternative names */ /* file reading api, like stdio */ typedef int *PAFile; typedef struct projFileAPI_t { - PAFile (*FOpen)(projCtx ctx, const char *filename, const char *access); + PAFile (*FOpen)(PJ_CONTEXT * ctx, const char *filename, const char *access); size_t (*FRead)(void *buffer, size_t size, size_t nmemb, PAFile file); int (*FSeek)(PAFile file, long offset, int whence); long (*FTell)(PAFile file); @@ -975,34 +948,34 @@ typedef struct projFileAPI_t { /* procedure prototypes */ -projCtx PROJ_DLL pj_get_default_ctx(void); -projCtx PROJ_DLL pj_get_ctx( projPJ ); +PJ_CONTEXT PROJ_DLL *pj_get_default_ctx(void); +PJ_CONTEXT PROJ_DLL *pj_get_ctx( PJ *); -projXY PROJ_DLL pj_fwd(projLP, projPJ); -projLP PROJ_DLL pj_inv(projXY, projPJ); +PJ_XY PROJ_DLL pj_fwd(PJ_LP, PJ *); +PJ_LP PROJ_DLL pj_inv(PJ_XY, PJ *); -projXYZ PROJ_DLL pj_fwd3d(projLPZ, projPJ); -projLPZ PROJ_DLL pj_inv3d(projXYZ, projPJ); +PJ_XYZ PROJ_DLL pj_fwd3d(PJ_LPZ, PJ *); +PJ_LPZ PROJ_DLL pj_inv3d(PJ_XYZ, PJ *); -int PROJ_DLL pj_apply_gridshift( projCtx, const char *, int, +int PROJ_DLL pj_apply_gridshift( PJ_CONTEXT *, const char *, int, long point_count, int point_offset, double *x, double *y, double *z ); void PROJ_DLL pj_clear_initcache(void); -int PROJ_DLL pj_is_latlong(projPJ); -int PROJ_DLL pj_is_geocent(projPJ); -void PROJ_DLL pj_get_spheroid_defn(projPJ defn, double *major_axis, double *eccentricity_squared); -void PROJ_DLL pj_pr_list(projPJ); -void PROJ_DLL pj_free(projPJ); +int PROJ_DLL pj_is_latlong(PJ *); +int PROJ_DLL pj_is_geocent(PJ *); +void PROJ_DLL pj_get_spheroid_defn(PJ *defn, double *major_axis, double *eccentricity_squared); +void PROJ_DLL pj_pr_list(PJ *); +void PROJ_DLL pj_free(PJ *); void PROJ_DLL pj_set_finder( const char *(*)(const char *) ); void PROJ_DLL pj_set_searchpath ( int count, const char **path ); -projPJ PROJ_DLL pj_init(int, char **); -projPJ PROJ_DLL pj_init_plus(const char *); -projPJ PROJ_DLL pj_init_ctx( projCtx, int, char ** ); -projPJ PROJ_DLL pj_init_plus_ctx( projCtx, const char * ); -char PROJ_DLL *pj_get_def(projPJ, int); -projPJ PROJ_DLL pj_latlong_from_proj( projPJ ); -int PROJ_DLL pj_has_inverse(projPJ); +PJ PROJ_DLL *pj_init(int, char **); +PJ PROJ_DLL *pj_init_plus(const char *); +PJ PROJ_DLL *pj_init_ctx( PJ_CONTEXT *, int, char ** ); +PJ PROJ_DLL *pj_init_plus_ctx( PJ_CONTEXT *, const char * ); +char PROJ_DLL *pj_get_def(PJ *, int); +PJ PROJ_DLL *pj_latlong_from_proj( PJ *); +int PROJ_DLL pj_has_inverse(PJ *); void PROJ_DLL *pj_malloc(size_t); @@ -1017,33 +990,33 @@ void PROJ_DLL pj_acquire_lock(void); void PROJ_DLL pj_release_lock(void); void PROJ_DLL pj_cleanup_lock(void); -void PROJ_DLL pj_set_ctx( projPJ, projCtx ); -projCtx PROJ_DLL pj_ctx_alloc(void); -void PROJ_DLL pj_ctx_free( projCtx ); -int PROJ_DLL pj_ctx_get_errno( projCtx ); -void PROJ_DLL pj_ctx_set_errno( projCtx, int ); -void PROJ_DLL pj_ctx_set_debug( projCtx, int ); -void PROJ_DLL pj_ctx_set_logger( projCtx, void (*)(void *, int, const char *) ); -void PROJ_DLL pj_ctx_set_app_data( projCtx, void * ); -void PROJ_DLL *pj_ctx_get_app_data( projCtx ); -void PROJ_DLL pj_ctx_set_fileapi( projCtx, projFileAPI *); -projFileAPI PROJ_DLL *pj_ctx_get_fileapi( projCtx ); - -void PROJ_DLL pj_log( projCtx ctx, int level, const char *fmt, ... ); +void PROJ_DLL pj_set_ctx( PJ *, PJ_CONTEXT * ); +PJ_CONTEXT PROJ_DLL *pj_ctx_alloc(void); +void PROJ_DLL pj_ctx_free( PJ_CONTEXT * ); +int PROJ_DLL pj_ctx_get_errno( PJ_CONTEXT * ); +void PROJ_DLL pj_ctx_set_errno( PJ_CONTEXT *, int ); +void PROJ_DLL pj_ctx_set_debug( PJ_CONTEXT *, int ); +void PROJ_DLL pj_ctx_set_logger( PJ_CONTEXT *, void (*)(void *, int, const char *) ); +void PROJ_DLL pj_ctx_set_app_data( PJ_CONTEXT *, void * ); +void PROJ_DLL *pj_ctx_get_app_data( PJ_CONTEXT * ); +void PROJ_DLL pj_ctx_set_fileapi( PJ_CONTEXT *, projFileAPI *); +projFileAPI PROJ_DLL *pj_ctx_get_fileapi( PJ_CONTEXT * ); + +void PROJ_DLL pj_log( PJ_CONTEXT * ctx, int level, const char *fmt, ... ); void PROJ_DLL pj_stderr_logger( void *, int, const char * ); /* file api */ projFileAPI PROJ_DLL *pj_get_default_fileapi(void); -PAFile PROJ_DLL pj_ctx_fopen(projCtx ctx, const char *filename, const char *access); -size_t PROJ_DLL pj_ctx_fread(projCtx ctx, void *buffer, size_t size, size_t nmemb, PAFile file); -int PROJ_DLL pj_ctx_fseek(projCtx ctx, PAFile file, long offset, int whence); -long PROJ_DLL pj_ctx_ftell(projCtx ctx, PAFile file); -void PROJ_DLL pj_ctx_fclose(projCtx ctx, PAFile file); -char PROJ_DLL *pj_ctx_fgets(projCtx ctx, char *line, int size, PAFile file); +PAFile PROJ_DLL pj_ctx_fopen(PJ_CONTEXT * ctx, const char *filename, const char *access); +size_t PROJ_DLL pj_ctx_fread(PJ_CONTEXT * ctx, void *buffer, size_t size, size_t nmemb, PAFile file); +int PROJ_DLL pj_ctx_fseek(PJ_CONTEXT * ctx, PAFile file, long offset, int whence); +long PROJ_DLL pj_ctx_ftell(PJ_CONTEXT * ctx, PAFile file); +void PROJ_DLL pj_ctx_fclose(PJ_CONTEXT * ctx, PAFile file); +char PROJ_DLL *pj_ctx_fgets(PJ_CONTEXT * ctx, char *line, int size, PAFile file); -PAFile PROJ_DLL pj_open_lib(projCtx, const char *, const char *); -int PROJ_DLL pj_find_file(projCtx ctx, const char *short_filename, +PAFile PROJ_DLL pj_open_lib(PJ_CONTEXT *, const char *, const char *); +int PROJ_DLL pj_find_file(PJ_CONTEXT * ctx, const char *short_filename, char* out_full_filename, size_t out_full_filename_size); diff --git a/src/proj_mdist.cpp b/src/proj_mdist.cpp index c515f6c5..086521b7 100644 --- a/src/proj_mdist.cpp +++ b/src/proj_mdist.cpp @@ -107,7 +107,7 @@ proj_mdist(double phi, double sphi, double cphi, const void *data) { return(D + sc * sum); } double -proj_inv_mdist(projCtx ctx, double dist, const void *data) { +proj_inv_mdist(PJ_CONTEXT *ctx, double dist, const void *data) { const struct MDIST *b = (const struct MDIST *)data; double s, t, phi, k; int i; diff --git a/src/projections/chamb.cpp b/src/projections/chamb.cpp index 36609e79..1b926b8a 100644 --- a/src/projections/chamb.cpp +++ b/src/projections/chamb.cpp @@ -29,7 +29,7 @@ PROJ_HEAD(chamb, "Chamberlin Trimetric") "\n\tMisc Sph, no inv" #define TOL 1e-9 /* distance and azimuth from point 1 to point 2 */ -static VECT vect(projCtx ctx, double dphi, double c1, double s1, double c2, double s2, double dlam) { +static VECT vect(PJ_CONTEXT *ctx, double dphi, double c1, double s1, double c2, double s2, double dlam) { VECT v; double cdl, dp, dl; @@ -49,7 +49,7 @@ static VECT vect(projCtx ctx, double dphi, double c1, double s1, double c2, doub } /* law of cosines */ -static double lc(projCtx ctx, double b,double c,double a) { +static double lc(PJ_CONTEXT *ctx, double b,double c,double a) { return aacos(ctx, .5 * (b * b + c * c - a * a) / (b * c)); } diff --git a/src/tests/multistresstest.cpp b/src/tests/multistresstest.cpp index 51720fbd..674f5ded 100644 --- a/src/tests/multistresstest.cpp +++ b/src/tests/multistresstest.cpp @@ -172,7 +172,7 @@ static TestItem test_list[] = { static volatile int active_thread_count = 0; -static projPJ custom_pj_init_plus_ctx(projCtx ctx, const char* def) +static PJ *custom_pj_init_plus_ctx(PJ_CONTEXT *ctx, const char* def) { return pj_init_plus_ctx(ctx, def); } @@ -191,11 +191,12 @@ static void TestThread() /* -------------------------------------------------------------------- */ /* Initialize coordinate system definitions. */ /* -------------------------------------------------------------------- */ - projPJ *src_pj_list, *dst_pj_list; - projCtx ctx = pj_ctx_alloc(); + PJ **src_pj_list; + PJ **dst_pj_list; + PJ_CONTEXT *ctx = pj_ctx_alloc(); - src_pj_list = (projPJ *) calloc(test_count,sizeof(projPJ)); - dst_pj_list = (projPJ *) calloc(test_count,sizeof(projPJ)); + src_pj_list = (PJ **) calloc(test_count,sizeof(PJ)); + dst_pj_list = (PJ **) calloc(test_count,sizeof(PJ)); if(!reinit_every_iteration) { @@ -345,7 +346,8 @@ static int do_main(void) { TestItem *test = test_list + i; - projPJ src_pj, dst_pj; + PJ *src_pj; + PJ *dst_pj; src_pj = custom_pj_init_plus_ctx( pj_get_default_ctx(), test->src_def ); dst_pj = custom_pj_init_plus_ctx( pj_get_default_ctx(), test->dst_def ); diff --git a/src/tests/test228.cpp b/src/tests/test228.cpp index bffb8e79..ae2eb9cc 100644 --- a/src/tests/test228.cpp +++ b/src/tests/test228.cpp @@ -50,9 +50,9 @@ static volatile int started = 0; static void* thread_main(void* unused) { - projCtx p_proj_ctxt; - projPJ p_WGS84_proj; - projPJ p_OSGB36_proj; + PJ_CONTEXT *p_proj_ctxt; + PJ *p_WGS84_proj; + PJ * p_OSGB36_proj; (void)unused; __sync_add_and_fetch(&started, 1); diff --git a/src/utils.cpp b/src/utils.cpp index 9cb13f44..d3ec7e35 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -172,7 +172,7 @@ PJ *pj_latlong_from_proj( PJ *pj_in ) /* b = a * sqrt(1 - es) */ /************************************************************************/ -void pj_get_spheroid_defn(projPJ defn, double *major_axis, double *eccentricity_squared) +void pj_get_spheroid_defn(PJ * defn, double *major_axis, double *eccentricity_squared) { if ( major_axis ) *major_axis = defn->a; diff --git a/test/fuzzers/standard_fuzzer.cpp b/test/fuzzers/standard_fuzzer.cpp index ab30200b..d54caa79 100644 --- a/test/fuzzers/standard_fuzzer.cpp +++ b/test/fuzzers/standard_fuzzer.cpp @@ -94,13 +94,13 @@ int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) } second_newline[0] = 0; char* third_line = second_newline + 1; - projPJ pj_src = pj_init_plus(first_line); + PJ *pj_src = pj_init_plus(first_line); if( !pj_src ) { free(buf_dup); return 0; } - projPJ pj_dst = pj_init_plus(second_line); + PJ *pj_dst = pj_init_plus(second_line); if( !pj_dst ) { free(buf_dup); diff --git a/test/unit/pj_phi2_test.cpp b/test/unit/pj_phi2_test.cpp index b4e6b68f..7ccbb01c 100644 --- a/test/unit/pj_phi2_test.cpp +++ b/test/unit/pj_phi2_test.cpp @@ -37,7 +37,7 @@ namespace { TEST(PjPhi2Test, Basic) { - projCtx ctx = pj_get_default_ctx(); + PJ_CONTEXT *ctx = pj_get_default_ctx(); // Expectation is that only sane values of e (and nan is here reckoned to // be sane) are passed to pj_phi2. Thus the return value with other values -- cgit v1.2.3 From 70c4c417313c5416fda1cac2f9ed48a201d1e4aa Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Mon, 16 Nov 2020 13:03:48 +0100 Subject: Convert multistresstest to new API --- src/tests/multistresstest.cpp | 170 ++++++++++++++++++------------------------ 1 file changed, 73 insertions(+), 97 deletions(-) diff --git a/src/tests/multistresstest.cpp b/src/tests/multistresstest.cpp index 674f5ded..6b7099ce 100644 --- a/src/tests/multistresstest.cpp +++ b/src/tests/multistresstest.cpp @@ -30,7 +30,7 @@ #include #include -#include "proj_internal.h" +#include "proj.h" #ifdef _WIN32 #include @@ -47,8 +47,8 @@ typedef struct { const char *src_def; const char *dst_def; - double src_x, src_y, src_z; - double dst_x, dst_y, dst_z; + PJ_COORD src; + PJ_COORD dst; int dst_error; int skip; @@ -58,125 +58,120 @@ static TestItem test_list[] = { { "+proj=utm +zone=11 +datum=WGS84", "+proj=latlong +datum=WGS84", - 150000.0, 3000000.0, 0.0, - 0.0, 0.0, 0.0, + proj_coord(150000.0, 3000000.0, 0.0, 0), + proj_coord(0.0, 0.0, 0.0, 0.0), 0, 0 }, { "+proj=utm +zone=11 +datum=NAD83", "+proj=latlong +datum=NAD27", - 150000.0, 3000000.0, 0.0, - 0.0, 0.0, 0.0, + proj_coord(150000.0, 3000000.0, 0.0, 0.0), + proj_coord(0.0, 0.0, 0.0, 0.0), 0, 0 }, { "+proj=utm +zone=11 +datum=NAD83", "+proj=latlong +nadgrids=@null +ellps=WGS84", - 150000.0, 3000000.0, 0.0, - 0.0, 0.0, 0.0, + proj_coord(150000.0, 3000000.0, 0.0, 0.0), + proj_coord(0.0, 0.0, 0.0, 0.0), 0, 0 }, { "+proj=utm +zone=11 +datum=WGS84", "+proj=merc +datum=potsdam", - 150000.0, 3000000.0, 0.0, - 0.0, 0.0, 0.0, + proj_coord(150000.0, 3000000.0, 0.0, 0.0), + proj_coord(0.0, 0.0, 0.0, 0.0), 0, 0 }, { "+proj=latlong +nadgrids=nzgd2kgrid0005.gsb", "+proj=latlong +datum=WGS84", - 150000.0, 3000000.0, 0.0, - 0.0, 0.0, 0.0, + proj_coord(150000.0, 3000000.0, 0.0, 0.0), + proj_coord(0.0, 0.0, 0.0, 0.0), 0, 0 }, { "+proj=latlong +nadgrids=nzgd2kgrid0005.gsb", "+proj=latlong +datum=WGS84", - 170 * DEG_TO_RAD, -40 * DEG_TO_RAD, 0.0, - 0.0, 0.0, 0.0, + proj_coord(170, -40, 0.0, 0.0), + proj_coord(0.0, 0.0, 0.0, 0.0), 0, 0 }, { "+proj=latlong +ellps=GRS80 +towgs84=2,3,5", "+proj=latlong +ellps=intl +towgs84=10,12,15", - 170 * DEG_TO_RAD, -40 * DEG_TO_RAD, 0.0, - 0.0, 0.0, 0.0, + proj_coord(170, -40, 0.0, 0.0), + proj_coord(0.0, 0.0, 0.0, 0.0), 0, 0 }, { "+proj=eqc +lat_0=11 +lon_0=12 +x_0=100000 +y_0=200000 +datum=WGS84 ", "+proj=stere +lat_0=11 +lon_0=12 +x_0=100000 +y_0=200000 +datum=WGS84 ", - 150000.0, 250000.0, 0.0, - 0.0, 0.0, 0.0, + proj_coord(150000.0, 250000.0, 0.0, 0.0), + proj_coord(0.0, 0.0, 0.0, 0.0), 0, 0 }, { "+proj=cea +lat_ts=11 +lon_0=12 +y_0=200000 +datum=WGS84 ", "+proj=merc +lon_0=12 +k=0.999 +x_0=100000 +y_0=200000 +datum=WGS84 ", - 150000.0, 250000.0, 0.0, - 0.0, 0.0, 0.0, + proj_coord(150000.0, 250000.0, 0.0, 0.0), + proj_coord(0.0, 0.0, 0.0, 0.0), 0, 0 }, { "+proj=bonne +lat_1=11 +lon_0=12 +y_0=200000 +datum=WGS84 ", "+proj=cass +lat_0=11 +lon_0=12 +x_0=100000 +y_0=200000 +datum=WGS84 ", - 150000.0, 250000.0, 0.0, - 0.0, 0.0, 0.0, + proj_coord(150000.0, 250000.0, 0.0, 0.0), + proj_coord(0.0, 0.0, 0.0, 0.0), 0, 0 }, { "+proj=nzmg +lat_0=11 +lon_0=12 +y_0=200000 +datum=WGS84 ", "+proj=gnom +lat_0=11 +lon_0=12 +x_0=100000 +y_0=200000 +datum=WGS84 ", - 150000.0, 250000.0, 0.0, - 0.0, 0.0, 0.0, + proj_coord(150000.0, 250000.0, 0.0, 0.0), + proj_coord(0.0, 0.0, 0.0, 0.0), 0, 0 }, { "+proj=ortho +lat_0=11 +lon_0=12 +y_0=200000 +datum=WGS84 ", "+proj=laea +lat_0=11 +lon_0=12 +x_0=100000 +y_0=200000 +datum=WGS84 ", - 150000.0, 250000.0, 0.0, - 0.0, 0.0, 0.0, + proj_coord(150000.0, 250000.0, 0.0, 0.0), + proj_coord(0.0, 0.0, 0.0, 0.0), 0, 0 }, { "+proj=aeqd +lat_0=11 +lon_0=12 +y_0=200000 +datum=WGS84 ", "+proj=eqdc +lat_1=20 +lat_2=5 +lat_0=11 +lon_0=12 +x_0=100000 +y_0=200000 +datum=WGS84 ", - 150000.0, 250000.0, 0.0, - 0.0, 0.0, 0.0, + proj_coord(150000.0, 250000.0, 0.0, 0.0), + proj_coord(0.0, 0.0, 0.0, 0.0), 0, 0 }, { "+proj=mill +lat_0=11 +lon_0=12 +y_0=200000 +datum=WGS84 ", "+proj=moll +lon_0=12 +x_0=100000 +y_0=200000 +datum=WGS84 ", - 150000.0, 250000.0, 0.0, - 0.0, 0.0, 0.0, + proj_coord(150000.0, 250000.0, 0.0, 0.0), + proj_coord(0.0, 0.0, 0.0, 0.0), 0, 0 }, { "+init=epsg:3309", "+init=epsg:4326", - 150000.0, 30000.0, 0.0, - 0.0, 0.0, 0.0, + proj_coord(150000.0, 30000.0, 0.0, 0.0), + proj_coord(0.0, 0.0, 0.0, 0.0), 0, 0 }, { /* Bad projection (invalid ellipsoid parameter +R_A=0) */ "+proj=utm +zone=11 +datum=WGS84", "+proj=merc +datum=potsdam +R_A=0", - 150000.0, 3000000.0, 0.0, - 0.0, 0.0, 0.0, + proj_coord(150000.0, 3000000.0, 0.0, 0.0), + proj_coord(0.0, 0.0, 0.0, 0.0), 0, 0 } }; static volatile int active_thread_count = 0; -static PJ *custom_pj_init_plus_ctx(PJ_CONTEXT *ctx, const char* def) -{ - return pj_init_plus_ctx(ctx, def); -} - /************************************************************************/ /* TestThread() */ /************************************************************************/ @@ -191,12 +186,10 @@ static void TestThread() /* -------------------------------------------------------------------- */ /* Initialize coordinate system definitions. */ /* -------------------------------------------------------------------- */ - PJ **src_pj_list; - PJ **dst_pj_list; - PJ_CONTEXT *ctx = pj_ctx_alloc(); + PJ **pj_list; + PJ_CONTEXT *ctx = proj_context_create(); - src_pj_list = (PJ **) calloc(test_count,sizeof(PJ)); - dst_pj_list = (PJ **) calloc(test_count,sizeof(PJ)); + pj_list = (PJ **) calloc(test_count,sizeof(PJ*)); if(!reinit_every_iteration) { @@ -204,8 +197,9 @@ static void TestThread() { TestItem *test = test_list + i; - src_pj_list[i] = custom_pj_init_plus_ctx( ctx, test->src_def ); - dst_pj_list[i] = custom_pj_init_plus_ctx( ctx, test->dst_def ); + pj_list[i] = proj_create_crs_to_crs( + ctx, test->src_def, test->dst_def, nullptr + ); } } @@ -218,28 +212,23 @@ static void TestThread() for( i = 0; i < test_count; i++ ) { TestItem *test = test_list + i; - double x, y, z; - int error; - - x = test->src_x; - y = test->src_y; - z = test->src_z; if( reinit_every_iteration ) { - src_pj_list[i] = custom_pj_init_plus_ctx( ctx, test->src_def ); - dst_pj_list[i] = custom_pj_init_plus_ctx( ctx, test->dst_def ); + proj_context_use_proj4_init_rules(nullptr, true); + pj_list[i] = proj_create_crs_to_crs( + ctx, test->src_def, test->dst_def, nullptr + ); { - int skipTest = (src_pj_list[i] == nullptr || dst_pj_list[i] == nullptr); + int skipTest = (pj_list[i] == nullptr); if ( skipTest != test->skip ) fprintf( stderr, "Threaded projection initialization does not match unthreaded initialization\n" ); if (skipTest) { - pj_free( src_pj_list[i] ); - pj_free( dst_pj_list[i] ); + proj_destroy( pj_list[i] ); continue; } } @@ -248,31 +237,32 @@ static void TestThread() if ( test->skip ) continue; - error = pj_transform( src_pj_list[i], dst_pj_list[i], 1, 0, - &x, &y, &z ); + PJ_COORD out = proj_trans(pj_list[i], PJ_FWD, test->src); + int error = proj_errno(pj_list[i]); if( error != test->dst_error ) { fprintf( stderr, "Got error %d, expected %d\n", error, test->dst_error ); } + proj_errno_reset(pj_list[i]); - if( x != test->dst_x || y != test->dst_y || z != test->dst_z ) + if ( out.xyz.x != test->dst.xyz.x || out.xyz.y != test->dst.xyz.y || out.xyz.z != test->dst.xyz.z) + //if( x != test->dst_x || y != test->dst_y || z != test->dst_z ) { fprintf( stderr, "Got %.15g,%.15g,%.15g\n" "Expected %.15g,%.15g,%.15g\n" "Diff %.15g,%.15g,%.15g\n", - x, y, z, - test->dst_x, test->dst_y, test->dst_z, - x-test->dst_x, y-test->dst_y, z-test->dst_z); + out.xyz.x, out.xyz.y, out.xyz.z, + test->dst.xyz.x, test->dst.xyz.y, test->dst.xyz.z, + out.xyz.x-test->dst.xyz.x, out.xyz.y-test->dst.xyz.y, out.xyz.z-test->dst.xyz.z); } if( reinit_every_iteration ) { - pj_free( src_pj_list[i] ); - pj_free( dst_pj_list[i] ); + proj_destroy( pj_list[i] ); } } } @@ -284,15 +274,13 @@ static void TestThread() { for( i = 0; i < test_count; i++ ) { - pj_free( src_pj_list[i] ); - pj_free( dst_pj_list[i] ); + proj_destroy( pj_list[i] ); } } - free( src_pj_list ); - free( dst_pj_list ); + free( pj_list ); - pj_ctx_free( ctx ); + proj_context_destroy( ctx ); printf( "%d iterations of the %d tests complete in thread X\n", repeat_count, test_count ); @@ -346,44 +334,32 @@ static int do_main(void) { TestItem *test = test_list + i; - PJ *src_pj; - PJ *dst_pj; - - src_pj = custom_pj_init_plus_ctx( pj_get_default_ctx(), test->src_def ); - dst_pj = custom_pj_init_plus_ctx( pj_get_default_ctx(), test->dst_def ); + PJ *pj; - if( src_pj == nullptr ) - { - printf( "Unable to translate:\n%s\n", test->src_def ); - test->skip = 1; - pj_free (dst_pj); - continue; - } + proj_context_use_proj4_init_rules(nullptr, true); + pj = proj_create_crs_to_crs( + nullptr, test->src_def, test->dst_def, nullptr + ); - if( dst_pj == nullptr ) + if( pj == nullptr ) { - printf( "Unable to translate:\n%s\n", test->dst_def ); + printf( "Unable to translate:\n%s\n or\n%s\n", test->src_def, test->dst_def ); test->skip = 1; - pj_free (src_pj); + proj_destroy(pj); continue; } - test->dst_x = test->src_x; - test->dst_y = test->src_y; - test->dst_z = test->src_z; - test->dst_error = pj_transform( src_pj, dst_pj, 1, 0, - &(test->dst_x), - &(test->dst_y), - &(test->dst_z) ); + PJ_COORD out = proj_trans(pj, PJ_FWD, test->src); + test->dst = out; + test->dst_error = proj_errno(pj); - pj_free( src_pj ); - pj_free( dst_pj ); + proj_destroy(pj); test->skip = 0; -#ifdef notdef - printf( "Test %d - output %.14g,%.14g,%g\n", i, test->dst_x, test->dst_y, test->dst_z ); +#ifdef nodef + printf( "Test %d - output %.14g,%.14g,%g\n", i, test->dst.xyz.x, test->dst.xyz.y, test->dst.xyz.z ); #endif } -- cgit v1.2.3 From 7f79fe7325a74d2a9eac93d7081a107ae54bb877 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Mon, 16 Nov 2020 21:10:45 +0100 Subject: Remove legacy file API --- src/Makefile.am | 1 - src/ctx.cpp | 2 - src/fileapi.cpp | 240 ---------------------------------------------------- src/filemanager.cpp | 95 --------------------- src/lib_proj.cmake | 1 - src/proj_internal.h | 27 ------ 6 files changed, 366 deletions(-) delete mode 100644 src/fileapi.cpp diff --git a/src/Makefile.am b/src/Makefile.am index edfd05ef..2c175e42 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -216,7 +216,6 @@ libproj_la_SOURCES = \ qsfn.cpp strerrno.cpp \ tsfn.cpp units.cpp ctx.cpp log.cpp zpoly1.cpp rtodms.cpp \ release.cpp gauss.cpp \ - fileapi.cpp \ generic_inverse.cpp \ quadtree.hpp \ \ diff --git a/src/ctx.cpp b/src/ctx.cpp index 24d3773b..d3eee39f 100644 --- a/src/ctx.cpp +++ b/src/ctx.cpp @@ -100,7 +100,6 @@ pj_ctx pj_ctx::createDefault() pj_ctx ctx; ctx.debug_level = PJ_LOG_NONE; ctx.logger = pj_stderr_logger; - ctx.fileapi_legacy = pj_get_default_fileapi(); NS_PROJ::FileManager::fillDefaultNetworkInterface(&ctx); if( getenv("PROJ_DEBUG") != nullptr ) @@ -170,7 +169,6 @@ pj_ctx::pj_ctx(const pj_ctx& other) : debug_level(other.debug_level), logger(other.logger), logger_app_data(other.logger_app_data), - fileapi_legacy(other.fileapi_legacy), cpp_context(other.cpp_context ? other.cpp_context->clone(this) : nullptr), use_proj4_init_rules(other.use_proj4_init_rules), epsg_file_exists(other.epsg_file_exists), diff --git a/src/fileapi.cpp b/src/fileapi.cpp deleted file mode 100644 index 0af83926..00000000 --- a/src/fileapi.cpp +++ /dev/null @@ -1,240 +0,0 @@ -/****************************************************************************** - * Project: PROJ.4 - * Purpose: Implementation of the pj_ctx_* file api, and the default stdio - * based implementation. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 2013, Frank Warmerdam - * - * 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 -#include -#include -#include -#include - -#include "proj.h" -#include "proj_internal.h" -#include "filemanager.hpp" - -static PAFile stdio_fopen(PJ_CONTEXT *ctx, const char *filename, - const char *access); -static size_t stdio_fread(void *buffer, size_t size, size_t nmemb, - PAFile file); -static int stdio_fseek(PAFile file, long offset, int whence); -static long stdio_ftell(PAFile file); -static void stdio_fclose(PAFile file); - -static projFileAPI default_fileapi = { - stdio_fopen, - stdio_fread, - stdio_fseek, - stdio_ftell, - stdio_fclose -}; - -typedef struct { - PJ_CONTEXT *ctx; - FILE *fp; -} stdio_pafile; - -/************************************************************************/ -/* pj_get_default_fileapi() */ -/************************************************************************/ - -projFileAPI *pj_get_default_fileapi(void) -{ - return &default_fileapi; -} - -/************************************************************************/ -/* stdio_fopen() */ -/************************************************************************/ - -static PAFile stdio_fopen(PJ_CONTEXT *ctx, const char *filename, - const char *access) -{ - stdio_pafile *pafile; - FILE *fp; - - fp = fopen(filename, access); - if (fp == nullptr) - { - return nullptr; - } - - pafile = (stdio_pafile *) malloc(sizeof(stdio_pafile)); - if (!pafile) - { - pj_ctx_set_errno(ctx, ENOMEM); - fclose(fp); - return nullptr; - } - - pafile->fp = fp; - pafile->ctx = ctx; - return (PAFile) pafile; -} - -/************************************************************************/ -/* stdio_fread() */ -/************************************************************************/ - -static size_t stdio_fread(void *buffer, size_t size, size_t nmemb, - PAFile file) -{ - stdio_pafile *pafile = (stdio_pafile *) file; - return fread(buffer, size, nmemb, pafile->fp); -} - -/************************************************************************/ -/* stdio_fseek() */ -/************************************************************************/ -static int stdio_fseek(PAFile file, long offset, int whence) -{ - stdio_pafile *pafile = (stdio_pafile *) file; - return fseek(pafile->fp, offset, whence); -} - -/************************************************************************/ -/* stdio_ftell() */ -/************************************************************************/ -static long stdio_ftell(PAFile file) -{ - stdio_pafile *pafile = (stdio_pafile *) file; - return ftell(pafile->fp); -} - -/************************************************************************/ -/* stdio_fclose() */ -/************************************************************************/ -static void stdio_fclose(PAFile file) -{ - stdio_pafile *pafile = (stdio_pafile *) file; - fclose(pafile->fp); - free(pafile); -} - -/************************************************************************/ -/* pj_ctx_fopen() */ -/* */ -/* Open a file using the provided file io hooks. */ -/************************************************************************/ - -PAFile pj_ctx_fopen(PJ_CONTEXT *ctx, const char *filename, const char *access) -{ - return ctx->fileapi_legacy->FOpen(ctx, filename, access); -} - -/************************************************************************/ -/* pj_ctx_fread() */ -/************************************************************************/ -size_t pj_ctx_fread(PJ_CONTEXT *ctx, void *buffer, size_t size, size_t nmemb, PAFile file) -{ - return ctx->fileapi_legacy->FRead(buffer, size, nmemb, file); -} - -/************************************************************************/ -/* pj_ctx_fseek() */ -/************************************************************************/ -int pj_ctx_fseek(PJ_CONTEXT *ctx, PAFile file, long offset, int whence) -{ - return ctx->fileapi_legacy->FSeek(file, offset, whence); -} - -/************************************************************************/ -/* pj_ctx_ftell() */ -/************************************************************************/ -long pj_ctx_ftell(PJ_CONTEXT *ctx, PAFile file) -{ - return ctx->fileapi_legacy->FTell(file); -} - -/************************************************************************/ -/* pj_ctx_fclose() */ -/************************************************************************/ -void pj_ctx_fclose(PJ_CONTEXT *ctx, PAFile file) -{ - ctx->fileapi_legacy->FClose(file); -} - -/************************************************************************/ -/* pj_ctx_fgets() */ -/* */ -/* A not very optimal implementation of fgets on top of */ -/* fread(). If we end up using this a lot more care should be */ -/* taken. */ -/************************************************************************/ - -char *pj_ctx_fgets(PJ_CONTEXT *ctx, char *line, int size, PAFile file) -{ - long start = pj_ctx_ftell(ctx, file); - size_t bytes_read; - int i; - int max_size; - - line[size-1] = '\0'; - bytes_read = pj_ctx_fread(ctx, line, 1, size-1, file); - if(bytes_read == 0) - return nullptr; - if(bytes_read < (size_t)size) - { - line[bytes_read] = '\0'; - } - - max_size = (int)MIN(bytes_read, (size_t)(size > 2 ? size - 2 : 0)); - for( i = 0; i < max_size; i++) - { - if (line[i] == '\n') - { - line[i+1] = '\0'; - pj_ctx_fseek(ctx, file, start + i + 1, SEEK_SET); - break; - } - } - return line; -} - -/************************************************************************/ -/* pj_ctx_set_fileapi() */ -/************************************************************************/ - -void pj_ctx_set_fileapi( PJ_CONTEXT *ctx, projFileAPI *fileapi ) - -{ - if (nullptr==ctx) - return; - ctx->fileapi_legacy = fileapi; -} - -/************************************************************************/ -/* pj_ctx_get_fileapi() */ -/************************************************************************/ - -projFileAPI *pj_ctx_get_fileapi( PJ_CONTEXT *ctx ) - -{ - if (nullptr==ctx) - return nullptr; - return ctx->fileapi_legacy; -} - diff --git a/src/filemanager.cpp b/src/filemanager.cpp index 37dc920e..66a8faf8 100644 --- a/src/filemanager.cpp +++ b/src/filemanager.cpp @@ -786,75 +786,6 @@ std::unique_ptr FileStdio::open(PJ_CONTEXT *ctx, const char *filename, // --------------------------------------------------------------------------- -#ifndef REMOVE_LEGACY_SUPPORT - -class FileLegacyAdapter : public File { - PJ_CONTEXT *m_ctx; - PAFile m_fp; - - FileLegacyAdapter(const FileLegacyAdapter &) = delete; - FileLegacyAdapter &operator=(const FileLegacyAdapter &) = delete; - - protected: - FileLegacyAdapter(const std::string &filename, PJ_CONTEXT *ctx, PAFile fp) - : File(filename), m_ctx(ctx), m_fp(fp) {} - - public: - ~FileLegacyAdapter() override; - - size_t read(void *buffer, size_t sizeBytes) override; - size_t write(const void *, size_t) override { return 0; } - bool seek(unsigned long long offset, int whence = SEEK_SET) override; - unsigned long long tell() override; - void reassign_context(PJ_CONTEXT *ctx) override { m_ctx = ctx; } - - // We may lie, but the real use case is only for network files - bool hasChanged() const override { return false; } - - static std::unique_ptr open(PJ_CONTEXT *ctx, const char *filename, - FileAccess access); -}; - -// --------------------------------------------------------------------------- - -FileLegacyAdapter::~FileLegacyAdapter() { pj_ctx_fclose(m_ctx, m_fp); } - -// --------------------------------------------------------------------------- - -size_t FileLegacyAdapter::read(void *buffer, size_t sizeBytes) { - return pj_ctx_fread(m_ctx, buffer, 1, sizeBytes, m_fp); -} - -// --------------------------------------------------------------------------- - -bool FileLegacyAdapter::seek(unsigned long long offset, int whence) { - if (offset != static_cast(static_cast(offset))) { - pj_log(m_ctx, PJ_LOG_ERROR, - "Attempt at seeking to a 64 bit offset. Not supported yet"); - return false; - } - return pj_ctx_fseek(m_ctx, m_fp, static_cast(offset), whence) == 0; -} - -// --------------------------------------------------------------------------- - -unsigned long long FileLegacyAdapter::tell() { - return pj_ctx_ftell(m_ctx, m_fp); -} - -// --------------------------------------------------------------------------- - -std::unique_ptr -FileLegacyAdapter::open(PJ_CONTEXT *ctx, const char *filename, FileAccess) { - auto fid = pj_ctx_fopen(ctx, filename, "rb"); - return std::unique_ptr(fid ? new FileLegacyAdapter(filename, ctx, fid) - : nullptr); -} - -#endif // REMOVE_LEGACY_SUPPORT - -// --------------------------------------------------------------------------- - class FileApiAdapter : public File { PJ_CONTEXT *m_ctx; PROJ_FILE_HANDLE *m_fp; @@ -954,12 +885,6 @@ std::unique_ptr FileManager::open(PJ_CONTEXT *ctx, const char *filename, } return pj_network_file_open(ctx, filename); } -#ifndef REMOVE_LEGACY_SUPPORT - // If the user has specified a legacy fileapi, use it - if (ctx->fileapi_legacy != pj_get_default_fileapi()) { - return FileLegacyAdapter::open(ctx, filename, access); - } -#endif if (ctx->fileApi.open_cbk != nullptr) { return FileApiAdapter::open(ctx, filename, access); } @@ -1728,26 +1653,6 @@ NS_PROJ::FileManager::open_resource_file(PJ_CONTEXT *ctx, const char *name) { return file; } -/************************************************************************/ -/* pj_open_lib() */ -/************************************************************************/ - -#ifndef REMOVE_LEGACY_SUPPORT - -// Used by following legacy function -static void *pj_ctx_fopen_adapter(PJ_CONTEXT *ctx, const char *name, - const char *mode) { - return pj_ctx_fopen(ctx, name, mode); -} - -// Legacy function -PAFile pj_open_lib(PJ_CONTEXT *ctx, const char *name, const char *mode) { - return (PAFile)pj_open_lib_internal(ctx, name, mode, pj_ctx_fopen_adapter, - nullptr, 0); -} - -#endif // REMOVE_LEGACY_SUPPORT - /************************************************************************/ /* pj_find_file() */ /************************************************************************/ diff --git a/src/lib_proj.cmake b/src/lib_proj.cmake index b0f9a6ba..997eb22d 100644 --- a/src/lib_proj.cmake +++ b/src/lib_proj.cmake @@ -219,7 +219,6 @@ set(SRC_LIBPROJ_CORE ellps.cpp errno.cpp factors.cpp - fileapi.cpp fwd.cpp gauss.cpp generic_inverse.cpp diff --git a/src/proj_internal.h b/src/proj_internal.h index 273c1efd..3c1571eb 100644 --- a/src/proj_internal.h +++ b/src/proj_internal.h @@ -711,7 +711,6 @@ struct pj_ctx{ int debug_level = 0; void (*logger)(void *, int, const char *) = nullptr; void *logger_app_data = nullptr; - struct projFileAPI_t *fileapi_legacy = nullptr; // for proj_api.h legacy API struct projCppContext* cpp_context = nullptr; /* internal context for C++ code */ int use_proj4_init_rules = -1; /* -1 = unknown, 0 = no, 1 = yes */ int epsg_file_exists = -1; /* -1 = unknown, 0 = no, 1 = yes */ @@ -933,19 +932,6 @@ PROJ_DLL extern int pj_errno; /* global error return code */ #endif -/* If included *after* proj.h finishes, we have alternative names */ -/* file reading api, like stdio */ -typedef int *PAFile; -typedef struct projFileAPI_t { - PAFile (*FOpen)(PJ_CONTEXT * ctx, const char *filename, const char *access); - size_t (*FRead)(void *buffer, size_t size, size_t nmemb, PAFile file); - int (*FSeek)(PAFile file, long offset, int whence); - long (*FTell)(PAFile file); - void (*FClose)(PAFile); -} projFileAPI; - - - /* procedure prototypes */ PJ_CONTEXT PROJ_DLL *pj_get_default_ctx(void); @@ -999,23 +985,10 @@ void PROJ_DLL pj_ctx_set_debug( PJ_CONTEXT *, int ); void PROJ_DLL pj_ctx_set_logger( PJ_CONTEXT *, void (*)(void *, int, const char *) ); void PROJ_DLL pj_ctx_set_app_data( PJ_CONTEXT *, void * ); void PROJ_DLL *pj_ctx_get_app_data( PJ_CONTEXT * ); -void PROJ_DLL pj_ctx_set_fileapi( PJ_CONTEXT *, projFileAPI *); -projFileAPI PROJ_DLL *pj_ctx_get_fileapi( PJ_CONTEXT * ); void PROJ_DLL pj_log( PJ_CONTEXT * ctx, int level, const char *fmt, ... ); void PROJ_DLL pj_stderr_logger( void *, int, const char * ); -/* file api */ -projFileAPI PROJ_DLL *pj_get_default_fileapi(void); - -PAFile PROJ_DLL pj_ctx_fopen(PJ_CONTEXT * ctx, const char *filename, const char *access); -size_t PROJ_DLL pj_ctx_fread(PJ_CONTEXT * ctx, void *buffer, size_t size, size_t nmemb, PAFile file); -int PROJ_DLL pj_ctx_fseek(PJ_CONTEXT * ctx, PAFile file, long offset, int whence); -long PROJ_DLL pj_ctx_ftell(PJ_CONTEXT * ctx, PAFile file); -void PROJ_DLL pj_ctx_fclose(PJ_CONTEXT * ctx, PAFile file); -char PROJ_DLL *pj_ctx_fgets(PJ_CONTEXT * ctx, char *line, int size, PAFile file); - -PAFile PROJ_DLL pj_open_lib(PJ_CONTEXT *, const char *, const char *); int PROJ_DLL pj_find_file(PJ_CONTEXT * ctx, const char *short_filename, char* out_full_filename, size_t out_full_filename_size); -- cgit v1.2.3 From a74b985b5006c2d279353a245cfcb850cf7fcc94 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Tue, 17 Nov 2020 12:54:24 +0100 Subject: Remove pj_ctx_* functions and use their proj_context counterparts --- src/4D_api.cpp | 15 ++--- src/aasincos.cpp | 4 +- src/apps/cs2cs.cpp | 15 ++++- src/ctx.cpp | 127 ++++-------------------------------------- src/datum_set.cpp | 6 +- src/dmstor.cpp | 4 +- src/ell_set.cpp | 22 ++++---- src/filemanager.cpp | 8 +-- src/gauss.cpp | 2 +- src/generic_inverse.cpp | 2 +- src/grids.cpp | 74 ++++++++++++------------ src/init.cpp | 10 ++-- src/internal.cpp | 12 ++-- src/iso19111/c_api.cpp | 4 +- src/iso19111/datum.cpp | 4 +- src/malloc.cpp | 4 +- src/mlfn.hpp | 2 +- src/networkfilemanager.cpp | 6 +- src/param.cpp | 2 +- src/phi2.cpp | 2 +- src/proj_internal.h | 10 ---- src/proj_mdist.cpp | 2 +- src/projections/aitoff.cpp | 2 +- src/projections/comill.cpp | 2 +- src/projections/eqearth.cpp | 2 +- src/projections/healpix.cpp | 8 +-- src/projections/krovak.cpp | 2 +- src/projections/natearth.cpp | 2 +- src/projections/natearth2.cpp | 2 +- src/projections/ortho.cpp | 2 +- src/projections/patterson.cpp | 2 +- src/projections/robin.cpp | 2 +- src/projections/tmerc.cpp | 6 +- src/utils.cpp | 2 +- 34 files changed, 137 insertions(+), 234 deletions(-) diff --git a/src/4D_api.cpp b/src/4D_api.cpp index 86c0e071..70b04bf1 100644 --- a/src/4D_api.cpp +++ b/src/4D_api.cpp @@ -1363,7 +1363,7 @@ int proj_errno (const PJ *P) { /****************************************************************************** Read an error level from the context of a PJ. ******************************************************************************/ - return pj_ctx_get_errno (pj_get_ctx ((PJ *) P)); + return proj_context_errno (pj_get_ctx ((PJ *) P)); } /*****************************************************************************/ @@ -1374,7 +1374,7 @@ int proj_context_errno (PJ_CONTEXT *ctx) { ******************************************************************************/ if (nullptr==ctx) ctx = pj_get_default_ctx(); - return pj_ctx_get_errno (ctx); + return ctx->last_errno; } /*****************************************************************************/ @@ -1389,6 +1389,7 @@ int proj_errno_set (const PJ *P, int err) { /* For P==0 err goes to the default context */ proj_context_errno_set (pj_get_ctx ((PJ *) P), err); errno = err; + return err; } @@ -1439,7 +1440,7 @@ int proj_errno_reset (const PJ *P) { int last_errno; last_errno = proj_errno (P); - pj_ctx_set_errno (pj_get_ctx ((PJ *) P), 0); + proj_context_errno_set (pj_get_ctx ((PJ *) P), 0); errno = 0; pj_errno = 0; return last_errno; @@ -1448,7 +1449,7 @@ int proj_errno_reset (const PJ *P) { /* Create a new context based on the default context */ PJ_CONTEXT *proj_context_create (void) { - return pj_ctx_alloc (); + return new (std::nothrow) pj_ctx(*pj_get_default_ctx()); } @@ -1460,7 +1461,7 @@ PJ_CONTEXT *proj_context_destroy (PJ_CONTEXT *ctx) { if (pj_get_default_ctx ()==ctx) return nullptr; - pj_ctx_free (ctx); + delete ctx; return nullptr; } @@ -1746,7 +1747,7 @@ PJ_INIT_INFO proj_init_info(const char *initname){ if( strcmp(initname, "epsg") == 0 || strcmp(initname, "EPSG") == 0 ) { const char* val; - pj_ctx_set_errno( ctx, 0 ); + proj_context_errno_set( ctx, 0 ); strncpy (ininfo.name, initname, sizeof(ininfo.name) - 1); strcpy(ininfo.origin, "EPSG"); @@ -1764,7 +1765,7 @@ PJ_INIT_INFO proj_init_info(const char *initname){ if( strcmp(initname, "IGNF") == 0 ) { const char* val; - pj_ctx_set_errno( ctx, 0 ); + proj_context_errno_set( ctx, 0 ); strncpy (ininfo.name, initname, sizeof(ininfo.name) - 1); strcpy(ininfo.origin, "IGNF"); diff --git a/src/aasincos.cpp b/src/aasincos.cpp index c3229d39..c4314c67 100644 --- a/src/aasincos.cpp +++ b/src/aasincos.cpp @@ -14,7 +14,7 @@ aasin(PJ_CONTEXT *ctx,double v) { if ((av = fabs(v)) >= 1.) { if (av > ONE_TOL) - pj_ctx_set_errno( ctx, PJD_ERR_ACOS_ASIN_ARG_TOO_LARGE ); + proj_context_errno_set( ctx, PJD_ERR_ACOS_ASIN_ARG_TOO_LARGE ); return (v < 0. ? -M_HALFPI : M_HALFPI); } return asin(v); @@ -26,7 +26,7 @@ aacos(PJ_CONTEXT *ctx, double v) { if ((av = fabs(v)) >= 1.) { if (av > ONE_TOL) - pj_ctx_set_errno( ctx, PJD_ERR_ACOS_ASIN_ARG_TOO_LARGE ); + proj_context_errno_set( ctx, PJD_ERR_ACOS_ASIN_ARG_TOO_LARGE ); return (v < 0. ? M_PI : 0.); } return acos(v); diff --git a/src/apps/cs2cs.cpp b/src/apps/cs2cs.cpp index 1a33d444..92e4441e 100644 --- a/src/apps/cs2cs.cpp +++ b/src/apps/cs2cs.cpp @@ -468,10 +468,23 @@ int main(int argc, char **argv) { reverseout = 1; continue; case 'D': /* set debug level */ + { if (--argc <= 0) goto noargument; - pj_ctx_set_debug(pj_get_default_ctx(), atoi(*++argv)); + int log_level = atoi(*++argv); + if (log_level <= 0) { + proj_log_level(pj_get_default_ctx(), PJ_LOG_NONE); + } else if (log_level == 1) { + proj_log_level(pj_get_default_ctx(), PJ_LOG_ERROR); + } else if (log_level == 2) { + proj_log_level(pj_get_default_ctx(), PJ_LOG_DEBUG); + } else if (log_level == 3) { + proj_log_level(pj_get_default_ctx(), PJ_LOG_TRACE); + } else { + proj_log_level(pj_get_default_ctx(), PJ_LOG_TELL); + } continue; + } case 'd': if (--argc <= 0) goto noargument; diff --git a/src/ctx.cpp b/src/ctx.cpp index d3eee39f..8e25db2a 100644 --- a/src/ctx.cpp +++ b/src/ctx.cpp @@ -54,13 +54,17 @@ PJ_CONTEXT* pj_get_ctx( PJ *pj ) } /************************************************************************/ -/* pj_set_ctx() */ -/* */ -/* Note we do not deallocate the old context! */ +/* proj_assign_context() */ /************************************************************************/ -void pj_set_ctx( PJ *pj, PJ_CONTEXT *ctx ) - +/** \brief Re-assign a context to a PJ* object. + * + * This may be useful if the PJ* has been created with a context that is + * thread-specific, and is later used in another thread. In that case, + * the user may want to assign another thread-specific context to the + * object. + */ +void proj_assign_context( PJ* pj, PJ_CONTEXT *ctx ) { if (pj==nullptr) return; @@ -71,24 +75,9 @@ void pj_set_ctx( PJ *pj, PJ_CONTEXT *ctx ) } for( const auto &alt: pj->alternativeCoordinateOperations ) { - pj_set_ctx(alt.pj, ctx); + proj_assign_context(alt.pj, ctx); } -} -/************************************************************************/ -/* proj_assign_context() */ -/************************************************************************/ - -/** \brief Re-assign a context to a PJ* object. - * - * This may be useful if the PJ* has been created with a context that is - * thread-specific, and is later used in another thread. In that case, - * the user may want to assign another thread-specific context to the - * object. - */ -void proj_assign_context( PJ* pj, PJ_CONTEXT *ctx ) -{ - pj_set_ctx( pj, ctx ); } /************************************************************************/ @@ -212,16 +201,6 @@ pj_ctx::~pj_ctx() proj_context_delete_cpp_context(cpp_context); } -/************************************************************************/ -/* pj_ctx_alloc() */ -/************************************************************************/ - -PJ_CONTEXT* pj_ctx_alloc() - -{ - return new (std::nothrow) pj_ctx(*pj_get_default_ctx()); -} - /************************************************************************/ /* proj_context_clone() */ /* Create a new context based on a custom context */ @@ -230,93 +209,9 @@ PJ_CONTEXT* pj_ctx_alloc() PJ_CONTEXT* proj_context_clone (PJ_CONTEXT *ctx) { if (nullptr==ctx) - return pj_ctx_alloc (); + return proj_context_create(); return new (std::nothrow) pj_ctx(*ctx); } -/************************************************************************/ -/* pj_ctx_free() */ -/************************************************************************/ - -void pj_ctx_free( PJ_CONTEXT *ctx ) - -{ - delete ctx; -} - -/************************************************************************/ -/* pj_ctx_get_errno() */ -/************************************************************************/ - -int pj_ctx_get_errno( PJ_CONTEXT *ctx ) -{ - if (nullptr==ctx) - return pj_get_default_ctx ()->last_errno; - return ctx->last_errno; -} - -/************************************************************************/ -/* pj_ctx_set_errno() */ -/* */ -/* Also sets the global errno */ -/************************************************************************/ - -void pj_ctx_set_errno( PJ_CONTEXT *ctx, int new_errno ) - -{ - ctx->last_errno = new_errno; - if( new_errno == 0 ) - return; - errno = new_errno; - pj_errno = new_errno; -} - -/************************************************************************/ -/* pj_ctx_set_debug() */ -/************************************************************************/ - -void pj_ctx_set_debug( PJ_CONTEXT *ctx, int new_debug ) - -{ - if (nullptr==ctx) - return; - ctx->debug_level = new_debug; -} - -/************************************************************************/ -/* pj_ctx_set_logger() */ -/************************************************************************/ - -void pj_ctx_set_logger( PJ_CONTEXT *ctx, void (*new_logger)(void*,int,const char*) ) - -{ - if (nullptr==ctx) - return; - ctx->logger = new_logger; -} - -/************************************************************************/ -/* pj_ctx_set_app_data() */ -/************************************************************************/ - -void pj_ctx_set_app_data( PJ_CONTEXT *ctx, void *new_app_data ) - -{ - if (nullptr==ctx) - return; - ctx->logger_app_data = new_app_data; -} - -/************************************************************************/ -/* pj_ctx_get_app_data() */ -/************************************************************************/ - -void *pj_ctx_get_app_data( PJ_CONTEXT *ctx ) - -{ - if (nullptr==ctx) - return nullptr; - return ctx->logger_app_data; -} diff --git a/src/datum_set.cpp b/src/datum_set.cpp index cc6f3dbe..398d85cd 100644 --- a/src/datum_set.cpp +++ b/src/datum_set.cpp @@ -71,7 +71,7 @@ int pj_datum_set(PJ_CONTEXT *ctx, paralist *pl, PJ *projdef) for (i = 0; (s = pj_datums[i].id) && strcmp(name, s) ; ++i) {} if (!s) { - pj_ctx_set_errno(ctx, PJD_ERR_UNKNOWN_ELLP_PARAM); + proj_context_errno_set(ctx, PJD_ERR_UNKNOWN_ELLP_PARAM); return 1; } @@ -87,7 +87,7 @@ int pj_datum_set(PJ_CONTEXT *ctx, paralist *pl, PJ *projdef) curr = curr->next = pj_mkparam(entry); if (nullptr == curr) { - pj_ctx_set_errno(ctx, ENOMEM); + proj_context_errno_set(ctx, ENOMEM); return 1; } } @@ -97,7 +97,7 @@ int pj_datum_set(PJ_CONTEXT *ctx, paralist *pl, PJ *projdef) curr = curr->next = pj_mkparam(pj_datums[i].defn); if (nullptr == curr) { - pj_ctx_set_errno(ctx, ENOMEM); + proj_context_errno_set(ctx, ENOMEM); return 1; } } diff --git a/src/dmstor.cpp b/src/dmstor.cpp index e72d9930..24887a11 100644 --- a/src/dmstor.cpp +++ b/src/dmstor.cpp @@ -61,7 +61,7 @@ dmstor_ctx(PJ_CONTEXT *ctx, const char *is, char **rs) { n = 2; break; case 'r': case 'R': if (nl) { - pj_ctx_set_errno( ctx, PJD_ERR_WRONG_FORMAT_DMS_VALUE ); + proj_context_errno_set( ctx, PJD_ERR_WRONG_FORMAT_DMS_VALUE ); return HUGE_VAL; } ++s; @@ -73,7 +73,7 @@ dmstor_ctx(PJ_CONTEXT *ctx, const char *is, char **rs) { continue; } if (n < nl) { - pj_ctx_set_errno( ctx, PJD_ERR_WRONG_FORMAT_DMS_VALUE ); + proj_context_errno_set( ctx, PJD_ERR_WRONG_FORMAT_DMS_VALUE ); return HUGE_VAL; } v += tv * vm[n]; diff --git a/src/ell_set.cpp b/src/ell_set.cpp index ec3e03eb..c7cbeb48 100644 --- a/src/ell_set.cpp +++ b/src/ell_set.cpp @@ -552,7 +552,7 @@ int pj_calc_ellipsoid_params (PJ *P, double a, double es) { 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); + proj_context_errno_set( P->ctx, PJD_ERR_INVALID_ECCENTRICITY); return PJD_ERR_INVALID_ECCENTRICITY; } P->rf = P->f != 0.0 ? 1.0/P->f: HUGE_VAL; @@ -573,7 +573,7 @@ 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_INVALID_ECCENTRICITY); + proj_context_errno_set( P->ctx, PJD_ERR_INVALID_ECCENTRICITY); return PJD_ERR_INVALID_ECCENTRICITY; } @@ -630,7 +630,7 @@ int pj_ell_set (PJ_CONTEXT *ctx, paralist *pl, double *a, double *es) { paralist *start = 0; /* clear any previous error */ - pj_ctx_set_errno(ctx,0); + proj_context_errno_set(ctx,0); /* check for varying forms of ellipsoid input */ *a = *es = 0.; @@ -648,7 +648,7 @@ int pj_ell_set (PJ_CONTEXT *ctx, paralist *pl, double *a, double *es) { for (start = pl; start && start->next ; start = start->next) ; for (i = 0; (s = pj_ellps[i].id) && strcmp(name, s) ; ++i) ; if (!s) { - pj_ctx_set_errno( ctx, PJD_ERR_UNKNOWN_ELLP_PARAM); + proj_context_errno_set( ctx, PJD_ERR_UNKNOWN_ELLP_PARAM); return 1; } start->next = pj_mkparam(pj_ellps[i].major); @@ -662,14 +662,14 @@ int pj_ell_set (PJ_CONTEXT *ctx, paralist *pl, double *a, double *es) { 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); + proj_context_errno_set(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; if (*es == 0.0) { - pj_ctx_set_errno(ctx, PJD_ERR_REV_FLATTENING_IS_ZERO); + proj_context_errno_set(ctx, PJD_ERR_REV_FLATTENING_IS_ZERO); goto bomb; } *es = 1./ *es; @@ -700,7 +700,7 @@ int pj_ell_set (PJ_CONTEXT *ctx, paralist *pl, double *a, double *es) { *es = 0.; } else if (pj_param(ctx,pl, "bR_h").i) { /* sphere--harmonic mean */ if ( (*a + b) == 0.0) { - pj_ctx_set_errno(ctx, PJD_ERR_TOLERANCE_CONDITION); + proj_context_errno_set(ctx, PJD_ERR_TOLERANCE_CONDITION); goto bomb; } *a = 2. * *a * b / (*a + b); @@ -711,7 +711,7 @@ int pj_ell_set (PJ_CONTEXT *ctx, paralist *pl, double *a, double *es) { tmp = sin(pj_param(ctx,pl, i ? "rR_lat_a" : "rR_lat_g").f); if (fabs(tmp) > M_HALFPI) { - pj_ctx_set_errno(ctx, PJD_ERR_REF_RAD_LARGER_THAN_90); + proj_context_errno_set(ctx, PJD_ERR_REF_RAD_LARGER_THAN_90); goto bomb; } tmp = 1. - *es * tmp * tmp; @@ -730,15 +730,15 @@ bomb: } /* some remaining checks */ if (*es < 0.) { - pj_ctx_set_errno(ctx, PJD_ERR_ES_LESS_THAN_ZERO); + proj_context_errno_set(ctx, PJD_ERR_ES_LESS_THAN_ZERO); return 1; } if (*es >= 1.) { - pj_ctx_set_errno(ctx, PJD_ERR_INVALID_ECCENTRICITY); + proj_context_errno_set(ctx, PJD_ERR_INVALID_ECCENTRICITY); return 1; } if (*a <= 0.) { - pj_ctx_set_errno(ctx, PJD_ERR_MAJOR_AXIS_NOT_GIVEN); + proj_context_errno_set(ctx, PJD_ERR_MAJOR_AXIS_NOT_GIVEN); return 1; } return 0; diff --git a/src/filemanager.cpp b/src/filemanager.cpp index 66a8faf8..dbcb8ddc 100644 --- a/src/filemanager.cpp +++ b/src/filemanager.cpp @@ -1491,7 +1491,7 @@ pj_open_lib_internal(PJ_CONTEXT *ctx, const char *name, const char *mode, } if (ctx->last_errno == 0 && errno != 0) - pj_ctx_set_errno(ctx, errno); + proj_context_errno_set(ctx, errno); pj_log(ctx, PJ_LOG_DEBUG_MAJOR, "pj_open_lib(%s): call fopen(%s) - %s", name, sysname, fid == nullptr ? "failed" : "succeeded"); @@ -1591,7 +1591,7 @@ NS_PROJ::FileManager::open_resource_file(PJ_CONTEXT *ctx, const char *name) { pj_open_file_with_manager, nullptr, 0))); if (file) { - pj_ctx_set_errno(ctx, 0); + proj_context_errno_set(ctx, 0); } else { // For final network access attempt, use the new // name. @@ -1621,7 +1621,7 @@ NS_PROJ::FileManager::open_resource_file(PJ_CONTEXT *ctx, const char *name) { pj_open_file_with_manager, nullptr, 0))); if (file) { - pj_ctx_set_errno(ctx, 0); + proj_context_errno_set(ctx, 0); } } } catch (const std::exception &e) { @@ -1646,7 +1646,7 @@ NS_PROJ::FileManager::open_resource_file(PJ_CONTEXT *ctx, const char *name) { if (file) { pj_log(ctx, PJ_LOG_DEBUG_MAJOR, "Using %s", remote_file.c_str()); - pj_ctx_set_errno(ctx, 0); + proj_context_errno_set(ctx, 0); } } } diff --git a/src/gauss.cpp b/src/gauss.cpp index 54dff5a8..96bd5166 100644 --- a/src/gauss.cpp +++ b/src/gauss.cpp @@ -109,6 +109,6 @@ PJ_LP pj_inv_gauss(PJ_CONTEXT *ctx, PJ_LP slp, const void *data) { } /* convergence failed */ if (!i) - pj_ctx_set_errno(ctx, PJD_ERR_NON_CONV_INV_MERI_DIST); + proj_context_errno_set(ctx, PJD_ERR_NON_CONV_INV_MERI_DIST); return (elp); } diff --git a/src/generic_inverse.cpp b/src/generic_inverse.cpp index a15cfae1..ddd5060b 100644 --- a/src/generic_inverse.cpp +++ b/src/generic_inverse.cpp @@ -109,6 +109,6 @@ PJ_LP pj_generic_inverse_2d(PJ_XY xy, PJ *P, PJ_LP lpInitial) { lp.phi = M_HALFPI; } } - pj_ctx_set_errno(P->ctx, PJD_ERR_NON_CONVERGENT); + proj_context_errno_set(P->ctx, PJD_ERR_NON_CONVERGENT); return lp; } diff --git a/src/grids.cpp b/src/grids.cpp index 8c1bc4cc..671485d7 100644 --- a/src/grids.cpp +++ b/src/grids.cpp @@ -197,7 +197,7 @@ GTXVerticalShiftGrid *GTXVerticalShiftGrid::open(PJ_CONTEXT *ctx, /* Read the header. */ /* -------------------------------------------------------------------- */ if (fp->read(header, sizeof(header)) != sizeof(header)) { - pj_ctx_set_errno(ctx, PJD_ERR_FAILED_TO_LOAD_GRID); + proj_context_errno_set(ctx, PJD_ERR_FAILED_TO_LOAD_GRID); return nullptr; } @@ -223,7 +223,7 @@ GTXVerticalShiftGrid *GTXVerticalShiftGrid::open(PJ_CONTEXT *ctx, if (xorigin < -360 || xorigin > 360 || yorigin < -90 || yorigin > 90) { pj_log(ctx, PJ_LOG_ERROR, "gtx file header has invalid extents, corrupt?"); - pj_ctx_set_errno(ctx, PJD_ERR_FAILED_TO_LOAD_GRID); + proj_context_errno_set(ctx, PJD_ERR_FAILED_TO_LOAD_GRID); return nullptr; } @@ -258,7 +258,7 @@ bool GTXVerticalShiftGrid::valueAt(int x, int y, float &out) const { m_fp->seek(40 + sizeof(float) * (y * m_width + x)); if (m_fp->read(&out, sizeof(out)) != sizeof(out)) { - pj_ctx_set_errno(m_ctx, PJD_ERR_FAILED_TO_LOAD_GRID); + proj_context_errno_set(m_ctx, PJD_ERR_FAILED_TO_LOAD_GRID); return false; } if (IS_LSB) { @@ -1389,7 +1389,7 @@ VerticalShiftGridSet::open(PJ_CONTEXT *ctx, const std::string &filename) { auto set = std::unique_ptr( GTiffVGridShiftSet::open(ctx, std::move(fp), actualName)); if (!set) - pj_ctx_set_errno(ctx, PJD_ERR_FAILED_TO_LOAD_GRID); + proj_context_errno_set(ctx, PJD_ERR_FAILED_TO_LOAD_GRID); return set; #else pj_log(ctx, PJ_LOG_ERROR, @@ -1570,7 +1570,7 @@ NTv1Grid *NTv1Grid::open(PJ_CONTEXT *ctx, std::unique_ptr fp, /* Read the header. */ /* -------------------------------------------------------------------- */ if (fp->read(header, sizeof(header)) != sizeof(header)) { - pj_ctx_set_errno(ctx, PJD_ERR_FAILED_TO_LOAD_GRID); + proj_context_errno_set(ctx, PJD_ERR_FAILED_TO_LOAD_GRID); return nullptr; } @@ -1590,7 +1590,7 @@ NTv1Grid *NTv1Grid::open(PJ_CONTEXT *ctx, std::unique_ptr fp, if (*((int *)(header + 8)) != 12) { pj_log(ctx, PJ_LOG_ERROR, "NTv1 grid shift file has wrong record count, corrupt?"); - pj_ctx_set_errno(ctx, PJD_ERR_FAILED_TO_LOAD_GRID); + proj_context_errno_set(ctx, PJD_ERR_FAILED_TO_LOAD_GRID); return nullptr; } @@ -1609,7 +1609,7 @@ NTv1Grid *NTv1Grid::open(PJ_CONTEXT *ctx, std::unique_ptr fp, extent.resY > 1e-10)) { pj_log(ctx, PJ_LOG_ERROR, "Inconsistent georeferencing for %s", filename.c_str()); - pj_ctx_set_errno(ctx, PJD_ERR_FAILED_TO_LOAD_GRID); + proj_context_errno_set(ctx, PJD_ERR_FAILED_TO_LOAD_GRID); return nullptr; } const int columns = static_cast( @@ -1631,7 +1631,7 @@ bool NTv1Grid::valueAt(int x, int y, bool compensateNTConvention, m_fp->seek(192 + 2 * sizeof(double) * (y * m_width + m_width - 1 - x)); if (m_fp->read(&two_doubles[0], sizeof(two_doubles)) != sizeof(two_doubles)) { - pj_ctx_set_errno(m_ctx, PJD_ERR_FAILED_TO_LOAD_GRID); + proj_context_errno_set(m_ctx, PJD_ERR_FAILED_TO_LOAD_GRID); return false; } if (IS_LSB) { @@ -1692,7 +1692,7 @@ CTable2Grid *CTable2Grid::open(PJ_CONTEXT *ctx, std::unique_ptr fp, /* Read the header. */ /* -------------------------------------------------------------------- */ if (fp->read(header, sizeof(header)) != sizeof(header)) { - pj_ctx_set_errno(ctx, PJD_ERR_FAILED_TO_LOAD_GRID); + proj_context_errno_set(ctx, PJD_ERR_FAILED_TO_LOAD_GRID); return nullptr; } @@ -1718,7 +1718,7 @@ CTable2Grid *CTable2Grid::open(PJ_CONTEXT *ctx, std::unique_ptr fp, extent.resX > 1e-10 && extent.resY > 1e-10)) { pj_log(ctx, PJ_LOG_ERROR, "Inconsistent georeferencing for %s", filename.c_str()); - pj_ctx_set_errno(ctx, PJD_ERR_FAILED_TO_LOAD_GRID); + proj_context_errno_set(ctx, PJD_ERR_FAILED_TO_LOAD_GRID); return nullptr; } int width; @@ -1726,7 +1726,7 @@ CTable2Grid *CTable2Grid::open(PJ_CONTEXT *ctx, std::unique_ptr fp, memcpy(&width, header + 128, 4); memcpy(&height, header + 132, 4); if (width <= 0 || height <= 0) { - pj_ctx_set_errno(ctx, PJD_ERR_FAILED_TO_LOAD_GRID); + proj_context_errno_set(ctx, PJD_ERR_FAILED_TO_LOAD_GRID); return nullptr; } extent.east = extent.west + (width - 1) * extent.resX; @@ -1744,7 +1744,7 @@ bool CTable2Grid::valueAt(int x, int y, bool compensateNTConvention, float two_floats[2]; m_fp->seek(160 + 2 * sizeof(float) * (y * m_width + x)); if (m_fp->read(&two_floats[0], sizeof(two_floats)) != sizeof(two_floats)) { - pj_ctx_set_errno(m_ctx, PJD_ERR_FAILED_TO_LOAD_GRID); + proj_context_errno_set(m_ctx, PJD_ERR_FAILED_TO_LOAD_GRID); return false; } if (!IS_LSB) { @@ -1828,7 +1828,7 @@ bool NTv2Grid::valueAt(int x, int y, bool compensateNTConvention, 4 * sizeof(float) * (static_cast(y) * m_width + m_width - 1 - x)); if (m_fp->read(&two_float[0], sizeof(two_float)) != sizeof(two_float)) { - pj_ctx_set_errno(m_ctx, PJD_ERR_FAILED_TO_LOAD_GRID); + proj_context_errno_set(m_ctx, PJD_ERR_FAILED_TO_LOAD_GRID); return false; } if (m_mustSwap) { @@ -1862,14 +1862,14 @@ std::unique_ptr NTv2GridSet::open(PJ_CONTEXT *ctx, /* Read the header. */ /* -------------------------------------------------------------------- */ if (fpRaw->read(header, sizeof(header)) != sizeof(header)) { - pj_ctx_set_errno(ctx, PJD_ERR_FAILED_TO_LOAD_GRID); + proj_context_errno_set(ctx, PJD_ERR_FAILED_TO_LOAD_GRID); return nullptr; } constexpr int OFFSET_GS_TYPE = 56; if (memcmp(header + OFFSET_GS_TYPE, "SECONDS", 7) != 0) { pj_log(ctx, PJ_LOG_ERROR, "Only GS_TYPE=SECONDS is supported"); - pj_ctx_set_errno(ctx, PJD_ERR_FAILED_TO_LOAD_GRID); + proj_context_errno_set(ctx, PJD_ERR_FAILED_TO_LOAD_GRID); return nullptr; } @@ -1899,12 +1899,12 @@ std::unique_ptr NTv2GridSet::open(PJ_CONTEXT *ctx, for (unsigned subfile = 0; subfile < num_subfiles; subfile++) { // Read header if (fpRaw->read(header, sizeof(header)) != sizeof(header)) { - pj_ctx_set_errno(ctx, PJD_ERR_FAILED_TO_LOAD_GRID); + proj_context_errno_set(ctx, PJD_ERR_FAILED_TO_LOAD_GRID); return nullptr; } if (strncmp(header, "SUB_NAME", 8) != 0) { - pj_ctx_set_errno(ctx, PJD_ERR_FAILED_TO_LOAD_GRID); + proj_context_errno_set(ctx, PJD_ERR_FAILED_TO_LOAD_GRID); return nullptr; } @@ -1946,7 +1946,7 @@ std::unique_ptr NTv2GridSet::open(PJ_CONTEXT *ctx, extent.resY > 1e-10)) { pj_log(ctx, PJ_LOG_ERROR, "Inconsistent georeferencing for %s", filename.c_str()); - pj_ctx_set_errno(ctx, PJD_ERR_FAILED_TO_LOAD_GRID); + proj_context_errno_set(ctx, PJD_ERR_FAILED_TO_LOAD_GRID); return nullptr; } const int columns = static_cast( @@ -1966,7 +1966,7 @@ std::unique_ptr NTv2GridSet::open(PJ_CONTEXT *ctx, pj_log(ctx, PJ_LOG_ERROR, "GS_COUNT(%u) does not match expected cells (%dx%d)", gs_count, columns, rows); - pj_ctx_set_errno(ctx, PJD_ERR_FAILED_TO_LOAD_GRID); + proj_context_errno_set(ctx, PJD_ERR_FAILED_TO_LOAD_GRID); return nullptr; } @@ -2367,7 +2367,7 @@ HorizontalShiftGridSet::open(PJ_CONTEXT *ctx, const std::string &filename) { auto set = std::unique_ptr( GTiffHGridShiftSet::open(ctx, std::move(fp), actualName)); if (!set) - pj_ctx_set_errno(ctx, PJD_ERR_FAILED_TO_LOAD_GRID); + proj_context_errno_set(ctx, PJD_ERR_FAILED_TO_LOAD_GRID); return set; #else pj_log(ctx, PJ_LOG_ERROR, @@ -2703,7 +2703,7 @@ GenericShiftGridSet::open(PJ_CONTEXT *ctx, const std::string &filename) { auto set = std::unique_ptr( GTiffGenericGridShiftSet::open(ctx, std::move(fp), actualName)); if (!set) - pj_ctx_set_errno(ctx, PJD_ERR_FAILED_TO_LOAD_GRID); + proj_context_errno_set(ctx, PJD_ERR_FAILED_TO_LOAD_GRID); return set; #else pj_log(ctx, PJ_LOG_ERROR, @@ -2786,11 +2786,11 @@ ListOfGenericGrids pj_generic_grid_init(PJ *P, const char *gridkey) { if (!gridSet) { if (!canFail) { if (proj_context_errno(P->ctx) != PJD_ERR_NETWORK_ERROR) { - pj_ctx_set_errno(P->ctx, PJD_ERR_FAILED_TO_LOAD_GRID); + proj_context_errno_set(P->ctx, PJD_ERR_FAILED_TO_LOAD_GRID); } return {}; } - pj_ctx_set_errno(P->ctx, 0); // don't treat as a persistent error + proj_context_errno_set(P->ctx, 0); // don't treat as a persistent error } else { grids.emplace_back(std::move(gridSet)); } @@ -2830,11 +2830,11 @@ static ListOfHGrids getListOfGridSets(PJ_CONTEXT *ctx, const char *grids) { if (!gridSet) { if (!canFail) { if (proj_context_errno(ctx) != PJD_ERR_NETWORK_ERROR) { - pj_ctx_set_errno(ctx, PJD_ERR_FAILED_TO_LOAD_GRID); + proj_context_errno_set(ctx, PJD_ERR_FAILED_TO_LOAD_GRID); } return {}; } - pj_ctx_set_errno(ctx, 0); // don't treat as a persistent error + proj_context_errno_set(ctx, 0); // don't treat as a persistent error } else { list.emplace_back(std::move(gridSet)); } @@ -3066,7 +3066,7 @@ PJ_LP pj_hgrid_apply(PJ_CONTEXT *ctx, const ListOfHGrids &grids, PJ_LP lp, HorizontalShiftGridSet *gridset = nullptr; const auto grid = findGrid(grids, lp, gridset); if (!grid) { - pj_ctx_set_errno(ctx, PJD_ERR_GRID_AREA); + proj_context_errno_set(ctx, PJD_ERR_GRID_AREA); return out; } if (grid->isNullGrid()) { @@ -3082,7 +3082,7 @@ PJ_LP pj_hgrid_apply(PJ_CONTEXT *ctx, const ListOfHGrids &grids, PJ_LP lp, } if (out.lam == HUGE_VAL || out.phi == HUGE_VAL) - pj_ctx_set_errno(ctx, PJD_ERR_GRID_AREA); + proj_context_errno_set(ctx, PJD_ERR_GRID_AREA); return out; } @@ -3098,7 +3098,7 @@ PJ_LP pj_hgrid_value(PJ *P, const ListOfHGrids &grids, PJ_LP lp) { HorizontalShiftGridSet *gridset = nullptr; const auto grid = findGrid(grids, lp, gridset); if (!grid) { - pj_ctx_set_errno(P->ctx, PJD_ERR_GRID_AREA); + proj_context_errno_set(P->ctx, PJD_ERR_GRID_AREA); return out; } @@ -3107,7 +3107,7 @@ PJ_LP pj_hgrid_value(PJ *P, const ListOfHGrids &grids, PJ_LP lp) { if (!extent.isGeographic) { pj_log(P->ctx, PJ_LOG_ERROR, "Can only handle grids referenced in a geographic CRS"); - pj_ctx_set_errno(P->ctx, PJD_ERR_FAILED_TO_LOAD_GRID); + proj_context_errno_set(P->ctx, PJD_ERR_FAILED_TO_LOAD_GRID); return out; } @@ -3130,7 +3130,7 @@ PJ_LP pj_hgrid_value(PJ *P, const ListOfHGrids &grids, PJ_LP lp) { } if (out.lam == HUGE_VAL || out.phi == HUGE_VAL) { - pj_ctx_set_errno(P->ctx, PJD_ERR_GRID_AREA); + proj_context_errno_set(P->ctx, PJD_ERR_GRID_AREA); } return out; @@ -3157,7 +3157,7 @@ static double read_vgrid_value(PJ_CONTEXT *ctx, const ListOfVGrids &grids, } } if (!grid) { - pj_ctx_set_errno(ctx, PJD_ERR_GRID_AREA); + proj_context_errno_set(ctx, PJD_ERR_GRID_AREA); return HUGE_VAL; } if (grid->isNullGrid()) { @@ -3168,7 +3168,7 @@ static double read_vgrid_value(PJ_CONTEXT *ctx, const ListOfVGrids &grids, if (!extent.isGeographic) { pj_log(ctx, PJ_LOG_ERROR, "Can only handle grids referenced in a geographic CRS"); - pj_ctx_set_errno(ctx, PJD_ERR_FAILED_TO_LOAD_GRID); + proj_context_errno_set(ctx, PJD_ERR_FAILED_TO_LOAD_GRID); return HUGE_VAL; } @@ -3200,7 +3200,7 @@ static double read_vgrid_value(PJ_CONTEXT *ctx, const ListOfVGrids &grids, if (!(grid_ix >= 0 && grid_ix < grid->width())) { // in the unlikely case we end up here... pj_log(ctx, PJ_LOG_ERROR, "grid_ix not in grid"); - pj_ctx_set_errno(ctx, PJD_ERR_GRID_AREA); + proj_context_errno_set(ctx, PJD_ERR_GRID_AREA); return HUGE_VAL; } int grid_iy = static_cast(lround(floor(grid_y))); @@ -3309,11 +3309,11 @@ ListOfVGrids pj_vgrid_init(PJ *P, const char *gridkey) { if (!gridSet) { if (!canFail) { if (proj_context_errno(P->ctx) != PJD_ERR_NETWORK_ERROR) { - pj_ctx_set_errno(P->ctx, PJD_ERR_FAILED_TO_LOAD_GRID); + proj_context_errno_set(P->ctx, PJD_ERR_FAILED_TO_LOAD_GRID); } return {}; } - pj_ctx_set_errno(P->ctx, 0); // don't treat as a persistent error + proj_context_errno_set(P->ctx, 0); // don't treat as a persistent error } else { grids.emplace_back(std::move(gridSet)); } @@ -3377,7 +3377,7 @@ bool pj_bilinear_interpolation_three_samples( if (!extent.isGeographic) { pj_log(ctx, PJ_LOG_ERROR, "Can only handle grids referenced in a geographic CRS"); - pj_ctx_set_errno(ctx, PJD_ERR_FAILED_TO_LOAD_GRID); + proj_context_errno_set(ctx, PJD_ERR_FAILED_TO_LOAD_GRID); return false; } @@ -3459,7 +3459,7 @@ int pj_apply_gridshift(PJ_CONTEXT *ctx, const char *nadgrids, int inverse, { auto hgrids = NS_PROJ::getListOfGridSets(ctx, nadgrids); if (hgrids.empty()) { - pj_ctx_set_errno(ctx, PJD_ERR_FAILED_TO_LOAD_GRID); + proj_context_errno_set(ctx, PJD_ERR_FAILED_TO_LOAD_GRID); return 1; } diff --git a/src/init.cpp b/src/init.cpp index a42bf963..2d679618 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -257,7 +257,7 @@ Expand key from buffer or (if not in buffer) from init file PJ* src; const char* proj_string; - pj_ctx_set_errno( ctx, 0 ); + proj_context_errno_set( ctx, 0 ); if( !allow_init_epsg ) { pj_log (ctx, PJ_LOG_TRACE, "%s expansion disallowed", xkey); @@ -448,7 +448,7 @@ pj_init_plus_ctx( PJ_CONTEXT *ctx, const char *definition ) if( argc+1 == MAX_ARG ) { pj_dalloc( defn_copy ); - pj_ctx_set_errno( ctx, PJD_ERR_UNPARSEABLE_CS_DEF ); + proj_context_errno_set( ctx, PJD_ERR_UNPARSEABLE_CS_DEF ); return nullptr; } @@ -538,7 +538,7 @@ pj_init_ctx_with_allow_init_epsg(PJ_CONTEXT *ctx, int argc, char **argv, int all ctx->last_errno = 0; if (argc <= 0) { - pj_ctx_set_errno (ctx, PJD_ERR_NO_ARGS); + proj_context_errno_set (ctx, PJD_ERR_NO_ARGS); return nullptr; } @@ -552,13 +552,13 @@ pj_init_ctx_with_allow_init_epsg(PJ_CONTEXT *ctx, int argc, char **argv, int all /* can't have nested pipelines directly */ if (n_pipelines > 1) { - pj_ctx_set_errno (ctx, PJD_ERR_MALFORMED_PIPELINE); + proj_context_errno_set (ctx, PJD_ERR_MALFORMED_PIPELINE); return nullptr; } /* don't allow more than one +init in non-pipeline operations */ if (n_pipelines == 0 && n_inits > 1) { - pj_ctx_set_errno (ctx, PJD_ERR_TOO_MANY_INITS); + proj_context_errno_set (ctx, PJD_ERR_TOO_MANY_INITS); return nullptr; } diff --git a/src/internal.cpp b/src/internal.cpp index 32dc1bba..c1ffc408 100644 --- a/src/internal.cpp +++ b/src/internal.cpp @@ -141,15 +141,15 @@ Check if a a PJ has an inverse. void proj_context_set (PJ *P, PJ_CONTEXT *ctx) { if (nullptr==ctx) ctx = pj_get_default_ctx (); - pj_set_ctx (P, ctx); + proj_assign_context (P, ctx); } void proj_context_inherit (PJ *parent, PJ *child) { if (nullptr==parent) - pj_set_ctx (child, pj_get_default_ctx()); + proj_assign_context (child, pj_get_default_ctx()); else - pj_set_ctx (child, pj_get_ctx(parent)); + proj_assign_context (child, pj_get_ctx(parent)); } @@ -411,7 +411,11 @@ to that context. ******************************************************************************/ if (nullptr==ctx) ctx = pj_get_default_ctx(); - pj_ctx_set_errno (ctx, err); + ctx->last_errno = err; + if( err == 0 ) + return; + errno = err; + pj_errno = err; } /* logging */ diff --git a/src/iso19111/c_api.cpp b/src/iso19111/c_api.cpp index cbbdcaa8..d6308c49 100644 --- a/src/iso19111/c_api.cpp +++ b/src/iso19111/c_api.cpp @@ -79,10 +79,10 @@ 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); + auto previous_errno = proj_context_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); + proj_context_errno_set(ctx, PJD_ERR_GENERIC_ERROR); } } diff --git a/src/iso19111/datum.cpp b/src/iso19111/datum.cpp index 4d7e78d3..60244779 100644 --- a/src/iso19111/datum.cpp +++ b/src/iso19111/datum.cpp @@ -417,7 +417,7 @@ std::string PrimeMeridian::getPROJStringWellKnownName(const common::Angle &angle) { const double valRad = angle.getSIValue(); std::string projPMName; - PJ_CONTEXT *ctxt = pj_ctx_alloc(); + PJ_CONTEXT *ctxt = proj_context_create(); auto proj_pm = proj_list_prime_meridians(); for (int i = 0; proj_pm[i].id != nullptr; ++i) { double valRefRad = dmstor_ctx(ctxt, proj_pm[i].defn, nullptr); @@ -426,7 +426,7 @@ PrimeMeridian::getPROJStringWellKnownName(const common::Angle &angle) { break; } } - pj_ctx_free(ctxt); + proj_context_destroy(ctxt); return projPMName; } //! @endcond diff --git a/src/malloc.cpp b/src/malloc.cpp index eb64023f..b1bcea1d 100644 --- a/src/malloc.cpp +++ b/src/malloc.cpp @@ -166,7 +166,7 @@ void *pj_dealloc_params (PJ_CONTEXT *ctx, paralist *start, int errlev) { n = t->next; pj_dealloc(t); } - pj_ctx_set_errno (ctx, errlev); + proj_context_errno_set (ctx, errlev); return (void *) nullptr; } @@ -218,7 +218,7 @@ PJ *pj_default_destructor (PJ *P, int errlev) { /* Destructor */ /* Note that both, in the multithreaded case, may then contain undefined */ /* values. This is expected behavior. For MT have one ctx per thread */ if (0!=errlev) - pj_ctx_set_errno (pj_get_ctx(P), errlev); + proj_context_errno_set (pj_get_ctx(P), errlev); if (nullptr==P) return nullptr; diff --git a/src/mlfn.hpp b/src/mlfn.hpp index e7138c63..228c65a4 100644 --- a/src/mlfn.hpp +++ b/src/mlfn.hpp @@ -66,7 +66,7 @@ inline_pj_inv_mlfn(PJ_CONTEXT *ctx, double arg, double es, const double *en, } *sinphi = s; *cosphi = c; - pj_ctx_set_errno( ctx, PJD_ERR_NON_CONV_INV_MERI_DIST ); + proj_context_errno_set( ctx, PJD_ERR_NON_CONV_INV_MERI_DIST ); return phi; } diff --git a/src/networkfilemanager.cpp b/src/networkfilemanager.cpp index f6521ed2..9edffaad 100644 --- a/src/networkfilemanager.cpp +++ b/src/networkfilemanager.cpp @@ -1315,7 +1315,7 @@ std::unique_ptr NetworkFile::open(PJ_CONTEXT *ctx, const char *filename) { errorBuffer.resize(strlen(errorBuffer.data())); pj_log(ctx, PJ_LOG_ERROR, "Cannot open %s: %s", filename, errorBuffer.c_str()); - pj_ctx_set_errno(ctx, PJD_ERR_NETWORK_ERROR); + proj_context_errno_set(ctx, PJD_ERR_NETWORK_ERROR); } bool ok = false; @@ -1404,7 +1404,7 @@ size_t NetworkFile::read(void *buffer, size_t sizeBytes) { &nRead, errorBuffer.size(), &errorBuffer[0], m_ctx->networking.user_data); if (!m_handle) { - pj_ctx_set_errno(m_ctx, PJD_ERR_NETWORK_ERROR); + proj_context_errno_set(m_ctx, PJD_ERR_NETWORK_ERROR); return 0; } } else { @@ -1420,7 +1420,7 @@ size_t NetworkFile::read(void *buffer, size_t sizeBytes) { pj_log(m_ctx, PJ_LOG_ERROR, "Cannot read in %s: %s", m_url.c_str(), errorBuffer.c_str()); } - pj_ctx_set_errno(m_ctx, PJD_ERR_NETWORK_ERROR); + proj_context_errno_set(m_ctx, PJD_ERR_NETWORK_ERROR); return 0; } diff --git a/src/param.cpp b/src/param.cpp index 9a3888e1..3e13b391 100644 --- a/src/param.cpp +++ b/src/param.cpp @@ -220,7 +220,7 @@ PROJVALUE pj_param (PJ_CONTEXT *ctx, paralist *pl, const char *opt) { value.i = 1; break; default: - pj_ctx_set_errno (ctx, PJD_ERR_INVALID_BOOLEAN_PARAM); + proj_context_errno_set (ctx, PJD_ERR_INVALID_BOOLEAN_PARAM); value.i = 0; break; } diff --git a/src/phi2.cpp b/src/phi2.cpp index 214d1058..2f258e47 100644 --- a/src/phi2.cpp +++ b/src/phi2.cpp @@ -103,7 +103,7 @@ double pj_sinhpsi2tanphi(PJ_CONTEXT *ctx, const double taup, const double e) { break; } if (i == 0) - pj_ctx_set_errno(ctx, PJD_ERR_NON_CONV_SINHPSI2TANPHI); + proj_context_errno_set(ctx, PJD_ERR_NON_CONV_SINHPSI2TANPHI); return tau; } diff --git a/src/proj_internal.h b/src/proj_internal.h index 3c1571eb..d9b01ab2 100644 --- a/src/proj_internal.h +++ b/src/proj_internal.h @@ -976,16 +976,6 @@ void PROJ_DLL pj_acquire_lock(void); void PROJ_DLL pj_release_lock(void); void PROJ_DLL pj_cleanup_lock(void); -void PROJ_DLL pj_set_ctx( PJ *, PJ_CONTEXT * ); -PJ_CONTEXT PROJ_DLL *pj_ctx_alloc(void); -void PROJ_DLL pj_ctx_free( PJ_CONTEXT * ); -int PROJ_DLL pj_ctx_get_errno( PJ_CONTEXT * ); -void PROJ_DLL pj_ctx_set_errno( PJ_CONTEXT *, int ); -void PROJ_DLL pj_ctx_set_debug( PJ_CONTEXT *, int ); -void PROJ_DLL pj_ctx_set_logger( PJ_CONTEXT *, void (*)(void *, int, const char *) ); -void PROJ_DLL pj_ctx_set_app_data( PJ_CONTEXT *, void * ); -void PROJ_DLL *pj_ctx_get_app_data( PJ_CONTEXT * ); - void PROJ_DLL pj_log( PJ_CONTEXT * ctx, int level, const char *fmt, ... ); void PROJ_DLL pj_stderr_logger( void *, int, const char * ); diff --git a/src/proj_mdist.cpp b/src/proj_mdist.cpp index 086521b7..ed07ffd1 100644 --- a/src/proj_mdist.cpp +++ b/src/proj_mdist.cpp @@ -124,6 +124,6 @@ proj_inv_mdist(PJ_CONTEXT *ctx, double dist, const void *data) { return phi; } /* convergence failed */ - pj_ctx_set_errno(ctx, PJD_ERR_NON_CONV_INV_MERI_DIST); + proj_context_errno_set(ctx, PJD_ERR_NON_CONV_INV_MERI_DIST); return phi; } diff --git a/src/projections/aitoff.cpp b/src/projections/aitoff.cpp index 7920309c..d02e7761 100644 --- a/src/projections/aitoff.cpp +++ b/src/projections/aitoff.cpp @@ -170,7 +170,7 @@ static PJ_LP aitoff_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inver if (iter == MAXITER && round == MAXROUND) { - pj_ctx_set_errno( P->ctx, PJD_ERR_NON_CONVERGENT ); + proj_context_errno_set( 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); */ } diff --git a/src/projections/comill.cpp b/src/projections/comill.cpp index 189e583e..44524990 100644 --- a/src/projections/comill.cpp +++ b/src/projections/comill.cpp @@ -66,7 +66,7 @@ static PJ_LP comill_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inver } } if( i == 0 ) - pj_ctx_set_errno( P->ctx, PJD_ERR_NON_CONVERGENT ); + proj_context_errno_set( P->ctx, PJD_ERR_NON_CONVERGENT ); lp.phi = yc; /* longitude */ diff --git a/src/projections/eqearth.cpp b/src/projections/eqearth.cpp index 832c9444..60effde0 100644 --- a/src/projections/eqearth.cpp +++ b/src/projections/eqearth.cpp @@ -110,7 +110,7 @@ static PJ_LP eqearth_e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal/sphe } if( i == 0 ) { - pj_ctx_set_errno( P->ctx, PJD_ERR_NON_CONVERGENT ); + proj_context_errno_set( P->ctx, PJD_ERR_NON_CONVERGENT ); return lp; } diff --git a/src/projections/healpix.cpp b/src/projections/healpix.cpp index aab5c41e..5a06125d 100644 --- a/src/projections/healpix.cpp +++ b/src/projections/healpix.cpp @@ -524,7 +524,7 @@ static PJ_LP s_healpix_inverse(PJ_XY xy, PJ *P) { /* sphere */ PJ_LP lp; lp.lam = HUGE_VAL; lp.phi = HUGE_VAL; - pj_ctx_set_errno(P->ctx, PJD_ERR_INVALID_X_OR_Y); + proj_context_errno_set(P->ctx, PJD_ERR_INVALID_X_OR_Y); return lp; } return healpix_spherhealpix_e_inverse(xy); @@ -540,7 +540,7 @@ static PJ_LP e_healpix_inverse(PJ_XY xy, PJ *P) { /* ellipsoid */ if (in_image(xy.x, xy.y, 0, 0, 0) == 0) { lp.lam = HUGE_VAL; lp.phi = HUGE_VAL; - pj_ctx_set_errno(P->ctx, PJD_ERR_INVALID_X_OR_Y); + proj_context_errno_set(P->ctx, PJD_ERR_INVALID_X_OR_Y); return lp; } lp = healpix_spherhealpix_e_inverse(xy); @@ -574,7 +574,7 @@ static PJ_LP s_rhealpix_inverse(PJ_XY xy, PJ *P) { /* sphere */ PJ_LP lp; lp.lam = HUGE_VAL; lp.phi = HUGE_VAL; - pj_ctx_set_errno(P->ctx, PJD_ERR_INVALID_X_OR_Y); + proj_context_errno_set(P->ctx, PJD_ERR_INVALID_X_OR_Y); return lp; } xy = combine_caps(xy.x, xy.y, Q->north_square, Q->south_square, 1); @@ -590,7 +590,7 @@ static PJ_LP e_rhealpix_inverse(PJ_XY xy, PJ *P) { /* ellipsoid */ if (in_image(xy.x, xy.y, 1, Q->north_square, Q->south_square) == 0) { lp.lam = HUGE_VAL; lp.phi = HUGE_VAL; - pj_ctx_set_errno(P->ctx, PJD_ERR_INVALID_X_OR_Y); + proj_context_errno_set(P->ctx, PJD_ERR_INVALID_X_OR_Y); return lp; } xy = combine_caps(xy.x, xy.y, Q->north_square, Q->south_square, 1); diff --git a/src/projections/krovak.cpp b/src/projections/krovak.cpp index aef44d42..3e6a5c30 100644 --- a/src/projections/krovak.cpp +++ b/src/projections/krovak.cpp @@ -181,7 +181,7 @@ static PJ_LP krovak_e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, fi1 = lp.phi; } if( i == 0 ) - pj_ctx_set_errno( P->ctx, PJD_ERR_NON_CONVERGENT ); + proj_context_errno_set( P->ctx, PJD_ERR_NON_CONVERGENT ); lp.lam -= P->lam0; diff --git a/src/projections/natearth.cpp b/src/projections/natearth.cpp index 5c096605..e1f71089 100644 --- a/src/projections/natearth.cpp +++ b/src/projections/natearth.cpp @@ -82,7 +82,7 @@ static PJ_LP natearth_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inv } } if( i == 0 ) - pj_ctx_set_errno( P->ctx, PJD_ERR_NON_CONVERGENT ); + proj_context_errno_set( P->ctx, PJD_ERR_NON_CONVERGENT ); lp.phi = yc; /* longitude */ diff --git a/src/projections/natearth2.cpp b/src/projections/natearth2.cpp index d149ca85..e4516a0a 100644 --- a/src/projections/natearth2.cpp +++ b/src/projections/natearth2.cpp @@ -76,7 +76,7 @@ static PJ_LP natearth2_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, in } } if( i == 0 ) - pj_ctx_set_errno( P->ctx, PJD_ERR_NON_CONVERGENT ); + proj_context_errno_set( P->ctx, PJD_ERR_NON_CONVERGENT ); lp.phi = yc; /* longitude */ diff --git a/src/projections/ortho.cpp b/src/projections/ortho.cpp index 8dcfb53c..d9c84dba 100644 --- a/src/projections/ortho.cpp +++ b/src/projections/ortho.cpp @@ -273,7 +273,7 @@ static PJ_LP ortho_e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inver return lp; } } - pj_ctx_set_errno(P->ctx, PJD_ERR_NON_CONVERGENT); + proj_context_errno_set(P->ctx, PJD_ERR_NON_CONVERGENT); return lp; } diff --git a/src/projections/patterson.cpp b/src/projections/patterson.cpp index 71099cdb..32544580 100644 --- a/src/projections/patterson.cpp +++ b/src/projections/patterson.cpp @@ -100,7 +100,7 @@ static PJ_LP patterson_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, in } } if( i == 0 ) - pj_ctx_set_errno( P->ctx, PJD_ERR_NON_CONVERGENT ); + proj_context_errno_set( P->ctx, PJD_ERR_NON_CONVERGENT ); lp.phi = yc; /* longitude */ diff --git a/src/projections/robin.cpp b/src/projections/robin.cpp index 8b646502..6a1405b6 100644 --- a/src/projections/robin.cpp +++ b/src/projections/robin.cpp @@ -138,7 +138,7 @@ static PJ_LP robin_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, invers break; } if( iters == 0 ) - pj_ctx_set_errno( P->ctx, PJD_ERR_NON_CONVERGENT ); + proj_context_errno_set( P->ctx, PJD_ERR_NON_CONVERGENT ); lp.phi = (5 * i + t) * DEG_TO_RAD; if (xy.y < 0.) lp.phi = -lp.phi; lp.lam /= V(X[i], t); diff --git a/src/projections/tmerc.cpp b/src/projections/tmerc.cpp index 69f4d352..ff1bc2a5 100644 --- a/src/projections/tmerc.cpp +++ b/src/projections/tmerc.cpp @@ -89,7 +89,7 @@ static PJ_XY approx_e_fwd (PJ_LP lp, PJ *P) if( lp.lam < -M_HALFPI || lp.lam > M_HALFPI ) { xy.x = HUGE_VAL; xy.y = HUGE_VAL; - pj_ctx_set_errno( P->ctx, PJD_ERR_LAT_OR_LON_EXCEED_LIMIT ); + proj_context_errno_set( P->ctx, PJD_ERR_LAT_OR_LON_EXCEED_LIMIT ); return xy; } @@ -130,7 +130,7 @@ static PJ_XY approx_s_fwd (PJ_LP lp, PJ *P) { if( lp.lam < -M_HALFPI || lp.lam > M_HALFPI ) { xy.x = HUGE_VAL; xy.y = HUGE_VAL; - pj_ctx_set_errno( P->ctx, PJD_ERR_LAT_OR_LON_EXCEED_LIMIT ); + proj_context_errno_set( P->ctx, PJD_ERR_LAT_OR_LON_EXCEED_LIMIT ); return xy; } @@ -679,7 +679,7 @@ static bool getAlgoFromParams(PJ* P, TMercAlgo& algo) else { pj_load_ini(P->ctx); // if not already done - pj_ctx_set_errno(P->ctx, 0); // reset error in case proj.ini couldn't be found + proj_context_errno_set(P->ctx, 0); // reset error in case proj.ini couldn't be found algo = P->ctx->defaultTmercAlgo; } diff --git a/src/utils.cpp b/src/utils.cpp index d3ec7e35..82449617 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -117,7 +117,7 @@ PJ *pj_latlong_from_proj( PJ *pj_in ) } else { - pj_ctx_set_errno( pj_in->ctx, PJD_ERR_MAJOR_AXIS_NOT_GIVEN ); + proj_context_errno_set( pj_in->ctx, PJD_ERR_MAJOR_AXIS_NOT_GIVEN ); return nullptr; } -- cgit v1.2.3 From 8e13c3acd86d1705ed865093f000835b51aec63e Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Tue, 17 Nov 2020 21:34:13 +0100 Subject: Removed unused functions from src/utils.cpp --- src/Makefile.am | 1 - src/lib_proj.cmake | 1 - src/proj_internal.h | 4 -- src/utils.cpp | 182 ---------------------------------------------------- 4 files changed, 188 deletions(-) delete mode 100644 src/utils.cpp diff --git a/src/Makefile.am b/src/Makefile.am index 2c175e42..e394b95b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -220,7 +220,6 @@ libproj_la_SOURCES = \ quadtree.hpp \ \ datums.cpp datum_set.cpp \ - utils.cpp \ mutex.cpp initcache.cpp geodesic.c \ strtod.cpp \ \ diff --git a/src/lib_proj.cmake b/src/lib_proj.cmake index 997eb22d..1361294d 100644 --- a/src/lib_proj.cmake +++ b/src/lib_proj.cmake @@ -247,7 +247,6 @@ set(SRC_LIBPROJ_CORE strtod.cpp tsfn.cpp units.cpp - utils.cpp wkt1_generated_parser.c wkt1_generated_parser.h wkt1_parser.cpp diff --git a/src/proj_internal.h b/src/proj_internal.h index d9b01ab2..e83c6f88 100644 --- a/src/proj_internal.h +++ b/src/proj_internal.h @@ -948,9 +948,6 @@ int PROJ_DLL pj_apply_gridshift( PJ_CONTEXT *, const char *, int, long point_count, int point_offset, double *x, double *y, double *z ); void PROJ_DLL pj_clear_initcache(void); -int PROJ_DLL pj_is_latlong(PJ *); -int PROJ_DLL pj_is_geocent(PJ *); -void PROJ_DLL pj_get_spheroid_defn(PJ *defn, double *major_axis, double *eccentricity_squared); void PROJ_DLL pj_pr_list(PJ *); void PROJ_DLL pj_free(PJ *); void PROJ_DLL pj_set_finder( const char *(*)(const char *) ); @@ -960,7 +957,6 @@ PJ PROJ_DLL *pj_init_plus(const char *); PJ PROJ_DLL *pj_init_ctx( PJ_CONTEXT *, int, char ** ); PJ PROJ_DLL *pj_init_plus_ctx( PJ_CONTEXT *, const char * ); char PROJ_DLL *pj_get_def(PJ *, int); -PJ PROJ_DLL *pj_latlong_from_proj( PJ *); int PROJ_DLL pj_has_inverse(PJ *); diff --git a/src/utils.cpp b/src/utils.cpp deleted file mode 100644 index 82449617..00000000 --- a/src/utils.cpp +++ /dev/null @@ -1,182 +0,0 @@ -/****************************************************************************** - * Project: PROJ.4 - * Purpose: Some utility functions we don't want to bother putting in - * their own source files. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 2001, Frank Warmerdam - * - * 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. - *****************************************************************************/ - -#define PJ_LIB__ - -#include -#include - -#include "proj.h" -#include "proj_internal.h" - -/************************************************************************/ -/* pj_is_latlong() */ -/* */ -/* Returns TRUE if this coordinate system object is */ -/* geographic. */ -/************************************************************************/ - -int pj_is_latlong( PJ *pj ) - -{ - return pj == nullptr || pj->is_latlong; -} - -/************************************************************************/ -/* pj_is_geocent() */ -/* */ -/* Returns TRUE if this coordinate system object is geocentric. */ -/************************************************************************/ - -int pj_is_geocent( PJ *pj ) - -{ - return pj != nullptr && pj->is_geocent; -} - -/************************************************************************/ -/* pj_latlong_from_proj() */ -/* */ -/* Return a PJ* definition defining the lat/long coordinate */ -/* system on which a projection is based. If the coordinate */ -/* system passed in is latlong, a clone of the same will be */ -/* returned. */ -/************************************************************************/ - -PJ *pj_latlong_from_proj( PJ *pj_in ) - -{ - char defn[512]; - int got_datum = FALSE; - - pj_errno = 0; - strcpy( defn, "+proj=latlong" ); - - if( pj_param(pj_in->ctx, pj_in->params, "tdatum").i ) - { - got_datum = TRUE; - sprintf( defn+strlen(defn), " +datum=%s", - pj_param(pj_in->ctx, pj_in->params,"sdatum").s ); - } - else if( pj_param(pj_in->ctx, pj_in->params, "tellps").i ) - { - sprintf( defn+strlen(defn), " +ellps=%s", - pj_param(pj_in->ctx, pj_in->params,"sellps").s ); - } - else if( pj_param(pj_in->ctx,pj_in->params, "ta").i ) - { - sprintf( defn+strlen(defn), " +a=%s", - pj_param(pj_in->ctx,pj_in->params,"sa").s ); - - if( pj_param(pj_in->ctx,pj_in->params, "tb").i ) - sprintf( defn+strlen(defn), " +b=%s", - pj_param(pj_in->ctx,pj_in->params,"sb").s ); - else if( pj_param(pj_in->ctx,pj_in->params, "tes").i ) - sprintf( defn+strlen(defn), " +es=%s", - pj_param(pj_in->ctx,pj_in->params,"ses").s ); - else if( pj_param(pj_in->ctx,pj_in->params, "tf").i ) - sprintf( defn+strlen(defn), " +f=%s", - pj_param(pj_in->ctx,pj_in->params,"sf").s ); - else - { - char* ptr = defn+strlen(defn); - sprintf( ptr, " +es=%.16g", pj_in->es ); - /* TODO later: use C++ ostringstream with imbue(std::locale::classic()) */ - /* to be locale unaware */ - for(; *ptr; ptr++) - { - if( *ptr == ',' ) - *ptr = '.'; - } - } - } - else - { - proj_context_errno_set( pj_in->ctx, PJD_ERR_MAJOR_AXIS_NOT_GIVEN ); - - return nullptr; - } - - if( !got_datum ) - { - if( pj_param(pj_in->ctx,pj_in->params, "ttowgs84").i ) - sprintf( defn+strlen(defn), " +towgs84=%s", - pj_param(pj_in->ctx,pj_in->params,"stowgs84").s ); - - if( pj_param(pj_in->ctx,pj_in->params, "tnadgrids").i ) - sprintf( defn+strlen(defn), " +nadgrids=%s", - pj_param(pj_in->ctx,pj_in->params,"snadgrids").s ); - } - - /* copy over some other information related to ellipsoid */ - if( pj_param(pj_in->ctx,pj_in->params, "tR").i ) - sprintf( defn+strlen(defn), " +R=%s", - pj_param(pj_in->ctx,pj_in->params,"sR").s ); - - if( pj_param(pj_in->ctx,pj_in->params, "tR_A").i ) - sprintf( defn+strlen(defn), " +R_A" ); - - if( pj_param(pj_in->ctx,pj_in->params, "tR_V").i ) - sprintf( defn+strlen(defn), " +R_V" ); - - if( pj_param(pj_in->ctx,pj_in->params, "tR_a").i ) - sprintf( defn+strlen(defn), " +R_a" ); - - if( pj_param(pj_in->ctx,pj_in->params, "tR_lat_a").i ) - sprintf( defn+strlen(defn), " +R_lat_a=%s", - pj_param(pj_in->ctx,pj_in->params,"sR_lat_a").s ); - - if( pj_param(pj_in->ctx,pj_in->params, "tR_lat_g").i ) - sprintf( defn+strlen(defn), " +R_lat_g=%s", - pj_param(pj_in->ctx,pj_in->params,"sR_lat_g").s ); - - /* copy over prime meridian */ - if( pj_param(pj_in->ctx,pj_in->params, "tpm").i ) - sprintf( defn+strlen(defn), " +pm=%s", - pj_param(pj_in->ctx,pj_in->params,"spm").s ); - - return pj_init_plus_ctx( pj_in->ctx, defn ); -} - -/************************************************************************/ -/* pj_get_spheroid_defn() */ -/* */ -/* Fetch the internal definition of the spheroid. Note that */ -/* you can compute "b" from eccentricity_squared as: */ -/* */ -/* b = a * sqrt(1 - es) */ -/************************************************************************/ - -void pj_get_spheroid_defn(PJ * defn, double *major_axis, double *eccentricity_squared) -{ - if ( major_axis ) - *major_axis = defn->a; - - if ( eccentricity_squared ) - *eccentricity_squared = defn->es; -} -- cgit v1.2.3 From eb04ffca4c62d48378ff4c4ffe230de76d218b64 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Wed, 18 Nov 2020 09:16:34 +0100 Subject: Remove unused pj_apply_gridshift() --- src/grids.cpp | 46 ---------------------------------------------- src/proj_internal.h | 3 --- 2 files changed, 49 deletions(-) diff --git a/src/grids.cpp b/src/grids.cpp index 671485d7..8bb865d8 100644 --- a/src/grids.cpp +++ b/src/grids.cpp @@ -3443,49 +3443,3 @@ bool pj_bilinear_interpolation_three_samples( NS_PROJ_END -/************************************************************************/ -/* pj_apply_gridshift() */ -/* */ -/* This is the externally callable interface - part of the */ -/* public API - though it is not used internally any more and I */ -/* doubt it is used by any other applications. But we preserve */ -/* it to honour our public api. */ -/************************************************************************/ - -int pj_apply_gridshift(PJ_CONTEXT *ctx, const char *nadgrids, int inverse, - long point_count, int point_offset, double *x, double *y, - double * /*z */) - -{ - auto hgrids = NS_PROJ::getListOfGridSets(ctx, nadgrids); - if (hgrids.empty()) { - proj_context_errno_set(ctx, PJD_ERR_FAILED_TO_LOAD_GRID); - return 1; - } - - for (long i = 0; i < point_count; i++) { - PJ_LP input; - - long io = i * point_offset; - input.phi = y[io]; - input.lam = x[io]; - - auto output = - pj_hgrid_apply(ctx, hgrids, input, inverse ? PJ_INV : PJ_FWD); - - if (output.lam != HUGE_VAL) { - y[io] = output.phi; - x[io] = output.lam; - } else { - if (ctx->debug_level >= PJ_LOG_DEBUG_MAJOR) { - pj_log(ctx, PJ_LOG_DEBUG_MAJOR, - "pj_apply_gridshift(): failed to find a grid shift " - "table for\n" - " location (%.7fdW,%.7fdN)", - x[io] * RAD_TO_DEG, y[io] * RAD_TO_DEG); - } - } - } - - return 0; -} diff --git a/src/proj_internal.h b/src/proj_internal.h index e83c6f88..2915284c 100644 --- a/src/proj_internal.h +++ b/src/proj_internal.h @@ -944,9 +944,6 @@ PJ_XYZ PROJ_DLL pj_fwd3d(PJ_LPZ, PJ *); PJ_LPZ PROJ_DLL pj_inv3d(PJ_XYZ, PJ *); -int PROJ_DLL pj_apply_gridshift( PJ_CONTEXT *, const char *, int, - long point_count, int point_offset, - double *x, double *y, double *z ); void PROJ_DLL pj_clear_initcache(void); void PROJ_DLL pj_pr_list(PJ *); void PROJ_DLL pj_free(PJ *); -- cgit v1.2.3 From ddb3b8da0756acbb8713aeb452de209eb350e996 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Wed, 18 Nov 2020 09:32:45 +0100 Subject: Removed unused function pj_set_searchpath() and pj_set_finder() --- src/ctx.cpp | 1 - src/filemanager.cpp | 30 ------------------------------ src/proj_internal.h | 2 -- 3 files changed, 33 deletions(-) diff --git a/src/ctx.cpp b/src/ctx.cpp index 8e25db2a..2093950b 100644 --- a/src/ctx.cpp +++ b/src/ctx.cpp @@ -163,7 +163,6 @@ pj_ctx::pj_ctx(const pj_ctx& other) : epsg_file_exists(other.epsg_file_exists), ca_bundle_path(other.ca_bundle_path), env_var_proj_lib(other.env_var_proj_lib), - file_finder_legacy(other.file_finder_legacy), file_finder(other.file_finder), file_finder_user_data(other.file_finder_user_data), custom_sqlite3_vfs_name(other.custom_sqlite3_vfs_name), diff --git a/src/filemanager.cpp b/src/filemanager.cpp index dbcb8ddc..b3b074a2 100644 --- a/src/filemanager.cpp +++ b/src/filemanager.cpp @@ -1418,10 +1418,6 @@ pj_open_lib_internal(PJ_CONTEXT *ctx, const char *name, const char *mode, ctx, name, ctx->file_finder_user_data)) != nullptr) ; - else if (ctx->file_finder_legacy != nullptr && - (sysname = ctx->file_finder_legacy(name)) != nullptr) - ; - /* The user has search paths set */ else if (!ctx->search_paths.empty()) { for (const auto &path : ctx->search_paths) { @@ -1795,19 +1791,6 @@ void pj_load_ini(PJ_CONTEXT *ctx) { //! @endcond -/************************************************************************/ -/* pj_set_finder() */ -/************************************************************************/ - -void pj_set_finder(const char *(*new_finder)(const char *)) - -{ - auto ctx = pj_get_default_ctx(); - if (ctx) { - ctx->file_finder_legacy = new_finder; - } -} - /************************************************************************/ /* proj_context_set_file_finder() */ /************************************************************************/ @@ -1878,19 +1861,6 @@ void proj_context_set_search_paths(PJ_CONTEXT *ctx, int count_paths, } } -/************************************************************************/ -/* pj_set_searchpath() */ -/* */ -/* Path control for callers that can't practically provide */ -/* pj_set_finder() style callbacks. Call with (0,NULL) as args */ -/* to clear the searchpath set. */ -/************************************************************************/ - -void pj_set_searchpath(int count, const char **path) { - proj_context_set_search_paths(nullptr, count, - const_cast(path)); -} - /************************************************************************/ /* proj_context_set_ca_bundle_path() */ /************************************************************************/ diff --git a/src/proj_internal.h b/src/proj_internal.h index 2915284c..24c9b653 100644 --- a/src/proj_internal.h +++ b/src/proj_internal.h @@ -947,8 +947,6 @@ PJ_LPZ PROJ_DLL pj_inv3d(PJ_XYZ, PJ *); void PROJ_DLL pj_clear_initcache(void); void PROJ_DLL pj_pr_list(PJ *); void PROJ_DLL pj_free(PJ *); -void PROJ_DLL pj_set_finder( const char *(*)(const char *) ); -void PROJ_DLL pj_set_searchpath ( int count, const char **path ); PJ PROJ_DLL *pj_init(int, char **); PJ PROJ_DLL *pj_init_plus(const char *); PJ PROJ_DLL *pj_init_ctx( PJ_CONTEXT *, int, char ** ); -- cgit v1.2.3 From 43efca4ab87fb37a0931edcb6be11c0bd3784098 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Wed, 18 Nov 2020 09:57:42 +0100 Subject: Remove pj_free() and move it's functional parts to proj_destroy() --- src/4D_api.cpp | 6 +----- src/apps/cct.cpp | 2 +- src/apps/proj.cpp | 2 +- src/init.cpp | 4 ++-- src/malloc.cpp | 19 ++++++++++--------- src/proj_internal.h | 1 - src/projections/goode.cpp | 4 ++-- test/unit/gie_self_tests.cpp | 2 +- 8 files changed, 18 insertions(+), 22 deletions(-) diff --git a/src/4D_api.cpp b/src/4D_api.cpp index 70b04bf1..78e9bdc3 100644 --- a/src/4D_api.cpp +++ b/src/4D_api.cpp @@ -1353,10 +1353,6 @@ PJ *proj_create_crs_to_crs_from_pj (PJ_CONTEXT *ctx, const PJ *source_crs, cons return P; } -PJ *proj_destroy (PJ *P) { - pj_free (P); - return nullptr; -} /*****************************************************************************/ int proj_errno (const PJ *P) { @@ -1636,7 +1632,7 @@ PJ_PROJ_INFO proj_pj_info(PJ *P) { pjinfo.definition = empty; else pjinfo.definition = pj_shrink (def); - /* Make pj_free clean this up eventually */ + /* Make proj_destroy clean this up eventually */ P->def_full = def; pjinfo.has_inverse = pj_has_inverse(P); diff --git a/src/apps/cct.cpp b/src/apps/cct.cpp index fa75267a..e63a5fc2 100644 --- a/src/apps/cct.cpp +++ b/src/apps/cct.cpp @@ -387,7 +387,7 @@ int main(int argc, char **argv) { buf = static_cast(calloc (1, 10000)); if (nullptr==buf) { print (PJ_LOG_ERROR, "%s: Out of memory", o->progname); - pj_free (P); + proj_destroy (P); free (o); if (stdout != fout) fclose (fout); diff --git a/src/apps/proj.cpp b/src/apps/proj.cpp index c9bd8950..8bfd99a3 100644 --- a/src/apps/proj.cpp +++ b/src/apps/proj.cpp @@ -562,7 +562,7 @@ int main(int argc, char **argv) { } if( Proj ) - pj_free(Proj); + proj_destroy(Proj); exit(0); /* normal completion */ } diff --git a/src/init.cpp b/src/init.cpp index 2d679618..95bb404f 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1,7 +1,7 @@ /****************************************************************************** * Project: PROJ.4 * Purpose: Initialize projection object from string definition. Includes - * pj_init(), pj_init_plus() and pj_free() function. + * pj_init(), and pj_init_plus() function. * Author: Gerald Evenden, Frank Warmerdam * ****************************************************************************** @@ -829,7 +829,7 @@ pj_init_ctx_with_allow_init_epsg(PJ_CONTEXT *ctx, int argc, char **argv, int all err = proj_errno_reset (PIN); PIN = proj(PIN); if (proj_errno (PIN)) { - pj_free(PIN); + proj_destroy(PIN); return nullptr; } proj_errno_restore (PIN, err); diff --git a/src/malloc.cpp b/src/malloc.cpp index b1bcea1d..590dd27f 100644 --- a/src/malloc.cpp +++ b/src/malloc.cpp @@ -174,7 +174,7 @@ void *pj_dealloc_params (PJ_CONTEXT *ctx, paralist *start, int errlev) { /************************************************************************/ -/* pj_free() */ +/* proj_destroy() */ /* */ /* This is the application callable entry point for destroying */ /* a projection definition. It does work generic to all */ @@ -183,15 +183,16 @@ void *pj_dealloc_params (PJ_CONTEXT *ctx, paralist *start, int errlev) { /* In most cases P->destructor()==pj_default_destructor. */ /************************************************************************/ -void pj_free(PJ *P) { +PJ *proj_destroy(PJ *P) { if (nullptr==P || !P->destructor) - return; + return nullptr; /* free projection parameters - all the hard work is done by */ /* pj_default_destructor, which is supposed */ /* to be called as the last step of the local destructor */ /* pointed to by P->destructor. In most cases, */ /* pj_default_destructor actually *is* what is pointed to */ P->destructor (P, proj_errno(P)); + return nullptr; } /*****************************************************************************/ @@ -246,12 +247,12 @@ PJ *pj_default_destructor (PJ *P, int errlev) { /* Destructor */ pj_dealloc (P->def_full); /* free the cs2cs emulation elements */ - pj_free (P->axisswap); - pj_free (P->helmert); - pj_free (P->cart); - pj_free (P->cart_wgs84); - pj_free (P->hgridshift); - pj_free (P->vgridshift); + proj_destroy (P->axisswap); + proj_destroy (P->helmert); + proj_destroy (P->cart); + proj_destroy (P->cart_wgs84); + proj_destroy (P->hgridshift); + proj_destroy (P->vgridshift); pj_dealloc (static_cast(P->opaque)); delete P; diff --git a/src/proj_internal.h b/src/proj_internal.h index 24c9b653..d57e87a2 100644 --- a/src/proj_internal.h +++ b/src/proj_internal.h @@ -946,7 +946,6 @@ PJ_LPZ PROJ_DLL pj_inv3d(PJ_XYZ, PJ *); void PROJ_DLL pj_clear_initcache(void); void PROJ_DLL pj_pr_list(PJ *); -void PROJ_DLL pj_free(PJ *); PJ PROJ_DLL *pj_init(int, char **); PJ PROJ_DLL *pj_init_plus(const char *); PJ PROJ_DLL *pj_init_ctx( PJ_CONTEXT *, int, char ** ); diff --git a/src/projections/goode.cpp b/src/projections/goode.cpp index fdace387..9a6fb86c 100644 --- a/src/projections/goode.cpp +++ b/src/projections/goode.cpp @@ -54,8 +54,8 @@ static PJ *destructor (PJ *P, int errlev) { /* Destructor */ return nullptr; if (nullptr==P->opaque) return pj_default_destructor (P, errlev); - pj_free (static_cast(P->opaque)->sinu); - pj_free (static_cast(P->opaque)->moll); + proj_destroy (static_cast(P->opaque)->sinu); + proj_destroy (static_cast(P->opaque)->moll); return pj_default_destructor (P, errlev); } diff --git a/test/unit/gie_self_tests.cpp b/test/unit/gie_self_tests.cpp index 6f1b3c32..f9252137 100644 --- a/test/unit/gie_self_tests.cpp +++ b/test/unit/gie_self_tests.cpp @@ -548,7 +548,7 @@ static void test_time(const char *args, double tol, double t_in, double t_exp) { out = proj_trans(P, PJ_INV, out); EXPECT_NEAR(out.xyzt.t, t_in, tol); - pj_free(P); + proj_destroy(P); proj_log_level(NULL, PJ_LOG_NONE); } -- cgit v1.2.3 From 56f0ad70054eea15e9671cd67aafd14bf7c11c74 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Wed, 18 Nov 2020 10:43:16 +0100 Subject: Remove pj_errno and related functions --- src/4D_api.cpp | 1 - src/Makefile.am | 2 +- src/apps/cct.cpp | 4 ++-- src/apps/cs2cs.cpp | 2 +- src/apps/gie.cpp | 8 ++++---- src/apps/proj.cpp | 8 +++----- src/errno.cpp | 18 ------------------ src/internal.cpp | 1 - src/lib_proj.cmake | 1 - src/pipeline.cpp | 2 +- src/proj_internal.h | 3 --- src/strerrno.cpp | 13 +++++-------- 12 files changed, 17 insertions(+), 46 deletions(-) delete mode 100644 src/errno.cpp diff --git a/src/4D_api.cpp b/src/4D_api.cpp index 78e9bdc3..83fda02c 100644 --- a/src/4D_api.cpp +++ b/src/4D_api.cpp @@ -1438,7 +1438,6 @@ int proj_errno_reset (const PJ *P) { proj_context_errno_set (pj_get_ctx ((PJ *) P), 0); errno = 0; - pj_errno = 0; return last_errno; } diff --git a/src/Makefile.am b/src/Makefile.am index e394b95b..4f3db3ed 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -209,7 +209,7 @@ libproj_la_SOURCES = \ \ aasincos.cpp adjlon.cpp \ dmstor.cpp auth.cpp \ - deriv.cpp ell_set.cpp ellps.cpp errno.cpp \ + deriv.cpp ell_set.cpp ellps.cpp \ factors.cpp fwd.cpp init.cpp inv.cpp \ list.cpp malloc.cpp mlfn.cpp mlfn.hpp msfn.cpp proj_mdist.cpp \ param.cpp phi2.cpp pr_list.cpp \ diff --git a/src/apps/cct.cpp b/src/apps/cct.cpp index e63a5fc2..92867b3a 100644 --- a/src/apps/cct.cpp +++ b/src/apps/cct.cpp @@ -360,7 +360,7 @@ int main(int argc, char **argv) { if (nullptr==P) { print (PJ_LOG_ERROR, "%s: Bad transformation arguments - (%s)\n '%s -h' for help", - o->progname, pj_strerrno (proj_errno(P)), o->progname); + o->progname, proj_errno_string (proj_errno(P)), o->progname); free (o); if (stdout != fout) fclose (fout); @@ -435,7 +435,7 @@ int main(int argc, char **argv) { if (HUGE_VAL==point.xyzt.x) { /* transformation error */ print (PJ_LOG_NONE, "# Record %d TRANSFORMATION ERROR: %s (%s)", - (int) o->record_index, buf, pj_strerrno (proj_errno(P))); + (int) o->record_index, buf, proj_errno_string (proj_errno(P))); proj_errno_restore (P, err); continue; } diff --git a/src/apps/cs2cs.cpp b/src/apps/cs2cs.cpp index 92e4441e..12e045bb 100644 --- a/src/apps/cs2cs.cpp +++ b/src/apps/cs2cs.cpp @@ -624,7 +624,7 @@ int main(int argc, char **argv) { if (!transformation) { emess(3, "cannot initialize transformation\ncause: %s", - pj_strerrno(pj_errno)); + proj_errno_string(proj_context_errno(nullptr))); } if (use_env_locale) { diff --git a/src/apps/gie.cpp b/src/apps/gie.cpp index 2fe854fa..b504b922 100644 --- a/src/apps/gie.cpp +++ b/src/apps/gie.cpp @@ -880,8 +880,8 @@ static int expect_failure_with_errno_message (int expected, int got) { banner (T.operation); fprintf (T.fout, "%s", T.op_ko? " -----\n": delim); fprintf (T.fout, " FAILURE in %s(%d):\n", opt_strip_path (T.curr_file), (int) F->lineno); - fprintf (T.fout, " got errno %s (%d): %s\n", err_const_from_errno(got), got, pj_strerrno (got)); - fprintf (T.fout, " expected %s (%d): %s", err_const_from_errno(expected), expected, pj_strerrno (expected)); + fprintf (T.fout, " got errno %s (%d): %s\n", err_const_from_errno(got), got, proj_errno_string (got)); + fprintf (T.fout, " expected %s (%d): %s", err_const_from_errno(expected), expected, proj_errno_string (expected)); fprintf (T.fout, "\n"); return 1; } @@ -934,7 +934,7 @@ Tell GIE what to expect, when transforming the ACCEPTed input /* Otherwise, it's a true failure */ banner (T.operation); errmsg (3, "%sInvalid operation definition in line no. %d:\n %s (errno=%s/%d)\n", - delim, (int) T.operation_lineno, pj_strerrno(proj_errno(T.P)), + delim, (int) T.operation_lineno, proj_errno_string (proj_errno(T.P)), err_const_from_errno (proj_errno(T.P)), proj_errno(T.P) ); return another_failing_failure (); @@ -1186,7 +1186,7 @@ static int list_err_codes (void) { if (9999==lookup[i].the_errno) break; fprintf (T.fout, "%25s (%2.2d): %s\n", lookup[i].the_err_const + 8, - lookup[i].the_errno, pj_strerrno(lookup[i].the_errno)); + lookup[i].the_errno, proj_errno_string (lookup[i].the_errno)); } return 0; } diff --git a/src/apps/proj.cpp b/src/apps/proj.cpp index 8bfd99a3..a5c917f6 100644 --- a/src/apps/proj.cpp +++ b/src/apps/proj.cpp @@ -250,10 +250,8 @@ static void vprocess(FILE *fid) { if (postscale) { dat_xy.x *= fscale; dat_xy.y *= fscale; } } - /* For some reason pj_errno does not work as expected in some */ - /* versions of Visual Studio, so using pj_get_errno_ref instead */ - if (*pj_get_errno_ref()) { - emess(-1, pj_strerrno(*pj_get_errno_ref())); + if (proj_context_errno(nullptr)) { + emess(-1, proj_errno_string(proj_context_errno(nullptr))); continue; } @@ -477,7 +475,7 @@ int main(int argc, char **argv) { } if (!(Proj = pj_init(pargc, pargv))) emess(3,"projection initialization failure\ncause: %s", - pj_strerrno(pj_errno)); + proj_errno_string(proj_context_errno(nullptr))); if (!proj_angular_input(Proj, PJ_FWD)) { emess(3, "can't initialize operations that take non-angular input coordinates"); diff --git a/src/errno.cpp b/src/errno.cpp deleted file mode 100644 index 4f3119b3..00000000 --- a/src/errno.cpp +++ /dev/null @@ -1,18 +0,0 @@ -/* For full ANSI compliance of global variable */ - -#include "proj.h" -#include "proj_internal.h" - -int pj_errno = 0; - -/************************************************************************/ -/* pj_get_errno_ref() */ -/************************************************************************/ - -int *pj_get_errno_ref() - -{ - return &pj_errno; -} - -/* end */ diff --git a/src/internal.cpp b/src/internal.cpp index c1ffc408..175ffa9b 100644 --- a/src/internal.cpp +++ b/src/internal.cpp @@ -415,7 +415,6 @@ to that context. if( err == 0 ) return; errno = err; - pj_errno = err; } /* logging */ diff --git a/src/lib_proj.cmake b/src/lib_proj.cmake index 1361294d..7ca7f3a4 100644 --- a/src/lib_proj.cmake +++ b/src/lib_proj.cmake @@ -217,7 +217,6 @@ set(SRC_LIBPROJ_CORE dmstor.cpp ell_set.cpp ellps.cpp - errno.cpp factors.cpp fwd.cpp gauss.cpp diff --git a/src/pipeline.cpp b/src/pipeline.cpp index 80ee0397..56a80848 100644 --- a/src/pipeline.cpp +++ b/src/pipeline.cpp @@ -533,7 +533,7 @@ PJ *OPERATION(pipeline,0) { int err_to_report = proj_errno(P); if (0==err_to_report) err_to_report = PJD_ERR_MALFORMED_PIPELINE; - proj_log_error (P, "Pipeline: Bad step definition: %s (%s)", current_argv[0], pj_strerrno (err_to_report)); + proj_log_error (P, "Pipeline: Bad step definition: %s (%s)", current_argv[0], proj_errno_string (err_to_report)); return destructor (P, err_to_report); /* ERROR: bad pipeline def */ } next_step->parent = P; diff --git a/src/proj_internal.h b/src/proj_internal.h index d57e87a2..7e41f0f9 100644 --- a/src/proj_internal.h +++ b/src/proj_internal.h @@ -921,7 +921,6 @@ PJ_LP pj_generic_inverse_2d(PJ_XY xy, PJ *P, PJ_LP lpInitial); extern char const PROJ_DLL pj_release[]; /* global release id string */ -PROJ_DLL extern int pj_errno; /* global error return code */ #ifndef PROJ_INTERNAL_H /* replaced by enum proj_log_level in proj_internal.h */ @@ -959,8 +958,6 @@ void PROJ_DLL pj_dalloc(void *); void PROJ_DLL *pj_calloc (size_t n, size_t size); void PROJ_DLL *pj_dealloc (void *ptr); char PROJ_DLL *pj_strdup(const char *str); -char PROJ_DLL *pj_strerrno(int); -int PROJ_DLL *pj_get_errno_ref(void); const char PROJ_DLL *pj_get_release(void); void PROJ_DLL pj_acquire_lock(void); void PROJ_DLL pj_release_lock(void); diff --git a/src/strerrno.cpp b/src/strerrno.cpp index 1c8673d0..3d0131c6 100644 --- a/src/strerrno.cpp +++ b/src/strerrno.cpp @@ -1,4 +1,4 @@ -/* list of projection system pj_errno values */ +/* list of projection system errno values */ #include #include @@ -74,10 +74,11 @@ pj_err_list[] = { "network error", /* -62 */ /* When adding error messages, remember to update ID defines in - projects.h, and transient_error array in pj_transform */ + src/proj_internal.h and src/apps/gie.cpp */ }; -char *pj_strerrno(int err) { + +const char* proj_errno_string(int err) { const int max_error = 9999; static char note[50]; size_t adjusted_err; @@ -98,7 +99,7 @@ char *pj_strerrno(int err) { #endif } - /* PROJ.4 error codes are negative: -1 to -9999 */ + /* PROJ error codes are negative: -1 to -9999 */ adjusted_err = err < -max_error ? max_error : -err - 1; if (adjusted_err < (sizeof(pj_err_list) / sizeof(char *))) return (char *)pj_err_list[adjusted_err]; @@ -107,7 +108,3 @@ char *pj_strerrno(int err) { (err > -max_error) ? err: -max_error); return note; } - -const char* proj_errno_string(int err) { - return pj_strerrno(err); -} -- cgit v1.2.3 From 046270a85faf20f38d01e02942d197db74bb8542 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Fri, 20 Nov 2020 16:37:12 +0100 Subject: Remove old pj_ memory (de)allocation functions Gone are pj_malloc, pj_calloc, pj_dalloc and pj_dealloc. Their primary function as API memory functions in proj_api.h is no longer there and the other use as a workaround for old errno problems is no longer valid either. Replaced with malloc and free across the codebase. --- src/4D_api.cpp | 26 ++++----- src/apps/geod_set.cpp | 2 +- src/auth.cpp | 2 +- src/conversions/axisswap.cpp | 2 +- src/conversions/set.cpp | 2 +- src/conversions/unitconvert.cpp | 2 +- src/ell_set.cpp | 22 ++++---- src/init.cpp | 50 ++++++++--------- src/initcache.cpp | 20 +++---- src/iso19111/c_api.cpp | 20 +++---- src/iso19111/io.cpp | 4 +- src/malloc.cpp | 112 +++++-------------------------------- src/mlfn.cpp | 2 +- src/param.cpp | 4 +- src/pipeline.cpp | 10 ++-- src/pr_list.cpp | 8 +-- src/proj_internal.h | 6 +- src/projections/adams.cpp | 2 +- src/projections/aea.cpp | 6 +- src/projections/aeqd.cpp | 4 +- src/projections/airy.cpp | 2 +- src/projections/aitoff.cpp | 4 +- src/projections/bacon.cpp | 6 +- src/projections/bertin1953.cpp | 2 +- src/projections/bipc.cpp | 2 +- src/projections/bonne.cpp | 4 +- src/projections/cass.cpp | 4 +- src/projections/ccon.cpp | 4 +- src/projections/cea.cpp | 4 +- src/projections/chamb.cpp | 2 +- src/projections/col_urban.cpp | 2 +- src/projections/eck3.cpp | 8 +-- src/projections/eqc.cpp | 2 +- src/projections/eqdc.cpp | 4 +- src/projections/eqearth.cpp | 4 +- src/projections/fouc_s.cpp | 2 +- src/projections/geos.cpp | 2 +- src/projections/gn_sinu.cpp | 10 ++-- src/projections/gnom.cpp | 2 +- src/projections/goode.cpp | 2 +- src/projections/gstmerc.cpp | 2 +- src/projections/hammer.cpp | 2 +- src/projections/healpix.cpp | 6 +- src/projections/igh.cpp | 2 +- src/projections/igh_o.cpp | 2 +- src/projections/imw_p.cpp | 4 +- src/projections/isea.cpp | 2 +- src/projections/krovak.cpp | 2 +- src/projections/labrd.cpp | 2 +- src/projections/laea.cpp | 4 +- src/projections/lagrng.cpp | 2 +- src/projections/lcc.cpp | 2 +- src/projections/lcca.cpp | 4 +- src/projections/loxim.cpp | 2 +- src/projections/lsat.cpp | 2 +- src/projections/misrsom.cpp | 2 +- src/projections/mod_ster.cpp | 10 ++-- src/projections/moll.cpp | 6 +- src/projections/nsper.cpp | 4 +- src/projections/ob_tran.cpp | 8 +-- src/projections/ocea.cpp | 2 +- src/projections/oea.cpp | 2 +- src/projections/omerc.cpp | 2 +- src/projections/ortho.cpp | 2 +- src/projections/poly.cpp | 4 +- src/projections/putp3.cpp | 4 +- src/projections/putp4p.cpp | 4 +- src/projections/putp5.cpp | 4 +- src/projections/putp6.cpp | 4 +- src/projections/qsc.cpp | 2 +- src/projections/rouss.cpp | 4 +- src/projections/rpoly.cpp | 2 +- src/projections/sch.cpp | 2 +- src/projections/sconics.cpp | 2 +- src/projections/somerc.cpp | 2 +- src/projections/stere.cpp | 4 +- src/projections/sterea.cpp | 4 +- src/projections/sts.cpp | 8 +-- src/projections/tmerc.cpp | 4 +- src/projections/tpeqd.cpp | 2 +- src/projections/urm5.cpp | 2 +- src/projections/urmfps.cpp | 4 +- src/projections/vandg2.cpp | 4 +- src/projections/wag3.cpp | 2 +- src/projections/wink1.cpp | 2 +- src/projections/wink2.cpp | 2 +- src/transformations/affine.cpp | 2 +- src/transformations/helmert.cpp | 2 +- src/transformations/horner.cpp | 10 ++-- src/transformations/molodensky.cpp | 2 +- 90 files changed, 227 insertions(+), 317 deletions(-) diff --git a/src/4D_api.cpp b/src/4D_api.cpp index 83fda02c..15bc73c8 100644 --- a/src/4D_api.cpp +++ b/src/4D_api.cpp @@ -778,14 +778,14 @@ PJ *pj_create_internal (PJ_CONTEXT *ctx, const char *definition) { argc = pj_trim_argc (args); if (argc==0) { - pj_dealloc (args); + free (args); proj_context_errno_set(ctx, PJD_ERR_NO_ARGS); return nullptr; } argv = pj_trim_argv (argc, args); if (!argv) { - pj_dealloc(args); + free(args); proj_context_errno_set(ctx, ENOMEM); return nullptr; } @@ -795,8 +795,8 @@ PJ *pj_create_internal (PJ_CONTEXT *ctx, const char *definition) { allow_init_epsg = proj_context_get_use_proj4_init_rules(ctx, FALSE); P = pj_init_ctx_with_allow_init_epsg (ctx, (int) argc, argv, allow_init_epsg); - pj_dealloc (argv); - pj_dealloc (args); + free (argv); + free (args); /* Support cs2cs-style modifiers */ ret = cs2cs_emulation_setup (P); @@ -834,7 +834,7 @@ indicator, as in {"+proj=utm", "+zone=32"}, or leave it out, as in {"proj=utm", P = proj_create (ctx, c); - pj_dealloc ((char *) c); + free ((char *) c); return P; } @@ -862,13 +862,13 @@ Same as proj_create_argv() but calls pj_create_internal() instead of proj_create P = pj_create_internal (ctx, c); - pj_dealloc ((char *) c); + free ((char *) c); return P; } /** Create an area of use */ PJ_AREA * proj_area_create(void) { - return static_cast(pj_calloc(1, sizeof(PJ_AREA))); + return static_cast(calloc(1, sizeof(PJ_AREA))); } /** Assign a bounding box to an area of use. */ @@ -886,7 +886,7 @@ void proj_area_set_bbox(PJ_AREA *area, /** Free an area of use */ void proj_area_destroy(PJ_AREA* area) { - pj_dealloc(area); + free(area); } /************************************************************************/ @@ -1495,15 +1495,15 @@ static char *path_append (char *buf, const char *app, size_t *buf_size) { /* "pj_realloc", so to speak */ if (*buf_size < len) { - p = static_cast(pj_calloc (2 * len, sizeof (char))); + p = static_cast(calloc (2 * len, sizeof (char))); if (nullptr==p) { - pj_dealloc (buf); + free (buf); return nullptr; } *buf_size = 2 * len; if (buf != nullptr) strcpy (p, buf); - pj_dealloc (buf); + free (buf); buf = p; } assert(buf); @@ -1556,7 +1556,7 @@ PJ_INFO proj_info (void) { } } - pj_dalloc(const_cast(info.searchpath)); + free(const_cast(info.searchpath)); info.searchpath = buf ? buf : empty; info.paths = ctx ? ctx->c_compat_paths : nullptr; @@ -1805,7 +1805,7 @@ PJ_INIT_INFO proj_init_info(const char *initname){ for ( ; start; start = next) { next = start->next; - pj_dalloc(start); + free(start); } return ininfo; diff --git a/src/apps/geod_set.cpp b/src/apps/geod_set.cpp index 603f0d95..d6516f22 100644 --- a/src/apps/geod_set.cpp +++ b/src/apps/geod_set.cpp @@ -75,6 +75,6 @@ geod_set(int argc, char **argv) { /* free up linked list */ for ( ; start; start = curr) { curr = start->next; - pj_dalloc(start); + free(start); } } diff --git a/src/auth.cpp b/src/auth.cpp index a8ee262a..ced02fb4 100644 --- a/src/auth.cpp +++ b/src/auth.cpp @@ -18,7 +18,7 @@ pj_authset(double es) { double t, *APA; - if ((APA = (double *)pj_malloc(APA_SIZE * sizeof(double))) != nullptr) { + if ((APA = (double *)malloc(APA_SIZE * sizeof(double))) != nullptr) { APA[0] = es * P00; t = es * es; APA[0] += t * P01; diff --git a/src/conversions/axisswap.cpp b/src/conversions/axisswap.cpp index 4ae2b4e4..1aa339c3 100644 --- a/src/conversions/axisswap.cpp +++ b/src/conversions/axisswap.cpp @@ -169,7 +169,7 @@ static PJ_COORD reverse_4d(PJ_COORD coo, PJ *P) { /***********************************************************************/ PJ *CONVERSION(axisswap,0) { /***********************************************************************/ - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); char *s; unsigned int i, j, n = 0; diff --git a/src/conversions/set.cpp b/src/conversions/set.cpp index 7628bf4f..2f30bda8 100644 --- a/src/conversions/set.cpp +++ b/src/conversions/set.cpp @@ -39,7 +39,7 @@ PJ *OPERATION(set, 0) { P->inv4d = set_fwd_inv; P->fwd4d = set_fwd_inv; - auto set = static_cast(pj_calloc (1, sizeof(struct Set))); + auto set = static_cast(calloc (1, sizeof(struct Set))); P->opaque = set; if (nullptr==P->opaque) return pj_default_destructor(P, ENOMEM); diff --git a/src/conversions/unitconvert.cpp b/src/conversions/unitconvert.cpp index 172e2c48..61bccbf1 100644 --- a/src/conversions/unitconvert.cpp +++ b/src/conversions/unitconvert.cpp @@ -433,7 +433,7 @@ static double get_unit_conversion_factor(const char* name, /***********************************************************************/ PJ *CONVERSION(unitconvert,0) { /***********************************************************************/ - struct pj_opaque_unitconvert *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque_unitconvert))); + struct pj_opaque_unitconvert *Q = static_cast(calloc (1, sizeof (struct pj_opaque_unitconvert))); const char *s, *name; int i; double f; diff --git a/src/ell_set.cpp b/src/ell_set.cpp index c7cbeb48..176fc553 100644 --- a/src/ell_set.cpp +++ b/src/ell_set.cpp @@ -77,13 +77,13 @@ int pj_ellipsoid (PJ *P) { int err = proj_errno_reset (P); const char *empty = {""}; - pj_dealloc(P->def_size); + free(P->def_size); P->def_size = nullptr; - pj_dealloc(P->def_shape); + free(P->def_shape); P->def_shape = nullptr; - pj_dealloc(P->def_spherification); + free(P->def_spherification); P->def_spherification = nullptr; - pj_dealloc(P->def_ellps); + free(P->def_ellps); P->def_ellps = nullptr; /* Specifying R overrules everything */ @@ -162,7 +162,7 @@ static int ellps_ellps (PJ *P) { new_params->next = pj_mkparam (ellps->ell); if (nullptr == new_params->next) { - pj_dealloc(new_params); + free(new_params); return proj_errno_set (P, ENOMEM); } paralist* old_params = P->params; @@ -176,8 +176,8 @@ static int ellps_ellps (PJ *P) { ellps_shape (P); P->params = old_params; - pj_dealloc (new_params->next); - pj_dealloc (new_params); + free (new_params->next); + free (new_params); if (proj_errno (P)) return proj_errno (P); @@ -195,7 +195,7 @@ static int ellps_size (PJ *P) { paralist *par = nullptr; int a_was_set = 0; - pj_dealloc(P->def_size); + free(P->def_size); P->def_size = nullptr; /* A size parameter *must* be given, but may have been given as ellps prior */ @@ -235,7 +235,7 @@ static int ellps_shape (PJ *P) { par = nullptr; len = sizeof (keys) / sizeof (char *); - pj_dealloc(P->def_shape); + free(P->def_shape); P->def_shape = nullptr; /* Check which shape key is specified */ @@ -721,8 +721,8 @@ int pj_ell_set (PJ_CONTEXT *ctx, paralist *pl, double *a, double *es) { } bomb: if (start) { /* clean up temporary extension of list */ - pj_dalloc(start->next->next); - pj_dalloc(start->next); + free(start->next->next); + free(start->next); start->next = 0; } if (ctx->last_errno) diff --git a/src/init.cpp b/src/init.cpp index 95bb404f..7b614c5f 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -55,7 +55,7 @@ static paralist *string_to_paralist (PJ_CONTEXT *ctx, char *definition) { /* Keep a handle to the start of the list, so we have something to return */ auto param = pj_mkparam_ws (c, &c); if (nullptr==param) { - pj_dealloc_params (ctx, first, ENOMEM); + free_params (ctx, first, ENOMEM); return nullptr; } if (nullptr==last) { @@ -84,7 +84,7 @@ static char *get_init_string (PJ_CONTEXT *ctx, const char *name) { char *buffer = nullptr; size_t n; - fname = static_cast(pj_malloc (MAX_PATH_FILENAME+ID_TAG_MAX+3)); + fname = static_cast(malloc (MAX_PATH_FILENAME+ID_TAG_MAX+3)); if (nullptr==fname) { return nullptr; } @@ -96,7 +96,7 @@ static char *get_init_string (PJ_CONTEXT *ctx, const char *name) { else key += 5; if (MAX_PATH_FILENAME + ID_TAG_MAX + 2 < strlen (key)) { - pj_dealloc (fname); + free (fname); return nullptr; } memmove (fname, key, strlen (key) + 1); @@ -105,7 +105,7 @@ static char *get_init_string (PJ_CONTEXT *ctx, const char *name) { section = strrchr(fname, ':'); if (nullptr==section) { proj_context_errno_set (ctx, PJD_ERR_NO_COLON_IN_INIT_STRING); - pj_dealloc (fname); + free (fname); return nullptr; } *section = 0; @@ -117,7 +117,7 @@ static char *get_init_string (PJ_CONTEXT *ctx, const char *name) { auto file = NS_PROJ::FileManager::open_resource_file(ctx, fname); if (nullptr==file) { - pj_dealloc (fname); + free (fname); proj_context_errno_set (ctx, PJD_ERR_NO_OPTION_IN_INIT_FILE); return nullptr; } @@ -131,7 +131,7 @@ static char *get_init_string (PJ_CONTEXT *ctx, const char *name) { line = file->read_line(MAX_LINE_LENGTH, maxLenReached, eofReached); /* End of file? */ if (maxLenReached || eofReached) { - pj_dealloc (fname); + free (fname); proj_context_errno_set (ctx, PJD_ERR_NO_OPTION_IN_INIT_FILE); return nullptr; } @@ -149,9 +149,9 @@ static char *get_init_string (PJ_CONTEXT *ctx, const char *name) { } /* We're at the first line of the right section - copy line to buffer */ - buffer = static_cast(pj_malloc (current_buffer_size)); + buffer = static_cast(malloc (current_buffer_size)); if (nullptr==buffer) { - pj_dealloc (fname); + free (fname); return nullptr; } @@ -183,22 +183,22 @@ static char *get_init_string (PJ_CONTEXT *ctx, const char *name) { pj_chomp (&line[0]); /* Remove '#' style comments */ next_length = strlen (line.data()) + buffer_length + 2; if (next_length > current_buffer_size) { - char *b = static_cast(pj_malloc (2 * current_buffer_size)); + char *b = static_cast(malloc (2 * current_buffer_size)); if (nullptr==b) { - pj_dealloc (buffer); + free (buffer); buffer = nullptr; break; } strcpy (b, buffer); current_buffer_size *= 2; - pj_dealloc (buffer); + free (buffer); buffer = b; } buffer[buffer_length] = ' '; strcpy (buffer + buffer_length + 1, line.data()); } - pj_dealloc (fname); + free (fname); if (nullptr==buffer) return nullptr; pj_shrink (buffer); @@ -306,7 +306,7 @@ Expand key from buffer or (if not in buffer) from init file definition, init_items->param, init_items->next ? init_items->next->param : "(empty)"); - pj_dealloc (definition); + free (definition); if (nullptr==init_items) return nullptr; @@ -424,7 +424,7 @@ pj_init_plus_ctx( PJ_CONTEXT *ctx, const char *definition ) PJ *result = nullptr; /* make a copy that we can manipulate */ - defn_copy = (char *) pj_malloc( strlen(definition)+1 ); + defn_copy = (char *) malloc( strlen(definition)+1 ); if (!defn_copy) return nullptr; strcpy( defn_copy, definition ); @@ -447,7 +447,7 @@ pj_init_plus_ctx( PJ_CONTEXT *ctx, const char *definition ) if( argc+1 == MAX_ARG ) { - pj_dalloc( defn_copy ); + free( defn_copy ); proj_context_errno_set( ctx, PJD_ERR_UNPARSEABLE_CS_DEF ); return nullptr; } @@ -477,7 +477,7 @@ pj_init_plus_ctx( PJ_CONTEXT *ctx, const char *definition ) /* perform actual initialization */ result = pj_init_ctx( ctx, argc, argv ); - pj_dalloc( defn_copy ); + free( defn_copy ); return result; } @@ -566,14 +566,14 @@ pj_init_ctx_with_allow_init_epsg(PJ_CONTEXT *ctx, int argc, char **argv, int all /* put arguments into internal linked list */ start = curr = pj_mkparam(argv[0]); if (!curr) { - pj_dealloc_params (ctx, start, ENOMEM); + free_params (ctx, start, ENOMEM); return nullptr; } for (i = 1; i < argc; ++i) { curr->next = pj_mkparam(argv[i]); if (!curr->next) { - pj_dealloc_params (ctx, start, ENOMEM); + free_params (ctx, start, ENOMEM); return nullptr; } curr = curr->next; @@ -588,31 +588,31 @@ pj_init_ctx_with_allow_init_epsg(PJ_CONTEXT *ctx, int argc, char **argv, int all if (init && n_pipelines == 0) { init = pj_expand_init_internal (ctx, init, allow_init_epsg); if (!init) { - pj_dealloc_params (ctx, start, PJD_ERR_NO_ARGS); + free_params (ctx, start, PJD_ERR_NO_ARGS); return nullptr; } } if (ctx->last_errno) { - pj_dealloc_params (ctx, start, ctx->last_errno); + free_params (ctx, start, ctx->last_errno); return nullptr; } /* Find projection selection */ curr = pj_param_exists (start, "proj"); if (nullptr==curr) { - pj_dealloc_params (ctx, start, PJD_ERR_PROJ_NOT_NAMED); + free_params (ctx, start, PJD_ERR_PROJ_NOT_NAMED); return nullptr; } name = curr->param; if (strlen (name) < 6) { - pj_dealloc_params (ctx, start, PJD_ERR_PROJ_NOT_NAMED); + free_params (ctx, start, PJD_ERR_PROJ_NOT_NAMED); return nullptr; } name += 5; proj = locate_constructor (name); if (nullptr==proj) { - pj_dealloc_params (ctx, start, PJD_ERR_UNKNOWN_PROJECTION_ID); + free_params (ctx, start, PJD_ERR_UNKNOWN_PROJECTION_ID); return nullptr; } @@ -621,7 +621,7 @@ pj_init_ctx_with_allow_init_epsg(PJ_CONTEXT *ctx, int argc, char **argv, int all /* Allocate projection structure */ PIN = proj(nullptr); if (nullptr==PIN) { - pj_dealloc_params (ctx, start, ENOMEM); + free_params (ctx, start, ENOMEM); return nullptr; } @@ -820,7 +820,7 @@ pj_init_ctx_with_allow_init_epsg(PJ_CONTEXT *ctx, int argc, char **argv, int all PIN->from_greenwich = 0.0; /* Private object for the geodesic functions */ - PIN->geod = static_cast(pj_calloc (1, sizeof (struct geod_geodesic))); + PIN->geod = static_cast(calloc (1, sizeof (struct geod_geodesic))); if (nullptr==PIN->geod) return pj_default_destructor (PIN, ENOMEM); geod_init(PIN->geod, PIN->a, (1 - sqrt (1 - PIN->es))); diff --git a/src/initcache.cpp b/src/initcache.cpp index af20fb82..cf9460ab 100644 --- a/src/initcache.cpp +++ b/src/initcache.cpp @@ -48,7 +48,7 @@ paralist *pj_clone_paralist( const paralist *list) for( ; list != nullptr; list = list->next ) { paralist *newitem = (paralist *) - pj_malloc(sizeof(paralist) + strlen(list->param)); + malloc(sizeof(paralist) + strlen(list->param)); newitem->used = 0; newitem->next = nullptr; @@ -83,17 +83,17 @@ void pj_clear_initcache() { paralist *n, *t = cache_paralist[i]; - pj_dalloc( cache_key[i] ); + free( cache_key[i] ); /* free parameter list elements */ for (; t != nullptr; t = n) { n = t->next; - pj_dalloc(t); + free(t); } } - pj_dalloc( cache_key ); - pj_dalloc( cache_paralist ); + free( cache_key ); + free( cache_paralist ); cache_count = 0; cache_alloc= 0; cache_key = nullptr; @@ -151,29 +151,29 @@ void pj_insert_initcache( const char *filekey, const paralist *list ) cache_alloc = cache_alloc * 2 + 15; - cache_key_new = (char **) pj_malloc(sizeof(char*) * cache_alloc); + cache_key_new = (char **) malloc(sizeof(char*) * cache_alloc); if( cache_key && cache_count ) { memcpy( cache_key_new, cache_key, sizeof(char*) * cache_count); } - pj_dalloc( cache_key ); + free( cache_key ); cache_key = cache_key_new; cache_paralist_new = (paralist **) - pj_malloc(sizeof(paralist*) * cache_alloc); + malloc(sizeof(paralist*) * cache_alloc); if( cache_paralist && cache_count ) { memcpy( cache_paralist_new, cache_paralist, sizeof(paralist*) * cache_count ); } - pj_dalloc( cache_paralist ); + free( cache_paralist ); cache_paralist = cache_paralist_new; } /* ** Duplicate the filekey and paralist, and insert in cache. */ - cache_key[cache_count] = (char *) pj_malloc(strlen(filekey)+1); + cache_key[cache_count] = (char *) malloc(strlen(filekey)+1); strcpy( cache_key[cache_count], filekey ); cache_paralist[cache_count] = pj_clone_paralist( list ); diff --git a/src/iso19111/c_api.cpp b/src/iso19111/c_api.cpp index d6308c49..8fdebcbd 100644 --- a/src/iso19111/c_api.cpp +++ b/src/iso19111/c_api.cpp @@ -2690,11 +2690,11 @@ proj_get_crs_info_list_from_database(PJ_CONTEXT *ctx, const char *auth_name, void proj_crs_info_list_destroy(PROJ_CRS_INFO **list) { if (list) { for (int i = 0; list[i] != nullptr; i++) { - pj_dalloc(list[i]->auth_name); - pj_dalloc(list[i]->code); - pj_dalloc(list[i]->name); - pj_dalloc(list[i]->area_name); - pj_dalloc(list[i]->projection_method_name); + free(list[i]->auth_name); + free(list[i]->code); + free(list[i]->name); + free(list[i]->area_name); + free(list[i]->projection_method_name); delete list[i]; } delete[] list; @@ -2784,11 +2784,11 @@ PROJ_UNIT_INFO **proj_get_units_from_database(PJ_CONTEXT *ctx, void proj_unit_list_destroy(PROJ_UNIT_INFO **list) { if (list) { for (int i = 0; list[i] != nullptr; i++) { - pj_dalloc(list[i]->auth_name); - pj_dalloc(list[i]->code); - pj_dalloc(list[i]->name); - pj_dalloc(list[i]->category); - pj_dalloc(list[i]->proj_short_name); + free(list[i]->auth_name); + free(list[i]->code); + free(list[i]->name); + free(list[i]->category); + free(list[i]->proj_short_name); delete list[i]; } delete[] list; diff --git a/src/iso19111/io.cpp b/src/iso19111/io.cpp index 8c815f36..6c710697 100644 --- a/src/iso19111/io.cpp +++ b/src/iso19111/io.cpp @@ -9778,7 +9778,7 @@ PROJStringParser::createFromPROJString(const std::string &projString) { paralist *list = pj_expand_init(ctx, init); ctx->projStringParserCreateFromPROJStringRecursionCounter--; if (!list) { - pj_dealloc(init); + free(init); throw ParsingException("cannot expand " + projString); } std::string expanded; @@ -9801,7 +9801,7 @@ PROJStringParser::createFromPROJString(const std::string &projString) { } auto n = t->next; - pj_dealloc(t); + free(t); t = n; } for (const auto &pair : d->steps_[0].paramValues) { diff --git a/src/malloc.cpp b/src/malloc.cpp index 590dd27f..6b7fbf26 100644 --- a/src/malloc.cpp +++ b/src/malloc.cpp @@ -53,99 +53,13 @@ using namespace NS_PROJ; -/**********************************************************************/ -void *pj_malloc(size_t size) { -/*********************************************************************** -Currently, pj_malloc is a hack to solve an errno problem. -The problem is described in more details at -https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=86420. -It seems, that pj_init and similar functions incorrectly -(under debian/glibs-2.3.2) assume that pj_malloc resets -errno after success. pj_malloc tries to mimic this. - -NOTE (2017-09-29): The problem described at the bugzilla page -referred to above, is most likely a case of someone not -understanding the proper usage of errno. We should review -whether "the problem is actually a problem" in PROJ.4 code. - -Library specific allocators can be useful, and improve -interoperability, if properly used. That is, by making them -run/initialization time switchable, somewhat like the file i/o -interface. - -But as things stand, we are more likely to get benefit -from reviewing the code for proper errno usage, which is hard, -due to the presence of context local and global pj_errnos. - -Probably, these were introduced in order to support incomplete -implementations of thread local errnos at an early phase of the -implementation of multithreading support in PROJ.4). - -It is likely too late to get rid of contexts, but we can still -benefit from a better usage of errno. -***********************************************************************/ - int old_errno = errno; - void *res = malloc(size); - if ( res && !old_errno ) - errno = 0; - return res; -} - - -/**********************************************************************/ -void *pj_calloc (size_t n, size_t size) { -/*********************************************************************** -pj_calloc is the pj-equivalent of calloc(). - -It allocates space for an array of elements of size . -The array is initialized to zeros. -***********************************************************************/ - void *res = pj_malloc (n*size); - if (nullptr==res) - return nullptr; - memset (res, 0, n*size); - return res; -} - - -/**********************************************************************/ -void pj_dalloc(void *ptr) { -/**********************************************************************/ - free(ptr); -} - - -/**********************************************************************/ -void *pj_dealloc (void *ptr) { -/*********************************************************************** -pj_dealloc supports the common use case of "clean up and return a null -pointer" to signal an error in a multi level allocation: - - struct foo { int bar; int *baz; }; - - struct foo *p = pj_calloc (1, sizeof (struct foo)); - if (0==p) - return 0; - - p->baz = pj_calloc (10, sizeof(int)); - if (0==p->baz) - return pj_dealloc (p); // clean up + signal error by 0-return - - return p; // success - -***********************************************************************/ - if (nullptr==ptr) - return nullptr; - pj_dalloc (ptr); - return nullptr; -} /**********************************************************************/ char *pj_strdup(const char *str) /**********************************************************************/ { size_t len = strlen(str) + 1; - char *dup = static_cast(pj_malloc(len)); + char *dup = static_cast(malloc(len)); if (dup) memcpy(dup, str, len); return dup; @@ -153,7 +67,7 @@ char *pj_strdup(const char *str) /*****************************************************************************/ -void *pj_dealloc_params (PJ_CONTEXT *ctx, paralist *start, int errlev) { +void *free_params (PJ_CONTEXT *ctx, paralist *start, int errlev) { /***************************************************************************** Companion to pj_default_destructor (below). Deallocates a linked list of "+proj=xxx" initialization parameters. @@ -164,7 +78,7 @@ void *pj_dealloc_params (PJ_CONTEXT *ctx, paralist *start, int errlev) { paralist *t, *n; for (t = start; t; t = n) { n = t->next; - pj_dealloc(t); + free(t); } proj_context_errno_set (ctx, errlev); return (void *) nullptr; @@ -225,26 +139,26 @@ PJ *pj_default_destructor (PJ *P, int errlev) { /* Destructor */ return nullptr; - pj_dealloc(P->def_size); - pj_dealloc(P->def_shape); - pj_dealloc(P->def_spherification); - pj_dealloc(P->def_ellps); + free(P->def_size); + free(P->def_shape); + free(P->def_spherification); + free(P->def_ellps); delete static_cast(P->hgrids_legacy); delete static_cast(P->vgrids_legacy); - /* We used to call pj_dalloc( P->catalog ), but this will leak */ + /* We used to call free( P->catalog ), but this will leak */ /* memory. The safe way to clear catalog and grid is to call */ - /* pj_gc_unloadall(pj_get_default_ctx()); and pj_deallocate_grids(); */ + /* pj_gc_unloadall(pj_get_default_ctx()); and freeate_grids(); */ /* TODO: we should probably have a public pj_cleanup() method to do all */ /* that */ /* free the interface to Charles Karney's geodesic library */ - pj_dealloc( P->geod ); + free( P->geod ); /* free parameter list elements */ - pj_dealloc_params (pj_get_ctx(P), P->params, errlev); - pj_dealloc (P->def_full); + free_params (pj_get_ctx(P), P->params, errlev); + free (P->def_full); /* free the cs2cs emulation elements */ proj_destroy (P->axisswap); @@ -254,7 +168,7 @@ PJ *pj_default_destructor (PJ *P, int errlev) { /* Destructor */ proj_destroy (P->hgridshift); proj_destroy (P->vgridshift); - pj_dealloc (static_cast(P->opaque)); + free (static_cast(P->opaque)); delete P; return nullptr; } diff --git a/src/mlfn.cpp b/src/mlfn.cpp index d4037897..763d83ee 100644 --- a/src/mlfn.cpp +++ b/src/mlfn.cpp @@ -26,7 +26,7 @@ double *pj_enfn(double es) { double t, *en; - en = (double *) pj_malloc(EN_SIZE * sizeof (double)); + en = (double *) malloc(EN_SIZE * sizeof (double)); if (nullptr==en) return nullptr; diff --git a/src/param.cpp b/src/param.cpp index 3e13b391..28d6bc3e 100644 --- a/src/param.cpp +++ b/src/param.cpp @@ -38,7 +38,7 @@ static void unquote_string(char* param_str) { paralist *pj_mkparam(const char *str) { paralist *newitem; - if((newitem = (paralist *)pj_malloc(sizeof(paralist) + strlen(str))) != nullptr) { + if((newitem = (paralist *)malloc(sizeof(paralist) + strlen(str))) != nullptr) { newitem->used = 0; newitem->next = nullptr; if (*str == '+') @@ -82,7 +82,7 @@ paralist *pj_mkparam_ws (const char *str, const char **next_str) { *next_str = str + len; /* Use calloc to automagically 0-terminate the copy */ - newitem = (paralist *) pj_calloc (1, sizeof(paralist) + len + 1); + newitem = (paralist *) calloc (1, sizeof(paralist) + len + 1); if (nullptr==newitem) return nullptr; memcpy(newitem->param, str, len); diff --git a/src/pipeline.cpp b/src/pipeline.cpp index 56a80848..e9d11604 100644 --- a/src/pipeline.cpp +++ b/src/pipeline.cpp @@ -294,8 +294,8 @@ static PJ *destructor (PJ *P, int errlev) { auto pipeline = static_cast(P->opaque); - pj_dealloc (pipeline->argv); - pj_dealloc (pipeline->current_argv); + free (pipeline->argv); + free (pipeline->current_argv); delete pipeline; P->opaque = nullptr; @@ -321,7 +321,7 @@ static const char *argv_sentinel = "step"; static char **argv_params (paralist *params, size_t argc) { char **argv; size_t i = 0; - argv = static_cast(pj_calloc (argc, sizeof (char *))); + argv = static_cast(calloc (argc, sizeof (char *))); if (nullptr==argv) return nullptr; for (; params != nullptr; params = params->next) @@ -461,7 +461,7 @@ PJ *OPERATION(pipeline,0) { if (nullptr==argv) return destructor (P, ENOMEM); - pipeline->current_argv = current_argv = static_cast(pj_calloc (argc, sizeof (char *))); + pipeline->current_argv = current_argv = static_cast(calloc (argc, sizeof (char *))); if (nullptr==current_argv) return destructor (P, ENOMEM); @@ -679,7 +679,7 @@ static PJ_COORD pop(PJ_COORD point, PJ *P) { static PJ *setup_pushpop(PJ *P) { - auto pushpop = static_cast(pj_calloc (1, sizeof(struct PushPop))); + auto pushpop = static_cast(calloc (1, sizeof(struct PushPop))); P->opaque = pushpop; if (nullptr==P->opaque) return destructor(P, ENOMEM); diff --git a/src/pr_list.cpp b/src/pr_list.cpp index 77db5bfb..30fc6571 100644 --- a/src/pr_list.cpp +++ b/src/pr_list.cpp @@ -66,7 +66,7 @@ char *pj_get_def( PJ *P, int options ) size_t def_max = 10; (void) options; - definition = (char *) pj_malloc(def_max); + definition = (char *) malloc(def_max); if (!definition) return nullptr; definition[0] = '\0'; @@ -84,14 +84,14 @@ char *pj_get_def( PJ *P, int options ) char *def2; def_max = def_max * 2 + l + 5; - def2 = (char *) pj_malloc(def_max); + def2 = (char *) malloc(def_max); if (def2) { strcpy( def2, definition ); - pj_dalloc( definition ); + free( definition ); definition = def2; } else { - pj_dalloc( definition ); + free( definition ); return nullptr; } } diff --git a/src/proj_internal.h b/src/proj_internal.h index 7e41f0f9..234ff80e 100644 --- a/src/proj_internal.h +++ b/src/proj_internal.h @@ -825,7 +825,7 @@ paralist *pj_search_initcache( const char *filekey ); void pj_insert_initcache( const char *filekey, const paralist *list); paralist *pj_expand_init(PJ_CONTEXT *ctx, paralist *init); -void *pj_dealloc_params (PJ_CONTEXT *ctx, paralist *start, int errlev); +void *free_params (PJ_CONTEXT *ctx, paralist *start, int errlev); double *pj_enfn(double); @@ -953,10 +953,6 @@ char PROJ_DLL *pj_get_def(PJ *, int); int PROJ_DLL pj_has_inverse(PJ *); -void PROJ_DLL *pj_malloc(size_t); -void PROJ_DLL pj_dalloc(void *); -void PROJ_DLL *pj_calloc (size_t n, size_t size); -void PROJ_DLL *pj_dealloc (void *ptr); char PROJ_DLL *pj_strdup(const char *str); const char PROJ_DLL *pj_get_release(void); void PROJ_DLL pj_acquire_lock(void); diff --git a/src/projections/adams.cpp b/src/projections/adams.cpp index 4f7d1a03..d1217ff1 100644 --- a/src/projections/adams.cpp +++ b/src/projections/adams.cpp @@ -205,7 +205,7 @@ static PJ_LP adams_inverse(PJ_XY xy, PJ *P) static PJ *setup(PJ *P, projection_type mode) { struct pj_opaque *Q = static_cast( - pj_calloc (1, sizeof (struct pj_opaque))); + calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); diff --git a/src/projections/aea.cpp b/src/projections/aea.cpp index 6ffb4fd6..af0f292d 100644 --- a/src/projections/aea.cpp +++ b/src/projections/aea.cpp @@ -94,7 +94,7 @@ static PJ *destructor (PJ *P, int errlev) { /* Destructor if (nullptr==P->opaque) return pj_default_destructor (P, errlev); - pj_dealloc (static_cast(P->opaque)->en); + free (static_cast(P->opaque)->en); return pj_default_destructor (P, errlev); } @@ -219,7 +219,7 @@ static PJ *setup(PJ *P) { PJ *PROJECTION(aea) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; @@ -232,7 +232,7 @@ PJ *PROJECTION(aea) { PJ *PROJECTION(leac) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; diff --git a/src/projections/aeqd.cpp b/src/projections/aeqd.cpp index ad8c289e..d5d90b62 100644 --- a/src/projections/aeqd.cpp +++ b/src/projections/aeqd.cpp @@ -69,7 +69,7 @@ static PJ *destructor (PJ *P, int errlev) { /* Destructor if (nullptr==P->opaque) return pj_default_destructor (P, errlev); - pj_dealloc (static_cast(P->opaque)->en); + free (static_cast(P->opaque)->en); return pj_default_destructor (P, errlev); } @@ -274,7 +274,7 @@ static PJ_LP aeqd_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse PJ *PROJECTION(aeqd) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; diff --git a/src/projections/airy.cpp b/src/projections/airy.cpp index f7602e53..15ff60d8 100644 --- a/src/projections/airy.cpp +++ b/src/projections/airy.cpp @@ -120,7 +120,7 @@ static PJ_XY airy_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward PJ *PROJECTION(airy) { double beta; - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); diff --git a/src/projections/aitoff.cpp b/src/projections/aitoff.cpp index d02e7761..857ebb80 100644 --- a/src/projections/aitoff.cpp +++ b/src/projections/aitoff.cpp @@ -187,7 +187,7 @@ static PJ *setup(PJ *P) { PJ *PROJECTION(aitoff) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor(P, ENOMEM); P->opaque = Q; @@ -198,7 +198,7 @@ PJ *PROJECTION(aitoff) { PJ *PROJECTION(wintri) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor(P, ENOMEM); P->opaque = Q; diff --git a/src/projections/bacon.cpp b/src/projections/bacon.cpp index 3efd4dbe..7ff2a7ac 100644 --- a/src/projections/bacon.cpp +++ b/src/projections/bacon.cpp @@ -43,7 +43,7 @@ static PJ_XY bacon_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forwar PJ *PROJECTION(bacon) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; @@ -57,7 +57,7 @@ PJ *PROJECTION(bacon) { PJ *PROJECTION(apian) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; @@ -70,7 +70,7 @@ PJ *PROJECTION(apian) { PJ *PROJECTION(ortel) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; diff --git a/src/projections/bertin1953.cpp b/src/projections/bertin1953.cpp index b864f83a..58509e16 100644 --- a/src/projections/bertin1953.cpp +++ b/src/projections/bertin1953.cpp @@ -75,7 +75,7 @@ static PJ_XY bertin1953_s_forward (PJ_LP lp, PJ *P) { PJ *PROJECTION(bertin1953) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; diff --git a/src/projections/bipc.cpp b/src/projections/bipc.cpp index bf4ba834..743acd1c 100644 --- a/src/projections/bipc.cpp +++ b/src/projections/bipc.cpp @@ -168,7 +168,7 @@ static PJ_LP bipc_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse PJ *PROJECTION(bipc) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; diff --git a/src/projections/bonne.cpp b/src/projections/bonne.cpp index c94764cf..7817e968 100644 --- a/src/projections/bonne.cpp +++ b/src/projections/bonne.cpp @@ -106,14 +106,14 @@ static PJ *destructor (PJ *P, int errlev) { /* Destructor if (nullptr==P->opaque) return pj_default_destructor (P, errlev); - pj_dealloc (static_cast(P->opaque)->en); + free (static_cast(P->opaque)->en); return pj_default_destructor (P, errlev); } PJ *PROJECTION(bonne) { double c; - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; diff --git a/src/projections/cass.cpp b/src/projections/cass.cpp index e253cafc..f5531f6a 100644 --- a/src/projections/cass.cpp +++ b/src/projections/cass.cpp @@ -95,7 +95,7 @@ static PJ *destructor (PJ *P, int errlev) { /* Destructor if (nullptr==P->opaque) return pj_default_destructor (P, errlev); - pj_dealloc (static_cast(P->opaque)->en); + free (static_cast(P->opaque)->en); return pj_default_destructor (P, errlev); } @@ -111,7 +111,7 @@ PJ *PROJECTION(cass) { } /* otherwise it's ellipsoidal */ - P->opaque = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + P->opaque = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==P->opaque) return pj_default_destructor (P, ENOMEM); P->destructor = destructor; diff --git a/src/projections/ccon.cpp b/src/projections/ccon.cpp index df995f21..7b3b7105 100644 --- a/src/projections/ccon.cpp +++ b/src/projections/ccon.cpp @@ -75,14 +75,14 @@ static PJ *destructor (PJ *P, int errlev) { if (nullptr==P->opaque) return pj_default_destructor (P, errlev); - pj_dealloc (static_cast(P->opaque)->en); + free (static_cast(P->opaque)->en); return pj_default_destructor (P, errlev); } PJ *PROJECTION(ccon) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; diff --git a/src/projections/cea.cpp b/src/projections/cea.cpp index 7e6d3212..b7874b90 100644 --- a/src/projections/cea.cpp +++ b/src/projections/cea.cpp @@ -66,14 +66,14 @@ static PJ *destructor (PJ *P, int errlev) { /* Destructor if (nullptr==P->opaque) return pj_default_destructor (P, errlev); - pj_dealloc (static_cast(P->opaque)->apa); + free (static_cast(P->opaque)->apa); return pj_default_destructor (P, errlev); } PJ *PROJECTION(cea) { double t = 0.0; - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; diff --git a/src/projections/chamb.cpp b/src/projections/chamb.cpp index 1b926b8a..b315832a 100644 --- a/src/projections/chamb.cpp +++ b/src/projections/chamb.cpp @@ -103,7 +103,7 @@ static PJ_XY chamb_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forwar PJ *PROJECTION(chamb) { int i, j; char line[10]; - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; diff --git a/src/projections/col_urban.cpp b/src/projections/col_urban.cpp index 5bc8407f..de0c178f 100644 --- a/src/projections/col_urban.cpp +++ b/src/projections/col_urban.cpp @@ -54,7 +54,7 @@ static PJ_LP col_urban_inverse (PJ_XY xy, PJ *P) { } PJ *PROJECTION(col_urban) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; diff --git a/src/projections/eck3.cpp b/src/projections/eck3.cpp index 0deeb4f3..2563053f 100644 --- a/src/projections/eck3.cpp +++ b/src/projections/eck3.cpp @@ -52,7 +52,7 @@ static PJ *setup(PJ *P) { PJ *PROJECTION(eck3) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; @@ -67,7 +67,7 @@ PJ *PROJECTION(eck3) { PJ *PROJECTION(kav7) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; @@ -85,7 +85,7 @@ PJ *PROJECTION(kav7) { PJ *PROJECTION(wag6) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; @@ -100,7 +100,7 @@ PJ *PROJECTION(wag6) { PJ *PROJECTION(putp1) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; diff --git a/src/projections/eqc.cpp b/src/projections/eqc.cpp index 194625ef..9ebc9286 100644 --- a/src/projections/eqc.cpp +++ b/src/projections/eqc.cpp @@ -39,7 +39,7 @@ static PJ_LP eqc_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse PJ *PROJECTION(eqc) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; diff --git a/src/projections/eqdc.cpp b/src/projections/eqdc.cpp index 659488b1..28767d74 100644 --- a/src/projections/eqdc.cpp +++ b/src/projections/eqdc.cpp @@ -68,7 +68,7 @@ static PJ *destructor (PJ *P, int errlev) { /* Destructor if (nullptr==P->opaque) return pj_default_destructor (P, errlev); - pj_dealloc (static_cast(P->opaque)->en); + free (static_cast(P->opaque)->en); return pj_default_destructor (P, errlev); } @@ -77,7 +77,7 @@ PJ *PROJECTION(eqdc) { double cosphi, sinphi; int secant; - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; diff --git a/src/projections/eqearth.cpp b/src/projections/eqearth.cpp index 60effde0..2ef2775b 100644 --- a/src/projections/eqearth.cpp +++ b/src/projections/eqearth.cpp @@ -137,13 +137,13 @@ static PJ *destructor (PJ *P, int errlev) { /* Destructor */ if (nullptr==P->opaque) return pj_default_destructor (P, errlev); - pj_dealloc (static_cast(P->opaque)->apa); + free (static_cast(P->opaque)->apa); return pj_default_destructor (P, errlev); } PJ *PROJECTION(eqearth) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; diff --git a/src/projections/fouc_s.cpp b/src/projections/fouc_s.cpp index c5989514..f7607635 100644 --- a/src/projections/fouc_s.cpp +++ b/src/projections/fouc_s.cpp @@ -55,7 +55,7 @@ static PJ_LP fouc_s_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inver PJ *PROJECTION(fouc_s) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; diff --git a/src/projections/geos.cpp b/src/projections/geos.cpp index 338f07c2..5de4c7ca 100644 --- a/src/projections/geos.cpp +++ b/src/projections/geos.cpp @@ -199,7 +199,7 @@ static PJ_LP geos_e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse PJ *PROJECTION(geos) { char *sweep_axis; - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; diff --git a/src/projections/gn_sinu.cpp b/src/projections/gn_sinu.cpp index 815de8be..ef312613 100644 --- a/src/projections/gn_sinu.cpp +++ b/src/projections/gn_sinu.cpp @@ -102,7 +102,7 @@ static PJ *destructor (PJ *P, int errlev) { /* Destructor if (nullptr==P->opaque) return pj_default_destructor (P, errlev); - pj_dealloc (static_cast(P->opaque)->en); + free (static_cast(P->opaque)->en); return pj_default_destructor (P, errlev); } @@ -121,7 +121,7 @@ static void setup(PJ *P) { PJ *PROJECTION(sinu) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; @@ -143,7 +143,7 @@ PJ *PROJECTION(sinu) { PJ *PROJECTION(eck6) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; @@ -158,7 +158,7 @@ PJ *PROJECTION(eck6) { PJ *PROJECTION(mbtfps) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; @@ -173,7 +173,7 @@ PJ *PROJECTION(mbtfps) { PJ *PROJECTION(gn_sinu) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; diff --git a/src/projections/gnom.cpp b/src/projections/gnom.cpp index 23dee030..9abbb7ce 100644 --- a/src/projections/gnom.cpp +++ b/src/projections/gnom.cpp @@ -124,7 +124,7 @@ static PJ_LP gnom_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse PJ *PROJECTION(gnom) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; diff --git a/src/projections/goode.cpp b/src/projections/goode.cpp index 9a6fb86c..c0afd2d8 100644 --- a/src/projections/goode.cpp +++ b/src/projections/goode.cpp @@ -62,7 +62,7 @@ static PJ *destructor (PJ *P, int errlev) { /* Destructor */ PJ *PROJECTION(goode) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; diff --git a/src/projections/gstmerc.cpp b/src/projections/gstmerc.cpp index 50814bb5..b21f6ffd 100644 --- a/src/projections/gstmerc.cpp +++ b/src/projections/gstmerc.cpp @@ -54,7 +54,7 @@ static PJ_LP gstmerc_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inve PJ *PROJECTION(gstmerc) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; diff --git a/src/projections/hammer.cpp b/src/projections/hammer.cpp index 8d6d9408..d9bcafc7 100644 --- a/src/projections/hammer.cpp +++ b/src/projections/hammer.cpp @@ -57,7 +57,7 @@ static PJ_LP hammer_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inver PJ *PROJECTION(hammer) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; diff --git a/src/projections/healpix.cpp b/src/projections/healpix.cpp index 5a06125d..c778f28f 100644 --- a/src/projections/healpix.cpp +++ b/src/projections/healpix.cpp @@ -607,13 +607,13 @@ static PJ *destructor (PJ *P, int errlev) { /* Destructor if (nullptr==P->opaque) return pj_default_destructor (P, errlev); - pj_dealloc (static_cast(P->opaque)->apa); + free (static_cast(P->opaque)->apa); return pj_default_destructor (P, errlev); } PJ *PROJECTION(healpix) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; @@ -641,7 +641,7 @@ PJ *PROJECTION(healpix) { PJ *PROJECTION(rhealpix) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; diff --git a/src/projections/igh.cpp b/src/projections/igh.cpp index 2be94889..8aaaaba1 100644 --- a/src/projections/igh.cpp +++ b/src/projections/igh.cpp @@ -208,7 +208,7 @@ static bool setup_zone(PJ *P, struct pj_opaque *Q, int n, PJ *PROJECTION(igh) { PJ_XY xy1, xy3; PJ_LP lp = { 0, phi_boundary }; - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; diff --git a/src/projections/igh_o.cpp b/src/projections/igh_o.cpp index b14d79a5..80874845 100644 --- a/src/projections/igh_o.cpp +++ b/src/projections/igh_o.cpp @@ -222,7 +222,7 @@ static bool setup_zone(PJ *P, struct pj_opaque *Q, int n, PJ *PROJECTION(igh_o) { PJ_XY xy1, xy4; PJ_LP lp = { 0, phi_boundary }; - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; diff --git a/src/projections/imw_p.cpp b/src/projections/imw_p.cpp index ee206091..6e82d287 100644 --- a/src/projections/imw_p.cpp +++ b/src/projections/imw_p.cpp @@ -160,7 +160,7 @@ static PJ *destructor (PJ *P, int errlev) { return pj_default_destructor (P, errlev); if( static_cast(P->opaque)->en ) - pj_dealloc (static_cast(P->opaque)->en); + free (static_cast(P->opaque)->en); return pj_default_destructor(P, errlev); } @@ -169,7 +169,7 @@ static PJ *destructor (PJ *P, int errlev) { PJ *PROJECTION(imw_p) { double del, sig, s, t, x1, x2, T2, y1, m1, m2, y2; int err; - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; diff --git a/src/projections/isea.cpp b/src/projections/isea.cpp index dd1d48ff..77a5689b 100644 --- a/src/projections/isea.cpp +++ b/src/projections/isea.cpp @@ -1039,7 +1039,7 @@ static PJ_XY isea_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward PJ *PROJECTION(isea) { char *opt; - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; diff --git a/src/projections/krovak.cpp b/src/projections/krovak.cpp index 3e6a5c30..adc039fe 100644 --- a/src/projections/krovak.cpp +++ b/src/projections/krovak.cpp @@ -191,7 +191,7 @@ static PJ_LP krovak_e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, PJ *PROJECTION(krovak) { double u0, n0, g; - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; diff --git a/src/projections/labrd.cpp b/src/projections/labrd.cpp index c9dfdfc6..4fbcf460 100644 --- a/src/projections/labrd.cpp +++ b/src/projections/labrd.cpp @@ -105,7 +105,7 @@ static PJ_LP labrd_e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, invers PJ *PROJECTION(labrd) { double Az, sinp, R, N, t; - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; diff --git a/src/projections/laea.cpp b/src/projections/laea.cpp index 3d135864..2d19cab1 100644 --- a/src/projections/laea.cpp +++ b/src/projections/laea.cpp @@ -234,7 +234,7 @@ static PJ *destructor (PJ *P, int errlev) { if (nullptr==P->opaque) return pj_default_destructor (P, errlev); - pj_dealloc (static_cast(P->opaque)->apa); + free (static_cast(P->opaque)->apa); return pj_default_destructor(P, errlev); } @@ -242,7 +242,7 @@ static PJ *destructor (PJ *P, int errlev) { PJ *PROJECTION(laea) { double t; - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; diff --git a/src/projections/lagrng.cpp b/src/projections/lagrng.cpp index d37a00e6..1029bf8d 100644 --- a/src/projections/lagrng.cpp +++ b/src/projections/lagrng.cpp @@ -71,7 +71,7 @@ static PJ_LP lagrng_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inver PJ *PROJECTION(lagrng) { double sin_phi1; - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; diff --git a/src/projections/lcc.cpp b/src/projections/lcc.cpp index 46378ce4..525281f4 100644 --- a/src/projections/lcc.cpp +++ b/src/projections/lcc.cpp @@ -80,7 +80,7 @@ static PJ_LP lcc_e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse PJ *PROJECTION(lcc) { double cosphi, sinphi; int secant; - struct pj_opaque *Q = static_cast(pj_calloc(1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc(1, sizeof (struct pj_opaque))); if (nullptr == Q) return pj_default_destructor(P, ENOMEM); diff --git a/src/projections/lcca.cpp b/src/projections/lcca.cpp index 51dd28aa..53646fc6 100644 --- a/src/projections/lcca.cpp +++ b/src/projections/lcca.cpp @@ -128,14 +128,14 @@ static PJ *destructor (PJ *P, int errlev) { if (nullptr==P->opaque) return pj_default_destructor (P, errlev); - pj_dealloc (static_cast(P->opaque)->en); + free (static_cast(P->opaque)->en); return pj_default_destructor (P, errlev); } PJ *PROJECTION(lcca) { double s2p0, N0, R0, tan0; - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; diff --git a/src/projections/loxim.cpp b/src/projections/loxim.cpp index 2ee88037..64124bdd 100644 --- a/src/projections/loxim.cpp +++ b/src/projections/loxim.cpp @@ -56,7 +56,7 @@ static PJ_LP loxim_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, invers PJ *PROJECTION(loxim) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; diff --git a/src/projections/lsat.cpp b/src/projections/lsat.cpp index f6114485..a811a3a6 100644 --- a/src/projections/lsat.cpp +++ b/src/projections/lsat.cpp @@ -158,7 +158,7 @@ static PJ_LP lsat_e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse PJ *PROJECTION(lsat) { int land, path; double lam, alf, esc, ess; - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor(P, ENOMEM); P->opaque = Q; diff --git a/src/projections/misrsom.cpp b/src/projections/misrsom.cpp index 71116e1e..d7e199f2 100644 --- a/src/projections/misrsom.cpp +++ b/src/projections/misrsom.cpp @@ -178,7 +178,7 @@ PJ *PROJECTION(misrsom) { int path; double lam, alf, esc, ess; - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; diff --git a/src/projections/mod_ster.cpp b/src/projections/mod_ster.cpp index c7a8e899..0c30b7b6 100644 --- a/src/projections/mod_ster.cpp +++ b/src/projections/mod_ster.cpp @@ -134,7 +134,7 @@ PJ *PROJECTION(mil_os) { {0.019430, 0.} }; - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; @@ -157,7 +157,7 @@ PJ *PROJECTION(lee_os) { {-0.0088162, -0.00617325} }; - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; @@ -182,7 +182,7 @@ PJ *PROJECTION(gs48) { {0.075528, 0.} }; - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; @@ -217,7 +217,7 @@ PJ *PROJECTION(alsk) { { .3660976, -.2937382} }; - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; @@ -265,7 +265,7 @@ PJ *PROJECTION(gs50) { {-.0225161, .0853673} }; - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; diff --git a/src/projections/moll.cpp b/src/projections/moll.cpp index 5d4f7825..4864c8e1 100644 --- a/src/projections/moll.cpp +++ b/src/projections/moll.cpp @@ -77,7 +77,7 @@ static PJ * setup(PJ *P, double p) { PJ *PROJECTION(moll) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; @@ -87,7 +87,7 @@ PJ *PROJECTION(moll) { PJ *PROJECTION(wag4) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; @@ -96,7 +96,7 @@ PJ *PROJECTION(wag4) { } PJ *PROJECTION(wag5) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; diff --git a/src/projections/nsper.cpp b/src/projections/nsper.cpp index 903946b9..951111ac 100644 --- a/src/projections/nsper.cpp +++ b/src/projections/nsper.cpp @@ -180,7 +180,7 @@ static PJ *setup(PJ *P) { PJ *PROJECTION(nsper) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; @@ -194,7 +194,7 @@ PJ *PROJECTION(nsper) { PJ *PROJECTION(tpers) { double omega, gamma; - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; diff --git a/src/projections/ob_tran.cpp b/src/projections/ob_tran.cpp index 7cf1cf98..4990ab2a 100644 --- a/src/projections/ob_tran.cpp +++ b/src/projections/ob_tran.cpp @@ -142,7 +142,7 @@ static ARGS ob_tran_target_params (paralist *params) { return args; /* all args except the proj_ob_tran */ - args.argv = static_cast(pj_calloc (argc - 1, sizeof (char *))); + args.argv = static_cast(calloc (argc - 1, sizeof (char *))); if (nullptr==args.argv) return args; @@ -160,7 +160,7 @@ static ARGS ob_tran_target_params (paralist *params) { continue; args.argv[i] += 2; if (strcmp(args.argv[i], "proj=ob_tran") == 0 ) { - pj_dealloc (args.argv); + free (args.argv); args.argc = 0; args.argv = nullptr; } @@ -177,7 +177,7 @@ PJ *PROJECTION(ob_tran) { ARGS args; PJ *R; /* projection to rotate */ - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return destructor(P, ENOMEM); @@ -195,7 +195,7 @@ PJ *PROJECTION(ob_tran) { 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); + free (args.argv); if (nullptr==R) return destructor (P, PJD_ERR_UNKNOWN_PROJECTION_ID); diff --git a/src/projections/ocea.cpp b/src/projections/ocea.cpp index de9838cb..c78e1ebc 100644 --- a/src/projections/ocea.cpp +++ b/src/projections/ocea.cpp @@ -52,7 +52,7 @@ static PJ_LP ocea_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse PJ *PROJECTION(ocea) { double phi_1, phi_2, lam_1, lam_2, lonz, alpha; - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; diff --git a/src/projections/oea.cpp b/src/projections/oea.cpp index 61fb0647..46c00d16 100644 --- a/src/projections/oea.cpp +++ b/src/projections/oea.cpp @@ -58,7 +58,7 @@ static PJ_LP oea_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse PJ *PROJECTION(oea) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; diff --git a/src/projections/omerc.cpp b/src/projections/omerc.cpp index e9f3b833..90067cc3 100644 --- a/src/projections/omerc.cpp +++ b/src/projections/omerc.cpp @@ -126,7 +126,7 @@ PJ *PROJECTION(omerc) { gamma0, lamc=0, lam1=0, lam2=0, phi1=0, phi2=0, alpha_c=0; int alp, gam, no_off = 0; - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; diff --git a/src/projections/ortho.cpp b/src/projections/ortho.cpp index d9c84dba..4417dac7 100644 --- a/src/projections/ortho.cpp +++ b/src/projections/ortho.cpp @@ -279,7 +279,7 @@ static PJ_LP ortho_e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inver PJ *PROJECTION(ortho) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor(P, ENOMEM); P->opaque = Q; diff --git a/src/projections/poly.cpp b/src/projections/poly.cpp index 10d93ed2..4ea95cc7 100644 --- a/src/projections/poly.cpp +++ b/src/projections/poly.cpp @@ -147,14 +147,14 @@ static PJ *destructor(PJ *P, int errlev) { return pj_default_destructor (P, errlev); if (static_cast(P->opaque)->en) - pj_dealloc (static_cast(P->opaque)->en); + free (static_cast(P->opaque)->en); return pj_default_destructor(P, errlev); } PJ *PROJECTION(poly) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); diff --git a/src/projections/putp3.cpp b/src/projections/putp3.cpp index c2df20e8..09763851 100644 --- a/src/projections/putp3.cpp +++ b/src/projections/putp3.cpp @@ -38,7 +38,7 @@ static PJ_LP putp3_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, invers PJ *PROJECTION(putp3) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; @@ -53,7 +53,7 @@ PJ *PROJECTION(putp3) { } PJ *PROJECTION(putp3p) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; diff --git a/src/projections/putp4p.cpp b/src/projections/putp4p.cpp index 365f7c1b..8df18972 100644 --- a/src/projections/putp4p.cpp +++ b/src/projections/putp4p.cpp @@ -45,7 +45,7 @@ static PJ_LP putp4p_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inver PJ *PROJECTION(putp4p) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; @@ -62,7 +62,7 @@ PJ *PROJECTION(putp4p) { PJ *PROJECTION(weren) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; diff --git a/src/projections/putp5.cpp b/src/projections/putp5.cpp index 1847e7a9..5e70382d 100644 --- a/src/projections/putp5.cpp +++ b/src/projections/putp5.cpp @@ -43,7 +43,7 @@ static PJ_LP putp5_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, invers PJ *PROJECTION(putp5) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; @@ -60,7 +60,7 @@ PJ *PROJECTION(putp5) { PJ *PROJECTION(putp5p) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; diff --git a/src/projections/putp6.cpp b/src/projections/putp6.cpp index db334ff9..da8c0a7c 100644 --- a/src/projections/putp6.cpp +++ b/src/projections/putp6.cpp @@ -59,7 +59,7 @@ static PJ_LP putp6_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, invers PJ *PROJECTION(putp6) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor(P, ENOMEM); P->opaque = Q; @@ -79,7 +79,7 @@ PJ *PROJECTION(putp6) { PJ *PROJECTION(putp6p) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor(P, ENOMEM); P->opaque = Q; diff --git a/src/projections/qsc.cpp b/src/projections/qsc.cpp index 98e3755e..dd9ce965 100644 --- a/src/projections/qsc.cpp +++ b/src/projections/qsc.cpp @@ -377,7 +377,7 @@ static PJ_LP qsc_e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse PJ *PROJECTION(qsc) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; diff --git a/src/projections/rouss.cpp b/src/projections/rouss.cpp index f5a8f12f..2eb13b3d 100644 --- a/src/projections/rouss.cpp +++ b/src/projections/rouss.cpp @@ -93,7 +93,7 @@ static PJ *destructor (PJ *P, int errlev) { return pj_default_destructor (P, errlev); if (static_cast(P->opaque)->en) - pj_dealloc (static_cast(P->opaque)->en); + free (static_cast(P->opaque)->en); return pj_default_destructor (P, ENOMEM); } @@ -102,7 +102,7 @@ static PJ *destructor (PJ *P, int errlev) { PJ *PROJECTION(rouss) { double N0, es2, t, t2, R_R0_2, R_R0_4; - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor(P, ENOMEM); P->opaque = Q; diff --git a/src/projections/rpoly.cpp b/src/projections/rpoly.cpp index b065861f..e3f09c59 100644 --- a/src/projections/rpoly.cpp +++ b/src/projections/rpoly.cpp @@ -44,7 +44,7 @@ static PJ_XY rpoly_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forwar PJ *PROJECTION(rpoly) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor(P, ENOMEM); P->opaque = Q; diff --git a/src/projections/sch.cpp b/src/projections/sch.cpp index 7548039d..359e8efc 100644 --- a/src/projections/sch.cpp +++ b/src/projections/sch.cpp @@ -184,7 +184,7 @@ static PJ *setup(PJ *P) { /* general initialization */ PJ *PROJECTION(sch) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor(P, ENOMEM); P->opaque = Q; diff --git a/src/projections/sconics.cpp b/src/projections/sconics.cpp index f305e291..c12b05a2 100644 --- a/src/projections/sconics.cpp +++ b/src/projections/sconics.cpp @@ -117,7 +117,7 @@ static PJ_LP sconics_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, (and ellipsoi static PJ *setup(PJ *P, enum Type type) { double del, cs; int err; - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; diff --git a/src/projections/somerc.cpp b/src/projections/somerc.cpp index fe6477fa..a184500c 100644 --- a/src/projections/somerc.cpp +++ b/src/projections/somerc.cpp @@ -71,7 +71,7 @@ static PJ_LP somerc_e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inver PJ *PROJECTION(somerc) { double cp, phip0, sp; - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; diff --git a/src/projections/stere.cpp b/src/projections/stere.cpp index 3fff722d..ad1caae2 100644 --- a/src/projections/stere.cpp +++ b/src/projections/stere.cpp @@ -302,7 +302,7 @@ static PJ *setup(PJ *P) { /* general initialization */ PJ *PROJECTION(stere) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; @@ -315,7 +315,7 @@ PJ *PROJECTION(stere) { PJ *PROJECTION(ups) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; diff --git a/src/projections/sterea.cpp b/src/projections/sterea.cpp index 55404c86..4dd22d2f 100644 --- a/src/projections/sterea.cpp +++ b/src/projections/sterea.cpp @@ -93,14 +93,14 @@ static PJ *destructor (PJ *P, int errlev) { if (nullptr==P->opaque) return pj_default_destructor (P, errlev); - pj_dealloc (static_cast(P->opaque)->en); + free (static_cast(P->opaque)->en); return pj_default_destructor (P, errlev); } PJ *PROJECTION(sterea) { double R; - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); diff --git a/src/projections/sts.cpp b/src/projections/sts.cpp index cbc36b7d..75190e85 100644 --- a/src/projections/sts.cpp +++ b/src/projections/sts.cpp @@ -70,7 +70,7 @@ static PJ *setup(PJ *P, double p, double q, int mode) { PJ *PROJECTION(fouc) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor(P, ENOMEM); P->opaque = Q; @@ -80,7 +80,7 @@ PJ *PROJECTION(fouc) { PJ *PROJECTION(kav5) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor(P, ENOMEM); P->opaque = Q; @@ -91,7 +91,7 @@ PJ *PROJECTION(kav5) { PJ *PROJECTION(qua_aut) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor(P, ENOMEM); P->opaque = Q; @@ -101,7 +101,7 @@ PJ *PROJECTION(qua_aut) { PJ *PROJECTION(mbt_s) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor(P, ENOMEM); P->opaque = Q; diff --git a/src/projections/tmerc.cpp b/src/projections/tmerc.cpp index ff1bc2a5..8cae9968 100644 --- a/src/projections/tmerc.cpp +++ b/src/projections/tmerc.cpp @@ -221,7 +221,7 @@ static PJ *destructor(PJ *P, int errlev) { if (nullptr==P->opaque) return pj_default_destructor(P, errlev); - pj_dealloc (static_cast(P->opaque)->approx.en); + free (static_cast(P->opaque)->approx.en); return pj_default_destructor(P, errlev); } @@ -592,7 +592,7 @@ static PJ_LP auto_e_inv (PJ_XY xy, PJ *P) { static PJ *setup(PJ *P, TMercAlgo eAlg) { - struct tmerc_data *Q = static_cast(pj_calloc (1, sizeof (struct tmerc_data))); + struct tmerc_data *Q = static_cast(calloc (1, sizeof (struct tmerc_data))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; diff --git a/src/projections/tpeqd.cpp b/src/projections/tpeqd.cpp index 58aeb8e1..90efb395 100644 --- a/src/projections/tpeqd.cpp +++ b/src/projections/tpeqd.cpp @@ -64,7 +64,7 @@ static PJ_LP tpeqd_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, invers PJ *PROJECTION(tpeqd) { double lam_1, lam_2, phi_1, phi_2, A12; - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor(P, ENOMEM); P->opaque = Q; diff --git a/src/projections/urm5.cpp b/src/projections/urm5.cpp index 499644d2..c3021841 100644 --- a/src/projections/urm5.cpp +++ b/src/projections/urm5.cpp @@ -30,7 +30,7 @@ static PJ_XY urm5_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward PJ *PROJECTION(urm5) { double alpha, t; - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor(P, ENOMEM); P->opaque = Q; diff --git a/src/projections/urmfps.cpp b/src/projections/urmfps.cpp index 3f9fdf23..5d689f9f 100644 --- a/src/projections/urmfps.cpp +++ b/src/projections/urmfps.cpp @@ -47,7 +47,7 @@ static PJ *setup(PJ *P) { PJ *PROJECTION(urmfps) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor(P, ENOMEM); @@ -66,7 +66,7 @@ PJ *PROJECTION(urmfps) { PJ *PROJECTION(wag1) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor(P, ENOMEM); P->opaque = Q; diff --git a/src/projections/vandg2.cpp b/src/projections/vandg2.cpp index 223620d6..cd7e7b6c 100644 --- a/src/projections/vandg2.cpp +++ b/src/projections/vandg2.cpp @@ -53,7 +53,7 @@ static PJ_XY vandg2_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forwa PJ *PROJECTION(vandg2) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; @@ -65,7 +65,7 @@ PJ *PROJECTION(vandg2) { } PJ *PROJECTION(vandg3) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; diff --git a/src/projections/wag3.cpp b/src/projections/wag3.cpp index 33313cdb..ed3250ef 100644 --- a/src/projections/wag3.cpp +++ b/src/projections/wag3.cpp @@ -35,7 +35,7 @@ static PJ_LP wag3_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse PJ *PROJECTION(wag3) { double ts; - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor(P, ENOMEM); diff --git a/src/projections/wink1.cpp b/src/projections/wink1.cpp index d097978f..f4ffafe3 100644 --- a/src/projections/wink1.cpp +++ b/src/projections/wink1.cpp @@ -33,7 +33,7 @@ static PJ_LP wink1_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, invers PJ *PROJECTION(wink1) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor(P, ENOMEM); P->opaque = Q; diff --git a/src/projections/wink2.cpp b/src/projections/wink2.cpp index d457f842..b5b1e812 100644 --- a/src/projections/wink2.cpp +++ b/src/projections/wink2.cpp @@ -53,7 +53,7 @@ static PJ_LP wink2_s_inverse(PJ_XY xy, PJ *P) PJ *PROJECTION(wink2) { - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor(P, ENOMEM); P->opaque = Q; diff --git a/src/transformations/affine.cpp b/src/transformations/affine.cpp index 28f73b9a..43fd8642 100644 --- a/src/transformations/affine.cpp +++ b/src/transformations/affine.cpp @@ -110,7 +110,7 @@ static PJ_LP reverse_2d(PJ_XY xy, PJ *P) { } static struct pj_opaque_affine * initQ() { - struct pj_opaque_affine *Q = static_cast(pj_calloc(1, sizeof(struct pj_opaque_affine))); + struct pj_opaque_affine *Q = static_cast(calloc(1, sizeof(struct pj_opaque_affine))); if (nullptr==Q) return nullptr; diff --git a/src/transformations/helmert.cpp b/src/transformations/helmert.cpp index d3857d89..99aa74a4 100644 --- a/src/transformations/helmert.cpp +++ b/src/transformations/helmert.cpp @@ -476,7 +476,7 @@ static PJ_COORD helmert_reverse_4d (PJ_COORD point, PJ *P) { static PJ* init_helmert_six_parameters(PJ* P) { - struct pj_opaque_helmert *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque_helmert))); + struct pj_opaque_helmert *Q = static_cast(calloc (1, sizeof (struct pj_opaque_helmert))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = (void *) Q; diff --git a/src/transformations/horner.cpp b/src/transformations/horner.cpp index a6638773..2c049186 100644 --- a/src/transformations/horner.cpp +++ b/src/transformations/horner.cpp @@ -89,8 +89,8 @@ PROJ_HEAD(horner, "Horner polynomial evaluation"); /* make horner.h interface with proj's memory management */ -#define horner_dealloc(x) pj_dealloc(x) -#define horner_calloc(n,x) pj_calloc(n,x) +#define horner_dealloc(x) free(x) +#define horner_calloc(n,x) calloc(n,x) namespace { // anonymous namespace struct horner { @@ -412,7 +412,7 @@ static int parse_coefs (PJ *P, double *coefs, const char *param, int ncoefs) { char *buf, *init, *next = nullptr; int i; - buf = static_cast(pj_calloc (strlen (param) + 2, sizeof(char))); + buf = static_cast(calloc (strlen (param) + 2, sizeof(char))); if (nullptr==buf) { proj_log_error (P, "Horner: No memory left"); return 0; @@ -420,12 +420,12 @@ static int parse_coefs (PJ *P, double *coefs, const char *param, int ncoefs) { sprintf (buf, "t%s", param); if (0==pj_param (P->ctx, P->params, buf).i) { - pj_dealloc (buf); + free (buf); return 0; } sprintf (buf, "s%s", param); init = pj_param(P->ctx, P->params, buf).s; - pj_dealloc (buf); + free (buf); for (i = 0; i < ncoefs; i++) { if (i > 0) { diff --git a/src/transformations/molodensky.cpp b/src/transformations/molodensky.cpp index 7d17f64c..bf5960d2 100644 --- a/src/transformations/molodensky.cpp +++ b/src/transformations/molodensky.cpp @@ -298,7 +298,7 @@ static PJ_COORD reverse_4d(PJ_COORD obs, PJ *P) { PJ *TRANSFORMATION(molodensky,1) { int count_required_params = 0; - struct pj_opaque_molodensky *Q = static_cast(pj_calloc(1, sizeof(struct pj_opaque_molodensky))); + struct pj_opaque_molodensky *Q = static_cast(calloc(1, sizeof(struct pj_opaque_molodensky))); if (nullptr==Q) return pj_default_destructor(P, ENOMEM); P->opaque = (void *) Q; -- cgit v1.2.3 From d9205b9245388f23b65917a21ec72d6bec15d035 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Tue, 17 Nov 2020 22:43:17 +0100 Subject: Update list of exported symbols --- scripts/reference_exported_symbols.txt | 127 ++++++++++++--------------------- 1 file changed, 44 insertions(+), 83 deletions(-) diff --git a/scripts/reference_exported_symbols.txt b/scripts/reference_exported_symbols.txt index 8db49a95..8ea2c231 100644 --- a/scripts/reference_exported_symbols.txt +++ b/scripts/reference_exported_symbols.txt @@ -284,8 +284,8 @@ osgeo::proj::datum::VerticalReferenceFrame::create(osgeo::proj::util::PropertyMa osgeo::proj::datum::VerticalReferenceFrame::realizationMethod() const osgeo::proj::datum::VerticalReferenceFrame::~VerticalReferenceFrame() osgeo::proj::File::~File() -osgeo::proj::FileManager::exists(projCtx_t*, char const*) -osgeo::proj::FileManager::open(projCtx_t*, char const*, osgeo::proj::FileAccess) +osgeo::proj::FileManager::exists(pj_ctx*, char const*) +osgeo::proj::FileManager::open(pj_ctx*, char const*, osgeo::proj::FileAccess) osgeo::proj::File::read_line(unsigned long, bool&, bool&) osgeo::proj::GenericShiftGrid::~GenericShiftGrid() osgeo::proj::GenericShiftGrid::GenericShiftGrid(std::string const&, int, int, osgeo::proj::ExtentAndRes const&) @@ -293,9 +293,9 @@ osgeo::proj::GenericShiftGrid::gridAt(double, double) const osgeo::proj::GenericShiftGridSet::~GenericShiftGridSet() osgeo::proj::GenericShiftGridSet::GenericShiftGridSet() osgeo::proj::GenericShiftGridSet::gridAt(double, double) const -osgeo::proj::GenericShiftGridSet::open(projCtx_t*, std::string const&) -osgeo::proj::GenericShiftGridSet::reassign_context(projCtx_t*) -osgeo::proj::GenericShiftGridSet::reopen(projCtx_t*) +osgeo::proj::GenericShiftGridSet::open(pj_ctx*, std::string const&) +osgeo::proj::GenericShiftGridSet::reassign_context(pj_ctx*) +osgeo::proj::GenericShiftGridSet::reopen(pj_ctx*) osgeo::proj::Grid::~Grid() osgeo::proj::Grid::Grid(std::string const&, int, int, osgeo::proj::ExtentAndRes const&) osgeo::proj::HorizontalShiftGrid::gridAt(double, double) const @@ -304,9 +304,9 @@ osgeo::proj::HorizontalShiftGrid::HorizontalShiftGrid(std::string const&, int, i osgeo::proj::HorizontalShiftGridSet::gridAt(double, double) const osgeo::proj::HorizontalShiftGridSet::~HorizontalShiftGridSet() osgeo::proj::HorizontalShiftGridSet::HorizontalShiftGridSet() -osgeo::proj::HorizontalShiftGridSet::open(projCtx_t*, std::string const&) -osgeo::proj::HorizontalShiftGridSet::reassign_context(projCtx_t*) -osgeo::proj::HorizontalShiftGridSet::reopen(projCtx_t*) +osgeo::proj::HorizontalShiftGridSet::open(pj_ctx*, std::string const&) +osgeo::proj::HorizontalShiftGridSet::reassign_context(pj_ctx*) +osgeo::proj::HorizontalShiftGridSet::reopen(pj_ctx*) osgeo::proj::internal::ci_equal(std::string const&, char const*) osgeo::proj::internal::ci_equal(std::string const&, std::string const&) osgeo::proj::internal::ci_find(std::string const&, char const*) @@ -351,9 +351,9 @@ osgeo::proj::io::AuthorityFactory::getUnitList() const osgeo::proj::io::AuthorityFactory::identifyBodyFromSemiMajorAxis(double, double) const osgeo::proj::io::AuthorityFactory::listAreaOfUseFromName(std::string const&, bool) const osgeo::proj::io::AuthorityFactory::UnitInfo::UnitInfo() -osgeo::proj::io::createFromUserInput(std::string const&, projCtx_t*) +osgeo::proj::io::createFromUserInput(std::string const&, pj_ctx*) osgeo::proj::io::createFromUserInput(std::string const&, std::shared_ptr const&, bool) -osgeo::proj::io::DatabaseContext::create(std::string const&, std::vector > const&, projCtx_t*) +osgeo::proj::io::DatabaseContext::create(std::string const&, std::vector > const&, pj_ctx*) osgeo::proj::io::DatabaseContext::create(void*) osgeo::proj::io::DatabaseContext::~DatabaseContext() osgeo::proj::io::DatabaseContext::getAuthorities() const @@ -413,7 +413,7 @@ osgeo::proj::io::PROJStringFormatter::setUseApproxTMerc(bool) osgeo::proj::io::PROJStringFormatter::startInversion() osgeo::proj::io::PROJStringFormatter::stopInversion() osgeo::proj::io::PROJStringFormatter::toString() const -osgeo::proj::io::PROJStringParser::attachContext(projCtx_t*) +osgeo::proj::io::PROJStringParser::attachContext(pj_ctx*) osgeo::proj::io::PROJStringParser::attachDatabaseContext(std::shared_ptr const&) osgeo::proj::io::PROJStringParser::createFromPROJString(std::string const&) osgeo::proj::io::PROJStringParser::~PROJStringParser() @@ -734,90 +734,51 @@ osgeo::proj::util::UnsupportedOperationException::~UnsupportedOperationException osgeo::proj::util::UnsupportedOperationException::UnsupportedOperationException(osgeo::proj::util::UnsupportedOperationException const&) osgeo::proj::VerticalShiftGrid::gridAt(double, double) const osgeo::proj::VerticalShiftGridSet::gridAt(double, double) const -osgeo::proj::VerticalShiftGridSet::open(projCtx_t*, std::string const&) -osgeo::proj::VerticalShiftGridSet::reassign_context(projCtx_t*) -osgeo::proj::VerticalShiftGridSet::reopen(projCtx_t*) +osgeo::proj::VerticalShiftGridSet::open(pj_ctx*, std::string const&) +osgeo::proj::VerticalShiftGridSet::reassign_context(pj_ctx*) +osgeo::proj::VerticalShiftGridSet::reopen(pj_ctx*) osgeo::proj::VerticalShiftGridSet::~VerticalShiftGridSet() osgeo::proj::VerticalShiftGridSet::VerticalShiftGridSet() osgeo::proj::VerticalShiftGrid::~VerticalShiftGrid() osgeo::proj::VerticalShiftGrid::VerticalShiftGrid(std::string const&, int, int, osgeo::proj::ExtentAndRes const&) -pj_acquire_lock +pj_acquire_lock() pj_add_type_crs_if_needed(std::string const&) -pj_apply_gridshift pj_approx_2D_trans(PJconsts*, PJ_DIRECTION, PJ_COORD) pj_approx_3D_trans(PJconsts*, PJ_DIRECTION, PJ_COORD) pj_atof(char const*) -pj_calloc pj_chomp(char*) -pj_cleanup_lock -pj_clear_initcache -pj_compare_datums -pj_context_get_grid_cache_filename(projCtx_t*) -pj_context_set_user_writable_directory(projCtx_t*, std::string const&) -pj_ctx_alloc -pj_ctx_fclose -pj_ctx_fgets -pj_ctx_fopen -pj_ctx_fread -pj_ctx_free -pj_ctx_fseek -pj_ctx_ftell -pj_ctx_get_app_data -pj_ctx_get_errno -pj_ctx_get_fileapi -pj_ctx_set_app_data -pj_ctx_set_debug -pj_ctx_set_errno -pj_ctx_set_fileapi -pj_ctx_set_logger -pj_dalloc -pj_datum_transform -pj_dealloc -pj_deallocate_grids -pj_ell_set(projCtx_t*, ARG_list*, double*, double*) -pj_find_file -pj_free -pj_fwd -pj_fwd3d -pj_geocentric_to_geodetic -pj_geodetic_to_geocentric -pj_get_ctx +pj_cleanup_lock() +pj_clear_initcache() +pj_context_get_grid_cache_filename(pj_ctx*) +pj_context_set_user_writable_directory(pj_ctx*, std::string const&) +pj_ell_set(pj_ctx*, ARG_list*, double*, double*) +pj_find_file(pj_ctx*, char const*, char*, unsigned long) +pj_fwd3d(PJ_LPZ, PJconsts*) +pj_fwd(PJ_LP, PJconsts*) +pj_get_ctx(PJconsts*) pj_get_datums_ref() -pj_get_def -pj_get_default_ctx -pj_get_default_fileapi -pj_get_default_searchpaths(projCtx_t*) -pj_get_errno_ref -pj_get_relative_share_proj(projCtx_t*) -pj_get_release -pj_get_spheroid_defn -pj_has_inverse -pj_init -pj_init_ctx -pj_init_plus -pj_init_plus_ctx -pj_inv -pj_inv3d -pj_is_geocent -pj_is_latlong -pj_latlong_from_proj -pj_log -pj_malloc +pj_get_default_ctx() +pj_get_default_searchpaths(pj_ctx*) +pj_get_def(PJconsts*, int) +pj_get_relative_share_proj(pj_ctx*) +pj_get_release() +pj_has_inverse(PJconsts*) +pj_init_ctx(pj_ctx*, int, char**) +pj_init(int, char**) +pj_init_plus(char const*) +pj_init_plus_ctx(pj_ctx*, char const*) +pj_inv3d(PJ_XYZ, PJconsts*) +pj_inv(PJ_XY, PJconsts*) +pj_log(pj_ctx*, int, char const*, ...) pj_mkparam(char const*) -pj_open_lib pj_param_exists(ARG_list*, char const*) -pj_param(projCtx_t*, ARG_list*, char const*) -pj_phi2(projCtx_t*, double, double) -pj_pr_list -pj_release_lock -pj_set_ctx -pj_set_finder -pj_set_searchpath +pj_param(pj_ctx*, ARG_list*, char const*) +pj_phi2(pj_ctx*, double, double) +pj_pr_list(PJconsts*) +pj_release_lock() pj_shrink(char*) -pj_stderr_logger -pj_strdup -pj_strerrno -pj_transform +pj_stderr_logger(void*, int, char const*) +pj_strdup(char const*) proj_alter_id proj_alter_name proj_angular_input @@ -852,7 +813,7 @@ proj_context_set_enable_network proj_context_set_fileapi proj_context_set_file_finder proj_context_set_network_callbacks -proj_context_set(PJconsts*, projCtx_t*) +proj_context_set(PJconsts*, pj_ctx*) proj_context_set_search_paths proj_context_set_sqlite3_vfs_name proj_context_set_url_endpoint -- cgit v1.2.3 From 571096201bf2cb1dde8933eb3fb7091e12ebbbe4 Mon Sep 17 00:00:00 2001 From: Nomit Rawat Date: Fri, 20 Nov 2020 21:13:40 +0530 Subject: Update utm.rst Typo --- docs/source/operations/projections/utm.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/operations/projections/utm.rst b/docs/source/operations/projections/utm.rst index 82715a02..cbbda09d 100644 --- a/docs/source/operations/projections/utm.rst +++ b/docs/source/operations/projections/utm.rst @@ -6,7 +6,7 @@ Universal Transverse Mercator (UTM) The Universal Transverse Mercator is a system of map projections divided into sixty zones across the globe, with each zone corresponding to 6 degrees of -longigude. +longitude. +---------------------+----------------------------------------------------------+ | **Classification** | Transverse cylindrical, conformal | -- cgit v1.2.3 From c3a83ef5ea6119f76c5db9af32baa0673f452318 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Sat, 21 Nov 2020 13:11:59 +0100 Subject: backport.yml: update to what QGIS uses --- .github/workflows/backport.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml index aa48cff3..f937c2ce 100644 --- a/.github/workflows/backport.yml +++ b/.github/workflows/backport.yml @@ -11,8 +11,8 @@ jobs: name: Backport steps: - name: Backport Bot - if: contains( join(github.event.pull_request.labels.*.name), 'backport') - uses: Gaurav0/backport@v1.0.24 + if: github.event.pull_request.merged && ( ( github.event.action == 'closed' && contains( join( github.event.pull_request.labels.*.name ), 'backport') ) || contains( github.event.label.name, 'backport' ) ) + uses: Gaurav0/backport@v1.0.26 with: bot_username: PROJ-BOT bot_token: c1c49a5799d0a3a3885db8a4792880cbe509c1d6 -- cgit v1.2.3 From 3dea81d9be4712aa90ba79f333338c0b3ecb21e2 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Sat, 21 Nov 2020 13:55:11 +0100 Subject: Make GeographicCRS/GeodeticCRS::isEquivalentTo() work properly when comparing to a DerivedGeographicCRS/DerivedGeodeticCRS --- include/proj/crs.hpp | 5 +++++ include/proj/util.hpp | 8 ++++++++ src/iso19111/crs.cpp | 27 ++++++++++++++++++--------- test/unit/test_crs.cpp | 24 ++++++++++++++++++++++++ 4 files changed, 55 insertions(+), 9 deletions(-) diff --git a/include/proj/crs.hpp b/include/proj/crs.hpp index ec755728..b921f4bb 100644 --- a/include/proj/crs.hpp +++ b/include/proj/crs.hpp @@ -340,6 +340,11 @@ class PROJ_GCC_DLL GeodeticCRS : virtual public SingleCRS, PROJ_INTERNAL std::list> _identify(const io::AuthorityFactoryPtr &authorityFactory) const override; + PROJ_INTERNAL bool + _isEquivalentToNoTypeCheck(const util::IComparable *other, + util::IComparable::Criterion criterion, + const io::DatabaseContextPtr &dbContext) const; + INLINED_MAKE_SHARED private: diff --git a/include/proj/util.hpp b/include/proj/util.hpp index 3d85e579..2ada4f79 100644 --- a/include/proj/util.hpp +++ b/include/proj/util.hpp @@ -213,6 +213,14 @@ template using nn_shared_ptr = nn>; // To avoid formatting differences between clang-format 3.8 and 7 #define PROJ_NOEXCEPT noexcept +//! @cond Doxygen_Suppress +// isOfExactType(*p) checks that the type of *p is exactly MyType +template +inline bool isOfExactType(const ObjectT &o) { + return typeid(TemplateT).hash_code() == typeid(o).hash_code(); +} +//! @endcond + /** \brief Loose transposition of [std::optional] * (https://en.cppreference.com/w/cpp/utility/optional) available from C++17. */ template class optional { diff --git a/src/iso19111/crs.cpp b/src/iso19111/crs.cpp index 84b98984..de882105 100644 --- a/src/iso19111/crs.cpp +++ b/src/iso19111/crs.cpp @@ -1924,13 +1924,21 @@ getStandardCriterion(util::IComparable::Criterion criterion) { //! @cond Doxygen_Suppress bool GeodeticCRS::_isEquivalentTo( + const util::IComparable *other, util::IComparable::Criterion criterion, + const io::DatabaseContextPtr &dbContext) const { + if (other == nullptr || !util::isOfExactType(*other)) { + return false; + } + return _isEquivalentToNoTypeCheck(other, criterion, dbContext); +} + +bool GeodeticCRS::_isEquivalentToNoTypeCheck( const util::IComparable *other, util::IComparable::Criterion criterion, const io::DatabaseContextPtr &dbContext) const { const auto standardCriterion = getStandardCriterion(criterion); - auto otherGeodCRS = dynamic_cast(other); + // TODO test velocityModel - return otherGeodCRS != nullptr && - SingleCRS::baseIsEquivalentTo(other, standardCriterion, dbContext); + return SingleCRS::baseIsEquivalentTo(other, standardCriterion, dbContext); } //! @endcond @@ -2486,12 +2494,13 @@ bool GeographicCRS::is2DPartOf3D(util::nn other, bool GeographicCRS::_isEquivalentTo( const util::IComparable *other, util::IComparable::Criterion criterion, const io::DatabaseContextPtr &dbContext) const { - auto otherGeogCRS = dynamic_cast(other); - if (otherGeogCRS == nullptr) { + if (other == nullptr || !util::isOfExactType(*other)) { return false; } + const auto standardCriterion = getStandardCriterion(criterion); - if (GeodeticCRS::_isEquivalentTo(other, standardCriterion, dbContext)) { + if (GeodeticCRS::_isEquivalentToNoTypeCheck(other, standardCriterion, + dbContext)) { return true; } if (criterion != @@ -2510,7 +2519,8 @@ bool GeographicCRS::_isEquivalentTo( cs::EllipsoidalCS::AxisOrder::LONG_EAST_LAT_NORTH ? cs::EllipsoidalCS::createLatitudeLongitude(unit) : cs::EllipsoidalCS::createLongitudeLatitude(unit)) - ->GeodeticCRS::_isEquivalentTo(other, standardCriterion, dbContext); + ->GeodeticCRS::_isEquivalentToNoTypeCheck(other, standardCriterion, + dbContext); } return false; } @@ -3889,8 +3899,7 @@ ProjectedCRS::create(const util::PropertyMap &properties, bool ProjectedCRS::_isEquivalentTo( const util::IComparable *other, util::IComparable::Criterion criterion, const io::DatabaseContextPtr &dbContext) const { - auto otherProjCRS = dynamic_cast(other); - return otherProjCRS != nullptr && + return other != nullptr && util::isOfExactType(*other) && DerivedCRS::_isEquivalentTo(other, criterion, dbContext); } diff --git a/test/unit/test_crs.cpp b/test/unit/test_crs.cpp index 38afdce3..aea72da2 100644 --- a/test/unit/test_crs.cpp +++ b/test/unit/test_crs.cpp @@ -4750,6 +4750,18 @@ static DerivedGeographicCRSNNPtr createDerivedGeographicCRS() { // --------------------------------------------------------------------------- +TEST(crs, derivedGeographicCRS_basic) { + + auto derivedCRS = createDerivedGeographicCRS(); + EXPECT_TRUE(derivedCRS->isEquivalentTo(derivedCRS.get())); + EXPECT_FALSE(derivedCRS->isEquivalentTo( + derivedCRS->baseCRS().get(), IComparable::Criterion::EQUIVALENT)); + EXPECT_FALSE(derivedCRS->baseCRS()->isEquivalentTo( + derivedCRS.get(), IComparable::Criterion::EQUIVALENT)); +} + +// --------------------------------------------------------------------------- + TEST(crs, derivedGeographicCRS_WKT2) { auto expected = "GEODCRS[\"WMO Atlantic Pole\",\n" @@ -4950,6 +4962,18 @@ static DerivedGeodeticCRSNNPtr createDerivedGeodeticCRS() { // --------------------------------------------------------------------------- +TEST(crs, derivedGeodeticCRS_basic) { + + auto derivedCRS = createDerivedGeodeticCRS(); + EXPECT_TRUE(derivedCRS->isEquivalentTo(derivedCRS.get())); + EXPECT_FALSE(derivedCRS->isEquivalentTo( + derivedCRS->baseCRS().get(), IComparable::Criterion::EQUIVALENT)); + EXPECT_FALSE(derivedCRS->baseCRS()->isEquivalentTo( + derivedCRS.get(), IComparable::Criterion::EQUIVALENT)); +} + +// --------------------------------------------------------------------------- + TEST(crs, derivedGeodeticCRS_WKT2) { auto expected = "GEODCRS[\"Derived geodetic CRS\",\n" -- cgit v1.2.3 From c2edd467c591f936f4eb81dfadd62a20f6bff371 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Sat, 21 Nov 2020 13:56:18 +0100 Subject: createOperation(): make it work properly when one of the CRS is a BoundCRS of a DerivedGeographicCRS (+proj=ob_tran +o_proj=lonlat +towgs84=....) --- src/iso19111/coordinateoperation.cpp | 53 ++++++++++++++++++++++++++++- src/iso19111/io.cpp | 4 +-- test/unit/test_operation.cpp | 65 ++++++++++++++++++++++++++++++++++++ 3 files changed, 119 insertions(+), 3 deletions(-) diff --git a/src/iso19111/coordinateoperation.cpp b/src/iso19111/coordinateoperation.cpp index 4cf1ae89..1d3b7a90 100644 --- a/src/iso19111/coordinateoperation.cpp +++ b/src/iso19111/coordinateoperation.cpp @@ -64,6 +64,30 @@ // #define DEBUG_CONCATENATED_OPERATION #if defined(DEBUG_SORT) || defined(DEBUG_CONCATENATED_OPERATION) #include + +void dumpWKT(const NS_PROJ::crs::CRS *crs); +void dumpWKT(const NS_PROJ::crs::CRS *crs) { + auto f(NS_PROJ::io::WKTFormatter::create( + NS_PROJ::io::WKTFormatter::Convention::WKT2_2019)); + std::cerr << crs->exportToWKT(f.get()) << std::endl; +} + +void dumpWKT(const NS_PROJ::crs::CRSPtr &crs); +void dumpWKT(const NS_PROJ::crs::CRSPtr &crs) { dumpWKT(crs.get()); } + +void dumpWKT(const NS_PROJ::crs::CRSNNPtr &crs); +void dumpWKT(const NS_PROJ::crs::CRSNNPtr &crs) { + dumpWKT(crs.as_nullable().get()); +} + +void dumpWKT(const NS_PROJ::crs::GeographicCRSPtr &crs); +void dumpWKT(const NS_PROJ::crs::GeographicCRSPtr &crs) { dumpWKT(crs.get()); } + +void dumpWKT(const NS_PROJ::crs::GeographicCRSNNPtr &crs); +void dumpWKT(const NS_PROJ::crs::GeographicCRSNNPtr &crs) { + dumpWKT(crs.as_nullable().get()); +} + #endif using namespace NS_PROJ::internal; @@ -9184,6 +9208,14 @@ static void setupPROJGeodeticSourceCRS(io::PROJStringFormatter *formatter, formatter->startInversion(); sourceCRSGeog->_exportToPROJString(formatter); formatter->stopInversion(); + if (util::isOfExactType( + *(sourceCRSGeog.get()))) { + // The export of a DerivedGeographicCRS in non-CRS mode adds + // unit conversion and axis swapping. We must compensate for that + formatter->startInversion(); + sourceCRSGeog->addAngularUnitConvertAndAxisSwap(formatter); + formatter->stopInversion(); + } if (addPushV3) { formatter->addStep("push"); @@ -9217,7 +9249,12 @@ static void setupPROJGeodeticTargetCRS(io::PROJStringFormatter *formatter, formatter->addStep("pop"); formatter->addParam("v_3"); } - + if (util::isOfExactType( + *(targetCRSGeog.get()))) { + // The export of a DerivedGeographicCRS in non-CRS mode adds + // unit conversion and axis swapping. We must compensate for that + targetCRSGeog->addAngularUnitConvertAndAxisSwap(formatter); + } targetCRSGeog->_exportToPROJString(formatter); } else { auto targetCRSGeod = dynamic_cast(crs.get()); @@ -14290,6 +14327,20 @@ void CoordinateOperationFactory::Private::createOperationsBoundToGeog( const auto &hubSrc = boundSrc->hubCRS(); auto hubSrcGeog = dynamic_cast(hubSrc.get()); auto geogCRSOfBaseOfBoundSrc = boundSrc->baseCRS()->extractGeographicCRS(); + { + // If geogCRSOfBaseOfBoundSrc is a DerivedGeographicCRS, use its base + // instead (if it is a GeographicCRS) + auto derivedGeogCRS = + std::dynamic_pointer_cast( + geogCRSOfBaseOfBoundSrc); + if (derivedGeogCRS) { + auto baseCRS = std::dynamic_pointer_cast( + derivedGeogCRS->baseCRS().as_nullable()); + if (baseCRS) { + geogCRSOfBaseOfBoundSrc = baseCRS; + } + } + } const auto &authFactory = context.context->getAuthorityFactory(); const auto dbContext = diff --git a/src/iso19111/io.cpp b/src/iso19111/io.cpp index 623ad6f9..fa359d39 100644 --- a/src/iso19111/io.cpp +++ b/src/iso19111/io.cpp @@ -9478,8 +9478,8 @@ CRSNNPtr PROJStringParser::Private::buildProjectedCRS( std::string methodName = "PROJ " + step.name; for (const auto ¶m : step.paramValues) { if (is_in_stringlist(param.key, - "wktext,no_defs,datum,ellps,a,b,R,towgs84," - "nadgrids,geoidgrids," + "wktext,no_defs,datum,ellps,a,b,R,f,rf," + "towgs84,nadgrids,geoidgrids," "units,to_meter,vunits,vto_meter,type")) { continue; } diff --git a/test/unit/test_operation.cpp b/test/unit/test_operation.cpp index 1181b6d8..b6e555b1 100644 --- a/test/unit/test_operation.cpp +++ b/test/unit/test_operation.cpp @@ -10033,6 +10033,71 @@ TEST(operation, createOperation_ossfuzz_18587) { // --------------------------------------------------------------------------- +TEST(operation, derivedGeographicCRS_with_to_wgs84_to_geographicCRS) { + auto objSrc = PROJStringParser().createFromPROJString( + "+proj=ob_tran +o_proj=latlon +lat_0=0 +lon_0=180 +o_lat_p=18.0 " + "+o_lon_p=-200.0 +ellps=WGS84 +towgs84=1,2,3 +type=crs"); + auto src = nn_dynamic_pointer_cast(objSrc); + ASSERT_TRUE(src != nullptr); + auto objDst = PROJStringParser().createFromPROJString( + "+proj=longlat +datum=WGS84 +type=crs"); + auto dst = nn_dynamic_pointer_cast(objDst); + ASSERT_TRUE(dst != nullptr); + + { + auto op = CoordinateOperationFactory::create()->createOperation( + NN_CHECK_ASSERT(src), NN_CHECK_ASSERT(dst)); + ASSERT_TRUE(op != nullptr); + std::string pipeline( + "+proj=pipeline " + "+step +proj=unitconvert +xy_in=deg +xy_out=rad " + "+step +inv +proj=ob_tran +o_proj=latlon +lat_0=0 +lon_0=180 " + "+o_lat_p=18 +o_lon_p=-200 +ellps=WGS84 " + "+step +proj=push +v_3 " + "+step +proj=cart +ellps=WGS84 " + "+step +proj=helmert +x=1 +y=2 +z=3 " + "+step +inv +proj=cart +ellps=WGS84 " + "+step +proj=pop +v_3 " + "+step +proj=unitconvert +xy_in=rad +xy_out=deg"); + EXPECT_EQ(op->exportToPROJString(PROJStringFormatter::create().get()), + pipeline); + + auto op2 = CoordinateOperationFactory::create()->createOperation( + NN_CHECK_ASSERT(src), + nn_static_pointer_cast(GeographicCRS::EPSG_4326)); + ASSERT_TRUE(op2 != nullptr); + EXPECT_EQ(op2->exportToPROJString(PROJStringFormatter::create().get()), + pipeline + " +step +proj=axisswap +order=2,1"); + } + + { + auto op = CoordinateOperationFactory::create()->createOperation( + NN_CHECK_ASSERT(dst), NN_CHECK_ASSERT(src)); + ASSERT_TRUE(op != nullptr); + std::string pipeline( + "+step +proj=unitconvert +xy_in=deg +xy_out=rad " + "+step +proj=push +v_3 " + "+step +proj=cart +ellps=WGS84 " + "+step +proj=helmert +x=-1 +y=-2 +z=-3 " + "+step +inv +proj=cart +ellps=WGS84 " + "+step +proj=pop +v_3 " + "+step +proj=ob_tran +o_proj=latlon +lat_0=0 +lon_0=180 " + "+o_lat_p=18 +o_lon_p=-200 +ellps=WGS84 " + "+step +proj=unitconvert +xy_in=rad +xy_out=deg"); + EXPECT_EQ(op->exportToPROJString(PROJStringFormatter::create().get()), + "+proj=pipeline " + pipeline); + + auto op2 = CoordinateOperationFactory::create()->createOperation( + nn_static_pointer_cast(GeographicCRS::EPSG_4326), + NN_CHECK_ASSERT(src)); + ASSERT_TRUE(op2 != nullptr); + EXPECT_EQ(op2->exportToPROJString(PROJStringFormatter::create().get()), + "+proj=pipeline +step +proj=axisswap +order=2,1 " + pipeline); + } +} + +// --------------------------------------------------------------------------- + TEST(operation, mercator_variant_A_to_variant_B) { auto projCRS = ProjectedCRS::create( PropertyMap(), GeographicCRS::EPSG_4326, -- cgit v1.2.3 From eb66679cde834096ff18f40b5b1d4bc10e3f4c1d Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Sat, 21 Nov 2020 22:58:05 +0100 Subject: WKT parsing: fix ingestion of WKT with a Geocentric CRS as the base of the projected CRS --- src/iso19111/io.cpp | 26 +++++++++++++++++++++++++ test/unit/test_io.cpp | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) diff --git a/src/iso19111/io.cpp b/src/iso19111/io.cpp index fa359d39..284729cd 100644 --- a/src/iso19111/io.cpp +++ b/src/iso19111/io.cpp @@ -2794,6 +2794,32 @@ WKTParser::Private::buildGeodeticCRS(const WKTNodeNNPtr &node) { .as_nullable() : nullptr; auto cs = buildCS(csNode, node, angularUnit); + + // If there's no CS[] node, typically for a BASEGEODCRS of a projected CRS, + // in a few rare cases, this might be a Geocentric CRS, and thus a + // Cartesian CS, and not the ellipsoidalCS we assumed above. The only way + // to figure that is to resolve the CRS from its code... + if (isNull(csNode) && dbContext_ && + ci_equal(nodeName, WKTConstants::BASEGEODCRS)) { + const auto &nodeChildren = nodeP->children(); + for (const auto &subNode : nodeChildren) { + const auto &subNodeName(subNode->GP()->value()); + if (ci_equal(subNodeName, WKTConstants::ID) || + ci_equal(subNodeName, WKTConstants::AUTHORITY)) { + auto id = buildId(subNode, true, false); + if (id) { + try { + auto authFactory = AuthorityFactory::create( + NN_NO_CHECK(dbContext_), *id->codeSpace()); + auto dbCRS = authFactory->createGeodeticCRS(id->code()); + cs = dbCRS->coordinateSystem(); + } catch (const util::Exception &) { + } + } + } + } + } + auto ellipsoidalCS = nn_dynamic_pointer_cast(cs); if (ellipsoidalCS) { if (ci_equal(nodeName, WKTConstants::GEOCCS)) { diff --git a/test/unit/test_io.cpp b/test/unit/test_io.cpp index dff8ec45..558b2a6f 100644 --- a/test/unit/test_io.cpp +++ b/test/unit/test_io.cpp @@ -1884,6 +1884,60 @@ TEST(wkt_parse, wkt2_2019_projected_utm_3D) { // --------------------------------------------------------------------------- +TEST(wkt_parse, wkt2_2019_projected_with_base_geocentric) { + auto wkt = + "PROJCRS[\"EPSG topocentric example B\",\n" + " BASEGEODCRS[\"WGS 84\",\n" + " ENSEMBLE[\"World Geodetic System 1984 ensemble\",\n" + " MEMBER[\"World Geodetic System 1984 (Transit)\"],\n" + " MEMBER[\"World Geodetic System 1984 (G730)\"],\n" + " MEMBER[\"World Geodetic System 1984 (G873)\"],\n" + " MEMBER[\"World Geodetic System 1984 (G1150)\"],\n" + " MEMBER[\"World Geodetic System 1984 (G1674)\"],\n" + " MEMBER[\"World Geodetic System 1984 (G1762)\"],\n" + " ELLIPSOID[\"WGS 84\",6378137,298.257223563,\n" + " LENGTHUNIT[\"metre\",1]],\n" + " ENSEMBLEACCURACY[2.0]],\n" + " PRIMEM[\"Greenwich\",0,\n" + " ANGLEUNIT[\"degree\",0.0174532925199433]],\n" + " ID[\"EPSG\",4978]],\n" + " CONVERSION[\"EPSG topocentric example B\",\n" + " METHOD[\"Geocentric/topocentric conversions\",\n" + " ID[\"EPSG\",9836]],\n" + " PARAMETER[\"Geocentric X of topocentric origin\",3771793.97,\n" + " LENGTHUNIT[\"metre\",1],\n" + " ID[\"EPSG\",8837]],\n" + " PARAMETER[\"Geocentric Y of topocentric origin\",140253.34,\n" + " LENGTHUNIT[\"metre\",1],\n" + " ID[\"EPSG\",8838]],\n" + " PARAMETER[\"Geocentric Z of topocentric origin\",5124304.35,\n" + " LENGTHUNIT[\"metre\",1],\n" + " ID[\"EPSG\",8839]]],\n" + " CS[Cartesian,3],\n" + " AXIS[\"topocentric East (U)\",east,\n" + " ORDER[1],\n" + " LENGTHUNIT[\"metre\",1]],\n" + " AXIS[\"topocentric North (V)\",north,\n" + " ORDER[2],\n" + " LENGTHUNIT[\"metre\",1]],\n" + " AXIS[\"topocentric height (W)\",up,\n" + " ORDER[3],\n" + " LENGTHUNIT[\"metre\",1]],\n" + " USAGE[\n" + " SCOPE[\"Example only (fictitious).\"],\n" + " AREA[\"Description of the extent of the CRS.\"],\n" + " BBOX[-90,-180,90,180]],\n" + " ID[\"EPSG\",5820]]"; + auto dbContext = DatabaseContext::create(); + // Need a database so that EPSG:4978 is resolved + auto obj = WKTParser().attachDatabaseContext(dbContext).createFromWKT(wkt); + auto crs = nn_dynamic_pointer_cast(obj); + ASSERT_TRUE(crs != nullptr); + EXPECT_TRUE(crs->baseCRS()->isGeocentric()); +} + +// --------------------------------------------------------------------------- + TEST(crs, projected_angular_unit_from_primem) { auto obj = WKTParser().createFromWKT( "PROJCRS[\"NTF (Paris) / Lambert Nord France\",\n" -- cgit v1.2.3 From 650e37f159b96d18f5ff03784466784a769688e4 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Sat, 21 Nov 2020 23:59:33 +0100 Subject: PROJJSON parsing: fix parsing of a Geodetic CRS with a DatumEnsemble, and fix parsing of a ProjectedCRS whose base is a Geocentric CRS --- src/iso19111/io.cpp | 33 ++++++++--- test/unit/test_io.cpp | 149 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 173 insertions(+), 9 deletions(-) diff --git a/src/iso19111/io.cpp b/src/iso19111/io.cpp index 284729cd..713a471d 100644 --- a/src/iso19111/io.cpp +++ b/src/iso19111/io.cpp @@ -4980,6 +4980,10 @@ class JSONParser { TransformationNNPtr buildTransformation(const json &j); ConcatenatedOperationNNPtr buildConcatenatedOperation(const json &j); + void buildGeodeticDatumOrDatumEnsemble(const json &j, + GeodeticReferenceFramePtr &datum, + DatumEnsemblePtr &datumEnsemble); + static util::optional getAnchor(const json &j) { util::optional anchor; if (j.contains("anchor")) { @@ -5439,9 +5443,9 @@ BaseObjectNNPtr JSONParser::create(const json &j) // --------------------------------------------------------------------------- -GeographicCRSNNPtr JSONParser::buildGeographicCRS(const json &j) { - GeodeticReferenceFramePtr datum; - DatumEnsemblePtr datumEnsemble; +void JSONParser::buildGeodeticDatumOrDatumEnsemble( + const json &j, GeodeticReferenceFramePtr &datum, + DatumEnsemblePtr &datumEnsemble) { if (j.contains("datum")) { auto datumJ = getObject(j, "datum"); datum = util::nn_dynamic_pointer_cast( @@ -5454,6 +5458,14 @@ GeographicCRSNNPtr JSONParser::buildGeographicCRS(const json &j) { datumEnsemble = buildDatumEnsemble(getObject(j, "datum_ensemble")).as_nullable(); } +} + +// --------------------------------------------------------------------------- + +GeographicCRSNNPtr JSONParser::buildGeographicCRS(const json &j) { + GeodeticReferenceFramePtr datum; + DatumEnsemblePtr datumEnsemble; + buildGeodeticDatumOrDatumEnsemble(j, datum, datumEnsemble); auto csJ = getObject(j, "coordinate_system"); auto ellipsoidalCS = util::nn_dynamic_pointer_cast(buildCS(csJ)); @@ -5467,12 +5479,9 @@ GeographicCRSNNPtr JSONParser::buildGeographicCRS(const json &j) { // --------------------------------------------------------------------------- GeodeticCRSNNPtr JSONParser::buildGeodeticCRS(const json &j) { - auto datumJ = getObject(j, "datum"); - if (getType(datumJ) != "GeodeticReferenceFrame") { - throw ParsingException("Unsupported type for datum."); - } - auto datum = buildGeodeticReferenceFrame(datumJ); + GeodeticReferenceFramePtr datum; DatumEnsemblePtr datumEnsemble; + buildGeodeticDatumOrDatumEnsemble(j, datum, datumEnsemble); auto csJ = getObject(j, "coordinate_system"); auto cs = buildCS(csJ); auto props = buildProperties(j); @@ -5507,7 +5516,13 @@ GeodeticCRSNNPtr JSONParser::buildGeodeticCRS(const json &j) { // --------------------------------------------------------------------------- ProjectedCRSNNPtr JSONParser::buildProjectedCRS(const json &j) { - auto baseCRS = buildGeographicCRS(getObject(j, "base_crs")); + auto jBaseCRS = getObject(j, "base_crs"); + auto jBaseCS = getObject(jBaseCRS, "coordinate_system"); + auto baseCS = buildCS(jBaseCS); + auto baseCRS = dynamic_cast(baseCS.get()) != nullptr + ? util::nn_static_pointer_cast( + buildGeographicCRS(jBaseCRS)) + : buildGeodeticCRS(jBaseCRS); auto csJ = getObject(j, "coordinate_system"); auto cartesianCS = util::nn_dynamic_pointer_cast(buildCS(csJ)); if (!cartesianCS) { diff --git a/test/unit/test_io.cpp b/test/unit/test_io.cpp index 558b2a6f..81894fb0 100644 --- a/test/unit/test_io.cpp +++ b/test/unit/test_io.cpp @@ -11206,6 +11206,155 @@ TEST(json_import, projected_crs) { // --------------------------------------------------------------------------- +TEST(json_import, projected_crs_with_geocentric_base) { + auto json = "{\n" + " \"$schema\": \"foo\",\n" + " \"type\": \"ProjectedCRS\",\n" + " \"name\": \"EPSG topocentric example B\",\n" + " \"base_crs\": {\n" + " \"name\": \"WGS 84\",\n" + " \"datum_ensemble\": {\n" + " \"name\": \"World Geodetic System 1984 ensemble\",\n" + " \"members\": [\n" + " {\n" + " \"name\": \"World Geodetic System 1984 (Transit)\"\n" + " },\n" + " {\n" + " \"name\": \"World Geodetic System 1984 (G730)\"\n" + " },\n" + " {\n" + " \"name\": \"World Geodetic System 1984 (G873)\"\n" + " },\n" + " {\n" + " \"name\": \"World Geodetic System 1984 (G1150)\"\n" + " },\n" + " {\n" + " \"name\": \"World Geodetic System 1984 (G1674)\"\n" + " },\n" + " {\n" + " \"name\": \"World Geodetic System 1984 (G1762)\"\n" + " }\n" + " ],\n" + " \"ellipsoid\": {\n" + " \"name\": \"WGS 84\",\n" + " \"semi_major_axis\": 6378137,\n" + " \"inverse_flattening\": 298.257223563\n" + " },\n" + " \"accuracy\": \"2.0\"\n" + " },\n" + " \"coordinate_system\": {\n" + " \"subtype\": \"Cartesian\",\n" + " \"axis\": [\n" + " {\n" + " \"name\": \"Geocentric X\",\n" + " \"abbreviation\": \"X\",\n" + " \"direction\": \"geocentricX\",\n" + " \"unit\": \"metre\"\n" + " },\n" + " {\n" + " \"name\": \"Geocentric Y\",\n" + " \"abbreviation\": \"Y\",\n" + " \"direction\": \"geocentricY\",\n" + " \"unit\": \"metre\"\n" + " },\n" + " {\n" + " \"name\": \"Geocentric Z\",\n" + " \"abbreviation\": \"Z\",\n" + " \"direction\": \"geocentricZ\",\n" + " \"unit\": \"metre\"\n" + " }\n" + " ]\n" + " },\n" + " \"id\": {\n" + " \"authority\": \"EPSG\",\n" + " \"code\": 4978\n" + " }\n" + " },\n" + " \"conversion\": {\n" + " \"name\": \"EPSG topocentric example B\",\n" + " \"method\": {\n" + " \"name\": \"Geocentric/topocentric conversions\",\n" + " \"id\": {\n" + " \"authority\": \"EPSG\",\n" + " \"code\": 9836\n" + " }\n" + " },\n" + " \"parameters\": [\n" + " {\n" + " \"name\": \"Geocentric X of topocentric origin\",\n" + " \"value\": 3771793.97,\n" + " \"unit\": \"metre\",\n" + " \"id\": {\n" + " \"authority\": \"EPSG\",\n" + " \"code\": 8837\n" + " }\n" + " },\n" + " {\n" + " \"name\": \"Geocentric Y of topocentric origin\",\n" + " \"value\": 140253.34,\n" + " \"unit\": \"metre\",\n" + " \"id\": {\n" + " \"authority\": \"EPSG\",\n" + " \"code\": 8838\n" + " }\n" + " },\n" + " {\n" + " \"name\": \"Geocentric Z of topocentric origin\",\n" + " \"value\": 5124304.35,\n" + " \"unit\": \"metre\",\n" + " \"id\": {\n" + " \"authority\": \"EPSG\",\n" + " \"code\": 8839\n" + " }\n" + " }\n" + " ]\n" + " },\n" + " \"coordinate_system\": {\n" + " \"subtype\": \"Cartesian\",\n" + " \"axis\": [\n" + " {\n" + " \"name\": \"Topocentric East\",\n" + " \"abbreviation\": \"U\",\n" + " \"direction\": \"east\",\n" + " \"unit\": \"metre\"\n" + " },\n" + " {\n" + " \"name\": \"Topocentric North\",\n" + " \"abbreviation\": \"V\",\n" + " \"direction\": \"north\",\n" + " \"unit\": \"metre\"\n" + " },\n" + " {\n" + " \"name\": \"Topocentric height\",\n" + " \"abbreviation\": \"W\",\n" + " \"direction\": \"up\",\n" + " \"unit\": \"metre\"\n" + " }\n" + " ]\n" + " },\n" + " \"scope\": \"Example only (fictitious).\",\n" + " \"area\": \"Description of the extent of the CRS.\",\n" + " \"bbox\": {\n" + " \"south_latitude\": -90,\n" + " \"west_longitude\": -180,\n" + " \"north_latitude\": 90,\n" + " \"east_longitude\": 180\n" + " },\n" + " \"id\": {\n" + " \"authority\": \"EPSG\",\n" + " \"code\": 5820\n" + " }\n" + "}"; + auto obj = createFromUserInput(json, nullptr); + auto pcrs = nn_dynamic_pointer_cast(obj); + ASSERT_TRUE(pcrs != nullptr); + EXPECT_TRUE(pcrs->baseCRS()->isGeocentric()); + EXPECT_EQ(pcrs->exportToJSON(&(JSONFormatter::create()->setSchema("foo"))), + json); +} + +// --------------------------------------------------------------------------- + TEST(json_import, compound_crs) { auto json = "{\n" " \"$schema\": \"foo\",\n" -- cgit v1.2.3 From f50221ed6606a67ef0354cacd449f02aca3faba7 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Sun, 22 Nov 2020 23:16:48 +0100 Subject: projinfo.cpp: improve hint when to use --spatial-test intersects --- src/apps/projinfo.cpp | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/apps/projinfo.cpp b/src/apps/projinfo.cpp index 6ee5925a..3d57dcd6 100644 --- a/src/apps/projinfo.cpp +++ b/src/apps/projinfo.cpp @@ -693,6 +693,7 @@ static void outputOperations( std::vector list; size_t spatialCriterionPartialIntersectionResultCount = 0; + bool spatialCriterionPartialIntersectionMoreRelevant = false; try { auto authFactory = dbContext @@ -718,10 +719,15 @@ static void outputOperations( ctxt->setSpatialCriterion( CoordinateOperationContext::SpatialCriterion:: PARTIAL_INTERSECTION); - spatialCriterionPartialIntersectionResultCount = - CoordinateOperationFactory::create() - ->createOperations(nnSourceCRS, nnTargetCRS, ctxt) - .size(); + auto list2 = + CoordinateOperationFactory::create()->createOperations( + nnSourceCRS, nnTargetCRS, ctxt); + spatialCriterionPartialIntersectionResultCount = list2.size(); + if (spatialCriterionPartialIntersectionResultCount == 1 && + list.size() == 1 && + list2[0]->nameStr() != list[0]->nameStr()) { + spatialCriterionPartialIntersectionMoreRelevant = true; + } } catch (const std::exception &) { } } @@ -740,6 +746,10 @@ static void outputOperations( "more results (" << spatialCriterionPartialIntersectionResultCount << ")" << std::endl; + } else if (spatialCriterionPartialIntersectionMoreRelevant) { + std::cout << "Note: using '--spatial-test intersects' would bring " + "more relevant results." + << std::endl; } if (summary) { for (const auto &op : list) { -- cgit v1.2.3 From 6bc444c1b0d12dbc1c942e805c4017d7c5c85e07 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Sun, 22 Nov 2020 23:52:42 +0100 Subject: Database ESRI: map 2 grids in grid_alternatives --- data/sql/esri.sql | 7 +++---- scripts/build_db_from_esri.py | 5 +++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/data/sql/esri.sql b/data/sql/esri.sql index 90e61f02..8b969bc4 100644 --- a/data/sql/esri.sql +++ b/data/sql/esri.sql @@ -17290,8 +17290,9 @@ VALUES ('c1hpgn', 'us_noaa_c1hpgn.tif', 'c1hpgn.gsb', 'GTiff', 'hgridshift', 0, NULL, 'https://cdn.proj.org/us_noaa_c1hpgn.tif', 1, 1, NULL), ('c2hpgn', 'us_noaa_c2hpgn.tif', 'c2hpgn.gsb', 'GTiff', 'hgridshift', 0, NULL, 'https://cdn.proj.org/us_noaa_c2hpgn.tif', 1, 1, NULL), ('spain/100800401','es_cat_icgc_100800401.tif','100800401.gsb','GTiff','hgridshift',0,NULL,'https://cdn.proj.org/es_cat_icgc_100800401.tif',1,1,NULL), -('australia/QLD_0900','au_icsm_National_84_02_07_01.tif','National_84_02_07_01.gsb','GTiff','hgridshift',0,NULL,'https://cdn.proj.org/au_icsm_National_84_02_07_01.tif',1,1,NULL) -- From https://www.dnrme.qld.gov.au/__data/assets/pdf_file/0006/105765/gday-21-user-guide.pdf: "Note that the Queensland grid QLD_0900.gsb produces identical results to the National AGD84 grid for the equivalent coverage." -; +('australia/QLD_0900','au_icsm_National_84_02_07_01.tif','National_84_02_07_01.gsb','GTiff','hgridshift',0,NULL,'https://cdn.proj.org/au_icsm_National_84_02_07_01.tif',1,1,NULL), -- From https://www.dnrme.qld.gov.au/__data/assets/pdf_file/0006/105765/gday-21-user-guide.pdf: "Note that the Queensland grid QLD_0900.gsb produces identical results to the National AGD84 grid for the equivalent coverage." +('spain/PENR2009','es_ign_SPED2ETV2.tif',NULL,'GTiff','hgridshift',0,NULL,'https://cdn.proj.org/es_ign_SPED2ETV2.tif',1,1,NULL), +('spain/BALR2009','es_ign_SPED2ETV2.tif',NULL,'GTiff','hgridshift',0,NULL,'https://cdn.proj.org/es_ign_SPED2ETV2.tif',1,1,NULL); -- 'france/RGNC1991_IGN72GrandeTerre' : we have a 3D geocentric corresponding one: no need for mapping -- 'france/RGNC1991_NEA74Noumea' : we have a 3D geocentric corresponding one: no need for mapping -- 'gc_nad83_harn_2007_conus_shifts': no mapping @@ -17301,8 +17302,6 @@ VALUES -- 'gc_nad83_2007_2011_alaska_shifts': no mapping -- 'gc_nad83_2007_2011_prvi_shifts': no mapping -- 'uk/osgb36_xrail84': no mapping --- 'spain/PENR2009': no mapping --- 'spain/BALR2009': no mapping -- 'japan/tky2jgd': no mapping -- 'spain/baleares': no mapping -- 'spain/peninsula': no mapping diff --git a/scripts/build_db_from_esri.py b/scripts/build_db_from_esri.py index 2e6f55ec..b55a1411 100755 --- a/scripts/build_db_from_esri.py +++ b/scripts/build_db_from_esri.py @@ -80,8 +80,9 @@ VALUES ('c1hpgn', 'us_noaa_c1hpgn.tif', 'c1hpgn.gsb', 'GTiff', 'hgridshift', 0, NULL, 'https://cdn.proj.org/us_noaa_c1hpgn.tif', 1, 1, NULL), ('c2hpgn', 'us_noaa_c2hpgn.tif', 'c2hpgn.gsb', 'GTiff', 'hgridshift', 0, NULL, 'https://cdn.proj.org/us_noaa_c2hpgn.tif', 1, 1, NULL), ('spain/100800401','es_cat_icgc_100800401.tif','100800401.gsb','GTiff','hgridshift',0,NULL,'https://cdn.proj.org/es_cat_icgc_100800401.tif',1,1,NULL), -('australia/QLD_0900','au_icsm_National_84_02_07_01.tif','National_84_02_07_01.gsb','GTiff','hgridshift',0,NULL,'https://cdn.proj.org/au_icsm_National_84_02_07_01.tif',1,1,NULL) -- From https://www.dnrme.qld.gov.au/__data/assets/pdf_file/0006/105765/gday-21-user-guide.pdf: "Note that the Queensland grid QLD_0900.gsb produces identical results to the National AGD84 grid for the equivalent coverage." -; +('australia/QLD_0900','au_icsm_National_84_02_07_01.tif','National_84_02_07_01.gsb','GTiff','hgridshift',0,NULL,'https://cdn.proj.org/au_icsm_National_84_02_07_01.tif',1,1,NULL), -- From https://www.dnrme.qld.gov.au/__data/assets/pdf_file/0006/105765/gday-21-user-guide.pdf: "Note that the Queensland grid QLD_0900.gsb produces identical results to the National AGD84 grid for the equivalent coverage." +('spain/PENR2009','es_ign_SPED2ETV2.tif',NULL,'GTiff','hgridshift',0,NULL,'https://cdn.proj.org/es_ign_SPED2ETV2.tif',1,1,NULL), +('spain/BALR2009','es_ign_SPED2ETV2.tif',NULL,'GTiff','hgridshift',0,NULL,'https://cdn.proj.org/es_ign_SPED2ETV2.tif',1,1,NULL); -- 'france/RGNC1991_IGN72GrandeTerre' : we have a 3D geocentric corresponding one: no need for mapping -- 'france/RGNC1991_NEA74Noumea' : we have a 3D geocentric corresponding one: no need for mapping """ -- cgit v1.2.3 From 765faba8984aa1e5f2a91853d18f0453e7bed105 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Sun, 22 Nov 2020 23:53:22 +0100 Subject: Remove no longer used build_db_create_ignf.py script --- scripts/build_db_create_ignf.py | 527 ---------------------------------------- 1 file changed, 527 deletions(-) delete mode 100755 scripts/build_db_create_ignf.py diff --git a/scripts/build_db_create_ignf.py b/scripts/build_db_create_ignf.py deleted file mode 100755 index 97157ec5..00000000 --- a/scripts/build_db_create_ignf.py +++ /dev/null @@ -1,527 +0,0 @@ -#!/usr/bin/env python -############################################################################### -# $Id$ -# -# Project: PROJ -# Purpose: Build SRS and coordinate transform database -# Author: Even Rouault -# -############################################################################### -# Copyright (c) 2018, Even Rouault -# -# 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. -############################################################################### - -import copy -import json -import os -import sqlite3 -import sys - -if len(sys.argv) != 3: - print('Usage: build_db_create_ignf.py path_to_IGNF_file proj.db') - sys.exit(1) - -def escape_literal(x): - return x.replace("'", "''") - -def find_ellipsoid(cursor, line, d): - for prec in (10,9,8,7,6): - cursor.execute('SELECT code, name FROM ellipsoid WHERE code != 1024 AND semi_major_axis = ? AND (inv_flattening = ? OR (abs(semi_major_axis / (semi_major_axis - semi_minor_axis)) - ?) < 1e-%d)' % prec, (float(d['a']), float(d['rf']), float(d['rf']))) - row = cursor.fetchone() - if prec > 6 and row is None: - continue - assert row, line - ellps_code, ellps_name = row - return ellps_code, ellps_name - -def find_geogcrs_code(line,d): - pm = None - if 'pm' in d: - pm = d['pm'] - assert pm == '2.337229167', pm - - key = { 'a' : d['a'], 'rf' : d['rf'], 'towgs84' : d['towgs84'], 'pm': pm } - key_geog_crs = json.dumps(key) - if 'W84' in code: - geogcrs_code = "WGS84G" - elif 'RGFG95' in code: - geogcrs_code = "RGFG95GEO" - elif 'ETRS89' in code: - geogcrs_code = "ETRS89GEO" - elif 'RGF93' in code: - geogcrs_code = "RGF93G" - elif 'LAMB93' in code: - geogcrs_code = "RGF93G" - elif 'MILLER' in code: - geogcrs_code = "WGS84G" - elif code.startswith('GEOPORTAL'): - geogcrs_code = 'RGF93G' - elif key_geog_crs not in map_geog_crs: - max_count_common = 0 - max_common_code = None - for k in map_geog_crs: - temp = copy.copy(key) - temp['code'] = map_geog_crs[k]['code'] - if temp == json.loads(k): - count_common = 0 - while True: - if len(code) <= count_common: - break - if len(map_geog_crs[k]['code']) <= count_common: - break - if code[count_common] == map_geog_crs[k]['code'][count_common]: - count_common += 1 - else: - break - if count_common > max_count_common: - max_count_common = count_common - max_common_code = map_geog_crs[k]['code'] - assert max_count_common >= 4, (max_common_code, max_count_common, line) - geogcrs_code = max_common_code - else: - geogcrs_code = map_geog_crs[key_geog_crs]['code'] - return geogcrs_code - - -IGNF_file = sys.argv[1] -proj_db = sys.argv[2] - -conn = sqlite3.connect(proj_db) -cursor = conn.cursor() - -all_sql = [] - -geocentric_crs_name_to_datum_code = {} -map_geog_crs = {} - -for line in open(IGNF_file, 'rt').readlines(): - line = line.strip('\n') - if line[0] == '#' or line.startswith(''): - continue - assert line[0] == '<' - code = line[1:line.find('>')] - proj4_string = line[line.find('>')+1:] - #print(code, proj4_string) - tokens = proj4_string.split(' +') - assert tokens[0] == '' - tokens = tokens[1:] - d = {} - for token in tokens: - if token == 'no_defs <>' or token == 'wktext': - continue - pos_equal = token.find('=') - assert pos_equal > 0, line - key = token[0:pos_equal] - value = token[pos_equal+1:] - d[key] = value - assert 'proj' in d, line - assert 'title' in d, line - proj = d['proj'] - - assert 'a' in d - assert 'rf' in d - assert (not 'nadgrids' in d) or d['nadgrids'] in ('null', '@null', 'ntf_r93.gsb,null'), line - assert 'towgs84' in d - - if proj == 'geocent': - - ellps_code, ellps_name = find_ellipsoid(cursor, line, d) - - datum_code = 'DATUM_' + code - - geocentric_crs_name_to_datum_code[d['title']] = datum_code - - sql = """INSERT INTO "geodetic_datum" VALUES('IGNF','%s','%s',NULL,NULL,'EPSG','%s','EPSG','8901','EPSG','1262',0);""" % (datum_code, escape_literal(d['title']), ellps_code) - all_sql.append(sql) - - #sql = """INSERT INTO "crs" VALUES('IGNF','%s','geocentric');""" % (code) - #all_sql.append(sql) - - sql = """INSERT INTO "geodetic_crs" VALUES('IGNF','%s','%s',NULL,NULL,'geocentric','EPSG','6500','IGNF','%s','EPSG','1262',NULL,0);""" % (code, escape_literal(d['title']), datum_code) - all_sql.append(sql) - - #sql = """INSERT INTO "coordinate_operation" VALUES('IGNF','IGNF_%s_TO_EPSG_4978','helmert_transformation');""" % (code) - #all_sql.append(sql) - - towgs84 = d['towgs84'].split(',') - assert len(towgs84) in (3, 7), towgs84 - x = towgs84[0] - y = towgs84[1] - z = towgs84[2] - if len(towgs84) == 3: - rx = 'NULL' - ry = 'NULL' - rz = 'NULL' - s = 'NULL' - r_uom_auth_name = 'NULL' - r_uom_code = 'NULL' - s_uom_auth_name = 'NULL' - s_uom_code = 'NULL' - method_code = "'1031'" - method_name = "'Geocentric translations (geocentric domain)'" - else: - rx = towgs84[3] - ry = towgs84[4] - rz = towgs84[5] - s = towgs84[6] - r_uom_auth_name = "'EPSG'" - r_uom_code = "'9104'" - s_uom_auth_name = "'EPSG'" - s_uom_code = "'9202'" - method_code = "'1033'" - method_name = "'Position Vector transformation (geocentric domain)'" - - sql = """INSERT INTO "helmert_transformation" VALUES('IGNF','IGNF_%s_TO_EPSG_4978','%s to WGS 84',NULL,NULL,'EPSG',%s,%s,'IGNF','%s','EPSG','4978','EPSG','1262',NULL,%s,%s,%s,'EPSG','9001',%s,%s,%s,%s,%s,%s,%s, %s,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0);""" % (code, escape_literal(d['title']), method_code, method_name, code, x, y, z, rx, ry, rz, r_uom_auth_name, r_uom_code, s, s_uom_auth_name, s_uom_code) - all_sql.append(sql) - - if 'nadgrids' in d and d['nadgrids'] == 'ntf_r93.gsb,null': - - #sql = """INSERT INTO "coordinate_operation" VALUES('IGNF','IGNF_%s_TO_EPSG_4978_GRID','grid_transformation');""" % (code) - #all_sql.append(sql) - - sql = """INSERT INTO "grid_transformation" VALUES('IGNF','IGNF_%s_TO_EPSG_4978_GRID','%s to WGS 84 (2)',NULL,NULL,'EPSG','9615','NTv2','IGNF','%s','EPSG','4978','EPSG','1262',NULL,'EPSG','8656','Latitude and longitude difference file','ntf_r93.gsb',NULL,NULL,NULL,NULL,NULL,NULL,0);""" % (code, escape_literal(d['title']), code) - all_sql.append(sql) - - all_sql.append('') - - elif proj == 'longlat': - - pm = None - pm_code = "'8901'" # Greenwich - if 'pm' in d: - pm = d['pm'] - assert pm == '2.337229167', pm - pm_code = "'8903'" # Paris - - ellps_code, ellps_name = find_ellipsoid(cursor, line, d) - - if d['title'] in geocentric_crs_name_to_datum_code: - datum_code = geocentric_crs_name_to_datum_code[d['title']] - else: - datum_code = 'DATUM_' + code - sql = """INSERT INTO "geodetic_datum" VALUES('IGNF','%s','%s',NULL,NULL,'EPSG','%s','EPSG',%s,'EPSG','1262',0);""" % (datum_code, escape_literal(d['title']), ellps_code, pm_code) - all_sql.append(sql) - - #sql = """INSERT INTO "crs" VALUES('IGNF','%s','geographic 2D');""" % (code) - #all_sql.append(sql) - - cs_code = "'6424'" # Long Lat deg - if 'grades' in d['title']: - cs_code = "'6425'" # Long Lat grad - - sql = """INSERT INTO "geodetic_crs" VALUES('IGNF','%s','%s',NULL,NULL,'geographic 2D','EPSG',%s,'IGNF','%s','EPSG','1262',NULL,0);""" % (code, escape_literal(d['title']), cs_code, datum_code) - all_sql.append(sql) - - key = { 'a' : d['a'], 'rf' : d['rf'], 'towgs84' : d['towgs84'], 'pm': pm } - if "+towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000" in line or code == 'WGS84G': - key['code'] = code - key_geog_crs = json.dumps(key) - assert key_geog_crs not in map_geog_crs, (line, map_geog_crs[key_geog_crs]) - map_geog_crs[ key_geog_crs ] = { 'code': code, 'title': d['title'] } - - if code == 'NTFP': # Grades - assert cs_code == "'6425'" # Long Lat grad - - #sql = """INSERT INTO "coordinate_operation" VALUES('IGNF','IGNF_NTFP_TO_IGNF_NTFG','other_transformation');""" - #all_sql.append(sql) - - sql = """INSERT INTO "other_transformation" VALUES('IGNF','IGNF_NTFP_TO_IGNF_NTFG','Nouvelle Triangulation Francaise Paris grades to Nouvelle Triangulation Francaise Greenwich degres sexagesimaux',NULL,NULL,'EPSG','9601','Longitude rotation','IGNF','NTFP','IGNF','NTFG','EPSG','1262',0.0,'EPSG','8602','Longitude offset',2.5969213,'EPSG','9105',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0);""" - all_sql.append(sql) - - #sql = """INSERT INTO "coordinate_operation" VALUES('IGNF','IGNF_%s_TO_EPSG_4326','concatenated_operation');""" % (code) - #all_sql.append(sql) - - sql = """INSERT INTO "concatenated_operation" VALUES('IGNF','IGNF_NTFP_TO_EPSG_4326','Nouvelle Triangulation Francaise Paris grades to WGS 84',NULL,NULL,'IGNF','NTFP','EPSG','4326','EPSG','1262',NULL,'IGNF','IGNF_NTFP_TO_IGNF_NTFG','IGNF','IGNF_NTFG_TO_EPSG_4326',NULL,NULL,0);""" - all_sql.append(sql) - - #sql = """INSERT INTO "coordinate_operation" VALUES('IGNF','IGNF_%s_TO_EPSG_4326_GRID','concatenated_operation');""" % (code) - #all_sql.append(sql) - - sql = """INSERT INTO "concatenated_operation" VALUES('IGNF','IGNF_NTFP_TO_EPSG_4326_GRID','Nouvelle Triangulation Francaise Paris grades to WGS 84 (2)',NULL,NULL,'IGNF','NTFP','EPSG','4326','EPSG','1262',NULL,'IGNF','IGNF_NTFP_TO_IGNF_NTFG','IGNF','IGNF_NTFG_TO_EPSG_4326_GRID',NULL,NULL,0);""" - all_sql.append(sql) - - continue - - assert cs_code == "'6424'" # Long Lat deg - - #sql = """INSERT INTO "coordinate_operation" VALUES('IGNF','IGNF_%s_TO_EPSG_4326','helmert_transformation');""" % (code) - #all_sql.append(sql) - - towgs84 = d['towgs84'].split(',') - assert len(towgs84) in (3, 7), towgs84 - x = towgs84[0] - y = towgs84[1] - z = towgs84[2] - if len(towgs84) == 3: - rx = 'NULL' - ry = 'NULL' - rz = 'NULL' - s = 'NULL' - r_uom_auth_name = 'NULL' - r_uom_code = 'NULL' - s_uom_auth_name = 'NULL' - s_uom_code = 'NULL' - method_code = "'9603'" - method_name = "'Geocentric translations (geog2D domain)'" - - else: - rx = towgs84[3] - ry = towgs84[4] - rz = towgs84[5] - s = towgs84[6] - r_uom_auth_name = "'EPSG'" - r_uom_code = "'9104'" - s_uom_auth_name = "'EPSG'" - s_uom_code = "'9202'" - method_code = "'9606'" - method_name = "'Position Vector transformation (geog2D domain)'" - - sql = """INSERT INTO "helmert_transformation" VALUES('IGNF','IGNF_%s_TO_EPSG_4326','%s to WGS 84',NULL,NULL,'EPSG',%s,%s,'IGNF','%s','EPSG','4326','EPSG','1262',NULL,%s,%s,%s,'EPSG','9001',%s,%s,%s,%s,%s,%s,%s, %s,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0);""" % (code, escape_literal(d['title']), method_code, method_name, code, x, y, z, rx, ry, rz, r_uom_auth_name, r_uom_code, s, s_uom_auth_name, s_uom_code) - all_sql.append(sql) - - if 'nadgrids' in d and d['nadgrids'] == 'ntf_r93.gsb,null': - - #sql = """INSERT INTO "coordinate_operation" VALUES('IGNF','IGNF_%s_TO_EPSG_4326_GRID','grid_transformation');""" % (code) - #all_sql.append(sql) - - sql = """INSERT INTO "grid_transformation" VALUES('IGNF','IGNF_%s_TO_EPSG_4326_GRID','%s to WGS 84 (2)',NULL,NULL,'EPSG','9615','NTv2','IGNF','%s','EPSG','4326','EPSG','1262',NULL,'EPSG','8656','Latitude and longitude difference file','ntf_r93.gsb',NULL,NULL,NULL,NULL,NULL,NULL,0);""" % (code, escape_literal(d['title']), code) - all_sql.append(sql) - - all_sql.append('') - - elif proj == 'tmerc': - - geogcrs_code = find_geogcrs_code(line,d) - - assert 'x_0' in d - assert 'y_0' in d - assert 'k_0' in d - assert 'lat_0' in d - assert 'lon_0' in d - assert 'units' in d and d['units'] == 'm' - - #sql = """INSERT INTO "coordinate_operation" VALUES('IGNF','CONV_%s','conversion');""" % (code) - #all_sql.append(sql) - - sql = """INSERT INTO "conversion" VALUES('IGNF','CONV_%s','Conversion for %s',NULL,NULL,'EPSG','1262','EPSG','9807','Transverse Mercator','EPSG','8801','Latitude of natural origin',%s,'EPSG','9102','EPSG','8802','Longitude of natural origin',%s,'EPSG','9102','EPSG','8805','Scale factor at natural origin',%s,'EPSG','9201','EPSG','8806','False easting',%s,'EPSG','9001','EPSG','8807','False northing',%s,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0);""" % (code, escape_literal(d['title']), d['lat_0'], d['lon_0'], d['k_0'], d['x_0'], d['y_0']) - all_sql.append(sql) - - #sql = """INSERT INTO "crs" VALUES('IGNF','%s','projected');""" % (code) - #all_sql.append(sql) - - sql = """INSERT INTO "projected_crs" VALUES('IGNF','%s','%s',NULL,NULL,'EPSG','4499','IGNF','%s','IGNF','CONV_%s','EPSG','1262',NULL,0);""" % (code, escape_literal(d['title']), geogcrs_code, code) - all_sql.append(sql) - - all_sql.append('') - - elif proj == 'laea': - - geogcrs_code = find_geogcrs_code(line,d) - - assert 'x_0' in d - assert 'y_0' in d - assert 'lat_0' in d - assert 'lon_0' in d - assert 'units' in d and d['units'] == 'm' - - #sql = """INSERT INTO "coordinate_operation" VALUES('IGNF','CONV_%s','conversion');""" % (code) - #all_sql.append(sql) - - sql = """INSERT INTO "conversion" VALUES('IGNF','CONV_%s','Conversion for %s',NULL,NULL,'EPSG','1262','EPSG','9820','Lambert Azimuthal Equal Area','EPSG','8801','Latitude of natural origin',%s,'EPSG','9102','EPSG','8802','Longitude of natural origin',%s,'EPSG','9102','EPSG','8806','False easting',%s,'EPSG','9001','EPSG','8807','False northing',%s,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0);""" % (code, escape_literal(d['title']), d['lat_0'], d['lon_0'], d['x_0'], d['y_0']) - all_sql.append(sql) - - #sql = """INSERT INTO "crs" VALUES('IGNF','%s','projected');""" % (code) - #all_sql.append(sql) - - sql = """INSERT INTO "projected_crs" VALUES('IGNF','%s','%s',NULL,NULL,'EPSG','4499','IGNF','%s','IGNF','CONV_%s','EPSG','1262',NULL,0);""" % (code, escape_literal(d['title']), geogcrs_code, code) - all_sql.append(sql) - - all_sql.append('') - - elif proj == 'lcc': - - geogcrs_code = find_geogcrs_code(line,d) - - assert 'x_0' in d - assert 'y_0' in d - assert 'lat_0' in d - assert 'lat_1' in d - assert 'k_0' in d or 'lat_2' in d, line - assert 'lon_0' in d - assert 'units' in d and d['units'] == 'm' - - #sql = """INSERT INTO "coordinate_operation" VALUES('IGNF','CONV_%s','conversion');""" % (code) - #all_sql.append(sql) - - if 'lat_2' in d: - sql = """INSERT INTO "conversion" VALUES('IGNF','CONV_%s','Conversion for %s',NULL,NULL,'EPSG','1262','EPSG','9802','Lambert Conic Conformal (2SP)','EPSG','8821','Latitude of false origin',%s,'EPSG','9102','EPSG','8822','Longitude of false origin',%s,'EPSG','9102','EPSG','8823','Latitude of 1st standard parallel',%s,'EPSG','9102','EPSG','8824','Latitude of 2nd standard parallel',%s,'EPSG','9102','EPSG','8826','Easting at false origin',%s,'EPSG','9001','EPSG','8827','Northing at false origin',%s,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,0);""" % (code, escape_literal(d['title']), d['lat_0'], d['lon_0'], d['lat_1'], d['lat_2'], d['x_0'], d['y_0']) - else: - assert d['lat_0'] == d['lat_1'], line - sql = """INSERT INTO "conversion" VALUES('IGNF','CONV_%s','Conversion for %s',NULL,NULL,'EPSG','1262','EPSG','9801','Lambert Conic Conformal (1SP)','EPSG','8801','Latitude of natural origin',%s,'EPSG','9102','EPSG','8802','Longitude of natural origin',%s,'EPSG','9102','EPSG','8805','Scale factor at natural origin',%s,'EPSG','9201','EPSG','8806','False easting',%s,'EPSG','9001','EPSG','8807','False northing',%s,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0);""" % (code, escape_literal(d['title']), d['lat_0'], d['lon_0'], d['k_0'], d['x_0'], d['y_0']) - - all_sql.append(sql) - - #sql = """INSERT INTO "crs" VALUES('IGNF','%s','projected');""" % (code) - #all_sql.append(sql) - - sql = """INSERT INTO "projected_crs" VALUES('IGNF','%s','%s',NULL,NULL,'EPSG','4499','IGNF','%s','IGNF','CONV_%s','EPSG','1262',NULL,0);""" % (code, escape_literal(d['title']), geogcrs_code, code) - all_sql.append(sql) - - all_sql.append('') - - elif proj == 'eqc': - - geogcrs_code = find_geogcrs_code(line,d) - - assert 'x_0' in d, line - assert 'y_0' in d, line - assert 'lat_0' in d, line - assert 'lat_ts' in d, line - assert 'lon_0' in d, line - assert 'units' in d and d['units'] == 'm', line - assert float(d['lat_0']) == 0, line - - #sql = """INSERT INTO "coordinate_operation" VALUES('IGNF','CONV_%s','conversion');""" % (code) - #all_sql.append(sql) - - sql = """INSERT INTO "conversion" VALUES('IGNF','CONV_%s','Conversion for %s',NULL,NULL,'EPSG','1262','EPSG','1028','Equidistant Cylindrical','EPSG','8823','Latitude of 1st standard parallel',%s,'EPSG','9102','EPSG','8802','Longitude of natural origin',%s,'EPSG','9102','EPSG','8806','False easting',%s,'EPSG','9001','EPSG','8807','False northing',%s,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0);""" % (code, escape_literal(d['title']), d['lat_ts'], d['lon_0'], d['x_0'], d['y_0']) - all_sql.append(sql) - - #sql = """INSERT INTO "crs" VALUES('IGNF','%s','projected');""" % (code) - #all_sql.append(sql) - - sql = """INSERT INTO "projected_crs" VALUES('IGNF','%s','%s',NULL,NULL,'EPSG','4499','IGNF','%s','IGNF','CONV_%s','EPSG','1262',NULL,0);""" % (code, escape_literal(d['title']), geogcrs_code, code) - all_sql.append(sql) - - all_sql.append('') - - elif proj == 'gstmerc': - - geogcrs_code = find_geogcrs_code(line,d) - - assert 'x_0' in d - assert 'y_0' in d - assert 'k_0' in d - assert 'lat_0' in d - assert 'lon_0' in d - assert 'units' in d and d['units'] == 'm' - - #sql = """INSERT INTO "coordinate_operation" VALUES('IGNF','CONV_%s','conversion');""" % (code) - #all_sql.append(sql) - - sql = """INSERT INTO "conversion" VALUES('IGNF','CONV_%s','Conversion for %s',NULL,NULL,'EPSG','1262',NULL,NULL,'Gauss Schreiber Transverse Mercator','EPSG','8801','Latitude of natural origin',%s,'EPSG','9102','EPSG','8802','Longitude of natural origin',%s,'EPSG','9102','EPSG','8805','Scale factor at natural origin',%s,'EPSG','9201','EPSG','8806','False easting',%s,'EPSG','9001','EPSG','8807','False northing',%s,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0);""" % (code, escape_literal(d['title']), d['lat_0'], d['lon_0'], d['k_0'], d['x_0'], d['y_0']) - all_sql.append(sql) - - #sql = """INSERT INTO "crs" VALUES('IGNF','%s','projected');""" % (code) - #all_sql.append(sql) - - sql = """INSERT INTO "projected_crs" VALUES('IGNF','%s','%s',NULL,NULL,'EPSG','4499','IGNF','%s','IGNF','CONV_%s','EPSG','1262',NULL,0);""" % (code, escape_literal(d['title']), geogcrs_code, code) - all_sql.append(sql) - - all_sql.append('') - - elif proj == 'stere': - - geogcrs_code = find_geogcrs_code(line,d) - - assert 'x_0' in d - assert 'y_0' in d - if 'k' in d or 'k_0' in d: - print('k/k_0 ignored for ' + line) - assert 'lat_0' in d - assert float(d['lat_0']) == -90, line - assert 'lat_ts' in d - assert 'lon_0' in d - assert float(d['lon_0']) == 140, line - assert 'units' in d and d['units'] == 'm' - - #sql = """INSERT INTO "coordinate_operation" VALUES('IGNF','CONV_%s','conversion');""" % (code) - #all_sql.append(sql) - - sql = """INSERT INTO "conversion" VALUES('IGNF','CONV_%s','Conversion for %s',NULL,NULL,'EPSG','1262','EPSG','9829','Polar Stereographic (variant B)','EPSG','8832','Latitude of standard parallel',%s,'EPSG','9102','EPSG','8833','Longitude of origin',%s,'EPSG','9102','EPSG','8806','False easting',%s,'EPSG','9001','EPSG','8807','False northing',%s,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0);""" % (code, escape_literal(d['title']), d['lat_ts'], d['lon_0'], d['x_0'], d['y_0']) - all_sql.append(sql) - - #sql = """INSERT INTO "crs" VALUES('IGNF','%s','projected');""" % (code) - #all_sql.append(sql) - - # Hardcoding 1025 for coordinate system since the only instance uses it - sql = """INSERT INTO "projected_crs" VALUES('IGNF','%s','%s',NULL,NULL,'EPSG','1025','IGNF','%s','IGNF','CONV_%s','EPSG','1262',NULL,0);""" % (code, escape_literal(d['title']), geogcrs_code, code) - all_sql.append(sql) - - all_sql.append('') - - elif proj == 'mill': - - geogcrs_code = find_geogcrs_code(line,d) - - assert 'x_0' in d - assert 'y_0' in d - assert 'lon_0' in d - assert 'units' in d and d['units'] == 'm' - assert float(d['x_0']) == 0, d - assert float(d['y_0']) == 0, d - assert float(d['lon_0']) == 0, d - - #sql = """INSERT INTO "coordinate_operation" VALUES('IGNF','CONV_%s','conversion');""" % (code) - #all_sql.append(sql) - - sql = """INSERT INTO "conversion" VALUES('IGNF','CONV_%s','Conversion for %s',NULL,NULL,'EPSG','1262',NULL,NULL,'PROJ mill',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0);""" % (code, escape_literal(d['title'])) - all_sql.append(sql) - - #sql = """INSERT INTO "crs" VALUES('IGNF','%s','projected');""" % (code) - #all_sql.append(sql) - - sql = """INSERT INTO "projected_crs" VALUES('IGNF','%s','%s',NULL,NULL,'EPSG','4499','IGNF','%s','IGNF','CONV_%s','EPSG','1262',NULL,0);""" % (code, escape_literal(d['title']), geogcrs_code, code) - all_sql.append(sql) - - all_sql.append('') - - else: - assert False, line - - -all_sql.append("""INSERT INTO grid_alternatives(original_grid_name, - proj_grid_name, - proj_grid_format, - proj_method, - inverse_direction, - package_name, - url, direct_download, open_license, directory) - VALUES ('ntf_r93.gsb', -- as referenced by the IGNF registry - 'ntf_r93.gsb', - 'NTv2', - 'hgridshift', - 0, - 'proj-datumgrid', - NULL, NULL, NULL, NULL); -""") - -#for k in map_geog_crs: -# print k, map_geog_crs[k] - -script_dir_name = os.path.dirname(os.path.realpath(__file__)) -sql_dir_name = os.path.join(os.path.dirname(script_dir_name), 'data', 'sql') - -f = open(os.path.join(sql_dir_name, 'ignf') + '.sql', 'wb') -f.write("--- This file has been generated by scripts/build_db_create_ignf.py from the PROJ4 IGNF definition file. DO NOT EDIT !\n\n".encode('UTF-8')) -for sql in all_sql: - f.write((sql + '\n').encode('UTF-8')) -f.close() - -- cgit v1.2.3 From b503c2e5ae4b90da5e390be929ab5a37ab534232 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Mon, 23 Nov 2020 16:54:48 +0100 Subject: GeographicCRS::_isEquivalentTo(EQUIVALENT_EXCEPT_AXIS_ORDER_GEOGCRS): make it work when comparing easting,northing,up and northing,easting,up --- src/iso19111/crs.cpp | 21 +++++++++++++++++++++ test/unit/test_crs.cpp | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/src/iso19111/crs.cpp b/src/iso19111/crs.cpp index de882105..5d2c6d7b 100644 --- a/src/iso19111/crs.cpp +++ b/src/iso19111/crs.cpp @@ -2522,6 +2522,27 @@ bool GeographicCRS::_isEquivalentTo( ->GeodeticCRS::_isEquivalentToNoTypeCheck(other, standardCriterion, dbContext); } + if (axisOrder == + cs::EllipsoidalCS::AxisOrder::LONG_EAST_LAT_NORTH_HEIGHT_UP || + axisOrder == + cs::EllipsoidalCS::AxisOrder::LAT_NORTH_LONG_EAST_HEIGHT_UP) { + const auto &angularUnit = coordinateSystem()->axisList()[0]->unit(); + const auto &linearUnit = coordinateSystem()->axisList()[2]->unit(); + return GeographicCRS::create( + util::PropertyMap().set(common::IdentifiedObject::NAME_KEY, + nameStr()), + datum(), datumEnsemble(), + axisOrder == cs::EllipsoidalCS::AxisOrder:: + LONG_EAST_LAT_NORTH_HEIGHT_UP + ? cs::EllipsoidalCS:: + createLatitudeLongitudeEllipsoidalHeight( + angularUnit, linearUnit) + : cs::EllipsoidalCS:: + createLongitudeLatitudeEllipsoidalHeight( + angularUnit, linearUnit)) + ->GeodeticCRS::_isEquivalentToNoTypeCheck(other, standardCriterion, + dbContext); + } return false; } //! @endcond diff --git a/test/unit/test_crs.cpp b/test/unit/test_crs.cpp index aea72da2..e470a621 100644 --- a/test/unit/test_crs.cpp +++ b/test/unit/test_crs.cpp @@ -2107,6 +2107,53 @@ TEST(crs, projectedCRS_as_PROJ_string) { // --------------------------------------------------------------------------- +TEST(crs, projectedCRS_3D_is_WKT1_equivalent_to_WKT2) { + auto dbContext = DatabaseContext::create(); + + // "Illegal" WKT1 with a Projected 3D CRS + auto wkt1 = "PROJCS[\"WGS 84 / UTM zone 16N [EGM08-1]\"," + "GEOGCS[\"WGS 84 / UTM zone 16N [EGM08-1]\"," + "DATUM[\"WGS84\",SPHEROID[\"WGS84\",6378137.000,298.257223563," + "AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]]," + "PRIMEM[\"Greenwich\",0.0000000000000000," + "AUTHORITY[\"EPSG\",\"8901\"]]," + "UNIT[\"Degree\",0.01745329251994329547," + "AUTHORITY[\"EPSG\",\"9102\"]],AUTHORITY[\"EPSG\",\"32616\"]]," + "UNIT[\"Meter\",1.00000000000000000000," + "AUTHORITY[\"EPSG\",\"9001\"]]," + "PROJECTION[\"Transverse_Mercator\"]," + "PARAMETER[\"latitude_of_origin\",0.0000000000000000]," + "PARAMETER[\"central_meridian\",-87.0000000002777938]," + "PARAMETER[\"scale_factor\",0.9996000000000000]," + "PARAMETER[\"false_easting\",500000.000]," + "PARAMETER[\"false_northing\",0.000]," + "AXIS[\"Easting\",EAST]," + "AXIS[\"Northing\",NORTH]," + "AXIS[\"Height\",UP]," + "AUTHORITY[\"EPSG\",\"32616\"]]"; + + auto obj = WKTParser() + .setStrict(false) + .attachDatabaseContext(dbContext) + .createFromWKT(wkt1); + auto crs = nn_dynamic_pointer_cast(obj); + ASSERT_TRUE(crs != nullptr); + + WKTFormatterNNPtr f( + WKTFormatter::create(WKTFormatter::Convention::WKT2_2019)); + auto wkt2 = crs->exportToWKT(f.get()); + auto obj2 = + WKTParser().attachDatabaseContext(dbContext).createFromWKT(wkt2); + auto crs2 = nn_dynamic_pointer_cast(obj2); + ASSERT_TRUE(crs2 != nullptr); + + EXPECT_TRUE(crs->isEquivalentTo( + crs2.get(), + IComparable::Criterion::EQUIVALENT_EXCEPT_AXIS_ORDER_GEOGCRS)); +} + +// --------------------------------------------------------------------------- + TEST(crs, projectedCRS_Krovak_EPSG_5221_as_PROJ_string) { auto factory = AuthorityFactory::create(DatabaseContext::create(), "EPSG"); auto crs = factory->createProjectedCRS("5221"); -- cgit v1.2.3 From 42b8c2012d7648345502337087a64b73698f9f29 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Mon, 23 Nov 2020 18:39:36 +0100 Subject: GitHub action: add a Mac build --- .github/workflows/mac.yml | 39 +++++++++++++++++++++++++++++++++ .github/workflows/mac/before_install.sh | 13 +++++++++++ .github/workflows/mac/install.sh | 13 +++++++++++ 3 files changed, 65 insertions(+) create mode 100644 .github/workflows/mac.yml create mode 100755 .github/workflows/mac/before_install.sh create mode 100755 .github/workflows/mac/install.sh diff --git a/.github/workflows/mac.yml b/.github/workflows/mac.yml new file mode 100644 index 00000000..1ccbd938 --- /dev/null +++ b/.github/workflows/mac.yml @@ -0,0 +1,39 @@ +name: MacOS build + +on: [push, pull_request] + +jobs: + + macos_build: + runs-on: macos-latest + if: "!contains(github.event.head_commit.message, '[ci skip]') && !contains(github.event.head_commit.message, '[skip ci]')" + steps: + + - uses: actions/checkout@v2 + + - uses: conda-incubator/setup-miniconda@v2 + with: + channels: conda-forge + auto-update-conda: true + + - name: Cache + uses: actions/cache@v2 + id: cache + with: + path: ~/.ccache + key: ${{ runner.os }}-cache-mac-${{ github.run_id }} + restore-keys: ${{ runner.os }}-cache-mac- + + - name: Install Requirements + shell: bash -l {0} + run: | + source .github/workflows/mac/before_install.sh + + - name: Build + shell: bash -l {0} + run: | + export TRAVIS_BUILD_DIR=$PWD + source .github/workflows/mac/install.sh + env: + TRAVIS_OS_NAME: osx + BUILD_NAME: osx diff --git a/.github/workflows/mac/before_install.sh b/.github/workflows/mac/before_install.sh new file mode 100755 index 00000000..217039fe --- /dev/null +++ b/.github/workflows/mac/before_install.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +set -e + + +conda update -n base -c defaults conda +conda install compilers -y + +conda config --set channel_priority strict +conda install --yes --quiet python=3.8 autoconf automake libtool ccache -y +conda install --yes --quiet proj=7.1.1=h45baca5_3 --only-deps -y + +./travis/before_install_pip.sh diff --git a/.github/workflows/mac/install.sh b/.github/workflows/mac/install.sh new file mode 100755 index 00000000..ed27150f --- /dev/null +++ b/.github/workflows/mac/install.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +set -e + +export CCACHE_CPP2=yes +export PROJ_DB_CACHE_DIR="$HOME/.ccache" + +ccache -M 200M +ccache -s + +CC="ccache clang" CXX="ccache clang++" CFLAGS="-Werror -O2" CXXFLAGS="-Werror -O2" ./travis/install.sh + +ccache -s -- cgit v1.2.3 From 95fd9665ef38942d4343744ec66339d60e315cac Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Mon, 23 Nov 2020 19:37:27 +0100 Subject: .travis.yml: remove mac job --- .travis.yml | 5 ----- travis/osx/after_success.sh | 5 ----- travis/osx/before_install.sh | 22 ---------------------- travis/osx/install.sh | 10 ---------- 4 files changed, 42 deletions(-) delete mode 100755 travis/osx/after_success.sh delete mode 100755 travis/osx/before_install.sh delete mode 100755 travis/osx/install.sh diff --git a/.travis.yml b/.travis.yml index dc5356ad..1053ce1e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -82,11 +82,6 @@ matrix: - BUILD_NAME=linux_generic - DETAILS="linux, arm64" - - os: osx - env: - - BUILD_NAME=osx - - DETAILS="osx" - - os: linux dist: xenial compiler: gcc diff --git a/travis/osx/after_success.sh b/travis/osx/after_success.sh deleted file mode 100755 index 9618f673..00000000 --- a/travis/osx/after_success.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - -set -e - -# nothing diff --git a/travis/osx/before_install.sh b/travis/osx/before_install.sh deleted file mode 100755 index 5af2fd7a..00000000 --- a/travis/osx/before_install.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash - -set -e - -export PATH=$HOME/Library/Python/3.7/bin:$PATH - -#brew unlink python@2 -#brew update -brew install ccache -#brew upgrade sqlite3 -#brew upgrade libtiff -#brew install doxygen graphviz -#brew install md5sha1sum -#brew reinstall python -#brew reinstall wget - -./travis/before_install_pip.sh - -# pip3 install --user sphinx sphinx-rtd-theme sphinxcontrib-bibtex breathe -# which sphinx-build - -# (cd docs; make html) diff --git a/travis/osx/install.sh b/travis/osx/install.sh deleted file mode 100755 index ff5266f6..00000000 --- a/travis/osx/install.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -set -e - -export CCACHE_CPP2=yes -export PROJ_DB_CACHE_DIR="$HOME/.ccache" - -export PATH=$HOME/Library/Python/3.6/bin:$PATH - -CC="ccache clang" CXX="ccache clang++" CFLAGS="-Werror -O2" CXXFLAGS="-Werror -O2" ./travis/install.sh -- cgit v1.2.3 From d8fe9964bcbc6d1eeaddf6f5d47ca6d444dc8744 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Sun, 22 Nov 2020 15:08:41 +0100 Subject: Add +proj=topocentric geocentric->topocentric conversion (fixes #500) --- .../ECEF_ENU_Longitude_Latitude_relationships.png | Bin 0 -> 30731 bytes .../ECEF_ENU_Longitude_Latitude_relationships.svg | 348 +++++++++++++++++++++ docs/source/operations/conversions/index.rst | 1 + docs/source/operations/conversions/topocentric.rst | 115 +++++++ .../internal/coordinateoperation_constants.hpp | 41 +++ src/Makefile.am | 1 + src/conversions/topocentric.cpp | 165 ++++++++++ src/iso19111/coordinateoperation.cpp | 55 +++- src/lib_proj.cmake | 1 + src/pj_list.h | 1 + src/proj_constants.h | 20 ++ test/gie/builtins.gie | 42 +++ test/unit/test_operation.cpp | 122 ++++++++ 13 files changed, 904 insertions(+), 8 deletions(-) create mode 100644 docs/source/operations/conversions/images/ECEF_ENU_Longitude_Latitude_relationships.png create mode 100644 docs/source/operations/conversions/images/ECEF_ENU_Longitude_Latitude_relationships.svg create mode 100644 docs/source/operations/conversions/topocentric.rst create mode 100644 src/conversions/topocentric.cpp diff --git a/docs/source/operations/conversions/images/ECEF_ENU_Longitude_Latitude_relationships.png b/docs/source/operations/conversions/images/ECEF_ENU_Longitude_Latitude_relationships.png new file mode 100644 index 00000000..224ff738 Binary files /dev/null and b/docs/source/operations/conversions/images/ECEF_ENU_Longitude_Latitude_relationships.png differ diff --git a/docs/source/operations/conversions/images/ECEF_ENU_Longitude_Latitude_relationships.svg b/docs/source/operations/conversions/images/ECEF_ENU_Longitude_Latitude_relationships.svg new file mode 100644 index 00000000..c97ca181 --- /dev/null +++ b/docs/source/operations/conversions/images/ECEF_ENU_Longitude_Latitude_relationships.svg @@ -0,0 +1,348 @@ + + + +Z + + + + + + +Y + + + + + + +X + + + + + + +North + + + + + + +East + + + + + + +Up + + + + + + +ecef + + +ecef + + +ecef + + + +φ + +λ + + \ No newline at end of file diff --git a/docs/source/operations/conversions/index.rst b/docs/source/operations/conversions/index.rst index b0bd0d37..b335c2ac 100644 --- a/docs/source/operations/conversions/index.rst +++ b/docs/source/operations/conversions/index.rst @@ -19,4 +19,5 @@ conversions. pop push set + topocentric unitconvert diff --git a/docs/source/operations/conversions/topocentric.rst b/docs/source/operations/conversions/topocentric.rst new file mode 100644 index 00000000..828ef4e0 --- /dev/null +++ b/docs/source/operations/conversions/topocentric.rst @@ -0,0 +1,115 @@ +.. _topocentric: + +================================================================================ +Geocentric to topocentric conversion +================================================================================ + +.. versionadded:: 8.0.0 + +Convert geocentric coordinates to topocentric coordinates (in the forward path). + ++---------------------+--------------------------------------------------------+ +| **Alias** | topocentric | ++---------------------+--------------------------------------------------------+ +| **Domain** | 3D | ++---------------------+--------------------------------------------------------+ +| **Input type** | Geocentric cartesian coordinates | ++---------------------+--------------------------------------------------------+ +| **Output type** | Topocentric cartesian coordinates | ++---------------------+--------------------------------------------------------+ + +This operation converts geocentric coordinate values (X, Y, Z) to topocentric +(E/East, N/North, U/Up) values. This is also sometimes known as the ECEF (Earth +Centered Earth Fixed) to ENU conversion. + +Topocentric coordinates are expressed in a frame whose East and North axis form +a local tangent plane to the Earth's ellipsoidal surface fixed to a specific +location (the topocentric origin), and the Up axis points upwards along the +normal to that plane. + +.. image:: ./images/ECEF_ENU_Longitude_Latitude_relationships.png + :align: center + :scale: 100% + :alt: ENU coordinate frame + +.. + Source : https://en.wikipedia.org/wiki/Local_tangent_plane_coordinates#/media/File:ECEF_ENU_Longitude_Latitude_relationships.svg + Public domain +.. + +The topocentric origin is a required parameter of the conversion, and can be +expressed either as geocentric coordinates (``X_0``, ``Y_0`` and ``Z_0``) or +as geographic coordinates (``lat_0``, ``lon_0``, ``h_0``). + +When conversion between geographic and topocentric coordinates is desired, the +topocentric conversion must be preceded by the :ref:`cart` conversion to +perform the initial geographic to geocentric coordinates conversion. + +The formulas used come from the "Geocentric/topocentric conversions" paragraph +of :cite:`IOGP2018` + +Usage +################################################################################ + +Convert geocentric coordinates to topocentric coordinates, with the topocentric +origin specified in geocentric coordinates:: + + echo 3771793.968 140253.342 5124304.349 2020 | \ + cct -d 3 +proj=topocentric +ellps=WGS84 +X_0=3652755.3058 +Y_0=319574.6799 +Z_0=5201547.3536 + + -189013.869 -128642.040 -4220.171 2020.0000 + +Convert geographic coordinates to topocentric coordinates, with the topocentric +origin specified in geographic coordinates:: + + echo 2.12955 53.80939444 73 2020 | cct -d 3 +proj=pipeline \ + +step +proj=cart +ellps=WGS84 \ + +step +proj=topocentric +ellps=WGS84 +lon_0=5 +lat_0=55 +h_0=200 + + -189013.869 -128642.040 -4220.171 2020.0000 + + +Parameters +################################################################################ + +.. include:: ../options/ellps.rst + +Topocentric origin described as geocentric coordinates +------------------------------------------------------ + +.. note:: + + The below options are mutually exclusive with the ones to express the origin as geographic coordinates. + +.. option:: +X_0= + + Geocentric X value of the topocentric origin (in metre) + +.. option:: +Y_0= + + Geocentric Y value of the topocentric origin (in metre) + +.. option:: +Z_0= + + Geocentric Z value of the topocentric origin (in metre) + +Topocentric origin described as geographic coordinates +------------------------------------------------------ + +.. note:: + + The below options are mutually exclusive with the ones to express the origin as geocentric coordinates. + +.. option:: +lat_0= + + Latitude of topocentric origin (in degree) + +.. option:: +lon_0= + + Longitude of topocentric origin (in degree) + +.. option:: +h_0= + + Ellipsoidal height of topocentric origin (in metre) + + *Defaults to 0.0.* diff --git a/include/proj/internal/coordinateoperation_constants.hpp b/include/proj/internal/coordinateoperation_constants.hpp index 592f6263..0ed3a027 100644 --- a/include/proj/internal/coordinateoperation_constants.hpp +++ b/include/proj/internal/coordinateoperation_constants.hpp @@ -532,6 +532,34 @@ static const ParamMapping *const paramsColombiaUrban[] = { ¶mProjectionPlaneOriginHeight, nullptr}; +static const ParamMapping paramGeocentricXTopocentricOrigin = { + EPSG_NAME_PARAMETER_GEOCENTRIC_X_TOPOCENTRIC_ORIGIN, + EPSG_CODE_PARAMETER_GEOCENTRIC_X_TOPOCENTRIC_ORIGIN, nullptr, + common::UnitOfMeasure::Type::LINEAR, "X_0"}; + +static const ParamMapping paramGeocentricYTopocentricOrigin = { + EPSG_NAME_PARAMETER_GEOCENTRIC_Y_TOPOCENTRIC_ORIGIN, + EPSG_CODE_PARAMETER_GEOCENTRIC_Y_TOPOCENTRIC_ORIGIN, nullptr, + common::UnitOfMeasure::Type::LINEAR, "Y_0"}; + +static const ParamMapping paramGeocentricZTopocentricOrigin = { + EPSG_NAME_PARAMETER_GEOCENTRIC_Z_TOPOCENTRIC_ORIGIN, + EPSG_CODE_PARAMETER_GEOCENTRIC_Z_TOPOCENTRIC_ORIGIN, nullptr, + common::UnitOfMeasure::Type::LINEAR, "Z_0"}; + +static const ParamMapping *const paramsGeocentricTopocentric[] = { + ¶mGeocentricXTopocentricOrigin, ¶mGeocentricYTopocentricOrigin, + ¶mGeocentricZTopocentricOrigin, nullptr}; + +static const ParamMapping paramHeightTopoOriginWithH0 = { + EPSG_NAME_PARAMETER_ELLIPSOIDAL_HEIGHT_TOPOCENTRIC_ORIGIN, + EPSG_CODE_PARAMETER_ELLIPSOIDAL_HEIGHT_TOPOCENTRIC_ORIGIN, nullptr, + common::UnitOfMeasure::Type::LINEAR, "h_0"}; + +static const ParamMapping *const paramsGeographicTopocentric[] = { + ¶mLatTopoOrigin, ¶mLonTopoOrigin, ¶mHeightTopoOriginWithH0, + nullptr}; + static const MethodMapping projectionMethodMappings[] = { {EPSG_NAME_METHOD_TRANSVERSE_MERCATOR, EPSG_CODE_METHOD_TRANSVERSE_MERCATOR, "Transverse_Mercator", "tmerc", nullptr, paramsNatOriginScaleK}, @@ -836,6 +864,14 @@ static const MethodMapping projectionMethodMappings[] = { {EPSG_NAME_METHOD_COLOMBIA_URBAN, EPSG_CODE_METHOD_COLOMBIA_URBAN, nullptr, "col_urban", nullptr, paramsColombiaUrban}, + + {EPSG_NAME_METHOD_GEOCENTRIC_TOPOCENTRIC, + EPSG_CODE_METHOD_GEOCENTRIC_TOPOCENTRIC, nullptr, "topocentric", nullptr, + paramsGeocentricTopocentric}, + + {EPSG_NAME_METHOD_GEOGRAPHIC_TOPOCENTRIC, + EPSG_CODE_METHOD_GEOGRAPHIC_TOPOCENTRIC, nullptr, nullptr, nullptr, + paramsGeographicTopocentric}, }; #define METHOD_NAME_CODE(method) \ @@ -878,6 +914,8 @@ static const struct MethodNameCode { METHOD_NAME_CODE(AXIS_ORDER_REVERSAL_2D), METHOD_NAME_CODE(AXIS_ORDER_REVERSAL_3D), METHOD_NAME_CODE(GEOGRAPHIC_GEOCENTRIC), + METHOD_NAME_CODE(GEOCENTRIC_TOPOCENTRIC), + METHOD_NAME_CODE(GEOGRAPHIC_TOPOCENTRIC), // Transformations METHOD_NAME_CODE(LONGITUDE_ROTATION), METHOD_NAME_CODE(AFFINE_PARAMETRIC_TRANSFORMATION), @@ -943,6 +981,9 @@ static const struct ParamNameCode { PARAM_NAME_CODE(LONGITUDE_OF_ORIGIN), PARAM_NAME_CODE(ELLIPSOID_SCALE_FACTOR), PARAM_NAME_CODE(PROJECTION_PLANE_ORIGIN_HEIGHT), + PARAM_NAME_CODE(GEOCENTRIC_X_TOPOCENTRIC_ORIGIN), + PARAM_NAME_CODE(GEOCENTRIC_Y_TOPOCENTRIC_ORIGIN), + PARAM_NAME_CODE(GEOCENTRIC_Z_TOPOCENTRIC_ORIGIN), // Parameters of transformations PARAM_NAME_CODE(SEMI_MAJOR_AXIS_DIFFERENCE), PARAM_NAME_CODE(FLATTENING_DIFFERENCE), diff --git a/src/Makefile.am b/src/Makefile.am index 5b36c8bd..4b904d9f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -187,6 +187,7 @@ libproj_la_SOURCES = \ conversions/geoc.cpp \ conversions/geocent.cpp \ conversions/noop.cpp \ + conversions/topocentric.cpp \ conversions/set.cpp \ conversions/unitconvert.cpp \ \ diff --git a/src/conversions/topocentric.cpp b/src/conversions/topocentric.cpp new file mode 100644 index 00000000..214f8221 --- /dev/null +++ b/src/conversions/topocentric.cpp @@ -0,0 +1,165 @@ +/****************************************************************************** + * Project: PROJ + * Purpose: Convert between geocentric coordinates and topocentric (ENU) coordinates + * + ****************************************************************************** + * Copyright (c) 2020, Even Rouault + * + * 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. + *****************************************************************************/ + +#define PJ_LIB__ + +#include "proj_internal.h" +#include +#include + +PROJ_HEAD(topocentric, "Geocentric/Topocentric conversion"); + +// Notations and formulas taken from IOGP Publication 373-7-2 - +// Geomatics Guidance Note number 7, part 2 - October 2020 + +namespace { // anonymous namespace +struct pj_opaque { + double X0; + double Y0; + double Z0; + double sinphi0; + double cosphi0; + double sinlam0; + double coslam0; +}; +} // anonymous namespace + +// Convert from geocentric to topocentric +static PJ_COORD topocentric_fwd(PJ_COORD in, PJ * P) +{ + struct pj_opaque *Q = static_cast(P->opaque); + PJ_COORD out; + const double dX = in.xyz.x - Q->X0; + const double dY = in.xyz.y - Q->Y0; + const double dZ = in.xyz.z - Q->Z0; + out.xyz.x = -dX * Q->sinlam0 + dY * Q->coslam0; + out.xyz.y = -dX * Q->sinphi0 * Q->coslam0 - dY * Q->sinphi0 * Q->sinlam0 + dZ * Q->cosphi0; + out.xyz.z = dX * Q->cosphi0 * Q->coslam0 + dY * Q->cosphi0 * Q->sinlam0 + dZ * Q->sinphi0; + return out; +} + +// Convert from topocentric to geocentric +static PJ_COORD topocentric_inv(PJ_COORD in, PJ * P) +{ + struct pj_opaque *Q = static_cast(P->opaque); + PJ_COORD out; + out.xyz.x = Q->X0 - in.xyz.x * Q->sinlam0 - in.xyz.y * Q->sinphi0 * Q->coslam0 + in.xyz.z * Q->cosphi0 * Q->coslam0; + out.xyz.y = Q->Y0 + in.xyz.x * Q->coslam0 - in.xyz.y * Q->sinphi0 * Q->sinlam0 + in.xyz.z * Q->cosphi0 * Q->sinlam0; + out.xyz.z = Q->Z0 + in.xyz.y * Q->cosphi0 + in.xyz.z * Q->sinphi0; + return out; +} + + +/*********************************************************************/ +PJ *CONVERSION(topocentric,1) { +/*********************************************************************/ + struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + if (nullptr==Q) + return pj_default_destructor (P, ENOMEM); + P->opaque = static_cast(Q); + + // The topocentric origin can be specified either in geocentric coordinates + // (X_0,Y_0,Z_0) or as geographic coordinates (lon_0,lat_0,h_0) + // Checks: + // - X_0 or lon_0 must be specified + // - If X_0 is specified, the Y_0 and Z_0 must also be + // - If lon_0 is specified, then lat_0 must also be + // - If any of X_0, Y_0, Z_0 is specified, then any of lon_0,lat_0,h_0 must + // not be, and vice versa. + const auto hasX0 = pj_param_exists(P->params, "X_0"); + const auto hasY0 = pj_param_exists(P->params, "Y_0"); + const auto hasZ0 = pj_param_exists(P->params, "Z_0"); + const auto hasLon0 = pj_param_exists(P->params, "lon_0"); + const auto hasLat0 = pj_param_exists(P->params, "lat_0"); + const auto hash0 = pj_param_exists(P->params, "h_0"); + if( !hasX0 && !hasLon0 ) + { + return pj_default_destructor(P, PJD_ERR_MISSING_ARGS); + } + if ( (hasX0 || hasY0 || hasZ0) && + (hasLon0 || hasLat0 || hash0) ) + { + return pj_default_destructor(P, PJD_ERR_MUTUALLY_EXCLUSIVE_ARGS); + } + if( hasX0 && (!hasY0 || !hasZ0) ) + { + return pj_default_destructor(P, PJD_ERR_MISSING_ARGS); + } + if( hasLon0 && !hasLat0 ) // allow missing h_0 + { + return pj_default_destructor(P, PJD_ERR_MISSING_ARGS); + } + + // Pass a dummy ellipsoid definition that will be overridden just afterwards + PJ* cart = proj_create(P->ctx, "+proj=cart +a=1"); + if (cart == nullptr) + return pj_default_destructor(P, ENOMEM); + /* inherit ellipsoid definition from P to cart */ + pj_inherit_ellipsoid_def (P, cart); + + if( hasX0 ) + { + Q->X0 = pj_param(P->ctx, P->params, "dX_0").f; + Q->Y0 = pj_param(P->ctx, P->params, "dY_0").f; + Q->Z0 = pj_param(P->ctx, P->params, "dZ_0").f; + + // Compute lam0, phi0 from X0,Y0,Z0 + PJ_XYZ xyz; + xyz.x = Q->X0; + xyz.y = Q->Y0; + xyz.z = Q->Z0; + const auto lpz = pj_inv3d(xyz, cart); + Q->sinphi0 = sin(lpz.phi); + Q->cosphi0 = cos(lpz.phi); + Q->sinlam0 = sin(lpz.lam); + Q->coslam0 = cos(lpz.lam); + } + else + { + // Compute X0,Y0,Z0 from lam0, phi0, h0 + PJ_LPZ lpz; + lpz.lam = P->lam0; + lpz.phi = P->phi0; + lpz.z = pj_param(P->ctx, P->params, "dh_0").f; + const auto xyz = pj_fwd3d(lpz, cart); + Q->X0 = xyz.x; + Q->Y0 = xyz.y; + Q->Z0 = xyz.z; + + Q->sinphi0 = sin(P->phi0); + Q->cosphi0 = cos(P->phi0); + Q->sinlam0 = sin(P->lam0); + Q->coslam0 = cos(P->lam0); + } + + proj_destroy(cart); + + P->fwd4d = topocentric_fwd; + P->inv4d = topocentric_inv; + P->left = PJ_IO_UNITS_CARTESIAN; + P->right = PJ_IO_UNITS_CARTESIAN; + return P; +} diff --git a/src/iso19111/coordinateoperation.cpp b/src/iso19111/coordinateoperation.cpp index 1d3b7a90..dfd349b5 100644 --- a/src/iso19111/coordinateoperation.cpp +++ b/src/iso19111/coordinateoperation.cpp @@ -6034,28 +6034,39 @@ void Conversion::_exportToPROJString( !isHeightDepthReversal; bool applyTargetCRSModifiers = applySourceCRSModifiers; + if (formatter->getCRSExport()) { + if (methodEPSGCode == EPSG_CODE_METHOD_GEOCENTRIC_TOPOCENTRIC || + methodEPSGCode == EPSG_CODE_METHOD_GEOGRAPHIC_TOPOCENTRIC) { + throw io::FormattingException("Transformation cannot be exported " + "as a PROJ.4 string (but can be part " + "of a PROJ pipeline)"); + } + } + auto l_sourceCRS = sourceCRS(); + crs::GeographicCRSPtr srcGeogCRS; if (!formatter->getCRSExport() && l_sourceCRS && applySourceCRSModifiers) { - crs::CRS *horiz = l_sourceCRS.get(); - const auto compound = dynamic_cast(horiz); + crs::CRSPtr horiz = l_sourceCRS; + const auto compound = + dynamic_cast(l_sourceCRS.get()); if (compound) { const auto &components = compound->componentReferenceSystems(); if (!components.empty()) { - horiz = components.front().get(); + horiz = components.front().as_nullable(); } } - auto geogCRS = dynamic_cast(horiz); - if (geogCRS) { + srcGeogCRS = std::dynamic_pointer_cast(horiz); + if (srcGeogCRS) { formatter->setOmitProjLongLatIfPossible(true); formatter->startInversion(); - geogCRS->_exportToPROJString(formatter); + srcGeogCRS->_exportToPROJString(formatter); formatter->stopInversion(); formatter->setOmitProjLongLatIfPossible(false); } - auto projCRS = dynamic_cast(horiz); + auto projCRS = dynamic_cast(horiz.get()); if (projCRS) { formatter->startInversion(); formatter->pushOmitZUnitConversion(); @@ -6325,6 +6336,30 @@ void Conversion::_exportToPROJString( } bConversionDone = true; bEllipsoidParametersDone = true; + } else if (methodEPSGCode == EPSG_CODE_METHOD_GEOGRAPHIC_TOPOCENTRIC) { + if (!srcGeogCRS) { + throw io::FormattingException( + "Export of Geographic/Topocentric conversion to a PROJ string " + "requires an input geographic CRS"); + } + + formatter->addStep("cart"); + srcGeogCRS->ellipsoid()->_exportToPROJString(formatter); + + formatter->addStep("topocentric"); + const auto latOrigin = parameterValueNumeric( + EPSG_CODE_PARAMETER_LATITUDE_TOPOGRAPHIC_ORIGIN, + common::UnitOfMeasure::DEGREE); + const auto lonOrigin = parameterValueNumeric( + EPSG_CODE_PARAMETER_LONGITUDE_TOPOGRAPHIC_ORIGIN, + common::UnitOfMeasure::DEGREE); + const auto heightOrigin = parameterValueNumeric( + EPSG_CODE_PARAMETER_ELLIPSOIDAL_HEIGHT_TOPOCENTRIC_ORIGIN, + common::UnitOfMeasure::METRE); + formatter->addParam("lat_0", latOrigin); + formatter->addParam("lon_0", lonOrigin); + formatter->addParam("h_0", heightOrigin); + bConversionDone = true; } auto l_targetCRS = targetCRS(); @@ -6449,7 +6484,9 @@ void Conversion::_exportToPROJString( } if (!bEllipsoidParametersDone) { - auto targetGeogCRS = horiz->extractGeographicCRS(); + auto targetGeodCRS = horiz->extractGeodeticCRS(); + auto targetGeogCRS = + std::dynamic_pointer_cast(targetGeodCRS); if (targetGeogCRS) { if (formatter->getCRSExport()) { targetGeogCRS->addDatumInfoToPROJString(formatter); @@ -6458,6 +6495,8 @@ void Conversion::_exportToPROJString( targetGeogCRS->primeMeridian()->_exportToPROJString( formatter); } + } else if (targetGeodCRS) { + targetGeodCRS->ellipsoid()->_exportToPROJString(formatter); } } diff --git a/src/lib_proj.cmake b/src/lib_proj.cmake index 67bc1f4e..9f482d19 100644 --- a/src/lib_proj.cmake +++ b/src/lib_proj.cmake @@ -173,6 +173,7 @@ set(SRC_LIBPROJ_CONVERSIONS conversions/geoc.cpp conversions/geocent.cpp conversions/noop.cpp + conversions/topocentric.cpp conversions/set.cpp conversions/unitconvert.cpp ) diff --git a/src/pj_list.h b/src/pj_list.h index bcdc189e..d00e780f 100644 --- a/src/pj_list.h +++ b/src/pj_list.h @@ -155,6 +155,7 @@ PROJ_HEAD(tinshift, "Triangulation based transformation") PROJ_HEAD(tissot, "Tissot Conic") PROJ_HEAD(tmerc, "Transverse Mercator") PROJ_HEAD(tobmerc, "Tobler-Mercator") +PROJ_HEAD(topocentric, "Geocentric/Topocentric conversion") PROJ_HEAD(tpeqd, "Two Point Equidistant") PROJ_HEAD(tpers, "Tilted perspective") PROJ_HEAD(unitconvert, "Unit conversion") diff --git a/src/proj_constants.h b/src/proj_constants.h index a3da2c10..ce3b2157 100644 --- a/src/proj_constants.h +++ b/src/proj_constants.h @@ -651,4 +651,24 @@ #define EPSG_CODE_METHOD_HEIGHT_DEPTH_REVERSAL 1068 #define EPSG_NAME_METHOD_HEIGHT_DEPTH_REVERSAL "Height Depth Reversal" +/* ------------------------------------------------------------------------ */ + +#define EPSG_NAME_METHOD_GEOCENTRIC_TOPOCENTRIC "Geocentric/topocentric conversions" +#define EPSG_CODE_METHOD_GEOCENTRIC_TOPOCENTRIC 9836 + +#define EPSG_NAME_PARAMETER_GEOCENTRIC_X_TOPOCENTRIC_ORIGIN "Geocentric X of topocentric origin" +#define EPSG_CODE_PARAMETER_GEOCENTRIC_X_TOPOCENTRIC_ORIGIN 8837 + +#define EPSG_NAME_PARAMETER_GEOCENTRIC_Y_TOPOCENTRIC_ORIGIN "Geocentric Y of topocentric origin" +#define EPSG_CODE_PARAMETER_GEOCENTRIC_Y_TOPOCENTRIC_ORIGIN 8838 + +#define EPSG_NAME_PARAMETER_GEOCENTRIC_Z_TOPOCENTRIC_ORIGIN "Geocentric Z of topocentric origin" +#define EPSG_CODE_PARAMETER_GEOCENTRIC_Z_TOPOCENTRIC_ORIGIN 8839 + +/* ------------------------------------------------------------------------ */ + +#define EPSG_NAME_METHOD_GEOGRAPHIC_TOPOCENTRIC "Geographic/topocentric conversions" +#define EPSG_CODE_METHOD_GEOGRAPHIC_TOPOCENTRIC 9837 + + #endif /* PROJ_CONSTANTS_INCLUDED */ diff --git a/test/gie/builtins.gie b/test/gie/builtins.gie index add5d925..72984931 100644 --- a/test/gie/builtins.gie +++ b/test/gie/builtins.gie @@ -6681,4 +6681,46 @@ accept -74.25 4.8 expect 80859.033 122543.174 roundtrip 1 +=============================================================================== +# Geocentric/topocentric conversion +=============================================================================== + +# Test parameter and point from IOGP Publication 373-7-2 - Geomatics Guidance Note number 7, part 2 - October 2020 +operation +proj=topocentric +ellps=WGS84 +X_0=3652755.3058 +Y_0=319574.6799 +Z_0=5201547.3536 +tolerance 1 mm +accept 3771793.968 140253.342 5124304.349 +expect -189013.869 -128642.040 -4220.171 +roundtrip 1 + +=============================================================================== +# Geographic/topocentric conversion +=============================================================================== + +# Test parameter and point from IOGP Publication 373-7-2 - Geomatics Guidance Note number 7, part 2 - October 2020 +operation +proj=pipeline +step +proj=cart +ellps=WGS84 +step +proj=topocentric +ellps=WGS84 +lon_0=5 +lat_0=55 +h_0=200 +tolerance 1 mm +accept 2.12955 53.80939444444444 73 +expect -189013.869 -128642.040 -4220.171 +roundtrip 1 + +=============================================================================== +# Error cases of topocentric +=============================================================================== + +# missing X_0,Y_0,Z_0 or lon_0,lat_0 +operation +proj=topocentric +ellps=WGS84 +expect failure errno missing_args + +# missing Z_0 +operation +proj=topocentric +ellps=WGS84 +X_0=0 +Y_0=0 +expect failure errno missing_args + +# missing lat_0 +operation +proj=topocentric +ellps=WGS84 +lon_0=0 +expect failure errno missing_args + +# X_0 and lon_0 are mutually exclusive +operation +proj=topocentric +ellps=WGS84 +X_0=0 +lon_0=0 +expect failure errno mutually_exclusive_args + diff --git a/test/unit/test_operation.cpp b/test/unit/test_operation.cpp index b6e555b1..269b1bbd 100644 --- a/test/unit/test_operation.cpp +++ b/test/unit/test_operation.cpp @@ -10098,6 +10098,128 @@ TEST(operation, derivedGeographicCRS_with_to_wgs84_to_geographicCRS) { // --------------------------------------------------------------------------- +TEST(operation, geographic_topocentric) { + auto wkt = + "PROJCRS[\"EPSG topocentric example A\",\n" + " BASEGEOGCRS[\"WGS 84\",\n" + " ENSEMBLE[\"World Geodetic System 1984 ensemble\",\n" + " MEMBER[\"World Geodetic System 1984 (Transit)\"],\n" + " MEMBER[\"World Geodetic System 1984 (G730)\"],\n" + " MEMBER[\"World Geodetic System 1984 (G873)\"],\n" + " MEMBER[\"World Geodetic System 1984 (G1150)\"],\n" + " MEMBER[\"World Geodetic System 1984 (G1674)\"],\n" + " MEMBER[\"World Geodetic System 1984 (G1762)\"],\n" + " ELLIPSOID[\"WGS 84\",6378137,298.257223563,\n" + " LENGTHUNIT[\"metre\",1]],\n" + " ENSEMBLEACCURACY[2.0]],\n" + " PRIMEM[\"Greenwich\",0,\n" + " ANGLEUNIT[\"degree\",0.0174532925199433]],\n" + " ID[\"EPSG\",4979]],\n" + " CONVERSION[\"EPSG topocentric example A\",\n" + " METHOD[\"Geographic/topocentric conversions\",\n" + " ID[\"EPSG\",9837]],\n" + " PARAMETER[\"Latitude of topocentric origin\",55,\n" + " ANGLEUNIT[\"degree\",0.0174532925199433],\n" + " ID[\"EPSG\",8834]],\n" + " PARAMETER[\"Longitude of topocentric origin\",5,\n" + " ANGLEUNIT[\"degree\",0.0174532925199433],\n" + " ID[\"EPSG\",8835]],\n" + " PARAMETER[\"Ellipsoidal height of topocentric origin\",0,\n" + " LENGTHUNIT[\"metre\",1],\n" + " ID[\"EPSG\",8836]]],\n" + " CS[Cartesian,3],\n" + " AXIS[\"topocentric East (U)\",east,\n" + " ORDER[1],\n" + " LENGTHUNIT[\"metre\",1]],\n" + " AXIS[\"topocentric North (V)\",north,\n" + " ORDER[2],\n" + " LENGTHUNIT[\"metre\",1]],\n" + " AXIS[\"topocentric height (W)\",up,\n" + " ORDER[3],\n" + " LENGTHUNIT[\"metre\",1]],\n" + " USAGE[\n" + " SCOPE[\"Example only (fictitious).\"],\n" + " AREA[\"Description of the extent of the CRS.\"],\n" + " BBOX[-90,-180,90,180]],\n" + " ID[\"EPSG\",5819]]"; + auto obj = WKTParser().createFromWKT(wkt); + auto dst = nn_dynamic_pointer_cast(obj); + ASSERT_TRUE(dst != nullptr); + auto op = CoordinateOperationFactory::create()->createOperation( + GeographicCRS::EPSG_4979, NN_CHECK_ASSERT(dst)); + ASSERT_TRUE(op != nullptr); + EXPECT_EQ(op->exportToPROJString(PROJStringFormatter::create().get()), + "+proj=pipeline " + "+step +proj=axisswap +order=2,1 " + "+step +proj=unitconvert +xy_in=deg +z_in=m +xy_out=rad +z_out=m " + "+step +proj=cart +ellps=WGS84 " + "+step +proj=topocentric +lat_0=55 +lon_0=5 +h_0=0 +ellps=WGS84"); +} + +// --------------------------------------------------------------------------- + +TEST(operation, geocentric_topocentric) { + auto wkt = + "PROJCRS[\"EPSG topocentric example B\",\n" + " BASEGEODCRS[\"WGS 84\",\n" + " ENSEMBLE[\"World Geodetic System 1984 ensemble\",\n" + " MEMBER[\"World Geodetic System 1984 (Transit)\"],\n" + " MEMBER[\"World Geodetic System 1984 (G730)\"],\n" + " MEMBER[\"World Geodetic System 1984 (G873)\"],\n" + " MEMBER[\"World Geodetic System 1984 (G1150)\"],\n" + " MEMBER[\"World Geodetic System 1984 (G1674)\"],\n" + " MEMBER[\"World Geodetic System 1984 (G1762)\"],\n" + " ELLIPSOID[\"WGS 84\",6378137,298.257223563,\n" + " LENGTHUNIT[\"metre\",1]],\n" + " ENSEMBLEACCURACY[2.0]],\n" + " PRIMEM[\"Greenwich\",0,\n" + " ANGLEUNIT[\"degree\",0.0174532925199433]],\n" + " ID[\"EPSG\",4978]],\n" + " CONVERSION[\"EPSG topocentric example B\",\n" + " METHOD[\"Geocentric/topocentric conversions\",\n" + " ID[\"EPSG\",9836]],\n" + " PARAMETER[\"Geocentric X of topocentric origin\",3771793.97,\n" + " LENGTHUNIT[\"metre\",1],\n" + " ID[\"EPSG\",8837]],\n" + " PARAMETER[\"Geocentric Y of topocentric origin\",140253.34,\n" + " LENGTHUNIT[\"metre\",1],\n" + " ID[\"EPSG\",8838]],\n" + " PARAMETER[\"Geocentric Z of topocentric origin\",5124304.35,\n" + " LENGTHUNIT[\"metre\",1],\n" + " ID[\"EPSG\",8839]]],\n" + " CS[Cartesian,3],\n" + " AXIS[\"topocentric East (U)\",east,\n" + " ORDER[1],\n" + " LENGTHUNIT[\"metre\",1]],\n" + " AXIS[\"topocentric North (V)\",north,\n" + " ORDER[2],\n" + " LENGTHUNIT[\"metre\",1]],\n" + " AXIS[\"topocentric height (W)\",up,\n" + " ORDER[3],\n" + " LENGTHUNIT[\"metre\",1]],\n" + " USAGE[\n" + " SCOPE[\"Example only (fictitious).\"],\n" + " AREA[\"Description of the extent of the CRS.\"],\n" + " BBOX[-90,-180,90,180]],\n" + " ID[\"EPSG\",5820]]"; + auto dbContext = DatabaseContext::create(); + // Need a database so that EPSG:4978 is resolved + auto obj = WKTParser().attachDatabaseContext(dbContext).createFromWKT(wkt); + auto dst = nn_dynamic_pointer_cast(obj); + ASSERT_TRUE(dst != nullptr); + auto f(NS_PROJ::io::WKTFormatter::create( + NS_PROJ::io::WKTFormatter::Convention::WKT2_2019)); + std::cerr << GeodeticCRS::EPSG_4978->exportToWKT(f.get()) << std::endl; + auto op = CoordinateOperationFactory::create()->createOperation( + GeodeticCRS::EPSG_4978, NN_CHECK_ASSERT(dst)); + ASSERT_TRUE(op != nullptr); + EXPECT_EQ(op->exportToPROJString(PROJStringFormatter::create().get()), + "+proj=topocentric +X_0=3771793.97 +Y_0=140253.34 " + "+Z_0=5124304.35 +ellps=WGS84"); +} + +// --------------------------------------------------------------------------- + TEST(operation, mercator_variant_A_to_variant_B) { auto projCRS = ProjectedCRS::create( PropertyMap(), GeographicCRS::EPSG_4326, -- cgit v1.2.3 From 78c8889a76602ef06e2b560cf72b6d5f68bf28ac Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Tue, 24 Nov 2020 00:26:20 +0100 Subject: GitHub action: add a mingw_w64 build --- .github/workflows/mingw_w64.yml | 24 +++++++ .github/workflows/mingw_w64/start.sh | 117 +++++++++++++++++++++++++++++++++++ 2 files changed, 141 insertions(+) create mode 100644 .github/workflows/mingw_w64.yml create mode 100755 .github/workflows/mingw_w64/start.sh diff --git a/.github/workflows/mingw_w64.yml b/.github/workflows/mingw_w64.yml new file mode 100644 index 00000000..8e323efa --- /dev/null +++ b/.github/workflows/mingw_w64.yml @@ -0,0 +1,24 @@ +name: mingw_w64 build + +on: [push, pull_request] + +jobs: + + mingw_w64_build: + runs-on: ubuntu-latest + if: "!contains(github.event.head_commit.message, '[ci skip]') && !contains(github.event.head_commit.message, '[skip ci]')" + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Cache + uses: actions/cache@v2 + id: cache + with: + path: | + ${{ github.workspace }}/ccache.tar.gz + key: ${{ runner.os }}-cache-mingw_w64-${{ github.run_id }} + restore-keys: ${{ runner.os }}-cache-mingw_w64- + + - name: Build + run: docker run -e CI -e TRAVIS_OS_NAME=linux -e BUILD_NAME=mingw_w64 -e WORK_DIR="$PWD" -v $PWD:$PWD ubuntu:18.04 $PWD/.github/workflows/mingw_w64/start.sh diff --git a/.github/workflows/mingw_w64/start.sh b/.github/workflows/mingw_w64/start.sh new file mode 100755 index 00000000..e6d04ff0 --- /dev/null +++ b/.github/workflows/mingw_w64/start.sh @@ -0,0 +1,117 @@ +#!/bin/sh + +set -e + +SCRIPT_DIR=$(dirname "$0") +case $SCRIPT_DIR in + "/"*) + ;; + ".") + SCRIPT_DIR=$(pwd) + ;; + *) + SCRIPT_DIR=$(pwd)/$(dirname "$0") + ;; +esac + +apt-get update -y +DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + sudo wget tzdata + +USER=root +export USER + +cd "$WORK_DIR" + +if test -f "$WORK_DIR/ccache.tar.gz"; then + echo "Restoring ccache..." + (cd $HOME && tar xzf "$WORK_DIR/ccache.tar.gz") +fi + +export PROJ_DB_CACHE_DIR="$HOME/.ccache" + +sudo apt-get install -y --no-install-recommends \ + ccache \ + binutils-mingw-w64-x86-64 \ + gcc-mingw-w64-x86-64 \ + g++-mingw-w64-x86-64 \ + g++-mingw-w64 \ + mingw-w64-tools \ + wine-stable \ + make autoconf automake libtool zip \ + sqlite3 \ + curl ca-certificates + +# Select posix/pthread for std::mutex +update-alternatives --set x86_64-w64-mingw32-gcc /usr/bin/x86_64-w64-mingw32-gcc-posix +update-alternatives --set x86_64-w64-mingw32-g++ /usr/bin/x86_64-w64-mingw32-g++-posix + +ccache -M 500M +ccache -s + +MINGW_ARCH=x86_64-w64-mingw32 +MINGW_PREFIX=/usr/lib/gcc/$MINGW_ARCH/7.3-posix + +export CCACHE_CPP2=yes +export CC="ccache $MINGW_ARCH-gcc" +export CXX="ccache $MINGW_ARCH-g++" +export LD=$MINGW_ARCH-ld + +UNAME="$(uname)" || UNAME="" +NPROC=$(nproc); +echo "NPROC=${NPROC}" +export MAKEFLAGS="-j ${NPROC}" + +# prepare wine environment +export WINE_PREFIX="$HOME/.wine" +WINE_SYSDIR=$WINE_PREFIX/drive_c/windows +wine64 cmd /c dir +ln -s $MINGW_PREFIX/libstdc++-6.dll $WINE_SYSDIR +ln -s $MINGW_PREFIX/libgcc_s_seh-1.dll $WINE_SYSDIR +ln -s $MINGW_PREFIX/libgcc_s_sjlj-1.dll $WINE_SYSDIR +ln -s /usr/$MINGW_ARCH/lib/libwinpthread-1.dll $WINE_SYSDIR + +# build zlib +wget https://github.com/madler/zlib/archive/v1.2.11.tar.gz +tar xzf v1.2.11.tar.gz +(cd zlib-1.2.11 && sudo make install -fwin32/Makefile.gcc SHARED_MODE=1 PREFIX=x86_64-w64-mingw32- DESTDIR=/usr/$MINGW_ARCH/) +sudo mkdir -p /usr/$MINGW_ARCH/include +sudo mkdir -p /usr/$MINGW_ARCH/lib +sudo cp /usr/$MINGW_ARCH/*.h /usr/$MINGW_ARCH/include +sudo cp /usr/$MINGW_ARCH/libz.* /usr/$MINGW_ARCH/lib +ln -s /usr/$MINGW_ARCH/zlib1.dll $WINE_SYSDIR + +# build libtiff +wget https://download.osgeo.org/libtiff/tiff-4.1.0.tar.gz +tar xzf tiff-4.1.0.tar.gz +(cd tiff-4.1.0 && ./configure --host=$MINGW_ARCH --prefix=/usr/$MINGW_ARCH && make && sudo make install) +ln -s /usr/$MINGW_ARCH/bin/libtiff-5.dll $WINE_SYSDIR + +# build sqlite3 +wget https://sqlite.org/2018/sqlite-autoconf-3250100.tar.gz +tar xzf sqlite-autoconf-3250100.tar.gz +(cd sqlite-autoconf-3250100 && +./configure --host=$MINGW_ARCH --prefix=/usr/$MINGW_ARCH && make && sudo make install) +ln -s /usr/$MINGW_ARCH/bin/libsqlite3-0.dll $WINE_SYSDIR + +# prepare build files +./autogen.sh +# autoconf build +mkdir build_autoconf +cd build_autoconf +CFLAGS="-Werror" CXXFLAGS="-Werror" ../configure --host=$MINGW_ARCH --prefix=/tmp/proj_autoconf_install --without-curl +make +make install +make dist-all +find /tmp/proj_autoconf_install +(cd test; make) +cp -r ../data/tests /tmp/proj_autoconf_install/share/proj +cp ../data/tests/egm96_15_downsampled.gtx /tmp/proj_autoconf_install/share/proj/egm96_15.gtx +cp ../data/tests/ntv2_0_downsampled.gsb /tmp/proj_autoconf_install/share/proj/ntv2_0.gsb +wine64 test/unit/test_cpp_api.exe + +ccache -s + +echo "Saving ccache..." +rm -f "$WORK_DIR/ccache.tar.gz" +(cd $HOME && tar czf "$WORK_DIR/ccache.tar.gz" .ccache) -- cgit v1.2.3 From 5d867c43a78a7a68968a0b6b2866b0797c29facd Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Tue, 24 Nov 2020 00:26:55 +0100 Subject: .travis.yml: remove mingw job --- .travis.yml | 7 ----- travis/mingw32/after_success.sh | 5 ---- travis/mingw32/before_install.sh | 15 ---------- travis/mingw32/install.sh | 59 ---------------------------------------- 4 files changed, 86 deletions(-) delete mode 100755 travis/mingw32/after_success.sh delete mode 100755 travis/mingw32/before_install.sh delete mode 100755 travis/mingw32/install.sh diff --git a/.travis.yml b/.travis.yml index 1053ce1e..c2f2b69d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -82,13 +82,6 @@ matrix: - BUILD_NAME=linux_generic - DETAILS="linux, arm64" - - os: linux - dist: xenial - compiler: gcc - env: - - BUILD_NAME=mingw32 - - DETAILS="mingw32" - - os: linux compiler: gcc dist: xenial diff --git a/travis/mingw32/after_success.sh b/travis/mingw32/after_success.sh deleted file mode 100755 index 9618f673..00000000 --- a/travis/mingw32/after_success.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - -set -e - -# nothing diff --git a/travis/mingw32/before_install.sh b/travis/mingw32/before_install.sh deleted file mode 100755 index f33d18ff..00000000 --- a/travis/mingw32/before_install.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash - -set -e - -./travis/before_install_apt.sh -./travis/before_install_pip.sh - -sudo apt-get install -qq \ - wget \ - binutils-mingw-w64-x86-64 \ - gcc-mingw-w64-x86-64 \ - g++-mingw-w64-x86-64 \ - mingw-w64-tools \ - wine1.4-amd64 \ - sqlite3 diff --git a/travis/mingw32/install.sh b/travis/mingw32/install.sh deleted file mode 100755 index 67873dd1..00000000 --- a/travis/mingw32/install.sh +++ /dev/null @@ -1,59 +0,0 @@ -#!/bin/bash - -set -e - -unset CC -unset CXX - -export CCACHE_CPP2=yes -export PROJ_DB_CACHE_DIR="$HOME/.ccache" - -MINGW_ARCH=x86_64-w64-mingw32 -MINGW_PREFIX=/usr/lib/gcc/$MINGW_ARCH/5.3-posix - -# prepare wine environment -WINE_SYSDIR=$HOME/.wine/drive_c/windows -wine64 cmd /c dir -ln -s $MINGW_PREFIX/libstdc++-6.dll $WINE_SYSDIR -ln -s $MINGW_PREFIX/libgcc_s_seh-1.dll $WINE_SYSDIR -ln -s $MINGW_PREFIX/libgcc_s_sjlj-1.dll $WINE_SYSDIR -ln -s /usr/$MINGW_ARCH/lib/libwinpthread-1.dll $WINE_SYSDIR - -# build zlib -wget https://github.com/madler/zlib/archive/v1.2.11.tar.gz -tar xzf v1.2.11.tar.gz -(cd zlib-1.2.11 && sudo make install -fwin32/Makefile.gcc SHARED_MODE=1 PREFIX=x86_64-w64-mingw32- DESTDIR=/usr/$MINGW_ARCH/) -sudo mkdir -p /usr/$MINGW_ARCH/include -sudo mkdir -p /usr/$MINGW_ARCH/lib -sudo cp /usr/$MINGW_ARCH/*.h /usr/$MINGW_ARCH/include -sudo cp /usr/$MINGW_ARCH/libz.* /usr/$MINGW_ARCH/lib -ln -s /usr/$MINGW_ARCH/zlib1.dll $WINE_SYSDIR - -# build libtiff -wget https://download.osgeo.org/libtiff/tiff-4.1.0.tar.gz -tar xzf tiff-4.1.0.tar.gz -(cd tiff-4.1.0 && ./configure --host=$MINGW_ARCH --prefix=/usr/$MINGW_ARCH && make -j2 && sudo make install) -ln -s /usr/$MINGW_ARCH/bin/libtiff-5.dll $WINE_SYSDIR - -# build sqlite3 -wget https://sqlite.org/2018/sqlite-autoconf-3250100.tar.gz -tar xzf sqlite-autoconf-3250100.tar.gz -(cd sqlite-autoconf-3250100 && CC="ccache $MINGW_ARCH-gcc" CXX="ccache $MINGW_ARCH-g++" LD=$MINGW_ARCH-ld -./configure --host=$MINGW_ARCH --prefix=/usr/$MINGW_ARCH && make -j2 && sudo make install) -ln -s /usr/$MINGW_ARCH/bin/libsqlite3-0.dll $WINE_SYSDIR - -# prepare build files -./autogen.sh -# autoconf build -mkdir build_autoconf -cd build_autoconf -CC="ccache $MINGW_ARCH-gcc" CXX="ccache $MINGW_ARCH-g++" LD=$MINGW_ARCH-ld ../configure --host=$MINGW_ARCH --prefix=/tmp/proj_autoconf_install --without-curl -make -j2 -make install -make dist-all -find /tmp/proj_autoconf_install -(cd test; make -j2) -cp -r ../data/tests /tmp/proj_autoconf_install/share/proj -cp ../data/tests/egm96_15_downsampled.gtx /tmp/proj_autoconf_install/share/proj/egm96_15.gtx -cp ../data/tests/ntv2_0_downsampled.gsb /tmp/proj_autoconf_install/share/proj/ntv2_0.gsb -test/unit/test_cpp_api.exe -- cgit v1.2.3 From 452f1dbb258b573c97ad0083a891b43d0b543cd1 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Tue, 24 Nov 2020 01:04:23 +0100 Subject: mutex.cpp: replace NULL by nullptr --- src/mutex.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/mutex.cpp b/src/mutex.cpp index da415e55..60ed5be1 100644 --- a/src/mutex.cpp +++ b/src/mutex.cpp @@ -184,7 +184,7 @@ void pj_cleanup_lock() #include -static HANDLE mutex_lock = NULL; +static HANDLE mutex_lock = nullptr; #if _WIN32_WINNT >= 0x0600 @@ -199,7 +199,7 @@ static BOOL CALLBACK pj_create_lock(PINIT_ONCE InitOnce, (void)InitOnce; (void)Parameter; (void)Context; - mutex_lock = CreateMutex( NULL, FALSE, NULL ); + mutex_lock = CreateMutex( nullptr, FALSE, nullptr ); return TRUE; } #endif @@ -213,10 +213,10 @@ static void pj_init_lock() { #if _WIN32_WINNT >= 0x0600 static INIT_ONCE sInitOnce = INIT_ONCE_STATIC_INIT; - InitOnceExecuteOnce( &sInitOnce, pj_create_lock, NULL, NULL ); + InitOnceExecuteOnce( &sInitOnce, pj_create_lock, nullptr, nullptr ); #else - if( mutex_lock == NULL ) - mutex_lock = CreateMutex( NULL, FALSE, NULL ); + if( mutex_lock == nullptr ) + mutex_lock = CreateMutex( nullptr, FALSE, nullptr ); #endif } @@ -228,7 +228,7 @@ static void pj_init_lock() void pj_acquire_lock() { - if( mutex_lock == NULL ) + if( mutex_lock == nullptr ) pj_init_lock(); WaitForSingleObject( mutex_lock, INFINITE ); @@ -242,7 +242,7 @@ void pj_acquire_lock() void pj_release_lock() { - if( mutex_lock == NULL ) + if( mutex_lock == nullptr ) pj_init_lock(); else ReleaseMutex( mutex_lock ); @@ -253,10 +253,10 @@ void pj_release_lock() /************************************************************************/ void pj_cleanup_lock() { - if( mutex_lock != NULL ) + if( mutex_lock != nullptr ) { CloseHandle( mutex_lock ); - mutex_lock = NULL; + mutex_lock = nullptr; } } -- cgit v1.2.3 From 2414eb2bb655588b4b7e9fe86bba70592bd7f911 Mon Sep 17 00:00:00 2001 From: Charles Karney Date: Mon, 23 Nov 2020 19:13:24 -0500 Subject: Sync w GeographicLib 1.51. Remove C99 compatibility functions. (#2445) Should be no changes in the compiled code. --- src/geodesic.c | 149 ++++++++------------------------------------------------- src/geodesic.h | 6 +-- 2 files changed, 22 insertions(+), 133 deletions(-) diff --git a/src/geodesic.c b/src/geodesic.c index 7d612d3f..53ec9ed6 100644 --- a/src/geodesic.c +++ b/src/geodesic.c @@ -18,7 +18,7 @@ * * See the comments in geodesic.h for documentation. * - * Copyright (c) Charles Karney (2012-2019) and licensed + * Copyright (c) Charles Karney (2012-2020) and licensed * under the MIT/X11 License. For more information, see * https://geographiclib.sourceforge.io/ */ @@ -28,15 +28,6 @@ #include #include -#if !defined(HAVE_C99_MATH) -#if defined(PROJ_LIB) -/* PROJ requires C99 so HAVE_C99_MATH is implicit */ -#define HAVE_C99_MATH 1 -#else -#define HAVE_C99_MATH 0 -#endif -#endif - #if !defined(__cplusplus) #define nullptr 0 #endif @@ -88,19 +79,7 @@ static void Init() { tolb = tol0 * tol2; xthresh = 1000 * tol2; degree = pi/180; -#if defined(NAN) - NaN = NAN; /* NAN is defined in C99 */ -#else -#if HAVE_C99_MATH NaN = nan("0"); -#else - { - real minus1 = -1; - /* cppcheck-suppress wrongmathcall */ - NaN = sqrt(minus1); - } -#endif -#endif init = 1; } } @@ -116,95 +95,6 @@ enum captype { OUT_ALL = 0x7F80U }; -#if HAVE_C99_MATH -#define hypotx hypot -/* no need to redirect log1px, since it's only used by atanhx */ -#define atanhx atanh -#define copysignx copysign -#define cbrtx cbrt -#define remainderx remainder -#define remquox remquo -#else -/* Replacements for C99 math functions */ - -static real hypotx(real x, real y) { - x = fabs(x); y = fabs(y); - if (x < y) { - x /= y; /* y is nonzero */ - return y * sqrt(1 + x * x); - } else { - y /= (x != 0 ? x : 1); - return x * sqrt(1 + y * y); - } -} - -static real log1px(real x) { - volatile real - y = 1 + x, - z = y - 1; - /* Here's the explanation for this magic: y = 1 + z, exactly, and z - * approx x, thus log(y)/z (which is nearly constant near z = 0) returns - * a good approximation to the true log(1 + x)/x. The multiplication x * - * (log(y)/z) introduces little additional error. */ - return z == 0 ? x : x * log(y) / z; -} - -static real atanhx(real x) { - real y = fabs(x); /* Enforce odd parity */ - y = log1px(2 * y/(1 - y))/2; - return x > 0 ? y : (x < 0 ? -y : x); /* atanh(-0.0) = -0.0 */ -} - -static real copysignx(real x, real y) { - /* 1/y trick to get the sign of -0.0 */ - return fabs(x) * (y < 0 || (y == 0 && 1/y < 0) ? -1 : 1); -} - -static real cbrtx(real x) { - real y = pow(fabs(x), 1/(real)(3)); /* Return the real cube root */ - return x > 0 ? y : (x < 0 ? -y : x); /* cbrt(-0.0) = -0.0 */ -} - -static real remainderx(real x, real y) { - real z; - y = fabs(y); /* The result doesn't depend on the sign of y */ - z = fmod(x, y); - if (z == 0) - /* This shouldn't be necessary. However, before version 14 (2015), - * Visual Studio had problems dealing with -0.0. Specifically - * VC 10,11,12 and 32-bit compile: fmod(-0.0, 360.0) -> +0.0 - * python 2.7 on Windows 32-bit machines has the same problem. */ - z = copysignx(z, x); - else if (2 * fabs(z) == y) - z -= fmod(x, 2 * y) - z; /* Implement ties to even */ - else if (2 * fabs(z) > y) - z += (z < 0 ? y : -y); /* Fold remaining cases to (-y/2, y/2) */ - return z; -} - -static real remquox(real x, real y, int* n) { - real z = remainderx(x, y); - if (n) { - real - a = remainderx(x, 2 * y), - b = remainderx(x, 4 * y), - c = remainderx(x, 8 * y); - *n = (a > z ? 1 : (a < z ? -1 : 0)); - *n += (b > a ? 2 : (b < a ? -2 : 0)); - *n += (c > b ? 4 : (c < b ? -4 : 0)); - if (y < 0) *n *= -1; - if (y != 0) { - if (x/y > 0 && *n <= 0) - *n += 8; - else if (x/y < 0 && *n >= 0) - *n -= 8; - } - } - return z; -} - -#endif - static real sq(real x) { return x * x; } static real sumx(real u, real v, real* t) { @@ -237,13 +127,13 @@ static void swapx(real* x, real* y) { real t = *x; *x = *y; *y = t; } static void norm2(real* sinx, real* cosx) { - real r = hypotx(*sinx, *cosx); + real r = hypot(*sinx, *cosx); *sinx /= r; *cosx /= r; } static real AngNormalize(real x) { - x = remainderx(x, (real)(360)); + x = remainder(x, (real)(360)); return x != -180 ? x : 180; } @@ -275,7 +165,7 @@ static void sincosdx(real x, real* sinx, real* cosx) { /* In order to minimize round-off errors, this function exactly reduces * the argument to the range [-45, 45] before converting it to radians. */ real r, s, c; int q; - r = remquox(x, (real)(90), &q); + r = remquo(x, (real)(90), &q); /* now abs(r) <= 45 */ r *= degree; /* Possibly could call the gnu extension sincos */ @@ -396,7 +286,7 @@ void geod_init(struct geod_geodesic* g, real a, real f) { g->b = g->a * g->f1; g->c2 = (sq(g->a) + sq(g->b) * (g->e2 == 0 ? 1 : - (g->e2 > 0 ? atanhx(sqrt(g->e2)) : atan(sqrt(-g->e2))) / + (g->e2 > 0 ? atanh(sqrt(g->e2)) : atan(sqrt(-g->e2))) / sqrt(fabs(g->e2))))/2; /* authalic radius squared */ /* The sig12 threshold for "really short". Using the auxiliary sphere * solution with dnm computed at (bet1 + bet2) / 2, the relative error in the @@ -446,7 +336,7 @@ static void geod_lineinit_int(struct geod_geodesicline* l, l->salp0 = l->salp1 * cbet1; /* alp0 in [0, pi/2 - |bet1|] */ /* Alt: calp0 = hypot(sbet1, calp1 * cbet1). The following * is slightly better (consider the case salp1 = 0). */ - l->calp0 = hypotx(l->calp1, l->salp1 * sbet1); + l->calp0 = hypot(l->calp1, l->salp1 * sbet1); /* Evaluate sig with tan(bet1) = tan(sig1) * cos(alp1). * sig = 0 is nearest northward crossing of equator. * With bet1 = 0, alp1 = pi/2, we have sig1 = 0 (equatorial line). @@ -550,9 +440,8 @@ real geod_genposition(const struct geod_geodesicline* l, (pS12 ? GEOD_AREA : GEOD_NONE); outmask &= l->caps & OUT_ALL; - if (!( /*Init() &&*/ - (flags & GEOD_ARCMODE || (l->caps & (GEOD_DISTANCE_IN & OUT_ALL))) )) - /* Uninitialized or impossible distance calculation requested */ + if (!( (flags & GEOD_ARCMODE || (l->caps & (GEOD_DISTANCE_IN & OUT_ALL))) )) + /* Impossible distance calculation requested */ return NaN; if (flags & GEOD_ARCMODE) { @@ -617,7 +506,7 @@ real geod_genposition(const struct geod_geodesicline* l, /* sin(bet2) = cos(alp0) * sin(sig2) */ sbet2 = l->calp0 * ssig2; /* Alt: cbet2 = hypot(csig2, salp0 * ssig2); */ - cbet2 = hypotx(l->salp0, l->calp0 * csig2); + cbet2 = hypot(l->salp0, l->calp0 * csig2); if (cbet2 == 0) /* I.e., salp0 = 0, csig2 = 0. Break the degeneracy in this case */ cbet2 = csig2 = tiny; @@ -630,7 +519,7 @@ real geod_genposition(const struct geod_geodesicline* l, s12_a12; if (outmask & GEOD_LONGITUDE) { - real E = copysignx(1, l->salp0); /* east or west going? */ + real E = copysign(1, l->salp0); /* east or west going? */ /* tan(omg2) = sin(alp0) * tan(sig2) */ somg2 = l->salp0 * ssig2; comg2 = csig2; /* No need to normalize */ /* omg12 = omg2 - omg1 */ @@ -1045,7 +934,7 @@ static real geod_geninverse_int(const struct geod_geodesic* g, real /* From Lambda12: sin(alp1) * cos(bet1) = sin(alp0) */ salp0 = salp1 * cbet1, - calp0 = hypotx(calp1, salp1 * sbet1); /* calp0 > 0 */ + calp0 = hypot(calp1, salp1 * sbet1); /* calp0 > 0 */ real alp12; if (calp0 != 0 && salp0 != 0) { real @@ -1279,8 +1168,8 @@ real Astroid(real x, real y) { * of precision due to cancellation. The result is unchanged because * of the way the T is used in definition of u. */ T3 += T3 < 0 ? -sqrt(disc) : sqrt(disc); /* T3 = (r * t)^3 */ - /* N.B. cbrtx always returns the real root. cbrtx(-8) = -2. */ - T = cbrtx(T3); /* T = r * t */ + /* N.B. cbrt always returns the real root. cbrt(-8) = -2. */ + T = cbrt(T3); /* T = r * t */ /* T can be zero; but then r2 / T -> 0. */ u += T + (T != 0 ? r2 / T : 0); } else { @@ -1348,7 +1237,7 @@ real InverseStart(const struct geod_geodesic* g, sbet12 + cbet2 * sbet1 * sq(somg12) / (1 + comg12) : sbet12a - cbet2 * sbet1 * sq(somg12) / (1 - comg12); - ssig12 = hypotx(salp1, calp1); + ssig12 = hypot(salp1, calp1); csig12 = sbet1 * sbet2 + cbet1 * cbet2 * comg12; if (shortline && ssig12 < g->etol2) { @@ -1500,7 +1389,7 @@ real Lambda12(const struct geod_geodesic* g, /* sin(alp1) * cos(bet1) = sin(alp0) */ salp0 = salp1 * cbet1; - calp0 = hypotx(calp1, salp1 * sbet1); /* calp0 > 0 */ + calp0 = hypot(calp1, salp1 * sbet1); /* calp0 > 0 */ /* tan(bet1) = tan(sig1) * cos(alp1) * tan(omg1) = sin(alp0) * tan(sig1) = tan(omg1)=tan(alp1)*sin(bet1) */ @@ -1850,8 +1739,8 @@ int transit(real lon1, real lon2) { int transitdirect(real lon1, real lon2) { /* Compute exactly the parity of int(ceil(lon2 / 360)) - int(ceil(lon1 / 360)) */ - lon1 = remainderx(lon1, (real)(720)); - lon2 = remainderx(lon2, (real)(720)); + lon1 = remainder(lon1, (real)(720)); + lon2 = remainder(lon2, (real)(720)); return ( (lon2 <= 0 && lon2 > -360 ? 1 : 0) - (lon1 <= 0 && lon1 > -360 ? 1 : 0) ); } @@ -1891,7 +1780,7 @@ void accneg(real s[]) { void accrem(real s[], real y) { /* Reduce to [-y/2, y/2]. */ - s[0] = remainderx(s[0], y); + s[0] = remainder(s[0], y); accadd(s, (real)(0)); } @@ -2093,7 +1982,7 @@ real areareduceA(real area[], real area0, real areareduceB(real area, real area0, int crossings, boolx reverse, boolx sign) { - area = remainderx(area, area0); + area = remainder(area, area0); if (crossings & 1) area += (area < 0 ? 1 : -1) * area0/2; /* area is with the clockwise sense. If !reverse convert to diff --git a/src/geodesic.h b/src/geodesic.h index b21e6c8c..548fbf47 100644 --- a/src/geodesic.h +++ b/src/geodesic.h @@ -107,12 +107,12 @@ * twice about restructuring the internals of the C code since this may make * porting fixes from the C++ code more difficult. * - * Copyright (c) Charles Karney (2012-2019) and licensed + * Copyright (c) Charles Karney (2012-2020) and licensed * under the MIT/X11 License. For more information, see * https://geographiclib.sourceforge.io/ * * This library was distributed with - * GeographicLib 1.50. + * GeographicLib 1.51. **********************************************************************/ #if !defined(GEODESIC_H) @@ -127,7 +127,7 @@ * The minor version of the geodesic library. (This tracks the version of * GeographicLib.) **********************************************************************/ -#define GEODESIC_VERSION_MINOR 50 +#define GEODESIC_VERSION_MINOR 51 /** * The patch level of the geodesic library. (This tracks the version of * GeographicLib.) -- cgit v1.2.3 From d6f6862352d0caeb827c0c3ec98ccf9aa2f9a1d2 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Tue, 24 Nov 2020 16:41:06 +0100 Subject: createOperation(): add a ballpark vertical transformation when dealing with GEOIDMODEL[] --- src/iso19111/coordinateoperation.cpp | 99 +++++++++++++++++++++++++++++++----- test/cli/testprojinfo_out.dist | 69 +++++++++++++++++++++++-- test/unit/test_c_api.cpp | 49 +++++++++++++----- test/unit/test_operation.cpp | 12 ++--- 4 files changed, 194 insertions(+), 35 deletions(-) diff --git a/src/iso19111/coordinateoperation.cpp b/src/iso19111/coordinateoperation.cpp index 1d3b7a90..0f1c680b 100644 --- a/src/iso19111/coordinateoperation.cpp +++ b/src/iso19111/coordinateoperation.cpp @@ -11233,6 +11233,12 @@ struct CoordinateOperationFactory::Private { const crs::GeographicCRS *geogDst, std::vector &res); + static void createOperationsVertToGeogBallpark( + const crs::CRSNNPtr &sourceCRS, const crs::CRSNNPtr &targetCRS, + Private::Context &context, const crs::VerticalCRS *vertSrc, + const crs::GeographicCRS *geogDst, + std::vector &res); + static void createOperationsBoundToBound( const crs::CRSNNPtr &sourceCRS, const crs::CRSNNPtr &targetCRS, Private::Context &context, const crs::BoundCRS *boundSrc, @@ -11334,6 +11340,7 @@ struct PrecomputedOpCharacteristics { bool gridsKnown_ = false; size_t stepCount_ = 0; bool isApprox_ = false; + bool hasBallparkVertical_ = false; bool isNullTransformation_ = false; PrecomputedOpCharacteristics() = default; @@ -11341,10 +11348,12 @@ struct PrecomputedOpCharacteristics { bool isPROJExportable, bool hasGrids, bool gridsAvailable, bool gridsKnown, size_t stepCount, bool isApprox, + bool hasBallparkVertical, bool isNullTransformation) : area_(area), accuracy_(accuracy), isPROJExportable_(isPROJExportable), hasGrids_(hasGrids), gridsAvailable_(gridsAvailable), gridsKnown_(gridsKnown), stepCount_(stepCount), isApprox_(isApprox), + hasBallparkVertical_(hasBallparkVertical), isNullTransformation_(isNullTransformation) {} }; @@ -11388,6 +11397,15 @@ struct SortFunction { return false; } + if (!iterA->second.hasBallparkVertical_ && + iterB->second.hasBallparkVertical_) { + return true; + } + if (iterA->second.hasBallparkVertical_ && + !iterB->second.hasBallparkVertical_) { + return false; + } + if (!iterA->second.isNullTransformation_ && iterB->second.isNullTransformation_) { return true; @@ -11654,7 +11672,9 @@ struct FilterResults { ? CoordinateOperationContext::SpatialCriterion:: STRICT_CONTAINMENT : context->getSpatialCriterion(); - bool hasFoundOpWithExtent = false; + bool hasOnlyBallpark = true; + bool hasNonBallparkWithoutExtent = false; + bool hasNonBallparkOpWithExtent = false; const bool allowBallpark = context->getAllowBallparkTransformations(); for (const auto &op : sourceList) { if (desiredAccuracy != 0) { @@ -11669,9 +11689,15 @@ struct FilterResults { if (areaOfInterest) { bool emptyIntersection = false; auto extent = getExtent(op, true, emptyIntersection); - if (!extent) + if (!extent) { + if (!op->hasBallparkTransformation()) { + hasNonBallparkWithoutExtent = true; + } continue; - hasFoundOpWithExtent = true; + } + if (!op->hasBallparkTransformation()) { + hasNonBallparkOpWithExtent = true; + } bool extentContains = extent->contains(NN_NO_CHECK(areaOfInterest)); if (!hasOpThatContainsAreaOfInterestAndNoGrid && @@ -11698,9 +11724,15 @@ struct FilterResults { BOTH) { bool emptyIntersection = false; auto extent = getExtent(op, true, emptyIntersection); - if (!extent) + if (!extent) { + if (!op->hasBallparkTransformation()) { + hasNonBallparkWithoutExtent = true; + } continue; - hasFoundOpWithExtent = true; + } + if (!op->hasBallparkTransformation()) { + hasNonBallparkOpWithExtent = true; + } bool extentContainsExtent1 = !extent1 || extent->contains(NN_NO_CHECK(extent1)); bool extentContainsExtent2 = @@ -11730,12 +11762,16 @@ struct FilterResults { } } } + if (!op->hasBallparkTransformation()) { + hasOnlyBallpark = false; + } res.emplace_back(op); } // In case no operation has an extent and no result is found, // retain all initial operations that match accuracy criterion. - if (res.empty() && !hasFoundOpWithExtent) { + if ((res.empty() && !hasNonBallparkOpWithExtent) || + (hasOnlyBallpark && hasNonBallparkWithoutExtent)) { for (const auto &op : sourceList) { if (desiredAccuracy != 0) { const double accuracy = getAccuracy(op); @@ -11839,6 +11875,8 @@ struct FilterResults { area, getAccuracy(op), isPROJExportable, hasGrids, gridsAvailable, gridsKnown, stepCount, op->hasBallparkTransformation(), + op->nameStr().find("ballpark vertical transformation") != + std::string::npos, isNullTransformation(op->nameStr())); } @@ -13647,11 +13685,17 @@ bool CoordinateOperationFactory::Private::createOperationsFromDatabase( ENTER_FUNCTION(); if (geogSrc && vertDst) { - res = createOperationsGeogToVertFromGeoid(sourceCRS, targetCRS, vertDst, - context); + createOperationsFromDatabase(targetCRS, sourceCRS, context, geodDst, + geodSrc, geogDst, geogSrc, vertDst, + vertSrc, res); + res = applyInverse(res); } else if (geogDst && vertSrc) { res = applyInverse(createOperationsGeogToVertFromGeoid( targetCRS, sourceCRS, vertSrc, context)); + if (!res.empty()) { + createOperationsVertToGeogBallpark(sourceCRS, targetCRS, context, + vertSrc, geogDst, res); + } } if (!res.empty()) { @@ -14762,17 +14806,32 @@ void CoordinateOperationFactory::Private::createOperationsVertToGeog( match.get(), util::IComparable::Criterion::EQUIVALENT) && !match->identifiers().empty()) { - res = createOperations( + auto resTmp = createOperations( NN_NO_CHECK( util::nn_dynamic_pointer_cast( match)), targetCRS, context); + res.insert(res.end(), resTmp.begin(), resTmp.end()); return; } } } } + createOperationsVertToGeogBallpark(sourceCRS, targetCRS, context, vertSrc, + geogDst, res); +} + +// --------------------------------------------------------------------------- + +void CoordinateOperationFactory::Private::createOperationsVertToGeogBallpark( + const crs::CRSNNPtr &sourceCRS, const crs::CRSNNPtr &targetCRS, + Private::Context &, const crs::VerticalCRS *vertSrc, + const crs::GeographicCRS *geogDst, + std::vector &res) { + + ENTER_FUNCTION(); + const auto &srcAxis = vertSrc->coordinateSystem()->axisList()[0]; const double convSrc = srcAxis->unit().conversionToSI(); double convDst = 1.0; @@ -14791,12 +14850,24 @@ void CoordinateOperationFactory::Private::createOperationsVertToGeog( ((srcIsUp && dstIsDown) || (srcIsDown && dstIsUp)); const double factor = convSrc / convDst; - auto conv = Transformation::createChangeVerticalUnit( - util::PropertyMap().set( - common::IdentifiedObject::NAME_KEY, + + const auto &sourceCRSExtent = getExtent(sourceCRS); + const auto &targetCRSExtent = getExtent(targetCRS); + const bool sameExtent = + sourceCRSExtent && targetCRSExtent && + sourceCRSExtent->_isEquivalentTo( + targetCRSExtent.get(), util::IComparable::Criterion::EQUIVALENT); + + util::PropertyMap map; + map.set(common::IdentifiedObject::NAME_KEY, buildTransfName(sourceCRS->nameStr(), targetCRS->nameStr()) + - BALLPARK_VERTICAL_TRANSFORMATION_NO_ELLIPSOID_VERT_HEIGHT), - sourceCRS, targetCRS, + BALLPARK_VERTICAL_TRANSFORMATION_NO_ELLIPSOID_VERT_HEIGHT) + .set(common::ObjectUsage::DOMAIN_OF_VALIDITY_KEY, + sameExtent ? NN_NO_CHECK(sourceCRSExtent) + : metadata::Extent::WORLD); + + auto conv = Transformation::createChangeVerticalUnit( + map, sourceCRS, targetCRS, common::Scale(heightDepthReversal ? -factor : factor), {}); conv->setHasBallparkTransformation(true); res.push_back(conv); diff --git a/test/cli/testprojinfo_out.dist b/test/cli/testprojinfo_out.dist index 174f11d3..8e8ef294 100644 --- a/test/cli/testprojinfo_out.dist +++ b/test/cli/testprojinfo_out.dist @@ -990,7 +990,7 @@ PROJ.4 string: +proj=utm +zone=32 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs +type=crs Testing RH2000 height to SWEREF99: projinfo -s EPSG:5613 -t EPSG:4977 -Candidate operations found: 1 +Candidate operations found: 2 ------------------------------------- Operation No. 1: @@ -1042,8 +1042,55 @@ COORDINATEOPERATION["Inverse of SWEREF99 to RH2000 height", BBOX[55.28,10.93,69.07,24.17]], ID["INVERSE(DERIVED_FROM(PROJ))","EPSG_4977_TO_EPSG_5613"]] +------------------------------------- +Operation No. 2: + +unknown id, Transformation from RH2000 height to SWEREF99 (ballpark vertical transformation, without ellipsoid height to vertical height correction), unknown accuracy, World, has ballpark transformation + +PROJ string: ++proj=noop + +WKT2:2019 string: +COORDINATEOPERATION["Transformation from RH2000 height to SWEREF99 (ballpark vertical transformation, without ellipsoid height to vertical height correction)", + SOURCECRS[ + VERTCRS["RH2000 height", + DYNAMIC[ + FRAMEEPOCH[2000]], + VDATUM["Rikets hojdsystem 2000"], + CS[vertical,1], + AXIS["gravity-related height (H)",up, + LENGTHUNIT["metre",1]], + ID["EPSG",5613]]], + TARGETCRS[ + GEOGCRS["SWEREF99", + DATUM["SWEREF99", + ELLIPSOID["GRS 1980",6378137,298.257222101, + LENGTHUNIT["metre",1]]], + PRIMEM["Greenwich",0, + ANGLEUNIT["degree",0.0174532925199433]], + CS[ellipsoidal,3], + AXIS["geodetic latitude (Lat)",north, + ORDER[1], + ANGLEUNIT["degree",0.0174532925199433]], + AXIS["geodetic longitude (Lon)",east, + ORDER[2], + ANGLEUNIT["degree",0.0174532925199433]], + AXIS["ellipsoidal height (h)",up, + ORDER[3], + LENGTHUNIT["metre",1]], + ID["EPSG",4977]]], + METHOD["Change of Vertical Unit", + ID["EPSG",1069]], + PARAMETER["Unit conversion scalar",1, + SCALEUNIT["unity",1], + ID["EPSG",1051]], + USAGE[ + SCOPE["unknown"], + AREA["World"], + BBOX[-90,-180,90,180]]] + Testing NAD83(2011) + NAVD88 height -> NAD83(2011) : projinfo -s EPSG:6349 -t EPSG:6319 --spatial-test intersects -o PROJ -Candidate operations found: 2 +Candidate operations found: 3 ------------------------------------- Operation No. 1: @@ -1070,8 +1117,16 @@ PROJ string: +step +proj=unitconvert +xy_in=rad +xy_out=deg +step +proj=axisswap +order=2,1 +------------------------------------- +Operation No. 3: + +unknown id, Transformation from NAVD88 height to NAD83(2011) (ballpark vertical transformation, without ellipsoid height to vertical height correction), unknown accuracy, World, has ballpark transformation + +PROJ string: ++proj=noop + Testing NGF IGN69 height to RGF93: projinfo -s EPSG:5720 -t EPSG:4965 -o PROJ -Candidate operations found: 1 +Candidate operations found: 2 ------------------------------------- Operation No. 1: @@ -1085,6 +1140,14 @@ PROJ string: +step +proj=unitconvert +xy_in=rad +xy_out=deg +step +proj=axisswap +order=2,1 +------------------------------------- +Operation No. 2: + +unknown id, Transformation from NGF-IGN69 height to RGF93 (ballpark vertical transformation, without ellipsoid height to vertical height correction), unknown accuracy, World, has ballpark transformation + +PROJ string: ++proj=noop + Testing EPSG:32631 --3d PROJ.4 string: +proj=utm +zone=31 +datum=WGS84 +units=m +no_defs +type=crs diff --git a/test/unit/test_c_api.cpp b/test/unit/test_c_api.cpp index a7c1eb53..9885d221 100644 --- a/test/unit/test_c_api.cpp +++ b/test/unit/test_c_api.cpp @@ -4650,10 +4650,21 @@ TEST_F(CApi, proj_create_vertical_crs_ex) { ObjectKeeper keeper_geog_crs(geog_crs); ASSERT_NE(geog_crs, nullptr); - auto P = proj_create_crs_to_crs_from_pj(m_ctxt, compound, geog_crs, nullptr, - nullptr); - ObjectKeeper keeper_P(P); - ASSERT_NE(P, nullptr); + PJ_OPERATION_FACTORY_CONTEXT *ctxt = + proj_create_operation_factory_context(m_ctxt, nullptr); + ASSERT_NE(ctxt, nullptr); + ContextKeeper keeper_ctxt(ctxt); + proj_operation_factory_context_set_grid_availability_use( + m_ctxt, ctxt, PROJ_GRID_AVAILABILITY_IGNORED); + proj_operation_factory_context_set_spatial_criterion( + m_ctxt, ctxt, PROJ_SPATIAL_CRITERION_PARTIAL_INTERSECTION); + PJ_OBJ_LIST *operations = + proj_create_operations(m_ctxt, compound, geog_crs, ctxt); + ASSERT_NE(operations, nullptr); + ObjListKeeper keeper_operations(operations); + EXPECT_GE(proj_list_get_count(operations), 1); + auto P = proj_list_get(m_ctxt, operations, 0); + ObjectKeeper keeper_transform(P); auto name = proj_get_name(P); ASSERT_TRUE(name != nullptr); @@ -4706,10 +4717,21 @@ TEST_F(CApi, proj_create_vertical_crs_ex_with_geog_crs) { ObjectKeeper keeper_geog_crs(geog_crs); ASSERT_NE(geog_crs, nullptr); - auto P = proj_create_crs_to_crs_from_pj(m_ctxt, compound, geog_crs, nullptr, - nullptr); - ObjectKeeper keeper_P(P); - ASSERT_NE(P, nullptr); + PJ_OPERATION_FACTORY_CONTEXT *ctxt = + proj_create_operation_factory_context(m_ctxt, nullptr); + ASSERT_NE(ctxt, nullptr); + ContextKeeper keeper_ctxt(ctxt); + proj_operation_factory_context_set_grid_availability_use( + m_ctxt, ctxt, PROJ_GRID_AVAILABILITY_IGNORED); + proj_operation_factory_context_set_spatial_criterion( + m_ctxt, ctxt, PROJ_SPATIAL_CRITERION_PARTIAL_INTERSECTION); + PJ_OBJ_LIST *operations = + proj_create_operations(m_ctxt, compound, geog_crs, ctxt); + ASSERT_NE(operations, nullptr); + ObjListKeeper keeper_operations(operations); + EXPECT_GE(proj_list_get_count(operations), 1); + auto P = proj_list_get(m_ctxt, operations, 0); + ObjectKeeper keeper_transform(P); auto name = proj_get_name(P); ASSERT_TRUE(name != nullptr); @@ -4739,10 +4761,13 @@ TEST_F(CApi, proj_create_vertical_crs_ex_with_geog_crs) { ObjectKeeper keeper_compound_from_projjson(compound_from_projjson); ASSERT_NE(compound_from_projjson, nullptr); - auto P2 = proj_create_crs_to_crs_from_pj(m_ctxt, compound_from_projjson, - geog_crs, nullptr, nullptr); - ObjectKeeper keeper_P2(P2); - ASSERT_NE(P2, nullptr); + PJ_OBJ_LIST *operations2 = + proj_create_operations(m_ctxt, compound_from_projjson, geog_crs, ctxt); + ASSERT_NE(operations2, nullptr); + ObjListKeeper keeper_operations2(operations2); + EXPECT_GE(proj_list_get_count(operations2), 1); + auto P2 = proj_list_get(m_ctxt, operations2, 0); + ObjectKeeper keeper_transform2(P2); auto name_bis = proj_get_name(P2); ASSERT_TRUE(name_bis != nullptr); diff --git a/test/unit/test_operation.cpp b/test/unit/test_operation.cpp index b6e555b1..9bf883d9 100644 --- a/test/unit/test_operation.cpp +++ b/test/unit/test_operation.cpp @@ -4867,7 +4867,7 @@ TEST(operation, vertCRS_to_geogCRS_context) { "3855"), // EGM2008 height authFactory->createCoordinateReferenceSystem("4979"), // WGS 84 ctxt); - ASSERT_EQ(list.size(), 2U); + ASSERT_EQ(list.size(), 3U); EXPECT_EQ( list[1]->exportToPROJString( PROJStringFormatter::create( @@ -4889,7 +4889,7 @@ TEST(operation, vertCRS_to_geogCRS_context) { "3855"), // EGM2008 height authFactory->createCoordinateReferenceSystem("4979"), // WGS 84 ctxt); - ASSERT_EQ(list.size(), 2U); + ASSERT_EQ(list.size(), 3U); EXPECT_EQ( list[0]->exportToPROJString(PROJStringFormatter::create().get()), "+proj=pipeline " @@ -4938,7 +4938,7 @@ TEST(operation, vertCRS_to_geogCRS_context) { authFactory->createCoordinateReferenceSystem("7839"), // NZGD2000 authFactory->createCoordinateReferenceSystem("4959"), ctxt); - ASSERT_EQ(list.size(), 1U); + ASSERT_EQ(list.size(), 2U); EXPECT_EQ( list[0]->exportToPROJString(PROJStringFormatter::create().get()), "+proj=pipeline " @@ -4964,7 +4964,7 @@ TEST(operation, vertCRS_to_geogCRS_context) { authFactory->createCoordinateReferenceSystem("8357"), // ETRS89 authFactory->createCoordinateReferenceSystem("4937"), ctxt); - ASSERT_EQ(list.size(), 1U); + ASSERT_EQ(list.size(), 2U); EXPECT_EQ( list[0]->exportToPROJString(PROJStringFormatter::create().get()), "+proj=pipeline " @@ -8912,7 +8912,7 @@ TEST(operation, compoundCRS_to_geogCRS_2D_promote_to_3D_context) { ctxt); // The checked value is not that important, but in case this changes, // likely due to a EPSG upgrade, worth checking - EXPECT_EQ(listCompoundToGeog2D.size(), 141U); + EXPECT_EQ(listCompoundToGeog2D.size(), 142U); auto listGeog2DToCompound = CoordinateOperationFactory::create()->createOperations(dst, nnSrc, @@ -11169,7 +11169,7 @@ TEST(operation, normalizeForVisualization) { src, authFactory->createCoordinateReferenceSystem("4979"), // WGS 84 3D ctxt); - ASSERT_EQ(list.size(), 2U); + ASSERT_EQ(list.size(), 3U); auto op = list[1]; auto opNormalized = op->normalizeForVisualization(); EXPECT_FALSE(opNormalized->_isEquivalentTo(op.get())); -- cgit v1.2.3 From 4caf32aedd4da6b1fd1b1ce0e04a1a08dc1e3f33 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Tue, 24 Nov 2020 19:16:12 +0100 Subject: Add option to allow export of Geographic/Projected 3D CRS in WKT1_GDAL as CompoundCRS with a VerticalCRS being an ellipsoidal height, which is not conformant. But needed for LAS 1.4 that only supports WKT1 --- docs/source/apps/projinfo.rst | 10 +++++ include/proj/io.hpp | 4 ++ scripts/reference_exported_symbols.txt | 2 + src/apps/projinfo.cpp | 7 ++++ src/iso19111/c_api.cpp | 12 ++++++ src/iso19111/crs.cpp | 43 ++++++++++++++++++++ src/iso19111/io.cpp | 25 ++++++++++++ test/unit/test_c_api.cpp | 15 ++++++- test/unit/test_crs.cpp | 72 ++++++++++++++++++++++++++++++++++ 9 files changed, 188 insertions(+), 2 deletions(-) diff --git a/docs/source/apps/projinfo.rst b/docs/source/apps/projinfo.rst index a07cf709..803c0a65 100644 --- a/docs/source/apps/projinfo.rst +++ b/docs/source/apps/projinfo.rst @@ -23,6 +23,7 @@ Synopsis | [--grid-check none|discard_missing|sort|known_available] | [--pivot-crs always|if_no_direct_transformation|never|{auth:code[,auth:code]*}] | [--show-superseded] [--hide-ballpark] + | [--allow-ellipsoidal-height-as-vertical-crs] | [--boundcrs-to-wgs84] | [--main-db-path path] [--aux-db-path path]* | [--identify] [--3d] @@ -212,6 +213,15 @@ The following control parameters can appear in any order: .. note:: only used for coordinate operation computation +.. option:: --allow-ellipsoidal-height-as-vertical-crs + + .. versionadded:: 8.0 + + Allow to export a geographic or projected 3D CRS as a compound CRS whose + vertical CRS represents the ellipsoidal height. + + .. note:: only used for CRS, and with WKT1:GDAL output format + .. option:: --boundcrs-to-wgs84 When specified, this option researches a coordinate operation from the diff --git a/include/proj/io.hpp b/include/proj/io.hpp index de8a90fc..bc11c220 100644 --- a/include/proj/io.hpp +++ b/include/proj/io.hpp @@ -243,6 +243,10 @@ class PROJ_GCC_DLL WKTFormatter { PROJ_DLL WKTFormatter &setStrict(bool strict) noexcept; PROJ_DLL bool isStrict() const noexcept; + PROJ_DLL WKTFormatter & + setAllowEllipsoidalHeightAsVerticalCRS(bool allow) noexcept; + PROJ_DLL bool isAllowedEllipsoidalHeightAsVerticalCRS() const noexcept; + PROJ_DLL const std::string &toString() const; PROJ_PRIVATE : diff --git a/scripts/reference_exported_symbols.txt b/scripts/reference_exported_symbols.txt index 8db49a95..b4576ac1 100644 --- a/scripts/reference_exported_symbols.txt +++ b/scripts/reference_exported_symbols.txt @@ -422,7 +422,9 @@ osgeo::proj::io::PROJStringParser::setUsePROJ4InitRules(bool) osgeo::proj::io::PROJStringParser::warningList() const osgeo::proj::io::WKTFormatter::create(dropbox::oxygen::nn > > const&) osgeo::proj::io::WKTFormatter::create(osgeo::proj::io::WKTFormatter::Convention, std::shared_ptr) +osgeo::proj::io::WKTFormatter::isAllowedEllipsoidalHeightAsVerticalCRS() const osgeo::proj::io::WKTFormatter::isStrict() const +osgeo::proj::io::WKTFormatter::setAllowEllipsoidalHeightAsVerticalCRS(bool) osgeo::proj::io::WKTFormatter::setIndentationWidth(int) osgeo::proj::io::WKTFormatter::setMultiLine(bool) osgeo::proj::io::WKTFormatter::setOutputAxis(osgeo::proj::io::WKTFormatter::OutputAxisRule) diff --git a/src/apps/projinfo.cpp b/src/apps/projinfo.cpp index 3d57dcd6..da885fbb 100644 --- a/src/apps/projinfo.cpp +++ b/src/apps/projinfo.cpp @@ -72,6 +72,7 @@ struct OutputOptions { bool singleLine = false; bool strict = true; bool ballparkAllowed = true; + bool allowEllipsoidalHeightAsVerticalCRS = false; }; } // anonymous namespace @@ -95,6 +96,8 @@ static void usage() { << " [--pivot-crs always|if_no_direct_transformation|" << "never|{auth:code[,auth:code]*}]" << std::endl << " [--show-superseded] [--hide-ballpark]" << std::endl + << " [--allow-ellipsoidal-height-as-vertical-crs]" + << std::endl << " [--boundcrs-to-wgs84]" << std::endl << " [--main-db-path path] [--aux-db-path path]*" << std::endl @@ -487,6 +490,8 @@ static void outputObject( formatter->setMultiLine(false); } formatter->setStrict(outputOpt.strict); + formatter->setAllowEllipsoidalHeightAsVerticalCRS( + outputOpt.allowEllipsoidalHeightAsVerticalCRS); auto wkt = wktExportable->exportToWKT(formatter.get()); if (outputOpt.c_ify) { wkt = c_ify_string(wkt); @@ -1070,6 +1075,8 @@ int main(int argc, char **argv) { showSuperseded = true; } else if (arg == "--lax") { outputOpt.strict = false; + } else if (arg == "--allow-ellipsoidal-height-as-vertical-crs") { + outputOpt.allowEllipsoidalHeightAsVerticalCRS = true; } else if (arg == "--hide-ballpark") { outputOpt.ballparkAllowed = false; } else if (ci_equal(arg, "--3d")) { diff --git a/src/iso19111/c_api.cpp b/src/iso19111/c_api.cpp index cbbdcaa8..d3c01e8f 100644 --- a/src/iso19111/c_api.cpp +++ b/src/iso19111/c_api.cpp @@ -1421,6 +1421,13 @@ const char *proj_get_id_code(const PJ *obj, int index) { * variants, for WKT1_GDAL for ProjectedCRS with easting/northing ordering * (otherwise stripped), but not for WKT1_ESRI. Setting to YES will output * them unconditionally, and to NO will omit them unconditionally. + *
  • STRICT=YES/NO. Default is YES. If NO, a Geographic 3D CRS can be for + * example exported as WKT1_GDAL with 3 axes, whereas this is normally not + * allowed.
  • + *
  • ALLOW_ELLIPSOIDAL_HEIGHT_AS_VERTICAL_CRS=YES/NO. Default is NO. If set + * to YES and type == PJ_WKT1_GDAL, a Geographic 3D CRS or a Projected 3D CRS + * will be exported as a compound CRS whose vertical part represents an + * ellipsoidal height (for example for use with LAS 1.4 WKT1).
  • * * @return a string, or NULL in case of error. */ @@ -1471,6 +1478,11 @@ const char *proj_as_wkt(PJ_CONTEXT *ctx, const PJ *obj, PJ_WKT_TYPE type, } } else if ((value = getOptionValue(*iter, "STRICT="))) { formatter->setStrict(ci_equal(value, "YES")); + } else if ((value = getOptionValue( + *iter, + "ALLOW_ELLIPSOIDAL_HEIGHT_AS_VERTICAL_CRS="))) { + formatter->setAllowEllipsoidalHeightAsVerticalCRS( + ci_equal(value, "YES")); } else { std::string msg("Unknown option :"); msg += *iter; diff --git a/src/iso19111/crs.cpp b/src/iso19111/crs.cpp index 5d2c6d7b..573dd6db 100644 --- a/src/iso19111/crs.cpp +++ b/src/iso19111/crs.cpp @@ -1620,6 +1620,34 @@ static bool exportAsESRIWktCompoundCRSWithEllipsoidalHeight( vertCRSList.front()->_exportToWKT(formatter); return true; } + +// --------------------------------------------------------------------------- + +// Try to format a Geographic/ProjectedCRS 3D CRS as a +// GEOGCS[]/PROJCS[],VERTCS["Ellipsoid (metre)",DATUM["Ellipsoid",2002],...] +static bool exportAsWKT1CompoundCRSWithEllipsoidalHeight( + const CRSNNPtr &base2DCRS, + const cs::CoordinateSystemAxisNNPtr &verticalAxis, + io::WKTFormatter *formatter) { + std::string verticalCRSName = "Ellipsoid ("; + verticalCRSName += verticalAxis->unit().name(); + verticalCRSName += ')'; + auto vertDatum = datum::VerticalReferenceFrame::create( + util::PropertyMap() + .set(common::IdentifiedObject::NAME_KEY, "Ellipsoid") + .set("VERT_DATUM_TYPE", "2002")); + auto vertCRS = VerticalCRS::create( + util::PropertyMap().set(common::IdentifiedObject::NAME_KEY, + verticalCRSName), + vertDatum.as_nullable(), nullptr, + cs::VerticalCS::create(util::PropertyMap(), verticalAxis)); + formatter->startNode(io::WKTConstants::COMPD_CS, false); + formatter->addQuotedString(base2DCRS->nameStr() + " + " + verticalCRSName); + base2DCRS->_exportToWKT(formatter); + vertCRS->_exportToWKT(formatter); + formatter->endNode(); + return true; +} //! @endcond // --------------------------------------------------------------------------- @@ -1687,6 +1715,13 @@ void GeodeticCRS::_exportToWKT(io::WKTFormatter *formatter) const { return; } + if (formatter->isAllowedEllipsoidalHeightAsVerticalCRS()) { + if (exportAsWKT1CompoundCRSWithEllipsoidalHeight( + geogCRS2D, axisList[2], formatter)) { + return; + } + } + io::FormattingException::Throw( "WKT1 does not support Geographic 3D CRS."); } @@ -3640,6 +3675,14 @@ void ProjectedCRS::_exportToWKT(io::WKTFormatter *formatter) const { return; } + if (!formatter->useESRIDialect() && + formatter->isAllowedEllipsoidalHeightAsVerticalCRS()) { + if (exportAsWKT1CompoundCRSWithEllipsoidalHeight( + projCRS2D, axisList[2], formatter)) { + return; + } + } + io::FormattingException::Throw( "Projected 3D CRS can only be exported since WKT2:2019"); } diff --git a/src/iso19111/io.cpp b/src/iso19111/io.cpp index 713a471d..b6a09bb6 100644 --- a/src/iso19111/io.cpp +++ b/src/iso19111/io.cpp @@ -140,6 +140,7 @@ struct WKTFormatter::Private { bool primeMeridianInDegree_ = false; bool use2019Keywords_ = false; bool useESRIDialect_ = false; + bool allowEllipsoidalHeightAsVerticalCRS_ = false; OutputAxisRule outputAxis_ = WKTFormatter::OutputAxisRule::YES; }; Params params_{}; @@ -251,6 +252,8 @@ WKTFormatter::setOutputAxis(OutputAxisRule outputAxisIn) noexcept { * * The default is strict mode, in which case a FormattingException can be * thrown. + * In non-strict mode, a Geographic 3D CRS can be for example exported as + * WKT1_GDAL with 3 axes, whereas this is normally not allowed. */ WKTFormatter &WKTFormatter::setStrict(bool strictIn) noexcept { d->params_.strict_ = strictIn; @@ -264,6 +267,28 @@ bool WKTFormatter::isStrict() const noexcept { return d->params_.strict_; } // --------------------------------------------------------------------------- +/** \brief Set whether the formatter should export, in WKT1, a Geographic or + * Projected 3D CRS as a compound CRS whose vertical part represents an + * ellipsoidal height. + */ +WKTFormatter & +WKTFormatter::setAllowEllipsoidalHeightAsVerticalCRS(bool allow) noexcept { + d->params_.allowEllipsoidalHeightAsVerticalCRS_ = allow; + return *this; +} + +// --------------------------------------------------------------------------- + +/** \brief Return whether the formatter should export, in WKT1, a Geographic or + * Projected 3D CRS as a compound CRS whose vertical part represents an + * ellipsoidal height. + */ +bool WKTFormatter::isAllowedEllipsoidalHeightAsVerticalCRS() const noexcept { + return d->params_.allowEllipsoidalHeightAsVerticalCRS_; +} + +// --------------------------------------------------------------------------- + /** Returns the WKT string from the formatter. */ const std::string &WKTFormatter::toString() const { if (d->indentLevel_ > 0 || d->level_ > 0) { diff --git a/test/unit/test_c_api.cpp b/test/unit/test_c_api.cpp index 9885d221..c417371d 100644 --- a/test/unit/test_c_api.cpp +++ b/test/unit/test_c_api.cpp @@ -433,16 +433,27 @@ TEST_F(CApi, proj_as_wkt) { ObjectKeeper keeper_crs4979(crs4979); ASSERT_NE(crs4979, nullptr); + EXPECT_EQ(proj_as_wkt(m_ctxt, crs4979, PJ_WKT1_GDAL, nullptr), nullptr); + // STRICT=NO { - EXPECT_EQ(proj_as_wkt(m_ctxt, crs4979, PJ_WKT1_GDAL, nullptr), nullptr); - const char *const options[] = {"STRICT=NO", nullptr}; auto wkt = proj_as_wkt(m_ctxt, crs4979, PJ_WKT1_GDAL, options); ASSERT_NE(wkt, nullptr); EXPECT_TRUE(std::string(wkt).find("GEOGCS[\"WGS 84\"") == 0) << wkt; } + // ALLOW_ELLIPSOIDAL_HEIGHT_AS_VERTICAL_CRS=YES + { + const char *const options[] = { + "ALLOW_ELLIPSOIDAL_HEIGHT_AS_VERTICAL_CRS=YES", nullptr}; + auto wkt = proj_as_wkt(m_ctxt, crs4979, PJ_WKT1_GDAL, options); + ASSERT_NE(wkt, nullptr); + EXPECT_TRUE(std::string(wkt).find( + "COMPD_CS[\"WGS 84 + Ellipsoid (metre)\"") == 0) + << wkt; + } + // unsupported option { const char *const options[] = {"unsupported=yes", nullptr}; diff --git a/test/unit/test_crs.cpp b/test/unit/test_crs.cpp index e470a621..9c81d0cb 100644 --- a/test/unit/test_crs.cpp +++ b/test/unit/test_crs.cpp @@ -513,6 +513,34 @@ TEST(crs, EPSG_4979_as_WKT1_GDAL) { // --------------------------------------------------------------------------- +TEST(crs, EPSG_4979_as_WKT1_GDAL_with_ellipsoidal_height_as_vertical_crs) { + auto crs = GeographicCRS::EPSG_4979; + auto wkt = crs->exportToWKT( + &(WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL, + DatabaseContext::create()) + ->setAllowEllipsoidalHeightAsVerticalCRS(true))); + + // For LAS 1.4 WKT1... + EXPECT_EQ(wkt, "COMPD_CS[\"WGS 84 + Ellipsoid (metre)\",\n" + " GEOGCS[\"WGS 84\",\n" + " DATUM[\"WGS_1984\",\n" + " SPHEROID[\"WGS 84\",6378137,298.257223563,\n" + " AUTHORITY[\"EPSG\",\"7030\"]],\n" + " AUTHORITY[\"EPSG\",\"6326\"]],\n" + " PRIMEM[\"Greenwich\",0,\n" + " AUTHORITY[\"EPSG\",\"8901\"]],\n" + " UNIT[\"degree\",0.0174532925199433,\n" + " AUTHORITY[\"EPSG\",\"9122\"]],\n" + " AUTHORITY[\"EPSG\",\"4326\"]],\n" + " VERT_CS[\"Ellipsoid (metre)\",\n" + " VERT_DATUM[\"Ellipsoid\",2002],\n" + " UNIT[\"metre\",1,\n" + " AUTHORITY[\"EPSG\",\"9001\"]],\n" + " AXIS[\"Ellipsoidal height\",UP]]]"); +} + +// --------------------------------------------------------------------------- + TEST(crs, EPSG_4979_as_WKT1_ESRI) { auto crs = GeographicCRS::EPSG_4979; WKTFormatterNNPtr f( @@ -2037,6 +2065,50 @@ TEST(crs, projectedCRS_as_WKT1_ESRI) { // --------------------------------------------------------------------------- +TEST(crs, + projectedCRS_3D_as_WKT1_GDAL_with_ellipsoidal_height_as_vertical_crs) { + auto dbContext = DatabaseContext::create(); + auto crs = AuthorityFactory::create(dbContext, "EPSG") + ->createProjectedCRS("32631") + ->promoteTo3D(std::string(), dbContext); + auto wkt = crs->exportToWKT( + &(WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL, dbContext) + ->setAllowEllipsoidalHeightAsVerticalCRS(true))); + + // For LAS 1.4 WKT1... + EXPECT_EQ(wkt, + "COMPD_CS[\"WGS 84 / UTM zone 31N + Ellipsoid (metre)\",\n" + " PROJCS[\"WGS 84 / UTM zone 31N\",\n" + " GEOGCS[\"WGS 84\",\n" + " DATUM[\"WGS_1984\",\n" + " SPHEROID[\"WGS 84\",6378137,298.257223563,\n" + " AUTHORITY[\"EPSG\",\"7030\"]],\n" + " AUTHORITY[\"EPSG\",\"6326\"]],\n" + " PRIMEM[\"Greenwich\",0,\n" + " AUTHORITY[\"EPSG\",\"8901\"]],\n" + " UNIT[\"degree\",0.0174532925199433,\n" + " AUTHORITY[\"EPSG\",\"9122\"]],\n" + " AUTHORITY[\"EPSG\",\"4326\"]],\n" + " PROJECTION[\"Transverse_Mercator\"],\n" + " PARAMETER[\"latitude_of_origin\",0],\n" + " PARAMETER[\"central_meridian\",3],\n" + " PARAMETER[\"scale_factor\",0.9996],\n" + " PARAMETER[\"false_easting\",500000],\n" + " PARAMETER[\"false_northing\",0],\n" + " UNIT[\"metre\",1,\n" + " AUTHORITY[\"EPSG\",\"9001\"]],\n" + " AXIS[\"Easting\",EAST],\n" + " AXIS[\"Northing\",NORTH],\n" + " AUTHORITY[\"EPSG\",\"32631\"]],\n" + " VERT_CS[\"Ellipsoid (metre)\",\n" + " VERT_DATUM[\"Ellipsoid\",2002],\n" + " UNIT[\"metre\",1,\n" + " AUTHORITY[\"EPSG\",\"9001\"]],\n" + " AXIS[\"Ellipsoidal height\",UP]]]"); +} + +// --------------------------------------------------------------------------- + TEST(crs, projectedCRS_with_ESRI_code_as_WKT1_ESRI) { auto dbContext = DatabaseContext::create(); auto crs = AuthorityFactory::create(dbContext, "ESRI") -- cgit v1.2.3 From 7cce6e64441053915ddc41035eae8c9819bbe566 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Thu, 26 Nov 2020 19:07:52 +0100 Subject: Github action: add a clang static analyzer job --- .github/workflows/clang_static_analyzer.yml | 15 ++++++++ .github/workflows/clang_static_analyzer/start.sh | 44 ++++++++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 .github/workflows/clang_static_analyzer.yml create mode 100755 .github/workflows/clang_static_analyzer/start.sh diff --git a/.github/workflows/clang_static_analyzer.yml b/.github/workflows/clang_static_analyzer.yml new file mode 100644 index 00000000..47dfc4ad --- /dev/null +++ b/.github/workflows/clang_static_analyzer.yml @@ -0,0 +1,15 @@ +name: CLang Static Analyzer + +on: [push, pull_request] + +jobs: + + clang_static_analyzer: + runs-on: ubuntu-16.04 + if: "!contains(github.event.head_commit.message, '[ci skip]') && !contains(github.event.head_commit.message, '[skip ci]')" + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Run + run: .github/workflows/clang_static_analyzer/start.sh diff --git a/.github/workflows/clang_static_analyzer/start.sh b/.github/workflows/clang_static_analyzer/start.sh new file mode 100755 index 00000000..7063c42f --- /dev/null +++ b/.github/workflows/clang_static_analyzer/start.sh @@ -0,0 +1,44 @@ +#!/bin/bash + +set -e + +DEBIAN_FRONTEND=noninteractive sudo apt-get install -y --no-install-recommends \ + autoconf automake libtool g++ make sqlite3 libsqlite3-dev libtiff-dev libcurl4-openssl-dev jq + +CLANG_LLVM=clang+llvm-9.0.0-x86_64-linux-gnu-ubuntu-16.04 +wget http://releases.llvm.org/9.0.0/$CLANG_LLVM.tar.xz +tar xJf $CLANG_LLVM.tar.xz +mv $CLANG_LLVM clang+llvm-9 + +# prepare build files +./autogen.sh + +NPROC=$(nproc) +echo "NPROC=${NPROC}" +export MAKEFLAGS="-j ${NPROC}" + +export PATH=$PWD/clang+llvm-9/bin:$PATH +CXXFLAGS="-std=c++11" scan-build -o scanbuildoutput -plist -v ./configure +rm -rf scanbuildoutput +TOPDIR=$PWD +scan-build -o $TOPDIR/scanbuildoutput -sarif -v -enable-checker alpha.unix.cstring.OutOfBounds,alpha.unix.cstring.BufferOverlap,optin.cplusplus.VirtualCall,optin.cplusplus.UninitializedObject make + +rm -f filtered_scanbuild.txt +files=$(find scanbuildoutput -name "*.sarif") +for f in $files; do + jq '.runs[].results[] | (if .locations[].physicalLocation.fileLocation.uri | (contains("_generated_parser") ) then empty else { "uri": .locations[].physicalLocation.fileLocation.uri, "msg": .message.text, "location": .codeFlows[-1].threadFlows[-1].locations[-1] } end)' < $f > tmp.txt + if [ -s tmp.txt ]; then + echo "Errors from $f: " + cat $f + echo "" + cat tmp.txt >> filtered_scanbuild.txt + fi +done +if [ -s filtered_scanbuild.txt ]; then + echo "" + echo "" + echo "========================" + echo "Summary of errors found:" + cat filtered_scanbuild.txt + /bin/false +fi -- cgit v1.2.3 From eeec780b20c44960f3b2fed817e00bf6c23f0bec Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Thu, 26 Nov 2020 19:08:34 +0100 Subject: Travis-CI: remove CSA job --- .travis.yml | 7 ------- travis/csa/after_success.sh | 5 ----- travis/csa/before_install.sh | 13 ------------- travis/csa/install.sh | 34 ---------------------------------- 4 files changed, 59 deletions(-) delete mode 100755 travis/csa/after_success.sh delete mode 100755 travis/csa/before_install.sh delete mode 100755 travis/csa/install.sh diff --git a/.travis.yml b/.travis.yml index c2f2b69d..a258ee2e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -82,13 +82,6 @@ matrix: - BUILD_NAME=linux_generic - DETAILS="linux, arm64" - - os: linux - compiler: gcc - dist: xenial - env: - - BUILD_NAME=csa - - DETAILS="CLang Static Analyzer" - allow_failures: - env: BUILD_NAME=mingw32 diff --git a/travis/csa/after_success.sh b/travis/csa/after_success.sh deleted file mode 100755 index 9618f673..00000000 --- a/travis/csa/after_success.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - -set -e - -# nothing diff --git a/travis/csa/before_install.sh b/travis/csa/before_install.sh deleted file mode 100755 index 0ebc94fb..00000000 --- a/travis/csa/before_install.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash - -set -e - -./travis/before_install_apt.sh -./travis/before_install_pip.sh - -sudo apt-get install -qq sqlite3 libsqlite3-dev libtiff-dev libcurl4-openssl-dev - -CLANG_LLVM=clang+llvm-9.0.0-x86_64-linux-gnu-ubuntu-16.04 -wget http://releases.llvm.org/9.0.0/$CLANG_LLVM.tar.xz -tar xJf $CLANG_LLVM.tar.xz -mv $CLANG_LLVM clang+llvm-9 diff --git a/travis/csa/install.sh b/travis/csa/install.sh deleted file mode 100755 index 349afcb1..00000000 --- a/travis/csa/install.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/bash - -set -e - -# prepare build files -./autogen.sh - -export PATH=$PWD/clang+llvm-9/bin:$PATH -CXXFLAGS="-std=c++11" scan-build -o scanbuildoutput -plist -v ./configure -rm -rf scanbuildoutput -TOPDIR=$PWD -scan-build -o $TOPDIR/scanbuildoutput -sarif -v -enable-checker alpha.unix.cstring.OutOfBounds,alpha.unix.cstring.BufferOverlap,optin.cplusplus.VirtualCall,optin.cplusplus.UninitializedObject make -j2 - -sudo apt-get install jq - -rm -f filtered_scanbuild.txt -files=$(find scanbuildoutput -name "*.sarif") -for f in $files; do - jq '.runs[].results[] | (if .locations[].physicalLocation.fileLocation.uri | (contains("_generated_parser") ) then empty else { "uri": .locations[].physicalLocation.fileLocation.uri, "msg": .message.text, "location": .codeFlows[-1].threadFlows[-1].locations[-1] } end)' < $f > tmp.txt - if [ -s tmp.txt ]; then - echo "Errors from $f: " - cat $f - echo "" - cat tmp.txt >> filtered_scanbuild.txt - fi -done -if [ -s filtered_scanbuild.txt ]; then - echo "" - echo "" - echo "========================" - echo "Summary of errors found:" - cat filtered_scanbuild.txt - /bin/false -fi -- cgit v1.2.3 From e7fc87b21ed9a3f193e750d24371c47615689831 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Thu, 26 Nov 2020 20:19:15 +0100 Subject: travis/install.sh: make it robust to objdump on 20.04 and/or clang outputing symbols in different order --- travis/install.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/travis/install.sh b/travis/install.sh index 8897f823..a4d8352a 100755 --- a/travis/install.sh +++ b/travis/install.sh @@ -41,8 +41,9 @@ make >/dev/null if [ "$(uname)" == "Linux" -a -f src/.libs/libproj.so ]; then if objdump -TC "src/.libs/libproj.so" | grep "elf64-x86-64">/dev/null; then echo "Checking exported symbols..." - $TRAVIS_BUILD_DIR/scripts/dump_exported_symbols.sh src/.libs/libproj.so > /tmp/got_symbols.txt - diff -u $TRAVIS_BUILD_DIR/scripts/reference_exported_symbols.txt /tmp/got_symbols.txt || (echo "Difference(s) found in exported symbols. If intended, refresh scripts/reference_exported_symbols.txt with 'scripts/dump_exported_symbols.sh src/.libs/libproj.so > scripts/reference_exported_symbols.txt'"; exit 1) + cat $TRAVIS_BUILD_DIR/scripts/reference_exported_symbols.txt | sort > /tmp/reference_exported_symbols.txt + $TRAVIS_BUILD_DIR/scripts/dump_exported_symbols.sh src/.libs/libproj.so | sort > /tmp/got_symbols.txt + diff -u /tmp/reference_exported_symbols.txt /tmp/got_symbols.txt || (echo "Difference(s) found in exported symbols. If intended, refresh scripts/reference_exported_symbols.txt with 'scripts/dump_exported_symbols.sh src/.libs/libproj.so > scripts/reference_exported_symbols.txt'"; exit 1) fi fi -- cgit v1.2.3 From 7562eee171f3a70acd7e012bff7c150b8dcd647c Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Thu, 26 Nov 2020 19:52:14 +0100 Subject: Github action: add a clang linux build job --- .github/workflows/clang_linux.yml | 24 ++++++++++++++++++++++++ .github/workflows/clang_linux/start.sh | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 .github/workflows/clang_linux.yml create mode 100755 .github/workflows/clang_linux/start.sh diff --git a/.github/workflows/clang_linux.yml b/.github/workflows/clang_linux.yml new file mode 100644 index 00000000..ba52cc95 --- /dev/null +++ b/.github/workflows/clang_linux.yml @@ -0,0 +1,24 @@ +name: CLang Linux + +on: [push, pull_request] + +jobs: + + clang_linux: + runs-on: ubuntu-latest + if: "!contains(github.event.head_commit.message, '[ci skip]') && !contains(github.event.head_commit.message, '[skip ci]')" + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Cache + uses: actions/cache@v2 + id: cache + with: + path: | + ${{ github.workspace }}/ccache.tar.gz + key: ${{ runner.os }}-cache-clang-${{ github.run_id }} + restore-keys: ${{ runner.os }}-cache-clang- + + - name: Run + run: docker run -e CI -e TRAVIS_BUILD_DIR="$PWD" -e WORK_DIR="$PWD" -e TRAVIS_OS_NAME=linux -e BUILD_NAME=linux_clang -v $PWD:$PWD ubuntu:20.04 $PWD/.github/workflows/clang_linux/start.sh diff --git a/.github/workflows/clang_linux/start.sh b/.github/workflows/clang_linux/start.sh new file mode 100755 index 00000000..83d2f8c2 --- /dev/null +++ b/.github/workflows/clang_linux/start.sh @@ -0,0 +1,32 @@ +#!/bin/sh + +set -e + +apt-get update -y +DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + sudo autoconf automake libtool clang++-10 python3-clang-10 make cmake ccache pkg-config tar zip \ + sqlite3 libsqlite3-dev libtiff-dev libcurl4-openssl-dev jq python3-pip + +pip3 install --user jsonschema + +cd "$WORK_DIR" + +if test -f "$WORK_DIR/ccache.tar.gz"; then + echo "Restoring ccache..." + (cd $HOME && tar xzf "$WORK_DIR/ccache.tar.gz") +fi + +export CCACHE_CPP2=yes +export PROJ_DB_CACHE_DIR="$HOME/.ccache" + +ccache -M 500M +ccache -s + +# -fno-use-cxa-atexit is needed to build with -coverage +CC="ccache clang-10" CXX="ccache clang++-10" CFLAGS="-Werror -fsanitize=address -fno-use-cxa-atexit" CXXFLAGS="-Werror -fsanitize=address -fno-use-cxa-atexit" LDFLAGS="-fsanitize=address" ./travis/install.sh + +ccache -s + +echo "Saving ccache..." +rm -f "$WORK_DIR/ccache.tar.gz" +(cd $HOME && tar czf "$WORK_DIR/ccache.tar.gz" .ccache) -- cgit v1.2.3 From f0842bb0b079801d9457579013e8aea5616d5f77 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Thu, 26 Nov 2020 19:52:56 +0100 Subject: Travis-CI: remove linux_clang job --- .travis.yml | 9 --------- travis/linux_clang/after_success.sh | 5 ----- travis/linux_clang/before_install.sh | 8 -------- travis/linux_clang/install.sh | 9 --------- 4 files changed, 31 deletions(-) delete mode 100755 travis/linux_clang/after_success.sh delete mode 100755 travis/linux_clang/before_install.sh delete mode 100755 travis/linux_clang/install.sh diff --git a/.travis.yml b/.travis.yml index a258ee2e..f0720523 100644 --- a/.travis.yml +++ b/.travis.yml @@ -57,15 +57,6 @@ matrix: - autoconf - automake - - os: linux - dist: xenial - compiler: clang - services: - - docker - env: - - BUILD_NAME=linux_clang - - DETAILS="linux, clang" - - os: linux dist: bionic compiler: gcc diff --git a/travis/linux_clang/after_success.sh b/travis/linux_clang/after_success.sh deleted file mode 100755 index 9618f673..00000000 --- a/travis/linux_clang/after_success.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - -set -e - -# nothing diff --git a/travis/linux_clang/before_install.sh b/travis/linux_clang/before_install.sh deleted file mode 100755 index c4b8acad..00000000 --- a/travis/linux_clang/before_install.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash - -set -e - -./travis/before_install_apt.sh -./travis/before_install_pip.sh - -sudo apt-get install -qq sqlite3 libsqlite3-dev libtiff-dev libcurl4-openssl-dev diff --git a/travis/linux_clang/install.sh b/travis/linux_clang/install.sh deleted file mode 100755 index 50c02882..00000000 --- a/travis/linux_clang/install.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash - -set -e - -export CCACHE_CPP2=yes -export PROJ_DB_CACHE_DIR="$HOME/.ccache" - -# -fno-use-cxa-atexit is needed to build with -coverage -CC="ccache clang" CXX="ccache clang++" CFLAGS="-Werror -fsanitize=address -fno-use-cxa-atexit" CXXFLAGS="-Werror -fsanitize=address -fno-use-cxa-atexit" LDFLAGS="-fsanitize=address" ./travis/install.sh -- cgit v1.2.3 From 83754e1f77bc407f6fa5fd34e07d3625e619ce41 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Thu, 26 Nov 2020 21:12:00 +0100 Subject: Fix mingw_w64 warning about pj_acquire_lock() prototype being missing --- src/mutex.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mutex.cpp b/src/mutex.cpp index 9fc78acf..b1a23ccd 100644 --- a/src/mutex.cpp +++ b/src/mutex.cpp @@ -33,8 +33,8 @@ #include "proj.h" #ifndef _WIN32 #include "proj_config.h" -#include "proj_internal.h" #endif +#include "proj_internal.h" /* on win32 we always use win32 mutexes, even if pthreads are available */ #if defined(_WIN32) && !defined(MUTEX_stub) -- cgit v1.2.3 From b27efedef0b3deb488d322d42b3d5b652ab55662 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Thu, 26 Nov 2020 18:49:25 +0100 Subject: PRIMEM WKT handling: fixes on import for 'sexagesimal DMS' or from WKT1:GDAL/ESRI when GEOGCS UNIT != Degree; morph to ESRI the PRIMEM name on export --- src/iso19111/datum.cpp | 17 +++++++++++ src/iso19111/io.cpp | 76 +++++++++++++++++++++++++++++++++++++++++++++++--- test/unit/test_crs.cpp | 14 ++++++++++ test/unit/test_io.cpp | 56 +++++++++++++++++++++++++++++++++++++ 4 files changed, 159 insertions(+), 4 deletions(-) diff --git a/src/iso19111/datum.cpp b/src/iso19111/datum.cpp index 60244779..8e1b8257 100644 --- a/src/iso19111/datum.cpp +++ b/src/iso19111/datum.cpp @@ -351,6 +351,23 @@ void PrimeMeridian::_exportToWKT( if (!(isWKT2 && formatter->primeMeridianOmittedIfGreenwich() && l_name == "Greenwich")) { formatter->startNode(io::WKTConstants::PRIMEM, !identifiers().empty()); + + if (formatter->useESRIDialect()) { + bool aliasFound = false; + const auto &dbContext = formatter->databaseContext(); + if (dbContext) { + auto l_alias = dbContext->getAliasFromOfficialName( + l_name, "prime_meridian", "ESRI"); + if (!l_alias.empty()) { + l_name = l_alias; + aliasFound = true; + } + } + if (!aliasFound) { + l_name = io::WKTFormatter::morphNameToESRI(l_name); + } + } + formatter->addQuotedString(l_name); const auto &l_long = longitude(); if (formatter->primeMeridianInDegree()) { diff --git a/src/iso19111/io.cpp b/src/iso19111/io.cpp index 867a0d53..52d46d27 100644 --- a/src/iso19111/io.cpp +++ b/src/iso19111/io.cpp @@ -1978,14 +1978,80 @@ PrimeMeridianNNPtr WKTParser::Private::buildPrimeMeridian( try { double angleValue = asDouble(children[1]); - // Correct for GDAL WKT1 departure + // Correct for GDAL WKT1 and WKT1-ESRI departure if (name == "Paris" && std::fabs(angleValue - 2.33722917) < 1e-8 && - unit == UnitOfMeasure::GRAD) { + unit._isEquivalentTo(UnitOfMeasure::GRAD, + util::IComparable::Criterion::EQUIVALENT)) { angleValue = 2.5969213; + } else { + static const struct { + const char *name; + int deg; + int min; + double sec; + } primeMeridiansDMS[] = { + {"Lisbon", -9, 7, 54.862}, {"Bogota", -74, 4, 51.3}, + {"Madrid", -3, 41, 14.55}, {"Rome", 12, 27, 8.4}, + {"Bern", 7, 26, 22.5}, {"Jakarta", 106, 48, 27.79}, + {"Ferro", -17, 40, 0}, {"Brussels", 4, 22, 4.71}, + {"Stockholm", 18, 3, 29.8}, {"Athens", 23, 42, 58.815}, + {"Oslo", 10, 43, 22.5}, {"Paris RGS", 2, 20, 13.95}, + {"Paris_RGS", 2, 20, 13.95}}; + + // Current epsg.org output may use the EPSG:9110 "sexagesimal DMS" + // unit and a DD.MMSSsss value, but this will likely be changed to + // use decimal degree. + // Or WKT1 may for example use the Paris RGS decimal degree value + // but with a GEOGCS with UNIT["Grad"] + for (const auto &pmDef : primeMeridiansDMS) { + if (name == pmDef.name) { + double dmsAsDecimalValue = + (pmDef.deg >= 0 ? 1 : -1) * + (std::abs(pmDef.deg) + pmDef.min / 100. + + pmDef.sec / 10000.); + double dmsAsDecimalDegreeValue = + (pmDef.deg >= 0 ? 1 : -1) * + (std::abs(pmDef.deg) + pmDef.min / 60. + + pmDef.sec / 3600.); + if (std::fabs(angleValue - dmsAsDecimalValue) < 1e-8 || + std::fabs(angleValue - dmsAsDecimalDegreeValue) < + 1e-8) { + angleValue = dmsAsDecimalDegreeValue; + unit = UnitOfMeasure::DEGREE; + } + break; + } + } + } + + auto &properties = buildProperties(node); + if (dbContext_ && esriStyle_) { + std::string outTableName; + std::string codeFromAlias; + std::string authNameFromAlias; + auto authFactory = AuthorityFactory::create(NN_NO_CHECK(dbContext_), + std::string()); + auto officialName = authFactory->getOfficialNameFromAlias( + name, "prime_meridian", "ESRI", false, outTableName, + authNameFromAlias, codeFromAlias); + if (!officialName.empty()) { + properties.set(IdentifiedObject::NAME_KEY, officialName); + if (!authNameFromAlias.empty()) { + auto identifiers = ArrayOfBaseObject::create(); + identifiers->add(Identifier::create( + codeFromAlias, + PropertyMap() + .set(Identifier::CODESPACE_KEY, authNameFromAlias) + .set(Identifier::AUTHORITY_KEY, + authNameFromAlias))); + properties.set(IdentifiedObject::IDENTIFIERS_KEY, + identifiers); + } + } } Angle angle(angleValue, unit); - return PrimeMeridian::create(buildProperties(node), angle); + return PrimeMeridian::create(properties, angle); } catch (const std::exception &e) { throw buildRethrow(__FUNCTION__, e); } @@ -2737,6 +2803,9 @@ WKTParser::Private::buildGeodeticCRS(const WKTNodeNNPtr &node) { throw ParsingException("Missing DATUM or ENSEMBLE node"); } + // Do that now so that esriStyle_ can be set before buildPrimeMeridian() + auto props = buildProperties(node); + auto &dynamicNode = nodeP->lookForChild(WKTConstants::DYNAMIC); auto &csNode = nodeP->lookForChild(WKTConstants::CS_); @@ -2774,7 +2843,6 @@ WKTParser::Private::buildGeodeticCRS(const WKTNodeNNPtr &node) { angularUnit = primeMeridian->longitude().unit(); } - auto props = buildProperties(node); addExtensionProj4ToProp(nodeP, props); // No explicit AXIS node ? (WKT1) diff --git a/test/unit/test_crs.cpp b/test/unit/test_crs.cpp index e470a621..af172b4c 100644 --- a/test/unit/test_crs.cpp +++ b/test/unit/test_crs.cpp @@ -414,6 +414,20 @@ TEST(crs, EPSG_4326_as_WKT1_ESRI_with_database) { // --------------------------------------------------------------------------- +TEST(crs, EPSG_4901_as_WKT1_ESRI_with_PRIMEM_unit_name_morphing) { + auto factory = AuthorityFactory::create(DatabaseContext::create(), "EPSG"); + auto crs = factory->createCoordinateReferenceSystem("4901"); + WKTFormatterNNPtr f(WKTFormatter::create( + WKTFormatter::Convention::WKT1_ESRI, DatabaseContext::create())); + EXPECT_EQ(crs->exportToWKT(f.get()), + "GEOGCS[\"GCS_ATF_Paris\",DATUM[\"D_ATF\"," + "SPHEROID[\"Plessis_1817\",6376523.0,308.64]]," + "PRIMEM[\"Paris_RGS\",2.33720833333333]," + "UNIT[\"Grad\",0.0157079632679489]]"); +} + +// --------------------------------------------------------------------------- + TEST(crs, EPSG_4326_as_WKT1_ESRI_without_database) { auto crs = GeographicCRS::EPSG_4326; WKTFormatterNNPtr f( diff --git a/test/unit/test_io.cpp b/test/unit/test_io.cpp index 81894fb0..f0e221d8 100644 --- a/test/unit/test_io.cpp +++ b/test/unit/test_io.cpp @@ -488,6 +488,62 @@ TEST(wkt_parse, wkt1_EPSG_4807_grad_mess) { // --------------------------------------------------------------------------- +TEST(wkt_parse, wkt1_esri_EPSG_4901_grad) { + auto obj = + WKTParser() + .attachDatabaseContext(DatabaseContext::create()) + .createFromWKT("GEOGCS[\"GCS_ATF_Paris\",DATUM[\"D_ATF\"," + "SPHEROID[\"Plessis_1817\",6376523.0,308.64]]," + "PRIMEM[\"Paris_RGS\",2.33720833333333]," + "UNIT[\"Grad\",0.0157079632679489]]"); + auto crs = nn_dynamic_pointer_cast(obj); + ASSERT_TRUE(crs != nullptr); + + auto datum = crs->datum(); + auto primem = datum->primeMeridian(); + EXPECT_EQ(primem->nameStr(), "Paris RGS"); + // The PRIMEM is really in degree + EXPECT_EQ(primem->longitude().unit(), UnitOfMeasure::DEGREE); + EXPECT_NEAR(primem->longitude().value(), 2.33720833333333, 1e-14); +} + +// --------------------------------------------------------------------------- + +TEST(wkt_parse, wkt2_epsg_org_EPSG_4901_PRIMEM_weird_sexagesimal_DMS) { + // Current epsg.org output may use the EPSG:9110 "sexagesimal DMS" + // unit and a DD.MMSSsss value, but this will likely be changed to + // use decimal degree. + auto obj = WKTParser().createFromWKT( + "GEOGCRS[\"ATF (Paris)\"," + " DATUM[\"Ancienne Triangulation Francaise (Paris)\"," + " ELLIPSOID[\"Plessis 1817\",6376523,308.64," + " LENGTHUNIT[\"metre\",1,ID[\"EPSG\",9001]]," + " ID[\"EPSG\",7027]]," + " ID[\"EPSG\",6901]]," + " PRIMEM[\"Paris RGS\",2.201395," + " ANGLEUNIT[\"sexagesimal DMS\",1,ID[\"EPSG\",9110]]," + " ID[\"EPSG\",8914]]," + " CS[ellipsoidal,2," + " ID[\"EPSG\",6403]]," + " AXIS[\"Geodetic latitude (Lat)\",north," + " ORDER[1]]," + " AXIS[\"Geodetic longitude (Lon)\",east," + " ORDER[2]]," + " ANGLEUNIT[\"grad\",0.015707963267949,ID[\"EPSG\",9105]]," + " USAGE[SCOPE[\"Geodesy.\"],AREA[\"France - mainland onshore.\"]," + " BBOX[42.33,-4.87,51.14,8.23]]," + "ID[\"EPSG\",4901]]"); + auto crs = nn_dynamic_pointer_cast(obj); + ASSERT_TRUE(crs != nullptr); + + auto datum = crs->datum(); + auto primem = datum->primeMeridian(); + EXPECT_EQ(primem->longitude().unit(), UnitOfMeasure::DEGREE); + EXPECT_NEAR(primem->longitude().value(), 2.33720833333333, 1e-14); +} + +// --------------------------------------------------------------------------- + TEST(wkt_parse, wkt1_geographic_old_datum_name_from_EPSG_code) { auto wkt = "GEOGCS[\"S-JTSK (Ferro)\",\n" -- cgit v1.2.3 From f5b4060847bf780c12b399b98e06ebc56e3ae8e3 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Fri, 27 Nov 2020 00:39:49 +0100 Subject: formatting fixes --- src/filemanager.cpp | 8 ++++---- src/grids.cpp | 7 ++++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/filemanager.cpp b/src/filemanager.cpp index b3b074a2..b51205eb 100644 --- a/src/filemanager.cpp +++ b/src/filemanager.cpp @@ -1369,10 +1369,10 @@ static bool dontReadUserWritableDirectory() { return envVar != nullptr && envVar[0] != '\0'; } -static void * -pj_open_lib_internal(PJ_CONTEXT *ctx, const char *name, const char *mode, - void *(*open_file)(PJ_CONTEXT *, const char *, const char *), - char *out_full_filename, size_t out_full_filename_size) { +static void *pj_open_lib_internal( + PJ_CONTEXT *ctx, const char *name, const char *mode, + void *(*open_file)(PJ_CONTEXT *, const char *, const char *), + char *out_full_filename, size_t out_full_filename_size) { try { std::string fname; const char *sysname = nullptr; diff --git a/src/grids.cpp b/src/grids.cpp index 8bb865d8..871e21ed 100644 --- a/src/grids.cpp +++ b/src/grids.cpp @@ -2790,7 +2790,8 @@ ListOfGenericGrids pj_generic_grid_init(PJ *P, const char *gridkey) { } return {}; } - proj_context_errno_set(P->ctx, 0); // don't treat as a persistent error + proj_context_errno_set(P->ctx, + 0); // don't treat as a persistent error } else { grids.emplace_back(std::move(gridSet)); } @@ -3313,7 +3314,8 @@ ListOfVGrids pj_vgrid_init(PJ *P, const char *gridkey) { } return {}; } - proj_context_errno_set(P->ctx, 0); // don't treat as a persistent error + proj_context_errno_set(P->ctx, + 0); // don't treat as a persistent error } else { grids.emplace_back(std::move(gridSet)); } @@ -3442,4 +3444,3 @@ bool pj_bilinear_interpolation_three_samples( } NS_PROJ_END - -- cgit v1.2.3 From cdac370a9c02df553ee4a8534b892b73687996de Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Fri, 27 Nov 2020 20:22:38 +0100 Subject: Github action: add a linux_gcc_32bit job --- .github/workflows/linux_gcc_32bit.yml | 24 +++++++++++++ .github/workflows/linux_gcc_32bit/start.sh | 56 ++++++++++++++++++++++++++++++ travis/install.sh | 2 +- 3 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/linux_gcc_32bit.yml create mode 100755 .github/workflows/linux_gcc_32bit/start.sh diff --git a/.github/workflows/linux_gcc_32bit.yml b/.github/workflows/linux_gcc_32bit.yml new file mode 100644 index 00000000..455bf301 --- /dev/null +++ b/.github/workflows/linux_gcc_32bit.yml @@ -0,0 +1,24 @@ +name: Linux GCC 32bit + +on: [push, pull_request] + +jobs: + + linux_gcc_32bit: + runs-on: ubuntu-latest + if: "!contains(github.event.head_commit.message, '[ci skip]') && !contains(github.event.head_commit.message, '[skip ci]')" + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Cache + uses: actions/cache@v2 + id: cache + with: + path: | + ${{ github.workspace }}/ccache.tar.gz + key: ${{ runner.os }}-cache-gcc32bit-${{ github.run_id }} + restore-keys: ${{ runner.os }}-cache-gcc32bit- + + - name: Run + run: docker run -e CI -e WORK_DIR="$PWD" -v $PWD:$PWD ubuntu:20.04 $PWD/.github/workflows/linux_gcc_32bit/start.sh diff --git a/.github/workflows/linux_gcc_32bit/start.sh b/.github/workflows/linux_gcc_32bit/start.sh new file mode 100755 index 00000000..42746fe8 --- /dev/null +++ b/.github/workflows/linux_gcc_32bit/start.sh @@ -0,0 +1,56 @@ +#!/bin/bash + +set -e + +export TRAVIS_OS_NAME=linux +export BUILD_NAME=linux_gcc_32bit +export TRAVIS_BUILD_DIR="$WORK_DIR" + +ARCH=i386 + +dpkg --add-architecture i386 +apt update -y + +DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + autoconf automake libtool gcc-multilib g++-multilib g++ sqlite3 \ + python3-pip \ + make cmake ccache pkg-config tar zip \ + libsqlite3-dev:$ARCH libtiff-dev:$ARCH libcurl4-openssl-dev:$ARCH \ + jq + +pip3 install --user jsonschema +export PATH=$HOME/.local/bin:$PATH + +export CXXFLAGS='-g -O2 -m32 -D_GLIBCXX_ASSERTIONS' +export CFLAGS='-g -O2 -m32' +export TIFF_CFLAGS=-I/usr/include/i386-linux-gnu +export TIFF_LIBS="-L/usr/lib/i386-linux-gnu -ltiff" +export SQLITE3_CFLAGS=-I/usr/include/i386-linux-gnu +export SQLITE3_LIBS="-L/usr/lib/i386-linux-gnu -lsqlite3" +export CC="ccache gcc" +export CXX="ccache g++" + +NPROC=$(nproc) +echo "NPROC=${NPROC}" +export MAKEFLAGS="-j ${NPROC}" + +cd "$WORK_DIR" + +if test -f "$WORK_DIR/ccache.tar.gz"; then + echo "Restoring ccache..." + (cd $HOME && tar xzf "$WORK_DIR/ccache.tar.gz") +fi + +export CCACHE_CPP2=yes +export PROJ_DB_CACHE_DIR="$HOME/.ccache" + +ccache -M 500M +ccache -s + +CFLAGS="-Werror $CFLAGS" CXXFLAGS="-Werror $CXXFLAGS" ./travis/install.sh + +ccache -s + +echo "Saving ccache..." +rm -f "$WORK_DIR/ccache.tar.gz" +(cd $HOME && tar czf "$WORK_DIR/ccache.tar.gz" .ccache) diff --git a/travis/install.sh b/travis/install.sh index a4d8352a..84e7de25 100755 --- a/travis/install.sh +++ b/travis/install.sh @@ -99,7 +99,7 @@ if [ $TRAVIS_OS_NAME != "osx" ]; then fi fi -if [ "$BUILD_NAME" != "linux_gcc8" ]; then +if [ "$BUILD_NAME" != "linux_gcc8" -a "$BUILD_NAME" != "linux_gcc_32bit" ]; then # cmake build from generated tarball mkdir build_cmake -- cgit v1.2.3 From 3b0102df6f1152563f37bfe2617535d81516cb75 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Fri, 27 Nov 2020 20:23:23 +0100 Subject: Travis-CI: remove linux_gcc8 job --- .travis.yml | 28 ---------------------------- travis/linux_gcc8/after_success.sh | 5 ----- travis/linux_gcc8/before_install.sh | 21 --------------------- travis/linux_gcc8/install.sh | 8 -------- 4 files changed, 62 deletions(-) delete mode 100755 travis/linux_gcc8/after_success.sh delete mode 100755 travis/linux_gcc8/before_install.sh delete mode 100755 travis/linux_gcc8/install.sh diff --git a/.travis.yml b/.travis.yml index f0720523..07138324 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,34 +29,6 @@ matrix: packages: - g++-4.8 - - os: linux - dist: bionic - compiler: gcc - services: - - docker - env: - - BUILD_NAME=linux_gcc8 - - DETAILS="linux, gcc8" - - DETAILS="linux, gcc8, i386" - - ARCH=i386 - - CC=gcc-8 - - CXX=g++-8 - - CXXFLAGS='-g -O2 -m32 -D_GLIBCXX_ASSERTIONS' - - CFLAGS='-g -O2 -m32' - - TIFF_CFLAGS=-I/usr/include/i386-linux-gnu - - TIFF_LIBS="-L/usr/lib/i386-linux-gnu -ltiff" - - SQLITE3_CFLAGS=-I/usr/include/i386-linux-gnu - - SQLITE3_LIBS="-L/usr/lib/i386-linux-gnu -lsqlite3" - addons: - apt: - sources: - - sourceline: 'ppa:ubuntu-toolchain-r/test' - packages: - - g++-8-multilib - - make - - autoconf - - automake - - os: linux dist: bionic compiler: gcc diff --git a/travis/linux_gcc8/after_success.sh b/travis/linux_gcc8/after_success.sh deleted file mode 100755 index 70c6f5cb..00000000 --- a/travis/linux_gcc8/after_success.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - -set -e - -#./travis/after_success.sh diff --git a/travis/linux_gcc8/before_install.sh b/travis/linux_gcc8/before_install.sh deleted file mode 100755 index ff6c0927..00000000 --- a/travis/linux_gcc8/before_install.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash - -set -e - -./travis/before_install_apt.sh -./travis/before_install_pip.sh - -sudo aptitude remove -q -y libtiff-dev libcurl4-gnutls-dev -sudo aptitude install -q -y \ - lcov \ - doxygen graphviz \ - sqlite3 libsqlite3-dev:$ARCH \ - libtiff-dev:$ARCH libcurl4-openssl-dev:$ARCH - -#scripts/cppcheck.sh -#scripts/doxygen.sh - -#pip install --user sphinxcontrib-bibtex -#pip install --user cpp-coveralls - -#./travis/docker.sh diff --git a/travis/linux_gcc8/install.sh b/travis/linux_gcc8/install.sh deleted file mode 100755 index 7fa8cfa4..00000000 --- a/travis/linux_gcc8/install.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash - -set -e - -export CCACHE_CPP2=yes -export PROJ_DB_CACHE_DIR="$HOME/.ccache" - -CC="ccache $CC" CXX="ccache $CXX" CFLAGS="-std=c99 -Werror $CFLAGS" CXXFLAGS="-Werror $CXXFLAGS" ./travis/install.sh -- cgit v1.2.3 From 59b112687a9ae26425c300738a14d73ae4090476 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Fri, 27 Nov 2020 21:27:31 +0100 Subject: crs.hpp: add cppcheck suppression for cppcheck 1.90 of ubuntu 20.04 --- include/proj/crs.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/proj/crs.hpp b/include/proj/crs.hpp index b921f4bb..8c1f9f6f 100644 --- a/include/proj/crs.hpp +++ b/include/proj/crs.hpp @@ -1410,6 +1410,7 @@ class PROJ_GCC_DLL DerivedCRSTemplate final : public DerivedCRSTraits::BaseType, DerivedCRSTemplate(const BaseNNPtr &baseCRSIn, const operation::ConversionNNPtr &derivingConversionIn, const CSNNPtr &csIn); + // cppcheck-suppress noExplicitConstructor PROJ_INTERNAL DerivedCRSTemplate(const DerivedCRSTemplate &other); PROJ_INTERNAL CRSNNPtr _shallowClone() const override; -- cgit v1.2.3 From c85a44110d19080215183e0e07d81408d68cdbec Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Fri, 27 Nov 2020 21:27:59 +0100 Subject: Add github action for cppcheck --- .github/workflows/code_checks.yml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 .github/workflows/code_checks.yml diff --git a/.github/workflows/code_checks.yml b/.github/workflows/code_checks.yml new file mode 100644 index 00000000..dc2cc6e4 --- /dev/null +++ b/.github/workflows/code_checks.yml @@ -0,0 +1,20 @@ +name: Code Checks + +on: [push, pull_request] + +jobs: + + cppcheck_2004: + runs-on: ubuntu-20.04 + if: "!contains(github.event.head_commit.message, '[ci skip]') && !contains(github.event.head_commit.message, '[skip ci]')" + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Install Requirements + run: | + sudo apt update + sudo apt install -y --no-install-recommends cppcheck + + - name: Run cppcheck test + run: ./scripts/cppcheck.sh -- cgit v1.2.3 From 90737bcf698c98b2a8600e4c79fb15a675489929 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Fri, 27 Nov 2020 21:51:52 +0100 Subject: Move linux_gcc 4.8 job to github action, and on Travis-CI only keep the doc publishing --- .github/workflows/linux_gcc_4_8.yml | 29 +++++++++++++++++ .github/workflows/linux_gcc_4_8/start.sh | 55 ++++++++++++++++++++++++++++++++ .travis.yml | 10 ++---- travis/after_success.sh | 7 ---- travis/install.sh | 8 ----- travis/linux_gcc/after_success.sh | 5 --- travis/linux_gcc/before_install.sh | 22 ------------- travis/linux_gcc/install.sh | 8 ----- travis/publish_doc/after_success.sh | 5 +++ travis/publish_doc/before_install.sh | 7 ++++ travis/publish_doc/install.sh | 3 ++ 11 files changed, 101 insertions(+), 58 deletions(-) create mode 100644 .github/workflows/linux_gcc_4_8.yml create mode 100755 .github/workflows/linux_gcc_4_8/start.sh delete mode 100755 travis/linux_gcc/after_success.sh delete mode 100755 travis/linux_gcc/before_install.sh delete mode 100755 travis/linux_gcc/install.sh create mode 100755 travis/publish_doc/after_success.sh create mode 100755 travis/publish_doc/before_install.sh create mode 100755 travis/publish_doc/install.sh diff --git a/.github/workflows/linux_gcc_4_8.yml b/.github/workflows/linux_gcc_4_8.yml new file mode 100644 index 00000000..1f37785c --- /dev/null +++ b/.github/workflows/linux_gcc_4_8.yml @@ -0,0 +1,29 @@ +name: Linux GCC 4.8 + +on: [push, pull_request] + +jobs: + + linux_gcc_4_8: + runs-on: ubuntu-latest + if: "!contains(github.event.head_commit.message, '[ci skip]') && !contains(github.event.head_commit.message, '[skip ci]')" + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Cache + uses: actions/cache@v2 + id: cache + with: + path: | + ${{ github.workspace }}/ccache.tar.gz + key: ${{ runner.os }}-cache-gcc-4-8-${{ github.run_id }} + restore-keys: ${{ runner.os }}-cache-gcc-4-8- + + - name: Run + run: docker run -e CI -e WORK_DIR="$PWD" -v $PWD:$PWD ubuntu:16.04 $PWD/.github/workflows/linux_gcc_4_8/start.sh + + - name: Coveralls + uses: coverallsapp/github-action@v1.1.2 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/linux_gcc_4_8/start.sh b/.github/workflows/linux_gcc_4_8/start.sh new file mode 100755 index 00000000..2493ea1a --- /dev/null +++ b/.github/workflows/linux_gcc_4_8/start.sh @@ -0,0 +1,55 @@ +#!/bin/bash + +set -e + +export TRAVIS_OS_NAME=linux +export BUILD_NAME=linux_gcc +export TRAVIS_BUILD_DIR="$WORK_DIR" + +apt update -y + +DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + autoconf automake libtool g++-4.8 sqlite3 \ + python3-pip python3-setuptools \ + make cmake ccache pkg-config tar zip \ + libsqlite3-dev libtiff-dev libcurl4-openssl-dev \ + jq lcov + +pip3 install --user --upgrade pip +echo `pip3 --version` +pip3 config --user set global.progress_bar off +pip3 install --user jsonschema +pip3 install --user cmake==3.9.6 + +export PATH=$HOME/.local/bin:$PATH + +export CC="ccache gcc-4.8" +export CXX="ccache g++-4.8" + +NPROC=$(nproc) +echo "NPROC=${NPROC}" +export MAKEFLAGS="-j ${NPROC}" + +cd "$WORK_DIR" + +if test -f "$WORK_DIR/ccache.tar.gz"; then + echo "Restoring ccache..." + (cd $HOME && tar xzf "$WORK_DIR/ccache.tar.gz") +fi + +export CCACHE_CPP2=yes +export PROJ_DB_CACHE_DIR="$HOME/.ccache" + +ccache -M 500M +ccache -s + +CFLAGS="-Werror $CFLAGS" CXXFLAGS="-Werror $CXXFLAGS" ./travis/install.sh + +ccache -s + +echo "Saving ccache..." +rm -f "$WORK_DIR/ccache.tar.gz" +(cd $HOME && tar czf "$WORK_DIR/ccache.tar.gz" .ccache) + +mkdir -p coverage +lcov --no-external --capture --directory src --output-file coverage/lcov.info diff --git a/.travis.yml b/.travis.yml index 07138324..bf53a57c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,14 +20,8 @@ matrix: services: - docker env: - - BUILD_NAME=linux_gcc - - DETAILS="linux, gcc-4.8" - - CC=gcc-4.8 - - CXX=g++-4.8 - addons: - apt: - packages: - - g++-4.8 + - BUILD_NAME=publish_doc + - DETAILS="publish_doc" - os: linux dist: bionic diff --git a/travis/after_success.sh b/travis/after_success.sh index 095bafbd..abe11d91 100755 --- a/travis/after_success.sh +++ b/travis/after_success.sh @@ -2,13 +2,6 @@ set -e -if [ "$BUILD_NAME" != "linux_clang" ]; then - # coveralls falsely reports .c-files in the build directories as having 100% coverage so we exclude them - coveralls --build-root src --extension .c --extension .cpp \ - --exclude build_autoconf --exclude build_cmake --exclude test --exclude examples \ - --exclude include/proj/internal/nlohmann -fi - echo "$TRAVIS_SECURE_ENV_VARS" ./travis/build_docs.sh # Only build and publish docs when changes are made on most recent maintenance branch diff --git a/travis/install.sh b/travis/install.sh index 84e7de25..6426e1b3 100755 --- a/travis/install.sh +++ b/travis/install.sh @@ -141,12 +141,4 @@ if [ "$BUILD_NAME" != "linux_gcc8" -a "$BUILD_NAME" != "linux_gcc_32bit" ]; then fi make >/dev/null make check - - if [ "$BUILD_NAME" != "linux_clang" ]; then - mv src/.libs/*.gc* src - mv src/conversions/.libs/*.gc* src/conversions - mv src/iso19111/.libs/*.gc* src/iso19111 - mv src/projections/.libs/*.gc* src/projections - mv src/transformations/.libs/*.gc* src/transformations - fi fi diff --git a/travis/linux_gcc/after_success.sh b/travis/linux_gcc/after_success.sh deleted file mode 100755 index 6602f6c3..00000000 --- a/travis/linux_gcc/after_success.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - -set -e - -./travis/after_success.sh diff --git a/travis/linux_gcc/before_install.sh b/travis/linux_gcc/before_install.sh deleted file mode 100755 index 3068794d..00000000 --- a/travis/linux_gcc/before_install.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash - -set -e - -./travis/before_install_apt.sh -./travis/before_install_pip.sh - -sudo apt-get install -qq \ - lcov \ - doxygen graphviz \ - sqlite3 libsqlite3-dev \ - libtiff-dev libcurl4-openssl-dev \ - cppcheck - -scripts/cppcheck.sh -scripts/doxygen.sh - -pip3 install --user sphinxcontrib-bibtex -pip3 install --user cpp-coveralls -pip3 install --user cmake==3.9.6 - -./travis/docker.sh diff --git a/travis/linux_gcc/install.sh b/travis/linux_gcc/install.sh deleted file mode 100755 index 5dd97f07..00000000 --- a/travis/linux_gcc/install.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash - -set -e - -export CCACHE_CPP2=yes -export PROJ_DB_CACHE_DIR="$HOME/.ccache" - -CC="ccache $CC" CXX="ccache $CXX" CFLAGS="-std=c99 -Werror" CXXFLAGS="-Werror" ./travis/install.sh diff --git a/travis/publish_doc/after_success.sh b/travis/publish_doc/after_success.sh new file mode 100755 index 00000000..6602f6c3 --- /dev/null +++ b/travis/publish_doc/after_success.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +set -e + +./travis/after_success.sh diff --git a/travis/publish_doc/before_install.sh b/travis/publish_doc/before_install.sh new file mode 100755 index 00000000..bbb7b35b --- /dev/null +++ b/travis/publish_doc/before_install.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +set -e + +./travis/before_install_apt.sh +./travis/before_install_pip.sh +./travis/docker.sh diff --git a/travis/publish_doc/install.sh b/travis/publish_doc/install.sh new file mode 100755 index 00000000..d9628ae7 --- /dev/null +++ b/travis/publish_doc/install.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +set -e -- cgit v1.2.3 From 24c3bbb299798db775ef10101ee8aa76f8320bbf Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Fri, 27 Nov 2020 23:43:28 +0100 Subject: testcct: create 'a' and 'b' from scratch --- test/cli/testcct | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/cli/testcct b/test/cli/testcct index db7c70a9..7ba17181 100755 --- a/test/cli/testcct +++ b/test/cli/testcct @@ -39,8 +39,8 @@ echo "Test cct with object name initialization" >> ${OUT} echo "3541657.3778 948984.2343 5201383.5231 2020.5" | $EXE "ITRF2014 to ETRF2014 (1)" >>${OUT} echo "Test cct with object code initialization and file input" >> ${OUT} -echo "3541657.3778 948984.2343 5201383.5231 2020.5" >> a -echo "3541658.0000 948985.0000 5201384.0000 2020.5" >> b +echo "3541657.3778 948984.2343 5201383.5231 2020.5" > a +echo "3541658.0000 948985.0000 5201384.0000 2020.5" > b $EXE EPSG:8366 a b >>${OUT} /bin/rm a b -- cgit v1.2.3 From 4de6f0bd24051ed60d9c0a98dbba1da376457f12 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Sat, 28 Nov 2020 00:07:18 +0100 Subject: createObjectsFromName(): in exact match, make looking for 'ETRS89 / UTM zone 32N' return only the exact match --- src/iso19111/factory.cpp | 31 ++++++++++++++++++++++++++++++- test/unit/test_factory.cpp | 6 ++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/src/iso19111/factory.cpp b/src/iso19111/factory.cpp index 03fd5267..7c9eac00 100644 --- a/src/iso19111/factory.cpp +++ b/src/iso19111/factory.cpp @@ -6155,6 +6155,8 @@ AuthorityFactory::createObjectsFromNameEx( auto sqlRes = d->run(sql, params); bool isFirst = true; bool firstIsDeprecated = false; + bool foundExactMatch = false; + std::size_t hashCodeFirstMatch = 0; for (const auto &row : sqlRes) { const auto &name = row[3]; if (approximateMatch) { @@ -6242,11 +6244,38 @@ AuthorityFactory::createObjectsFromNameEx( } throw std::runtime_error("Unsupported table_name"); }; - res.emplace_back(PairObjectName(getObject(table_name, code), name)); + const auto obj = getObject(table_name, code); + if (metadata::Identifier::canonicalizeName(obj->nameStr()) == + canonicalizedSearchedName) { + foundExactMatch = true; + } + + const auto objPtr = obj.get(); + if (res.empty()) { + hashCodeFirstMatch = typeid(*objPtr).hash_code(); + } else if (hashCodeFirstMatch != typeid(*objPtr).hash_code()) { + hashCodeFirstMatch = 0; + } + + res.emplace_back(PairObjectName(obj, name)); if (limitResultCount > 0 && res.size() == limitResultCount) { break; } } + + // If we found a name that is an exact match, and all objects have the + // same type, and we are not in approximate mode, only keep the objet(s) + // with the exact name match. + if (foundExactMatch && hashCodeFirstMatch != 0 && !approximateMatch) { + std::list resTmp; + for (const auto &pair : res) { + if (metadata::Identifier::canonicalizeName( + pair.first->nameStr()) == canonicalizedSearchedName) { + resTmp.emplace_back(pair); + } + } + res = std::move(resTmp); + } } auto sortLambda = [](const PairObjectName &a, const PairObjectName &b) { diff --git a/test/unit/test_factory.cpp b/test/unit/test_factory.cpp index 8e9b7ab6..ff86c4d3 100644 --- a/test/unit/test_factory.cpp +++ b/test/unit/test_factory.cpp @@ -3082,6 +3082,12 @@ TEST(factory, createObjectsFromName) { .size(), 1U); + // Exact name, but with other CRS that have an aliases to it ==> should + // match only the CRS with the given name, not those other CRS. + EXPECT_EQ(factory->createObjectsFromName("ETRS89 / UTM zone 32N", {}, false) + .size(), + 1U); + // Prime meridian EXPECT_EQ(factoryEPSG->createObjectsFromName("Paris", {}, false, 2).size(), 1U); -- cgit v1.2.3 From 24c74a4d1cead8df41a7f22c8f28b1bf9e884de9 Mon Sep 17 00:00:00 2001 From: Houder <74594217+Houder@users.noreply.github.com> Date: Sat, 28 Nov 2020 13:45:06 +0100 Subject: Use same arguments to printf format string for both radians and degrees in output by cct (#2453) Currently the output of the cct utility is different between radians and degrees (as expected by cct), because of a bug in cct: $ printf "1 2\n" | cct -z 0 -t 0 +proj=pipeline +step +proj=unitconvert +xy_in=deg +xy_out=rad 1.0000000000 2.0000000000 0.0000 0.0000 $ printf "1 2\n" | cct -z 0 -t 0 +proj=pipeline +step +proj=unitconvert +xy_in=deg +xy_out=deg 1.0000 2.0000 0.0000 0.0000 The arguments to the printf format string are as follows: * radians: width 14, precision 10 * degrees: width 13, precision 4 (this is by mistake. bug!) After the suggested fix has been applied, output will be the same for both radians and degrees: $ printf "1 2\n" | cct -z 0 -t 0 +proj=pipeline +step +proj=unitconvert +xy_in=deg +xy_out=rad 1.0000000000 2.0000000000 0.0000 0.0000 $ printf "1 2\n" | cct -z 0 -t 0 +proj=pipeline +step +proj=unitconvert +xy_in=deg +xy_out=deg 1.0000000000 2.0000000000 0.0000 0.0000 The cause of the bug is that cct does test if it "has radians to output", but "neglects" to test if it "has degrees to output", resulting in using different arguments to the printf format string in the latter case. The fix makes cct test if it "has either radians or degrees to output". --- src/apps/cct.cpp | 11 ++++++++--- test/cli/testcct | 22 ++++++++++++++++++++++ test/cli/testcct_out.dist | 14 ++++++++++++++ 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/src/apps/cct.cpp b/src/apps/cct.cpp index ebfa6a23..4f21f10a 100644 --- a/src/apps/cct.cpp +++ b/src/apps/cct.cpp @@ -458,9 +458,14 @@ int main(int argc, char **argv) { comment_delimiter = (comment && *comment) ? whitespace : blank_comment; /* Time to print the result */ - if (proj_angular_output (P, direction)) { - point.lpzt.lam = proj_todeg (point.lpzt.lam); - point.lpzt.phi = proj_todeg (point.lpzt.phi); + /* use same arguments to printf format string for both radians and + degrees; convert radians to degrees before printing */ + if (proj_angular_output (P, direction) || + proj_degree_output (P, direction)) { + if (proj_angular_output (P, direction)) { + point.lpzt.lam = proj_todeg (point.lpzt.lam); + point.lpzt.phi = proj_todeg (point.lpzt.phi); + } print (PJ_LOG_NONE, "%14.*f %14.*f %12.*f %12.4f%s%s", decimals_angles, point.xyzt.x, decimals_angles, point.xyzt.y, diff --git a/test/cli/testcct b/test/cli/testcct index 7ba17181..686931ea 100755 --- a/test/cli/testcct +++ b/test/cli/testcct @@ -32,6 +32,28 @@ echo "Testing cct -d 8 +proj=merc +R=1" >> ${OUT} echo "90 45" 0 | $EXE -d 8 +proj=merc +R=1 >>${OUT} echo "" >>${OUT} +# tests without specifying the number of decimals (by default: 10 for radians and degrees, 4 for meters) +echo "Testing echo 0.5 2 | cct -z 0 -t 0 +proj=pipeline +step +proj=unitconvert +xy_in=deg +xy_out=rad" >> ${OUT} +echo 0.5 2 | $EXE -z 0 -t 0 +proj=pipeline +step +proj=unitconvert +xy_in=deg +xy_out=rad >> ${OUT} + +echo "Testing echo 0.5 2 | cct -z 0 -t 0 +proj=pipeline +step +proj=unitconvert +xy_in=deg +xy_out=deg" >> ${OUT} +echo 0.5 2 | $EXE -z 0 -t 0 +proj=pipeline +step +proj=unitconvert +xy_in=deg +xy_out=deg >> ${OUT} + +echo "Testing echo 0.5 2 | cct -z 0 -t 0 +proj=pipeline +step +proj=unitconvert +xy_in=m +xy_out=km" >> ${OUT} +echo 0.5 2 | $EXE -z 0 -t 0 +proj=pipeline +step +proj=unitconvert +xy_in=m +xy_out=km >> ${OUT} +echo "" >> ${OUT} + +# tests for which the number of decimals has been specified (-d 6) +echo "Testing echo 0.5 2 | cct -d 6 -z 0 -t 0 +proj=pipeline +step +proj=unitconvert +xy_in=deg +xy_out=rad" >> ${OUT} +echo 0.5 2 | $EXE -d 6 -z 0 -t 0 +proj=pipeline +step +proj=unitconvert +xy_in=deg +xy_out=rad >> ${OUT} + +echo "Testing echo 0.5 2 | cct -d 6 -z 0 -t 0 +proj=pipeline +step +proj=unitconvert +xy_in=deg +xy_out=deg" >> ${OUT} +echo 0.5 2 | $EXE -d 6 -z 0 -t 0 +proj=pipeline +step +proj=unitconvert +xy_in=deg +xy_out=deg >> ${OUT} + +echo "Testing echo 0.5 2 | cct -d 6 -z 0 -t 0 +proj=pipeline +step +proj=unitconvert +xy_in=m +xy_out=km" >> ${OUT} +echo 0.5 2 | $EXE -d 6 -z 0 -t 0 +proj=pipeline +step +proj=unitconvert +xy_in=m +xy_out=km >> ${OUT} +echo "" >> ${OUT} + echo "Test cct with object code initialization" >> ${OUT} echo "3541657.3778 948984.2343 5201383.5231 2020.5" | $EXE EPSG:8366 >>${OUT} diff --git a/test/cli/testcct_out.dist b/test/cli/testcct_out.dist index 353deb17..7762ace7 100644 --- a/test/cli/testcct_out.dist +++ b/test/cli/testcct_out.dist @@ -1,6 +1,20 @@ Testing cct -d 8 +proj=merc +R=1 1.57079633 0.88137359 0.00000000 inf +Testing echo 0.5 2 | cct -z 0 -t 0 +proj=pipeline +step +proj=unitconvert +xy_in=deg +xy_out=rad + 0.5000000000 2.0000000000 0.0000 0.0000 +Testing echo 0.5 2 | cct -z 0 -t 0 +proj=pipeline +step +proj=unitconvert +xy_in=deg +xy_out=deg + 0.5000000000 2.0000000000 0.0000 0.0000 +Testing echo 0.5 2 | cct -z 0 -t 0 +proj=pipeline +step +proj=unitconvert +xy_in=m +xy_out=km + 0.0005 0.0020 0.0000 0.0000 + +Testing echo 0.5 2 | cct -d 6 -z 0 -t 0 +proj=pipeline +step +proj=unitconvert +xy_in=deg +xy_out=rad + 0.500000 2.000000 0.000000 0.0000 +Testing echo 0.5 2 | cct -d 6 -z 0 -t 0 +proj=pipeline +step +proj=unitconvert +xy_in=deg +xy_out=deg + 0.500000 2.000000 0.000000 0.0000 +Testing echo 0.5 2 | cct -d 6 -z 0 -t 0 +proj=pipeline +step +proj=unitconvert +xy_in=m +xy_out=km + 0.000500 0.002000 0.000000 0.0000 + Test cct with object code initialization 3541657.9112 948983.7503 5201383.2482 2020.5000 Test cct with object name initialization -- cgit v1.2.3 From 0b4c8b0a76c65d8b1146224bf314cad53e9f6607 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Sat, 28 Nov 2020 15:51:27 +0100 Subject: cs2cs: add --area and --bbox options to restrict candidate coordinate operations (fixes #2423) --- docs/source/apps/cs2cs.rst | 29 ++++++++- src/apps/cs2cs.cpp | 154 +++++++++++++++++++++++++++++++++++++++++++-- test/cli/td_out.dist | 12 ++++ test/cli/testdatumfile | 21 +++++++ 4 files changed, 210 insertions(+), 6 deletions(-) diff --git a/docs/source/apps/cs2cs.rst b/docs/source/apps/cs2cs.rst index e214a5c0..7fe570d9 100644 --- a/docs/source/apps/cs2cs.rst +++ b/docs/source/apps/cs2cs.rst @@ -11,11 +11,15 @@ cs2cs Synopsis ******** - **cs2cs** [**-eEfIlrstvwW** [args]] [*+opt[=arg]* ...] [+to *+opt[=arg]* ...] file ... + **cs2cs** [**-eEfIlrstvwW** [args]] + [[--area name_or_code] | [--bbox west_long,south_lat,east_long,north_lat]] + [*+opt[=arg]* ...] [+to *+opt[=arg]* ...] file ... or - **cs2cs** [**-eEfIlrstvwW** [args]] {source_crs} {target_crs} file ... + **cs2cs** [**-eEfIlrstvwW** [args]] [--area name_or_code] + [[--area name_or_code] | [--bbox west_long,south_lat,east_long,north_lat]] + {source_crs} {target_crs} file ... where {source_crs} or {target_crs} is one of the possibilities accepted by :c:func:`proj_create`, provided it expresses a CRS @@ -144,6 +148,27 @@ The following control parameters can appear in any order: Causes a listing of cartographic control parameters tested for and used by the program to be printed prior to input data. +.. option:: --area name_or_code + + .. versionadded:: 8.0.0 + + Specify an area of interest to restrict the results when researching + coordinate operations between 2 CRS. The area of interest can be specified either + as a name (e.g "Denmark - onshore") or a AUTHORITY:CODE (EPSG:3237) + + This option is mutually exclusive with :option:`--bbox`. + +.. option:: --bbox west_long,south_lat,east_long,north_lat + + .. versionadded:: 8.0.0 + + Specify an area of interest to restrict the results when researching + coordinate operations between 2 CRS. The area of interest is specified as a + bounding box with geographic coordinates, expressed in degrees in a + unspecified geographic CRS. + `west_long` and `east_long` should be in the [-180,180] range, and + `south_lat` and `north_lat` in the [-90,90]. `west_long` is generally lower than + `east_long`, except in the case where the area of interest crosses the antimeridian. .. only:: man diff --git a/src/apps/cs2cs.cpp b/src/apps/cs2cs.cpp index 12e045bb..dd65baf4 100644 --- a/src/apps/cs2cs.cpp +++ b/src/apps/cs2cs.cpp @@ -36,8 +36,13 @@ #include #include +#include #include +#include +#include +#include + #include // PROJ include order is sensitive @@ -70,12 +75,18 @@ 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]] [+opt[=arg] ...]\n" - " [+to +opt[=arg] ...] [file ...]\n"; + "%s\nusage: %s [-dDeEfIlrstvwW [args]]\n" + " [[--area name_or_code] | [--bbox west_long,south_lat,east_long,north_lat]]\n" + " [+opt[=arg] ...] [+to +opt[=arg] ...] [file ...]\n"; static double (*informat)(const char *, char **); /* input data deformatter function */ +using namespace NS_PROJ::io; +using namespace NS_PROJ::metadata; +using namespace NS_PROJ::util; +using namespace NS_PROJ::internal; + /************************************************************************/ /* process() */ /* */ @@ -359,9 +370,47 @@ int main(int argc, char **argv) { } } + ExtentPtr bboxFilter; + std::string area; + /* process run line arguments */ while (--argc > 0) { /* collect run line arguments */ - if (**++argv == '-') { + ++argv; + if (strcmp(*argv, "--area") == 0 ) { + ++argv; + --argc; + if( argc == 0 ) { + emess(1, "missing argument for --area"); + std::exit(1); + } + area = *argv; + } + else if (strcmp(*argv, "--bbox") == 0) { + ++argv; + --argc; + if( argc == 0 ) { + emess(1, "missing argument for --bbox"); + std::exit(1); + } + auto bboxStr(*argv); + auto bbox(split(bboxStr, ',')); + if (bbox.size() != 4) { + std::cerr << "Incorrect number of values for option --bbox: " + << bboxStr << std::endl; + std::exit(1); + } + try { + bboxFilter = Extent::createFromBBOX( + c_locale_stod(bbox[0]), c_locale_stod(bbox[1]), + c_locale_stod(bbox[2]), c_locale_stod(bbox[3])) + .as_nullable(); + } catch (const std::exception &e) { + std::cerr << "Invalid value for option --bbox: " << bboxStr + << ", " << e.what() << std::endl; + std::exit(1); + } + } + else if (**argv == '-') { for (arg = *argv;;) { switch (*++arg) { case '\0': /* position of "stdin" */ @@ -536,6 +585,102 @@ int main(int argc, char **argv) { } } + if (bboxFilter && !area.empty()) { + std::cerr << "ERROR: --bbox and --area are exclusive" << std::endl; + std::exit(1); + } + + PJ_AREA* pj_area = nullptr; + if (!area.empty()) { + + DatabaseContextPtr dbContext; + try { + dbContext = + DatabaseContext::create().as_nullable(); + } catch (const std::exception &e) { + std::cerr << "ERROR: Cannot create database connection: " + << e.what() << std::endl; + std::exit(1); + } + + // Process area of use + try { + if (area.find(' ') == std::string::npos && + area.find(':') != std::string::npos) { + auto tokens = split(area, ':'); + if (tokens.size() == 2) { + const std::string &areaAuth = tokens[0]; + const std::string &areaCode = tokens[1]; + bboxFilter = AuthorityFactory::create( + NN_NO_CHECK(dbContext), areaAuth) + ->createExtent(areaCode) + .as_nullable(); + } + } + if (!bboxFilter) { + auto authFactory = AuthorityFactory::create( + NN_NO_CHECK(dbContext), std::string()); + auto res = authFactory->listAreaOfUseFromName(area, false); + if (res.size() == 1) { + bboxFilter = + AuthorityFactory::create(NN_NO_CHECK(dbContext), + res.front().first) + ->createExtent(res.front().second) + .as_nullable(); + } else { + res = authFactory->listAreaOfUseFromName(area, true); + if (res.size() == 1) { + bboxFilter = + AuthorityFactory::create(NN_NO_CHECK(dbContext), + res.front().first) + ->createExtent(res.front().second) + .as_nullable(); + } else if (res.empty()) { + std::cerr << "No area of use matching provided name" + << std::endl; + std::exit(1); + } else { + std::cerr << "Several candidates area of use " + "matching provided name :" + << std::endl; + for (const auto &candidate : res) { + auto obj = + AuthorityFactory::create( + NN_NO_CHECK(dbContext), candidate.first) + ->createExtent(candidate.second); + std::cerr << " " << candidate.first << ":" + << candidate.second << " : " + << *obj->description() << std::endl; + } + std::exit(1); + } + } + } + } catch (const std::exception &e) { + std::cerr << "Area of use retrieval failed: " << e.what() + << std::endl; + std::exit(1); + } + } + + if (bboxFilter) { + auto geogElts = bboxFilter->geographicElements(); + if (geogElts.size() == 1) + { + auto bbox = std::dynamic_pointer_cast( + geogElts[0].as_nullable()); + if (bbox) + { + pj_area = proj_area_create(); + proj_area_set_bbox(pj_area, + bbox->westBoundLongitude(), + bbox->southBoundLatitude(), + bbox->eastBoundLongitude(), + bbox->northBoundLatitude()); + } + } + } + /* * If the user has requested inverse, then just reverse the * coordinate systems. @@ -617,10 +762,11 @@ int main(int argc, char **argv) { } transformation = proj_create_crs_to_crs_from_pj(nullptr, src, dst, - nullptr, nullptr); + pj_area, nullptr); proj_destroy(src); proj_destroy(dst); + proj_area_destroy(pj_area); if (!transformation) { emess(3, "cannot initialize transformation\ncause: %s", diff --git a/test/cli/td_out.dist b/test/cli/td_out.dist index ab0c0911..6bad8e57 100644 --- a/test/cli/td_out.dist +++ b/test/cli/td_out.dist @@ -7,6 +7,18 @@ As above, but without ntv1 everything goes through conus file. 111d00'00.000"W 44d00'00.000"N 0.0 111d0'2.788"W 43d59'59.725"N 0.000 111d00'00.000"W 39d00'00.000"N 0.0 111d0'2.604"W 38d59'59.912"N 0.000 ############################################################## +Test --area Canada NAD27 NAD83 (using ntv1_can) +43d59'59.732"N 111d0'3.208"W 0.000 +* * inf +############################################################## +Test --bbox -141.01,40.04,-47.74,86.46 NAD27 NAD83 (using ntv1_can) +43d59'59.732"N 111d0'3.208"W 0.000 +* * inf +############################################################## +Test --area "USA - CONUS - onshore" NAD27 NAD83 (using conus) +43d59'59.725"N 111d0'2.788"W 0.000 +38d59'59.912"N 111d0'2.604"W 0.000 +############################################################## Test MD used where available 79d58'00.000"W 37d02'00.000"N 0.0 79d58'0.005"W 37d1'59.998"N 0.000 79d58'00.000"W 36d58'00.000"N 0.0 79d57'59.128"W 36d58'0.501"N 0.000 diff --git a/test/cli/testdatumfile b/test/cli/testdatumfile index 16e4bbc3..5a013f12 100755 --- a/test/cli/testdatumfile +++ b/test/cli/testdatumfile @@ -59,6 +59,27 @@ $EXE +proj=latlong +ellps=clrk66 '+nadgrids="./dir with "" space/myconus"' \ 111d00'00.000"W 39d00'00.000"N 0.0 EOF +echo "##############################################################" >> ${OUT} +echo "Test --area Canada NAD27 NAD83 (using ntv1_can)" >> ${OUT} +$EXE --area Canada NAD27 NAD83 >>${OUT} <> ${OUT} +echo "Test --bbox -141.01,40.04,-47.74,86.46 NAD27 NAD83 (using ntv1_can)" >> ${OUT} +$EXE --bbox -141.01,40.04,-47.74,86.46 NAD27 NAD83 >>${OUT} <> ${OUT} +echo "Test --area \"USA - CONUS - onshore\" NAD27 NAD83 (using conus)" >> ${OUT} +$EXE --area "USA - CONUS - onshore" NAD27 NAD83 >>${OUT} <> ${OUT} echo Test MD used where available >> ${OUT} # -- cgit v1.2.3 From ebe3425bf66287e004958eb53976d3837f88b9e1 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Sat, 28 Nov 2020 15:57:17 +0100 Subject: proj_create_crs_to_crs_from_pj(): do not use PROJ_SPATIAL_CRITERION_PARTIAL_INTERSECTION if area is specified --- src/4D_api.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/4D_api.cpp b/src/4D_api.cpp index 15bc73c8..9231a7ed 100644 --- a/src/4D_api.cpp +++ b/src/4D_api.cpp @@ -1287,9 +1287,11 @@ PJ *proj_create_crs_to_crs_from_pj (PJ_CONTEXT *ctx, const PJ *source_crs, cons area->east_lon_degree, area->north_lat_degree); } + else { + proj_operation_factory_context_set_spatial_criterion( + ctx, operation_ctx, PROJ_SPATIAL_CRITERION_PARTIAL_INTERSECTION); + } - proj_operation_factory_context_set_spatial_criterion( - ctx, operation_ctx, PROJ_SPATIAL_CRITERION_PARTIAL_INTERSECTION); proj_operation_factory_context_set_grid_availability_use( ctx, operation_ctx, proj_context_is_network_enabled(ctx) ? -- cgit v1.2.3 From 2a13213dcfbc5ce2ec9b5773f7463046edfc2bae Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Sat, 28 Nov 2020 16:33:10 +0100 Subject: Add github action for VS2019 x64 build --- .github/workflows/windows.yml | 62 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 .github/workflows/windows.yml diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml new file mode 100644 index 00000000..13179c18 --- /dev/null +++ b/.github/workflows/windows.yml @@ -0,0 +1,62 @@ +name: Windows build + +on: [push, pull_request] + +jobs: + + MSVC: + runs-on: windows-latest + if: "!contains(github.event.head_commit.message, '[ci skip]') && !contains(github.event.head_commit.message, '[skip ci]')" + + env: + ARCH: x64 + BUILD_SHARED_LIBS: ON + + steps: + + - uses: actions/checkout@v2 + - uses: ilammy/msvc-dev-cmd@v1 + + - name: Cache vcpkg packages + uses: actions/cache@v2 + id: cache + with: + path: c:\vcpkg\installed + key: ${{ runner.os }}-vcpkg-${{ hashFiles('.github/workflows/windows.yml') }} + + - name: Install build requirements + shell: cmd + if: steps.cache.outputs.cache-hit != 'true' + run: | + vcpkg install sqlite3[core,tool]:${{ env.ARCH }}-windows + vcpkg install tiff:${{ env.ARCH }}-windows + vcpkg install curl:${{ env.ARCH }}-windows + + - name: Build + shell: cmd + run: | + set VCPKG_INSTALLED=c:\vcpkg\installed\${{ env.ARCH }}-windows + dir %VCPKG_INSTALLED%\bin + set PATH=%VCPKG_INSTALLED%\bin;%PATH% + set PROJ_BUILD=%GITHUB_WORKSPACE%\build + mkdir %PROJ_BUILD% + cd %PROJ_BUILD% + set PROJ_DIR=%GITHUB_WORKSPACE%\proj_dir + cmake -GNinja .. -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS="{{ env.BUILD_SHARED_LIBS }}" -DCMAKE_C_FLAGS="/WX" -DCMAKE_CXX_FLAGS="/WX" -DCMAKE_TOOLCHAIN_FILE=c:/vcpkg/scripts/buildsystems/vcpkg.cmake -DCMAKE_INSTALL_PREFIX="%PROJ_DIR%" + ninja -v + ninja install + dir %PROJ_DIR%\bin + + - name: Run tests + shell: cmd + run: | + set VCPKG_INSTALLED=c:\vcpkg\installed\${{ env.ARCH }}-windows + set PATH=%VCPKG_INSTALLED%\bin;%PATH% + set PROJ_DIR=%GITHUB_WORKSPACE%\proj_dir + set PROJ_LIB=%PROJ_DIR%\share\proj + set PROJ_BUILD=%GITHUB_WORKSPACE%\build + cd %PROJ_BUILD% + ctest -V -C Release + set PATH=%PROJ_DIR%\bin;%PATH% + call %GITHUB_WORKSPACE%\test\postinstall\test_cmake.bat %PROJ_DIR% + proj -- cgit v1.2.3 From cc5d46523eeda309bd27fbb0e6db9719a361792f Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Sat, 28 Nov 2020 18:07:41 +0100 Subject: appveyor.yml: disable VS2017 x64 build --- appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index dad1f35d..17447a64 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -11,9 +11,9 @@ environment: BUILD_SHARED_LIBS: OFF # VS 2017 - - platform: x64 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 - BUILD_SHARED_LIBS: ON +# - platform: x64 +# APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 +# BUILD_SHARED_LIBS: ON shallow_clone: true -- cgit v1.2.3 From e44a2acd9bc6006b66674609d39872b6291efee7 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Sat, 28 Nov 2020 19:10:58 +0100 Subject: test/fuzzers: remove standard_fuzzer that used proj_api.h now removed --- test/fuzzers/build.sh | 4 - test/fuzzers/standard_fuzzer.cpp | 217 --------------------------------------- 2 files changed, 221 deletions(-) delete mode 100644 test/fuzzers/standard_fuzzer.cpp diff --git a/test/fuzzers/build.sh b/test/fuzzers/build.sh index 1b2bf79c..37a207e0 100755 --- a/test/fuzzers/build.sh +++ b/test/fuzzers/build.sh @@ -69,12 +69,8 @@ build_fuzzer() $LIB_FUZZING_ENGINE src/.libs/libproj.a $EXTRA_LIBS } -build_fuzzer standard_fuzzer test/fuzzers/standard_fuzzer.cpp build_fuzzer proj_crs_to_crs_fuzzer test/fuzzers/proj_crs_to_crs_fuzzer.cpp -echo "[libfuzzer]" > $OUT/standard_fuzzer.options -echo "max_len = 10000" >> $OUT/standard_fuzzer.options - echo "[libfuzzer]" > $OUT/proj_crs_to_crs_fuzzer.options echo "max_len = 10000" >> $OUT/proj_crs_to_crs_fuzzer.options diff --git a/test/fuzzers/standard_fuzzer.cpp b/test/fuzzers/standard_fuzzer.cpp deleted file mode 100644 index d54caa79..00000000 --- a/test/fuzzers/standard_fuzzer.cpp +++ /dev/null @@ -1,217 +0,0 @@ -/****************************************************************************** - * - * Project: proj.4 - * Purpose: Fuzzer - * Author: Even Rouault, even.rouault at spatialys.com - * - ****************************************************************************** - * Copyright (c) 2017, Even Rouault - * - * 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 -#include -#include -#include -#include -#include -#include - -#include "proj.h" -#include "proj_internal.h" - -/* Standalone build: -g++ -g -std=c++11 standard_fuzzer.cpp -o standard_fuzzer -fvisibility=hidden -DSTANDALONE ../../src/.libs/libproj.a -lpthread -lsqlite3 -I../../src -I../../include -*/ - -extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv); -extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len); - -int LLVMFuzzerInitialize(int* /*argc*/, char*** argv) -{ - const char* argv0 = (*argv)[0]; - char* path = pj_strdup(argv0); - char* lastslash = strrchr(path, '/'); - if( lastslash ) - { - *lastslash = '\0'; - setenv("PROJ_LIB", path, 1); - } - else - { - setenv("PROJ_LIB", ".", 1); - } - free(path); - return 0; -} - -int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) -{ - if( len > 1000 ) - { -#ifdef STANDALONE - fprintf(stderr, "Input too large\n"); -#endif - return 0; - } - - /* We expect the blob to be 3 lines: */ - /* source proj string\ndestination proj string\nx y */ - char* buf_dup = (char*)malloc(len+1); - memcpy(buf_dup, buf, len); - buf_dup[len] = 0; - char* first_line = buf_dup; - char* first_newline = strchr(first_line, '\n'); - if( !first_newline ) - { - free(buf_dup); - return 0; - } - first_newline[0] = 0; - char* second_line = first_newline + 1; - char* second_newline = strchr(second_line, '\n'); - if( !second_newline ) - { - free(buf_dup); - return 0; - } - second_newline[0] = 0; - char* third_line = second_newline + 1; - PJ *pj_src = pj_init_plus(first_line); - if( !pj_src ) - { - free(buf_dup); - return 0; - } - PJ *pj_dst = pj_init_plus(second_line); - if( !pj_dst ) - { - free(buf_dup); - pj_free(pj_src); - proj_cleanup(); - return 0; - } - double x = 0, y = 0, z = 9; - bool from_binary = false; - bool has_z = false; - if( strncmp(third_line, "BINARY_2D:", strlen("BINARY_2D:")) == 0 && - third_line - first_line + strlen("BINARY_2D:") + 2 * sizeof(double) <= len ) - { - from_binary = true; - memcpy(&x, third_line + strlen("BINARY_2D:"), sizeof(double)); - memcpy(&y, third_line + strlen("BINARY_2D:") + sizeof(double), sizeof(double)); - } - else if( strncmp(third_line, "BINARY_3D:", strlen("BINARY_3D:")) == 0 && - third_line - first_line + strlen("BINARY_3D:") + 3 * sizeof(double) <= len ) - { - from_binary = true; - has_z = true; - memcpy(&x, third_line + strlen("BINARY_3D:"), sizeof(double)); - memcpy(&y, third_line + strlen("BINARY_3D:") + sizeof(double), sizeof(double)); - memcpy(&z, third_line + strlen("BINARY_3D:") + 2 * sizeof(double), sizeof(double)); - } - else if( sscanf(third_line, "%lf %lf", &x, &y) != 2 ) - { - free(buf_dup); - pj_free(pj_src); - pj_free(pj_dst); - proj_cleanup(); - return 0; - } -#ifdef STANDALONE - fprintf(stderr, "src=%s\n", first_line); - fprintf(stderr, "dst=%s\n", second_line); - if( from_binary ) - { - if( has_z ) - fprintf(stderr, "coord (from binary)=%.18g %.18g %.18g\n", x, y, z); - else - fprintf(stderr, "coord (from binary)=%.18g %.18g\n", x, y); - } - else - fprintf(stderr, "coord=%s\n", third_line); -#endif - if( has_z ) - pj_transform( pj_src, pj_dst, 1, 0, &x, &y, &z ); - else - pj_transform( pj_src, pj_dst, 1, 0, &x, &y, NULL ); - free(buf_dup); - pj_free(pj_src); - pj_free(pj_dst); - proj_cleanup(); - return 0; -} - -#ifdef STANDALONE - -int main(int argc, char* argv[]) -{ - if( argc < 2 ) - { - const char str[] = - "+proj=longlat +datum=WGS84 +nodefs\n+proj=longlat +datum=WGS84 +nodefs\n2 49"; - int ret = LLVMFuzzerTestOneInput((const uint8_t*)(str), sizeof(str) - 1); - if( ret ) - return ret; - - const char str2[] = - "+proj=longlat +datum=WGS84 +nodefs\n+proj=longlat +datum=WGS84 +nodefs\nBINARY_2D:\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF"; - ret = LLVMFuzzerTestOneInput((const uint8_t*)(str2), sizeof(str2) - 1); - if( ret ) - return ret; - - const char str3[] = - "+proj=longlat +datum=WGS84 +nodefs\n+proj=longlat +datum=WGS84 +nodefs\nBINARY_3D:\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00"; - ret = LLVMFuzzerTestOneInput((const uint8_t*)(str3), sizeof(str3) - 1); - if( ret ) - return ret; - - return 0; - } - else - { - int nRet = 0; - void* buf = NULL; - int nLen = 0; - FILE* f = fopen(argv[1], "rb"); - if( !f ) - { - fprintf(stderr, "%s does not exist.\n", argv[1]); - exit(1); - } - fseek(f, 0, SEEK_END); - nLen = (int)ftell(f); - fseek(f, 0, SEEK_SET); - buf = malloc(nLen); - if( !buf ) - { - fprintf(stderr, "malloc failed.\n"); - fclose(f); - exit(1); - } - fread(buf, nLen, 1, f); - fclose(f); - nRet = LLVMFuzzerTestOneInput((const uint8_t*)(buf), nLen); - free(buf); - return nRet; - } -} - -#endif // STANDALONE -- cgit v1.2.3 From c6dda7637c0c49ece9216395caffa2bbd6184a92 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Sat, 28 Nov 2020 20:02:15 +0100 Subject: WKT1 import: better deal with apps.epsg.org output w.r.t datum ensemble names --- src/iso19111/io.cpp | 8 +++++++- test/unit/test_io.cpp | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/src/iso19111/io.cpp b/src/iso19111/io.cpp index 52d46d27..125105ec 100644 --- a/src/iso19111/io.cpp +++ b/src/iso19111/io.cpp @@ -2163,9 +2163,15 @@ GeodeticReferenceFrameNNPtr WKTParser::Private::buildGeodeticReferenceFrame( return false; }; - if (name == "WGS_1984") { + // Remap GDAL WGS_1984 to EPSG v9 "World Geodetic System 1984" official + // name. + // Also remap EPSG v10 datum ensemble names to non-ensemble EPSG v9 + if (name == "WGS_1984" || name == "World Geodetic System 1984 ensemble") { properties.set(IdentifiedObject::NAME_KEY, GeodeticReferenceFrame::EPSG_6326->nameStr()); + } else if (name == "European Terrestrial Reference System 1989 ensemble") { + properties.set(IdentifiedObject::NAME_KEY, + "European Terrestrial Reference System 1989"); } else if (starts_with(name, "D_")) { esriStyle_ = true; const char *tableNameForAlias = nullptr; diff --git a/test/unit/test_io.cpp b/test/unit/test_io.cpp index f0e221d8..5463adc3 100644 --- a/test/unit/test_io.cpp +++ b/test/unit/test_io.cpp @@ -675,6 +675,53 @@ TEST(wkt_parse, wkt1_geographic_with_PROJ4_extension) { // --------------------------------------------------------------------------- +TEST(wkt_parse, wkt1_geographic_epsg_org_api_4326) { + // Output from + // https://apps.epsg.org/api/v1/CoordRefSystem/4326/export/?format=wkt&formatVersion=1 + // using a datum ensemble name + auto wkt = + "GEOGCS[\"WGS 84\",DATUM[\"World Geodetic System 1984 ensemble\"," + "SPHEROID[\"WGS 84\",6378137,298.257223563," + "AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]]," + "PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]]," + "UNIT[\"degree (supplier to define representation)\"," + "0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]]," + "AXIS[\"Lat\",north],AXIS[\"Lon\",east]," + "AUTHORITY[\"EPSG\",\"4326\"]]"; + auto obj = WKTParser().createFromWKT(wkt); + auto crs = nn_dynamic_pointer_cast(obj); + ASSERT_TRUE(crs != nullptr); + + auto datum = crs->datum(); + EXPECT_EQ(datum->nameStr(), "World Geodetic System 1984"); +} + +// --------------------------------------------------------------------------- + +TEST(wkt_parse, wkt1_geographic_epsg_org_api_4258) { + // Output from + // https://apps.epsg.org/api/v1/CoordRefSystem/4258/export/?format=wkt&formatVersion=1 + // using a datum ensemble name + auto wkt = + "GEOGCS[\"ETRS89\"," + "DATUM[\"European Terrestrial Reference System 1989 ensemble\"," + "SPHEROID[\"GRS 1980\",6378137,298.257222101," + "AUTHORITY[\"EPSG\",\"7019\"]],AUTHORITY[\"EPSG\",\"6258\"]]," + "PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]]," + "UNIT[\"degree (supplier to define representation)\"," + "0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]]," + "AXIS[\"Lat\",north],AXIS[\"Lon\",east]," + "AUTHORITY[\"EPSG\",\"4258\"]]"; + auto obj = WKTParser().createFromWKT(wkt); + auto crs = nn_dynamic_pointer_cast(obj); + ASSERT_TRUE(crs != nullptr); + + auto datum = crs->datum(); + EXPECT_EQ(datum->nameStr(), "European Terrestrial Reference System 1989"); +} + +// --------------------------------------------------------------------------- + TEST(wkt_parse, wkt1_geocentric_with_PROJ4_extension) { auto wkt = "GEOCCS[\"WGS 84\",\n" " DATUM[\"unknown\",\n" -- cgit v1.2.3 From 87270ae6f1840872d5f49c70258941197b0ce809 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Sat, 28 Nov 2020 23:39:33 +0100 Subject: createOperations(): get a '+proj=noop' instead of '+proj=affine +s33=-1' when attempting (non-sensical) EPSG:3855 to EPSG:4326 --- src/iso19111/coordinateoperation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/iso19111/coordinateoperation.cpp b/src/iso19111/coordinateoperation.cpp index 0f1c680b..5ef32d31 100644 --- a/src/iso19111/coordinateoperation.cpp +++ b/src/iso19111/coordinateoperation.cpp @@ -14837,7 +14837,7 @@ void CoordinateOperationFactory::Private::createOperationsVertToGeogBallpark( double convDst = 1.0; const auto &geogAxis = geogDst->coordinateSystem()->axisList(); bool dstIsUp = true; - bool dstIsDown = true; + bool dstIsDown = false; if (geogAxis.size() == 3) { const auto &dstAxis = geogAxis[2]; convDst = dstAxis->unit().conversionToSI(); -- cgit v1.2.3 From bc0c9f3e96dc4a9829f1f3d1e1307b4dd5dd10de Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Sun, 29 Nov 2020 14:10:15 +0100 Subject: Inverse tmerc spherical: fix wrong sign of latitude when lat_0 is used (fixes #2468) Corrected formula given by @evanmiller --- src/projections/tmerc.cpp | 6 ++- test/gie/builtins.gie | 124 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 128 insertions(+), 2 deletions(-) diff --git a/src/projections/tmerc.cpp b/src/projections/tmerc.cpp index 8cae9968..2d13b064 100644 --- a/src/projections/tmerc.cpp +++ b/src/projections/tmerc.cpp @@ -203,11 +203,13 @@ static PJ_LP approx_s_inv (PJ_XY xy, PJ *P) { return proj_coord_error().lp; } g = .5 * (h - 1. / h); - h = cos (P->phi0 + xy.y / Q->esp); + /* D, as in equation 8-8 of USGS "Map Projections - A Working Manual" */ + const double D = P->phi0 + xy.y / Q->esp; + h = cos (D); lp.phi = asin(sqrt((1. - h * h) / (1. + g * g))); /* Make sure that phi is on the correct hemisphere when false northing is used */ - if (xy.y < 0. && -lp.phi+P->phi0 < 0.0) lp.phi = -lp.phi; + lp.phi = copysign(lp.phi, D); lp.lam = (g != 0.0 || h != 0.0) ? atan2 (g, h) : 0.; return lp; diff --git a/test/gie/builtins.gie b/test/gie/builtins.gie index add5d925..0f86bed2 100644 --- a/test/gie/builtins.gie +++ b/test/gie/builtins.gie @@ -5781,6 +5781,130 @@ expect -0.001790493 0.000895247 accept -200 -100 expect -0.001790493 -0.000895247 +------------------------------------------------------------------------------- +# Approx tmerc on a almost spherical ellipsoid, lat_0 north hemisphere + +operation +proj=tmerc +a=6400000 +rf=1e12 +k=0.9 +lat_0=40 +approx +------------------------------------------------------------------------------- +tolerance 0.1 mm + +accept 0 -30 +expect 0 -7037167.5440 +roundtrip 1 + +accept 1 -30 +expect 87064.5795 -7037547.4590 +roundtrip 1 + +accept -1 -30 +expect -87064.5795 -7037547.4590 +roundtrip 1 + +accept 0 30 +expect 0 -1005309.6491 +roundtrip 1 + +accept 0 40 +expect 0 0 +roundtrip 1 + +accept 1 41 +expect 75872.2182 100965.3718 +roundtrip 1 + +------------------------------------------------------------------------------- +# Approx tmerc on a sphere, lat_0 north hemisphere + +operation +proj=tmerc +R=6400000 +k=0.9 +lat_0=40 +------------------------------------------------------------------------------- +tolerance 0.1 mm + +accept 0 -30 +expect 0 -7037167.5440 +roundtrip 1 + +accept 1 -30 +expect 87064.5795 -7037547.4590 +roundtrip 1 + +accept -1 -30 +expect -87064.5795 -7037547.4590 +roundtrip 1 + +accept 0 30 +expect 0 -1005309.6491 +roundtrip 1 + +accept 0 40 +expect 0 0 +roundtrip 1 + +accept 1 41 +expect 75872.2182 100965.3718 +roundtrip 1 + +------------------------------------------------------------------------------- +# Approx tmerc on a almost spherical ellipsoid, lat_0 south hemisphere + +operation +proj=tmerc +a=6400000 +rf=1e12 +k=0.9 +lat_0=-40 +approx +------------------------------------------------------------------------------- +tolerance 0.1 mm + +accept 0 -30 +expect 0 1005309.6491 +roundtrip 1 + +accept 1 -30 +expect 87064.5795 1004929.7341 +roundtrip 1 + +accept -1 -30 +expect -87064.5795 1004929.7341 +roundtrip 1 + +accept 0 30 +expect 0 7037167.5440 +roundtrip 1 + +accept 0 -40 +expect 0 0 +roundtrip 1 + +accept 1 -41 +expect 75872.2182 -100965.3718 +roundtrip 1 + +------------------------------------------------------------------------------- +# Approx tmerc on a sphere, lat_0 south hemisphere + +operation +proj=tmerc +R=6400000 +k=0.9 +lat_0=-40 +------------------------------------------------------------------------------- +tolerance 0.1 mm + +accept 0 -30 +expect 0 1005309.6491 +roundtrip 1 + +accept 1 -30 +expect 87064.5795 1004929.7341 +roundtrip 1 + +accept -1 -30 +expect -87064.5795 1004929.7341 +roundtrip 1 + +accept 0 30 +expect 0 7037167.5440 +roundtrip 1 + +accept 0 -40 +expect 0 0 +roundtrip 1 + +accept 1 -41 +expect 75872.2182 -100965.3718 +roundtrip 1 + ------------------------------------------------------------------------------- operation +proj=tmerc +R=1 ------------------------------------------------------------------------------- -- cgit v1.2.3 From 284feecd27f3fd43569d3d37d62ae7b0153c20ce Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Sun, 29 Nov 2020 20:53:21 +0100 Subject: Spherical tmerc forward: do not restrict to [-90,90] longitude range The restriction was a copy&paste from the Evenden/Snyder approximate ellipsoidal implementation, but the spherical one is exact, so this restriction isn't needed. Also tune a bit the handling of lat=0, |lon| > 90 --- src/projections/tmerc.cpp | 29 +++++++------------- test/gie/builtins.gie | 68 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 19 deletions(-) diff --git a/src/projections/tmerc.cpp b/src/projections/tmerc.cpp index 2d13b064..8f897061 100644 --- a/src/projections/tmerc.cpp +++ b/src/projections/tmerc.cpp @@ -115,25 +115,11 @@ static PJ_XY approx_e_fwd (PJ_LP lp, PJ *P) return (xy); } -static PJ_XY approx_s_fwd (PJ_LP lp, PJ *P) { +static PJ_XY tmerc_spherical_fwd (PJ_LP lp, PJ *P) { PJ_XY xy = {0.0,0.0}; double b, cosphi; const auto *Q = &(static_cast(P->opaque)->approx); - /* - * Fail if our longitude is more than 90 degrees from the - * central meridian since the results are essentially garbage. - * Is error -20 really an appropriate return value? - * - * http://trac.osgeo.org/proj/ticket/5 - */ - if( lp.lam < -M_HALFPI || lp.lam > M_HALFPI ) { - xy.x = HUGE_VAL; - xy.y = HUGE_VAL; - proj_context_errno_set( P->ctx, PJD_ERR_LAT_OR_LON_EXCEED_LIMIT ); - return xy; - } - cosphi = cos(lp.phi); b = cosphi * sin (lp.lam); if (fabs (fabs (b) - 1.) <= EPS10) { @@ -145,7 +131,12 @@ static PJ_XY approx_s_fwd (PJ_LP lp, PJ *P) { xy.y = cosphi * cos (lp.lam) / sqrt (1. - b * b); b = fabs ( xy.y ); - if (b >= 1.) { + if (cosphi == 1 && (lp.lam < -M_HALFPI || lp.lam > M_HALFPI) ) { + /* Helps to be able to roundtrip |longitudes| > 90 at lat=0 */ + /* We could also map to -M_PI ... */ + xy.y = M_PI; + } + else if (b >= 1.) { if ((b - 1.) > EPS10) { proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION); return xy; @@ -192,7 +183,7 @@ static PJ_LP approx_e_inv (PJ_XY xy, PJ *P) { return lp; } -static PJ_LP approx_s_inv (PJ_XY xy, PJ *P) { +static PJ_LP tmerc_spherical_inv (PJ_XY xy, PJ *P) { PJ_LP lp = {0.0, 0.0}; double h, g; const auto *Q = &(static_cast(P->opaque)->approx); @@ -611,8 +602,8 @@ static PJ *setup(PJ *P, TMercAlgo eAlg) { return nullptr; if( P->es == 0 ) { - P->inv = approx_s_inv; - P->fwd = approx_s_fwd; + P->inv = tmerc_spherical_inv; + P->fwd = tmerc_spherical_fwd; } else { diff --git a/test/gie/builtins.gie b/test/gie/builtins.gie index 0f86bed2..e870f1d4 100644 --- a/test/gie/builtins.gie +++ b/test/gie/builtins.gie @@ -5771,6 +5771,74 @@ expect -223413.466406322 111769.145040597 accept -2 -1 expect -223413.466406322 -111769.145040597 +accept 0 0 +expect 0 0 +roundtrip 1 + +accept 0 90 +expect 0 10053096.491487337276 +roundtrip 1 + +accept 0 -90 +expect 0 -10053096.491487337276 +roundtrip 1 + +accept 170 60 +expect 557076.820490954560 13361866.764138307422 +roundtrip 1 + +accept 89 0.01 +expect 30344312.098578717560 64001.116414904580 +roundtrip 1 + +accept 91 0.01 +expect 30344312.098578717560 20042191.866555366665 +roundtrip 1 + +accept 179.999 0.01 +expect 111.701070433669 20105075.972255337983 +roundtrip 1 + +accept -89 0.01 +expect -30344312.098578717560 64001.116414904580 +roundtrip 1 + +accept -91 0.01 +expect -30344312.098578717560 20042191.866555366665 +roundtrip 1 + +accept -179.999 0.01 +expect -111.701070433669 20105075.972255337983 +roundtrip 1 + +accept 89 -0.01 +expect 30344312.098578717560 -64001.116414904580 +roundtrip 1 + +accept 91 -0.01 +expect 30344312.098578717560 -20042191.866555366665 +roundtrip 1 + +accept 179.999 -0.01 +expect 111.701070433669 -20105075.972255337983 +roundtrip 1 + +accept -89 -0.01 +expect -30344312.098578717560 -64001.116414904580 +roundtrip 1 + +accept -91 -0.01 +expect -30344312.098578717560 -20042191.866555366665 +roundtrip 1 + +accept -179.999 -0.01 +expect -111.701070433669 -20105075.972255337983 +roundtrip 1 + +accept 150 0 +expect 3515559.323737951461 20106192.982974674553 +roundtrip 1 + direction inverse accept 200 100 expect 0.001790493 0.000895247 -- cgit v1.2.3 From ee534a70ef35ba34f773d92ce336108e8d90b6bd Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Mon, 30 Nov 2020 00:31:21 +0100 Subject: pj_datum_set(): make code more obvious to humans and analyzers --- src/datum_set.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/datum_set.cpp b/src/datum_set.cpp index 398d85cd..3f612633 100644 --- a/src/datum_set.cpp +++ b/src/datum_set.cpp @@ -84,25 +84,27 @@ int pj_datum_set(PJ_CONTEXT *ctx, paralist *pl, PJ *projdef) sizeof(entry) - 1 - strlen(entry) ); entry[ sizeof(entry) - 1 ] = '\0'; - curr = curr->next = pj_mkparam(entry); - if (nullptr == curr) + auto param = pj_mkparam(entry); + if (nullptr == param) { proj_context_errno_set(ctx, ENOMEM); return 1; } + curr->next = param; + curr = param; } if( pj_datums[i].defn && strlen(pj_datums[i].defn) > 0 ) { - curr = curr->next = pj_mkparam(pj_datums[i].defn); - if (nullptr == curr) + auto param = pj_mkparam(pj_datums[i].defn); + if (nullptr == param) { proj_context_errno_set(ctx, ENOMEM); return 1; } + curr->next = param; + /* curr = param; */ } - - (void)curr; /* make clang static analyzer happy */ } /* -------------------------------------------------------------------- */ -- cgit v1.2.3 From f4dc79075c19706dda6e3253c2f224e9df468291 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Mon, 30 Nov 2020 01:35:59 +0100 Subject: API cleanup: unexport number of internal symbols, and remove/replace a few unused ones --- scripts/reference_exported_symbols.txt | 17 ----- src/Makefile.am | 4 +- src/apps/proj.cpp | 18 +++--- src/init.cpp | 97 ----------------------------- src/proj_internal.h | 32 +++++----- src/projections/ob_tran.cpp | 9 +-- src/tests/test228.cpp | 109 --------------------------------- test/cli/Makefile.am | 6 +- 8 files changed, 34 insertions(+), 258 deletions(-) delete mode 100644 src/tests/test228.cpp diff --git a/scripts/reference_exported_symbols.txt b/scripts/reference_exported_symbols.txt index ee734297..167b8a27 100644 --- a/scripts/reference_exported_symbols.txt +++ b/scripts/reference_exported_symbols.txt @@ -743,44 +743,27 @@ osgeo::proj::VerticalShiftGridSet::~VerticalShiftGridSet() osgeo::proj::VerticalShiftGridSet::VerticalShiftGridSet() osgeo::proj::VerticalShiftGrid::~VerticalShiftGrid() osgeo::proj::VerticalShiftGrid::VerticalShiftGrid(std::string const&, int, int, osgeo::proj::ExtentAndRes const&) -pj_acquire_lock() pj_add_type_crs_if_needed(std::string const&) pj_approx_2D_trans(PJconsts*, PJ_DIRECTION, PJ_COORD) pj_approx_3D_trans(PJconsts*, PJ_DIRECTION, PJ_COORD) pj_atof(char const*) pj_chomp(char*) -pj_cleanup_lock() -pj_clear_initcache() pj_context_get_grid_cache_filename(pj_ctx*) pj_context_set_user_writable_directory(pj_ctx*, std::string const&) pj_ell_set(pj_ctx*, ARG_list*, double*, double*) -pj_find_file(pj_ctx*, char const*, char*, unsigned long) -pj_fwd3d(PJ_LPZ, PJconsts*) pj_fwd(PJ_LP, PJconsts*) -pj_get_ctx(PJconsts*) pj_get_datums_ref() pj_get_default_ctx() pj_get_default_searchpaths(pj_ctx*) -pj_get_def(PJconsts*, int) pj_get_relative_share_proj(pj_ctx*) pj_get_release() -pj_has_inverse(PJconsts*) -pj_init_ctx(pj_ctx*, int, char**) -pj_init(int, char**) -pj_init_plus(char const*) -pj_init_plus_ctx(pj_ctx*, char const*) -pj_inv3d(PJ_XYZ, PJconsts*) pj_inv(PJ_XY, PJconsts*) -pj_log(pj_ctx*, int, char const*, ...) pj_mkparam(char const*) pj_param_exists(ARG_list*, char const*) pj_param(pj_ctx*, ARG_list*, char const*) pj_phi2(pj_ctx*, double, double) pj_pr_list(PJconsts*) -pj_release_lock() pj_shrink(char*) -pj_stderr_logger(void*, int, char const*) -pj_strdup(char const*) proj_alter_id proj_alter_name proj_angular_input diff --git a/src/Makefile.am b/src/Makefile.am index 4f3db3ed..1d772207 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,6 +1,6 @@ AM_CFLAGS = @C_WFLAGS@ -EXTRA_PROGRAMS = multistresstest test228 +EXTRA_PROGRAMS = multistresstest TESTS = geodtest check_PROGRAMS = geodtest @@ -36,7 +36,6 @@ bin_PROGRAMS = proj geod cs2cs gie cct projinfo $(PROJSYNC_BIN) gie_SOURCES = apps/gie.cpp apps/proj_strtod.cpp apps/proj_strtod.h apps/optargpm.h multistresstest_SOURCES = tests/multistresstest.cpp -test228_SOURCES = tests/test228.cpp geodtest_SOURCES = tests/geodtest.cpp cct_LDADD = libproj.la @@ -47,7 +46,6 @@ projinfo_LDADD = libproj.la gie_LDADD = libproj.la multistresstest_LDADD = libproj.la @THREAD_LIB@ -test228_LDADD = libproj.la @THREAD_LIB@ geodtest_LDADD = libproj.la lib_LTLIBRARIES = libproj.la diff --git a/src/apps/proj.cpp b/src/apps/proj.cpp index a5c917f6..0108cb74 100644 --- a/src/apps/proj.cpp +++ b/src/apps/proj.cpp @@ -9,6 +9,8 @@ #include "emess.h" #include "utils.h" +#include + #if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__WIN32__) # include # include @@ -292,10 +294,10 @@ static void vprocess(FILE *fid) { int main(int argc, char **argv) { char *arg; - char *pargv[MAX_PARGS] = {}; + std::vector argvVector; char **eargv = argv; FILE *fid; - int pargc = 0, eargc = 0, mon = 0; + int eargc = 0, mon = 0; if ( (emess_dat.Prog_name = strrchr(*argv,DIR_CHAR)) != nullptr) ++emess_dat.Prog_name; @@ -450,10 +452,7 @@ int main(int argc, char **argv) { } break; } else if (**argv == '+') { /* + argument */ - if (pargc < MAX_PARGS) - pargv[pargc++] = *argv + 1; - else - emess(1,"overflowed + argument table"); + argvVector.push_back(*argv + 1); } else /* assumed to be input file name(s) */ eargv[eargc++] = *argv; } @@ -473,7 +472,12 @@ int main(int argc, char **argv) { postscale = 0; fscale = 1./fscale; } - if (!(Proj = pj_init(pargc, pargv))) + proj_context_use_proj4_init_rules(nullptr, true); + + // proj historically ignores any datum shift specifier, like nadgrids, towgs84, etc + argvVector.push_back(const_cast("break_cs2cs_recursion")); + + if (!(Proj = proj_create_argv(nullptr, static_cast(argvVector.size()), argvVector.data()))) emess(3,"projection initialization failure\ncause: %s", proj_errno_string(proj_context_errno(nullptr))); diff --git a/src/init.cpp b/src/init.cpp index 7b614c5f..1e89402d 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -399,90 +399,6 @@ paralist *pj_expand_init(PJ_CONTEXT *ctx, paralist *init) { } -/************************************************************************/ -/* pj_init_plus() */ -/* */ -/* Same as pj_init() except it takes one argument string with */ -/* individual arguments preceded by '+', such as "+proj=utm */ -/* +zone=11 +ellps=WGS84". */ -/************************************************************************/ - -PJ * -pj_init_plus( const char *definition ) - -{ - return pj_init_plus_ctx( pj_get_default_ctx(), definition ); -} - -PJ * -pj_init_plus_ctx( PJ_CONTEXT *ctx, const char *definition ) -{ -#define MAX_ARG 200 - char *argv[MAX_ARG]; - char *defn_copy; - int argc = 0, i, blank_count = 0; - PJ *result = nullptr; - - /* make a copy that we can manipulate */ - defn_copy = (char *) malloc( strlen(definition)+1 ); - if (!defn_copy) - return nullptr; - strcpy( defn_copy, definition ); - - /* split into arguments based on '+' and trim white space */ - - for( i = 0; defn_copy[i] != '\0'; i++ ) - { - switch( defn_copy[i] ) - { - case '+': - if( i == 0 || defn_copy[i-1] == '\0' || blank_count > 0 ) - { - /* trim trailing spaces from the previous param */ - if( blank_count > 0 ) - { - defn_copy[i - blank_count] = '\0'; - blank_count = 0; - } - - if( argc+1 == MAX_ARG ) - { - free( defn_copy ); - proj_context_errno_set( ctx, PJD_ERR_UNPARSEABLE_CS_DEF ); - return nullptr; - } - - argv[argc++] = defn_copy + i + 1; - } - break; - - case ' ': - case '\t': - case '\n': - /* trim leading spaces from the current param */ - if( i == 0 || defn_copy[i-1] == '\0' || argc == 0 || argv[argc-1] == defn_copy + i ) - defn_copy[i] = '\0'; - else - blank_count++; - break; - - default: - /* reset blank_count */ - blank_count = 0; - } - } - /* trim trailing spaces from the last param */ - defn_copy[i - blank_count] = '\0'; - - /* perform actual initialization */ - result = pj_init_ctx( ctx, argc, argv ); - - free( defn_copy ); - return result; -} - - - /************************************************************************/ /* pj_init() */ /* */ @@ -492,11 +408,6 @@ pj_init_plus_ctx( PJ_CONTEXT *ctx, const char *definition ) /* large enough to hold projection specific parameters. */ /************************************************************************/ -PJ * -pj_init(int argc, char **argv) { - return pj_init_ctx( pj_get_default_ctx(), argc, argv ); -} - static PJ_CONSTRUCTOR locate_constructor (const char *name) { int i; @@ -510,14 +421,6 @@ static PJ_CONSTRUCTOR locate_constructor (const char *name) { } -PJ * -pj_init_ctx(PJ_CONTEXT *ctx, int argc, char **argv) { - /* Legacy interface: allow init=epsg:XXXX syntax by default */ - int allow_init_epsg = proj_context_get_use_proj4_init_rules(ctx, TRUE); - return pj_init_ctx_with_allow_init_epsg(ctx, argc, argv, allow_init_epsg); -} - - PJ * pj_init_ctx_with_allow_init_epsg(PJ_CONTEXT *ctx, int argc, char **argv, int allow_init_epsg) { const char *s; diff --git a/src/proj_internal.h b/src/proj_internal.h index 234ff80e..32aaa1ec 100644 --- a/src/proj_internal.h +++ b/src/proj_internal.h @@ -934,35 +934,31 @@ extern char const PROJ_DLL pj_release[]; /* global release id string */ /* procedure prototypes */ PJ_CONTEXT PROJ_DLL *pj_get_default_ctx(void); -PJ_CONTEXT PROJ_DLL *pj_get_ctx( PJ *); +PJ_CONTEXT *pj_get_ctx( PJ *); PJ_XY PROJ_DLL pj_fwd(PJ_LP, PJ *); PJ_LP PROJ_DLL pj_inv(PJ_XY, PJ *); -PJ_XYZ PROJ_DLL pj_fwd3d(PJ_LPZ, PJ *); -PJ_LPZ PROJ_DLL pj_inv3d(PJ_XYZ, PJ *); +PJ_XYZ pj_fwd3d(PJ_LPZ, PJ *); +PJ_LPZ pj_inv3d(PJ_XYZ, PJ *); -void PROJ_DLL pj_clear_initcache(void); -void PROJ_DLL pj_pr_list(PJ *); -PJ PROJ_DLL *pj_init(int, char **); -PJ PROJ_DLL *pj_init_plus(const char *); -PJ PROJ_DLL *pj_init_ctx( PJ_CONTEXT *, int, char ** ); -PJ PROJ_DLL *pj_init_plus_ctx( PJ_CONTEXT *, const char * ); -char PROJ_DLL *pj_get_def(PJ *, int); -int PROJ_DLL pj_has_inverse(PJ *); +void pj_clear_initcache(void); +void PROJ_DLL pj_pr_list(PJ *); /* used by proj.cpp */ +char *pj_get_def(PJ *, int); +int pj_has_inverse(PJ *); -char PROJ_DLL *pj_strdup(const char *str); +char *pj_strdup(const char *str); const char PROJ_DLL *pj_get_release(void); -void PROJ_DLL pj_acquire_lock(void); -void PROJ_DLL pj_release_lock(void); -void PROJ_DLL pj_cleanup_lock(void); +void pj_acquire_lock(void); +void pj_release_lock(void); +void pj_cleanup_lock(void); -void PROJ_DLL pj_log( PJ_CONTEXT * ctx, int level, const char *fmt, ... ); -void PROJ_DLL pj_stderr_logger( void *, int, const char * ); +void pj_log( PJ_CONTEXT * ctx, int level, const char *fmt, ... ); +void pj_stderr_logger( void *, int, const char * ); -int PROJ_DLL pj_find_file(PJ_CONTEXT * ctx, const char *short_filename, +int pj_find_file(PJ_CONTEXT * ctx, const char *short_filename, char* out_full_filename, size_t out_full_filename_size); diff --git a/src/projections/ob_tran.cpp b/src/projections/ob_tran.cpp index 4990ab2a..86798e0a 100644 --- a/src/projections/ob_tran.cpp +++ b/src/projections/ob_tran.cpp @@ -141,14 +141,15 @@ static ARGS ob_tran_target_params (paralist *params) { if (argc < 2) return args; - /* all args except the proj_ob_tran */ + /* all args except the proj=ob_tran */ args.argv = static_cast(calloc (argc - 1, sizeof (char *))); if (nullptr==args.argv) return args; - /* Copy all args *except* the proj=ob_tran arg to the argv array */ + /* Copy all args *except* the proj=ob_tran or inv arg to the argv array */ for (i = 0; params != nullptr; params = params->next) { - if (0==strcmp (params->param, "proj=ob_tran")) + if (0==strcmp (params->param, "proj=ob_tran") || + 0==strcmp (params->param, "inv") ) continue; args.argv[i++] = params->param; } @@ -194,7 +195,7 @@ PJ *PROJECTION(ob_tran) { 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); + R = proj_create_argv (P->ctx, args.argc, args.argv); free (args.argv); if (nullptr==R) diff --git a/src/tests/test228.cpp b/src/tests/test228.cpp deleted file mode 100644 index ae2eb9cc..00000000 --- a/src/tests/test228.cpp +++ /dev/null @@ -1,109 +0,0 @@ -/****************************************************************************** - * - * Project: PROJ - * Purpose: Test - * Author: Even Rouault - * - ****************************************************************************** - * Copyright (c) 2014, Even Rouault - * - * 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 "proj_internal.h" -#include /* for printf declaration */ - - -#ifdef _WIN32 - -int main(int argc, char* argv[]) -{ - printf("Test not yet ported on Win32\n"); - return 0; -} - -#else - -#include -#include -#include -#include - -static volatile int run = 0; -static volatile int started = 0; - -static void* thread_main(void* unused) -{ - PJ_CONTEXT *p_proj_ctxt; - PJ *p_WGS84_proj; - PJ * p_OSGB36_proj; - (void)unused; - - __sync_add_and_fetch(&started, 1); - while(run == 0); - - p_proj_ctxt=pj_ctx_alloc(); - p_WGS84_proj=pj_init_plus_ctx(p_proj_ctxt,"+proj=longlat " - "+ellps=WGS84 +datum=WGS84"); - p_OSGB36_proj=pj_init_plus_ctx(p_proj_ctxt, - "+proj=longlat +ellps=airy +datum=OSGB36 +nadgrids=OSTN15_NTv2_OSGBtoETRS.gsb"); - - while(run) - { - double x, y; - int proj_ret; - - x = -5.2*DEG_TO_RAD; - y = 50*DEG_TO_RAD; - proj_ret = pj_transform(p_WGS84_proj, - p_OSGB36_proj, 1, 1, &x, &y, nullptr ); - x *= RAD_TO_DEG; - y *= RAD_TO_DEG; - /*printf("%.18f %.18f\n", x, y); */ - assert(proj_ret == 0); - assert(fabs(x - -5.198965207267856492) < 1e-15); - assert(fabs(y - 49.999396074140378232) < 1e-15); - } - - pj_free (p_OSGB36_proj); - pj_free (p_WGS84_proj); - return nullptr; -} - -int main() -{ - int i; - - pthread_t tid1, tid2; - pthread_attr_t attr1, attr2; - - pthread_attr_init(&attr1); - pthread_attr_init(&attr2); - - pthread_create(&tid1, &attr1, thread_main, nullptr); - pthread_create(&tid2, &attr2, thread_main, nullptr); - while(started != 2); - run = 1; - for(i=0;i<2;i++) - sleep(1); - run = 0; - return 0; -} - -#endif /* _WIN32 */ diff --git a/test/cli/Makefile.am b/test/cli/Makefile.am index 4d11eaf3..46d9d36c 100644 --- a/test/cli/Makefile.am +++ b/test/cli/Makefile.am @@ -35,13 +35,13 @@ testprojinfo-check: PROJ_SKIP_READ_USER_WRITABLE_DIRECTORY=YES PROJ_LIB=$(PROJ_LIB) $(TESTPROJINFO) $(PROJINFOEXE) test27-check: - $(TEST27) $(PROJEXE) + PROJ_LIB=$(PROJ_LIB) $(TEST27) $(PROJEXE) test83-check: - $(TEST83) $(PROJEXE) + PROJ_LIB=$(PROJ_LIB) $(TEST83) $(PROJEXE) testproj-check: - $(TESTPROJ) $(PROJEXE) + PROJ_LIB=$(PROJ_LIB) $(TESTPROJ) $(PROJEXE) testvarious-check: PROJ_SKIP_READ_USER_WRITABLE_DIRECTORY=YES PROJ_LIB=$(PROJ_LIB) $(TESTVARIOUS) $(CS2CSEXE) -- cgit v1.2.3 From 36c700192cee19a1070916dd094118a33a29ebe2 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Mon, 30 Nov 2020 13:35:33 +0100 Subject: test_io.cpp: formatting fix --- test/unit/test_io.cpp | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/test/unit/test_io.cpp b/test/unit/test_io.cpp index 5463adc3..4e903473 100644 --- a/test/unit/test_io.cpp +++ b/test/unit/test_io.cpp @@ -702,16 +702,15 @@ TEST(wkt_parse, wkt1_geographic_epsg_org_api_4258) { // Output from // https://apps.epsg.org/api/v1/CoordRefSystem/4258/export/?format=wkt&formatVersion=1 // using a datum ensemble name - auto wkt = - "GEOGCS[\"ETRS89\"," - "DATUM[\"European Terrestrial Reference System 1989 ensemble\"," - "SPHEROID[\"GRS 1980\",6378137,298.257222101," - "AUTHORITY[\"EPSG\",\"7019\"]],AUTHORITY[\"EPSG\",\"6258\"]]," - "PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]]," - "UNIT[\"degree (supplier to define representation)\"," - "0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]]," - "AXIS[\"Lat\",north],AXIS[\"Lon\",east]," - "AUTHORITY[\"EPSG\",\"4258\"]]"; + auto wkt = "GEOGCS[\"ETRS89\"," + "DATUM[\"European Terrestrial Reference System 1989 ensemble\"," + "SPHEROID[\"GRS 1980\",6378137,298.257222101," + "AUTHORITY[\"EPSG\",\"7019\"]],AUTHORITY[\"EPSG\",\"6258\"]]," + "PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]]," + "UNIT[\"degree (supplier to define representation)\"," + "0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]]," + "AXIS[\"Lat\",north],AXIS[\"Lon\",east]," + "AUTHORITY[\"EPSG\",\"4258\"]]"; auto obj = WKTParser().createFromWKT(wkt); auto crs = nn_dynamic_pointer_cast(obj); ASSERT_TRUE(crs != nullptr); -- cgit v1.2.3 From eef73e3eca2959768563d2dbb95a591c68b1d807 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Mon, 30 Nov 2020 14:00:46 +0100 Subject: Database: add metadata with the version number of the database layout and check it in the code This is aimed at detecting running a PROJ version against a proj.db that is not meant to work with it. This happens sometimes in complex setups mixing PROJ versions. Hopefully this will help spotting the issue earlier. --- data/sql/metadata.sql | 11 +++++++++ src/iso19111/factory.cpp | 64 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) diff --git a/data/sql/metadata.sql b/data/sql/metadata.sql index 3c21636c..adcee507 100644 --- a/data/sql/metadata.sql +++ b/data/sql/metadata.sql @@ -1,2 +1,13 @@ +-- Version of the database structure. +-- The major number indicates an incompatible change (e.g. table or column +-- removed or renamed). +-- The minor number is incremented if a backward compatible change done, that +-- is the new database can still work with an older PROJ version. +-- When updating those numbers, the DATABASE_LAYOUT_VERSION_MAJOR and +-- DATABASE_LAYOUT_VERSION_MINOR constants in src/iso19111/factory.cpp must be +-- updated as well. +INSERT INTO "metadata" VALUES('DATABASE.LAYOUT.VERSION.MAJOR', 1); +INSERT INTO "metadata" VALUES('DATABASE.LAYOUT.VERSION.MINOR', 0); + INSERT INTO "metadata" VALUES('EPSG.VERSION', 'v10.007'); INSERT INTO "metadata" VALUES('EPSG.DATE', '2020-11-18'); diff --git a/src/iso19111/factory.cpp b/src/iso19111/factory.cpp index 7c9eac00..2a03fd4e 100644 --- a/src/iso19111/factory.cpp +++ b/src/iso19111/factory.cpp @@ -93,6 +93,12 @@ namespace io { #define GEOG_3D_SINGLE_QUOTED "'geographic 3D'" #define GEOCENTRIC_SINGLE_QUOTED "'geocentric'" +// See data/sql/metadata.sql for the semantics of those constants +constexpr int DATABASE_LAYOUT_VERSION_MAJOR = 1; +// If the code depends on the new additions, then DATABASE_LAYOUT_VERSION_MINOR +// must be incremented. +constexpr int DATABASE_LAYOUT_VERSION_MINOR = 0; + // --------------------------------------------------------------------------- struct SQLValues { @@ -277,6 +283,8 @@ struct DatabaseContext::Private { lru11::Cache> cacheAliasNames_{ CACHE_SIZE}; + void checkDatabaseLayout(); + static void insertIntoCache(LRUCacheOfObjects &cache, const std::string &code, const util::BaseObjectPtr &obj); @@ -571,6 +579,61 @@ void DatabaseContext::Private::open(const std::string &databasePath, // --------------------------------------------------------------------------- +void DatabaseContext::Private::checkDatabaseLayout() { + auto res = run("SELECT key, value FROM metadata WHERE key IN " + "('DATABASE.LAYOUT.VERSION.MAJOR', " + "'DATABASE.LAYOUT.VERSION.MINOR')"); + if (res.size() != 2) { + // The database layout of PROJ 7.2 that shipped with EPSG v10.003 is + // at the time of writing still compatible of the one we support. + static_assert( + // cppcheck-suppress knownConditionTrueFalse + DATABASE_LAYOUT_VERSION_MAJOR == 1 && + // cppcheck-suppress knownConditionTrueFalse + DATABASE_LAYOUT_VERSION_MINOR == 0, + "remove that assertion and below lines next time we upgrade " + "database structure"); + res = run("SELECT 1 FROM metadata WHERE key = 'EPSG.VERSION' AND " + "value = 'v10.003'"); + if (!res.empty()) { + return; + } + + throw FactoryException( + databasePath_ + + " lacks DATABASE.LAYOUT.VERSION.MAJOR / " + "DATABASE.LAYOUT.VERSION.MINOR " + "metadata. It comes from another PROJ installation."); + } + int nMajor = 0; + int nMinor = 0; + for (const auto &row : res) { + if (row[0] == "DATABASE.LAYOUT.VERSION.MAJOR") { + nMajor = atoi(row[1].c_str()); + } else if (row[0] == "DATABASE.LAYOUT.VERSION.MINOR") { + nMinor = atoi(row[1].c_str()); + } + } + if (nMajor != DATABASE_LAYOUT_VERSION_MAJOR) { + throw FactoryException(databasePath_ + + " contains DATABASE.LAYOUT.VERSION.MAJOR = " + + toString(nMajor) + " whereas " + + toString(DATABASE_LAYOUT_VERSION_MAJOR) + + " is expected. " + "It comes from another PROJ installation."); + } + if (nMinor < DATABASE_LAYOUT_VERSION_MINOR) { + throw FactoryException(databasePath_ + + " contains DATABASE.LAYOUT.VERSION.MINOR = " + + toString(nMinor) + " whereas a number >= " + + toString(DATABASE_LAYOUT_VERSION_MINOR) + + " is expected. " + "It comes from another PROJ installation."); + } +} + +// --------------------------------------------------------------------------- + void DatabaseContext::Private::setHandle(sqlite3 *sqlite_handle) { assert(sqlite_handle); @@ -888,6 +951,7 @@ DatabaseContext::create(const std::string &databasePath, if (!auxiliaryDatabasePaths.empty()) { dbCtx->getPrivate()->attachExtraDatabases(auxiliaryDatabasePaths); } + dbCtx->getPrivate()->checkDatabaseLayout(); return dbCtx; } -- cgit v1.2.3 From ebe00831b7d6de3aae01ddd5f3074e53ac6d981e Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Wed, 2 Dec 2020 15:22:48 +0100 Subject: fix build --- src/conversions/topocentric.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/conversions/topocentric.cpp b/src/conversions/topocentric.cpp index 214f8221..f6f328ad 100644 --- a/src/conversions/topocentric.cpp +++ b/src/conversions/topocentric.cpp @@ -76,7 +76,7 @@ static PJ_COORD topocentric_inv(PJ_COORD in, PJ * P) /*********************************************************************/ PJ *CONVERSION(topocentric,1) { /*********************************************************************/ - struct pj_opaque *Q = static_cast(pj_calloc (1, sizeof (struct pj_opaque))); + struct pj_opaque *Q = static_cast(calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = static_cast(Q); -- cgit v1.2.3 From 18ab7ef2e357e0c01464848a6911e754ebca471f Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Wed, 2 Dec 2020 17:12:54 +0100 Subject: cs2cs / proj_create_crs_to_crs_from_pj(): add a --authority switch to control where coordinate operations are looked for (fixes #2442) --- docs/source/apps/cs2cs.rst | 33 ++++++++++++++++--------- docs/source/development/reference/functions.rst | 14 ++++++++++- src/4D_api.cpp | 29 ++++++++++++++++++++-- src/apps/cs2cs.cpp | 20 ++++++++++++++- test/cli/testvarious | 13 ++++++++++ test/cli/tv_out.dist | 7 ++++++ 6 files changed, 101 insertions(+), 15 deletions(-) diff --git a/docs/source/apps/cs2cs.rst b/docs/source/apps/cs2cs.rst index 7fe570d9..7df8890f 100644 --- a/docs/source/apps/cs2cs.rst +++ b/docs/source/apps/cs2cs.rst @@ -11,15 +11,11 @@ cs2cs Synopsis ******** - **cs2cs** [**-eEfIlrstvwW** [args]] - [[--area name_or_code] | [--bbox west_long,south_lat,east_long,north_lat]] - [*+opt[=arg]* ...] [+to *+opt[=arg]* ...] file ... - -or - - **cs2cs** [**-eEfIlrstvwW** [args]] [--area name_or_code] - [[--area name_or_code] | [--bbox west_long,south_lat,east_long,north_lat]] - {source_crs} {target_crs} file ... + | **cs2cs** [**-eEfIlrstvwW** [args]] + | [[--area ] | [--bbox ]] + | [--authority ] + | ([*+opt[=arg]* ...] [+to *+opt[=arg]* ...] | {source_crs} {target_crs}) + | file ... where {source_crs} or {target_crs} is one of the possibilities accepted by :c:func:`proj_create`, provided it expresses a CRS @@ -148,7 +144,7 @@ The following control parameters can appear in any order: Causes a listing of cartographic control parameters tested for and used by the program to be printed prior to input data. -.. option:: --area name_or_code +.. option:: --area .. versionadded:: 8.0.0 @@ -158,7 +154,7 @@ The following control parameters can appear in any order: This option is mutually exclusive with :option:`--bbox`. -.. option:: --bbox west_long,south_lat,east_long,north_lat +.. option:: --bbox .. versionadded:: 8.0.0 @@ -170,6 +166,21 @@ The following control parameters can appear in any order: `south_lat` and `north_lat` in the [-90,90]. `west_long` is generally lower than `east_long`, except in the case where the area of interest crosses the antimeridian. +.. option:: --authority + + .. versionadded:: 8.0.0 + + This option can be used to restrict the authority of coordinate operations + looked up in the database. When not specified, coordinate + operations from any authority will be searched, with the restrictions set + in the ``authority_to_authority_preference`` database table related to the authority + of the source/target CRS themselves. + If authority is set to ``any``, then coordinate operations from any authority will be searched + If authority is a non-empty string different of ``any``, then coordinate operations + will be searched only in that authority namespace (e.g ``EPSG``). + + This option is mutually exclusive with :option:`--bbox`. + .. only:: man The *+opt* run-line arguments are associated with cartographic diff --git a/docs/source/development/reference/functions.rst b/docs/source/development/reference/functions.rst index cc29743c..32902916 100644 --- a/docs/source/development/reference/functions.rst +++ b/docs/source/development/reference/functions.rst @@ -182,7 +182,19 @@ paragraph for more details. This is the same as :c:func:`proj_create_crs_to_crs` except that the source and target CRS are passed as PJ* objects which must of the CRS variety. - :param `options`: should be set to NULL currently. + :param `options`: a list of NUL terminated options, or NULL. + + The list of supported options is: + + - AUTHORITY=name: to restrict the authority of coordinate operations + looked up in the database. When not specified, coordinate + ``operations from any authority`` will be searched, with the restrictions set + in the authority_to_authority_preference database table related to the authority + of the source/target CRS themselves. + If authority is set to "any", then coordinate operations from any authority will be searched + If authority is a non-empty string different of ``any``, then coordinate operations + will be searched only in that authority namespace (e.g ``EPSG``). + .. doxygenfunction:: proj_normalize_for_visualization :project: doxygen_api diff --git a/src/4D_api.cpp b/src/4D_api.cpp index 9231a7ed..d6eb901d 100644 --- a/src/4D_api.cpp +++ b/src/4D_api.cpp @@ -1260,8 +1260,20 @@ std::vector pj_create_prepared_operations(PJ_CONTEXT *ctx, } } +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +static const char *getOptionValue(const char *option, + const char *keyWithEqual) noexcept { + if (ci_starts_with(option, keyWithEqual)) { + return option + strlen(keyWithEqual); + } + return nullptr; +} +//! @endcond + /*****************************************************************************/ -PJ *proj_create_crs_to_crs_from_pj (PJ_CONTEXT *ctx, const PJ *source_crs, const PJ *target_crs, PJ_AREA *area, const char* const *) { +PJ *proj_create_crs_to_crs_from_pj (PJ_CONTEXT *ctx, const PJ *source_crs, const PJ *target_crs, PJ_AREA *area, const char* const * options) { /****************************************************************************** Create a transformation pipeline between two known coordinate reference systems. @@ -1273,7 +1285,20 @@ PJ *proj_create_crs_to_crs_from_pj (PJ_CONTEXT *ctx, const PJ *source_crs, cons ctx = pj_get_default_ctx(); } - auto operation_ctx = proj_create_operation_factory_context(ctx, nullptr); + const char* authority = nullptr; + for (auto iter = options; iter && iter[0]; ++iter) { + const char *value; + if ((value = getOptionValue(*iter, "AUTHORITY="))) { + authority = value; + } else { + std::string msg("Unknown option :"); + msg += *iter; + ctx->logger(ctx->logger_app_data, PJ_LOG_ERROR, msg.c_str()); + return nullptr; + } + } + + auto operation_ctx = proj_create_operation_factory_context(ctx, authority); if( !operation_ctx ) { return nullptr; } diff --git a/src/apps/cs2cs.cpp b/src/apps/cs2cs.cpp index dd65baf4..409a5ef3 100644 --- a/src/apps/cs2cs.cpp +++ b/src/apps/cs2cs.cpp @@ -77,6 +77,7 @@ static const char *oterr = "*\t*"; /* output line for unprojectable input */ static const char *usage = "%s\nusage: %s [-dDeEfIlrstvwW [args]]\n" " [[--area name_or_code] | [--bbox west_long,south_lat,east_long,north_lat]]\n" + " [--authority {name}]\n" " [+opt[=arg] ...] [+to +opt[=arg] ...] [file ...]\n"; static double (*informat)(const char *, @@ -372,6 +373,7 @@ int main(int argc, char **argv) { ExtentPtr bboxFilter; std::string area; + const char* authority = nullptr; /* process run line arguments */ while (--argc > 0) { /* collect run line arguments */ @@ -410,6 +412,15 @@ int main(int argc, char **argv) { std::exit(1); } } + else if (strcmp(*argv, "--authority") == 0 ) { + ++argv; + --argc; + if( argc == 0 ) { + emess(1, "missing argument for --authority"); + std::exit(1); + } + authority = *argv; + } else if (**argv == '-') { for (arg = *argv;;) { switch (*++arg) { @@ -761,8 +772,15 @@ int main(int argc, char **argv) { } } + std::string authorityOption; /* keep this variable in this outer scope ! */ + const char* options[2] = { nullptr, nullptr }; + if( authority ) { + authorityOption = "AUTHORITY="; + authorityOption += authority; + options[0] = authorityOption.data(); + } transformation = proj_create_crs_to_crs_from_pj(nullptr, src, dst, - pj_area, nullptr); + pj_area, options); proj_destroy(src); proj_destroy(dst); diff --git a/test/cli/testvarious b/test/cli/testvarious index 292ee316..82be4992 100755 --- a/test/cli/testvarious +++ b/test/cli/testvarious @@ -1009,6 +1009,19 @@ $EXE -f %.3f EPSG:4686 EPSG:6247 -E >> ${OUT} <> ${OUT} +echo "Test effect of --authority (https://github.com/OSGeo/PROJ/issues/2442)" >> ${OUT} +echo "This test might be a bit fragile if proj.db content changes" >> ${OUT} +echo "The first result should use the 'WGS_1984_(ITRF08)_To_NAD_1983_2011' (ESRI:108363) operation" >> ${OUT} +echo "and the second one a no-op" >> ${OUT} +$EXE -E +proj=latlong +datum=WGS84 +no_defs +to +init=epsg:6342 >> ${OUT} <> ${OUT} < Date: Fri, 4 Dec 2020 22:12:05 +0100 Subject: Database: fix building proj.db with SQLite built with -DSQLITE_DQS=0 That is the option to make SQLite reject misuses of double quotes instead of single quotes. Most SQLite builds are forgiving, but some forks proposing a CMake build system default to SQLITE_DQS=0 --- data/sql/proj_db_table_defs.sql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data/sql/proj_db_table_defs.sql b/data/sql/proj_db_table_defs.sql index 05c64e45..b879cab8 100644 --- a/data/sql/proj_db_table_defs.sql +++ b/data/sql/proj_db_table_defs.sql @@ -1460,9 +1460,9 @@ CREATE VIEW object_view AS UNION ALL SELECT 'prime_meridian', auth_name, code, name, NULL, deprecated FROM prime_meridian UNION ALL - SELECT 'geodetic_datum', auth_name, code, name, CASE WHEN ensemble_accuracy IS NOT NULL THEN "ensemble" ELSE "datum" END, deprecated FROM geodetic_datum + SELECT 'geodetic_datum', auth_name, code, name, CASE WHEN ensemble_accuracy IS NOT NULL THEN 'ensemble' ELSE 'datum' END, deprecated FROM geodetic_datum UNION ALL - SELECT 'vertical_datum', auth_name, code, name, CASE WHEN ensemble_accuracy IS NOT NULL THEN "ensemble" ELSE "datum" END, deprecated FROM vertical_datum + SELECT 'vertical_datum', auth_name, code, name, CASE WHEN ensemble_accuracy IS NOT NULL THEN 'ensemble' ELSE 'datum' END, deprecated FROM vertical_datum UNION ALL SELECT 'axis', auth_name, code, name, NULL, 0 as deprecated FROM axis UNION ALL -- cgit v1.2.3 From bf81813e9f3eda1b7a61407e02ebe57a520b335e Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Fri, 4 Dec 2020 22:46:45 +0100 Subject: CI: test with a SQLite3 binary built with SQLITE_DQS=0 to avoid issue #2480 --- .github/workflows/mingw_w64/start.sh | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/mingw_w64/start.sh b/.github/workflows/mingw_w64/start.sh index e6d04ff0..2b42381f 100755 --- a/.github/workflows/mingw_w64/start.sh +++ b/.github/workflows/mingw_w64/start.sh @@ -88,10 +88,11 @@ tar xzf tiff-4.1.0.tar.gz ln -s /usr/$MINGW_ARCH/bin/libtiff-5.dll $WINE_SYSDIR # build sqlite3 -wget https://sqlite.org/2018/sqlite-autoconf-3250100.tar.gz -tar xzf sqlite-autoconf-3250100.tar.gz -(cd sqlite-autoconf-3250100 && -./configure --host=$MINGW_ARCH --prefix=/usr/$MINGW_ARCH && make && sudo make install) +wget https://sqlite.org/2020/sqlite-autoconf-3330000.tar.gz +tar xzf sqlite-autoconf-3330000.tar.gz +# Build with SQLITE_DQS=0 to ensure we properly use single quotes and double quotes (cf issue #2480) +(cd sqlite-autoconf-3330000 && +CFLAGS="-DSQLITE_DQS=0" ./configure --host=$MINGW_ARCH --prefix=/usr/$MINGW_ARCH && make && sudo make install) ln -s /usr/$MINGW_ARCH/bin/libsqlite3-0.dll $WINE_SYSDIR # prepare build files -- cgit v1.2.3 From 29d2542cc37d404b9fdef0effe1e006f8969b1c5 Mon Sep 17 00:00:00 2001 From: Zac Miller Date: Wed, 2 Dec 2020 12:23:28 -0500 Subject: Update isea.rst Clarifying defaults for ISEA. --- docs/source/operations/projections/isea.rst | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/source/operations/projections/isea.rst b/docs/source/operations/projections/isea.rst index adb703a1..73f0af7a 100644 --- a/docs/source/operations/projections/isea.rst +++ b/docs/source/operations/projections/isea.rst @@ -43,7 +43,9 @@ Parameters .. option:: +orient= - Can be set to either ``isea`` or ``pole``. + Can be set to either ``isea`` or ``pole``. See Snyder's Figure 12 for pole orientation :cite:`Snyder1992`. + + *Defaults to isea* .. option:: +azi= @@ -62,6 +64,8 @@ Parameters .. option:: +mode= Can be either ``plane``, ``di``, ``dd`` or ``hex``. + + *Defaults to plane* .. include:: ../options/lon_0.rst -- cgit v1.2.3 From 372b5b74804b1d279c952f4a7811ade3e5815a35 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Wed, 9 Dec 2020 19:28:13 +0100 Subject: Doc: fix return data type of proj_trans_array() --- docs/source/development/reference/functions.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/development/reference/functions.rst b/docs/source/development/reference/functions.rst index 32902916..df452032 100644 --- a/docs/source/development/reference/functions.rst +++ b/docs/source/development/reference/functions.rst @@ -364,7 +364,7 @@ Coordinate transformation -.. c:function:: size_t proj_trans_array(PJ *P, PJ_DIRECTION direction, size_t n, PJ_COORD *coord) +.. c:function:: int proj_trans_array(PJ *P, PJ_DIRECTION direction, size_t n, PJ_COORD *coord) Batch transform an array of :c:type:`PJ_COORD`. @@ -374,7 +374,7 @@ Coordinate transformation :type `direction`: PJ_DIRECTION :param n: Number of coordinates in :c:data:`coord` :type n: `size_t` - :returns: :c:type:`size_t` 0 if all observations are transformed without error, otherwise returns error number + :returns: :c:type:`int` 0 if all observations are transformed without error, otherwise returns error number Error reporting -- cgit v1.2.3 From 2e13f14493b57cce761c188d17a6abf0a7f71bbf Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Fri, 11 Dec 2020 20:37:03 +0100 Subject: test_operation.cpp: remove debug message --- test/unit/test_operation.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/test/unit/test_operation.cpp b/test/unit/test_operation.cpp index d8e7347c..d0085004 100644 --- a/test/unit/test_operation.cpp +++ b/test/unit/test_operation.cpp @@ -10209,7 +10209,6 @@ TEST(operation, geocentric_topocentric) { ASSERT_TRUE(dst != nullptr); auto f(NS_PROJ::io::WKTFormatter::create( NS_PROJ::io::WKTFormatter::Convention::WKT2_2019)); - std::cerr << GeodeticCRS::EPSG_4978->exportToWKT(f.get()) << std::endl; auto op = CoordinateOperationFactory::create()->createOperation( GeodeticCRS::EPSG_4978, NN_CHECK_ASSERT(dst)); ASSERT_TRUE(op != nullptr); -- cgit v1.2.3 From acab18920ec25ccbc2affe8bda924ff5f961d30c Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Fri, 11 Dec 2020 21:50:35 +0100 Subject: funtions.rst: fix sphynx syntax --- docs/source/development/reference/functions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/development/reference/functions.rst b/docs/source/development/reference/functions.rst index df452032..b37eacdd 100644 --- a/docs/source/development/reference/functions.rst +++ b/docs/source/development/reference/functions.rst @@ -374,7 +374,7 @@ Coordinate transformation :type `direction`: PJ_DIRECTION :param n: Number of coordinates in :c:data:`coord` :type n: `size_t` - :returns: :c:type:`int` 0 if all observations are transformed without error, otherwise returns error number + :returns: `int` 0 if all observations are transformed without error, otherwise returns error number Error reporting -- cgit v1.2.3 From f51c723b45b139cd5f833c0ece6953ce65b2ad7d Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Fri, 11 Dec 2020 21:50:49 +0100 Subject: .github/workflows/clang_static_analyzer/start.sh: add apt update --- .github/workflows/clang_static_analyzer/start.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/clang_static_analyzer/start.sh b/.github/workflows/clang_static_analyzer/start.sh index 7063c42f..3a06c46a 100755 --- a/.github/workflows/clang_static_analyzer/start.sh +++ b/.github/workflows/clang_static_analyzer/start.sh @@ -2,6 +2,8 @@ set -e +sudo apt update + DEBIAN_FRONTEND=noninteractive sudo apt-get install -y --no-install-recommends \ autoconf automake libtool g++ make sqlite3 libsqlite3-dev libtiff-dev libcurl4-openssl-dev jq -- cgit v1.2.3 From 6857d1a4a8eb6fcb7b88b0339413913ba2c3351a Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Fri, 11 Dec 2020 22:15:38 +0100 Subject: conda.yml: restrict to main repository builds, otherwise fails to build in forks --- .github/workflows/conda.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/conda.yml b/.github/workflows/conda.yml index 296754f1..596aaad2 100644 --- a/.github/workflows/conda.yml +++ b/.github/workflows/conda.yml @@ -7,6 +7,7 @@ on: jobs: build: name: Conda ${{ matrix.platform }} + if: github.repository == 'OSGeo/PROJ' runs-on: ${{ matrix.platform }} strategy: -- cgit v1.2.3