diff options
| author | Even Rouault <even.rouault@spatialys.com> | 2018-12-19 13:00:37 +0100 |
|---|---|---|
| committer | Even Rouault <even.rouault@spatialys.com> | 2018-12-26 10:08:55 +0100 |
| commit | df574ae332d57f556fd56314883b3354cab1d0ff (patch) | |
| tree | 63a68d40d7ed7932d6329d9c7baa340bb6294f7f /src/projections/sch.cpp | |
| parent | e6de172371ea203f6393d745641d66c82b5b13e2 (diff) | |
| download | PROJ-df574ae332d57f556fd56314883b3354cab1d0ff.tar.gz PROJ-df574ae332d57f556fd56314883b3354cab1d0ff.zip | |
cpp conversion: remove useless pj_, PJ_ and proj_ filename prefixes
Diffstat (limited to 'src/projections/sch.cpp')
| -rw-r--r-- | src/projections/sch.cpp | 232 |
1 files changed, 232 insertions, 0 deletions
diff --git a/src/projections/sch.cpp b/src/projections/sch.cpp new file mode 100644 index 00000000..5a2f944b --- /dev/null +++ b/src/projections/sch.cpp @@ -0,0 +1,232 @@ +/****************************************************************************** + * Project: SCH Coordinate system + * Purpose: Implementation of SCH Coordinate system + * References : + * 1. Hensley. Scott. SCH Coordinates and various transformations. June 15, 2000. + * 2. Buckley, Sean Monroe. Radar interferometry measurement of land subsidence. 2000.. + * PhD Thesis. UT Austin. (Appendix) + * 3. Hensley, Scott, Elaine Chapin, and T. Michel. "Improved processing of AIRSAR + * data based on the GeoSAR processor." Airsar earth science and applications + * workshop, March. 2002. (http://airsar.jpl.nasa.gov/documents/workshop2002/papers/T3.pdf) + * + * Author: Piyush Agram (piyush.agram@jpl.nasa.gov) + * Copyright (c) 2015 California Institute of Technology. + * Government sponsorship acknowledged. + * + * NOTE: The SCH coordinate system is a sensor aligned coordinate system + * developed at JPL for radar mapping missions. Details pertaining to the + * coordinate system have been release in the public domain (see references above). + * This code is an independent implementation of the SCH coordinate system + * that conforms to the PROJ.4 conventions and uses the details presented in these + * publicly released documents. All credit for the development of the coordinate + * system and its use should be directed towards the original developers at JPL. + ****************************************************************************** + * 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 <errno.h> +#include <math.h> + +#include "proj.h" +#include "projects.h" +#include "geocent.h" + +namespace { // anonymous namespace +struct pj_opaque { + double plat; /*Peg Latitude */ + double plon; /*Peg Longitude*/ + double phdg; /*Peg heading */ + double h0; /*Average altitude */ + double transMat[9]; + double xyzoff[3]; + double rcurv; + GeocentricInfo sph; + GeocentricInfo elp_0; +}; +} // anonymous namespace + +PROJ_HEAD(sch, "Spherical Cross-track Height") "\n\tMisc\n\tplat_0= plon_0= phdg_0= [h_0=]"; + +static LPZ inverse3d(XYZ xyz, PJ *P) { + LPZ lpz = {0.0, 0.0, 0.0}; + struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque); + double temp[3]; + double pxyz[3]; + + /* Local lat,lon using radius */ + pxyz[0] = xyz.y * P->a / Q->rcurv; + pxyz[1] = xyz.x * P->a / Q->rcurv; + pxyz[2] = xyz.z; + + if( pj_Convert_Geodetic_To_Geocentric( &(Q->sph), pxyz[0], pxyz[1], pxyz[2], temp, temp+1, temp+2) != 0) { + proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION); + return lpz; + } + + /* Apply rotation */ + pxyz[0] = Q->transMat[0] * temp[0] + Q->transMat[1] * temp[1] + Q->transMat[2] * temp[2]; + pxyz[1] = Q->transMat[3] * temp[0] + Q->transMat[4] * temp[1] + Q->transMat[5] * temp[2]; + pxyz[2] = Q->transMat[6] * temp[0] + Q->transMat[7] * temp[1] + Q->transMat[8] * temp[2]; + + /* Apply offset */ + pxyz[0] += Q->xyzoff[0]; + pxyz[1] += Q->xyzoff[1]; + pxyz[2] += Q->xyzoff[2]; + + /* Convert geocentric coordinates to lat lon */ + pj_Convert_Geocentric_To_Geodetic( &(Q->elp_0), pxyz[0], pxyz[1], pxyz[2], + temp, temp+1, temp+2); + + + lpz.lam = temp[1] ; + lpz.phi = temp[0] ; + lpz.z = temp[2]; + + return lpz; +} + +static XYZ forward3d(LPZ lpz, PJ *P) { + XYZ xyz = {0.0, 0.0, 0.0}; + struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque); + double temp[3]; + double pxyz[3]; + + + /* Convert lat lon to geocentric coordinates */ + if( pj_Convert_Geodetic_To_Geocentric( &(Q->elp_0), lpz.phi, lpz.lam, lpz.z, temp, temp+1, temp+2 ) != 0 ) { + proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION); + return xyz; + } + + + /* Adjust for offset */ + temp[0] -= Q->xyzoff[0]; + temp[1] -= Q->xyzoff[1]; + temp[2] -= Q->xyzoff[2]; + + + /* Apply rotation */ + pxyz[0] = Q->transMat[0] * temp[0] + Q->transMat[3] * temp[1] + Q->transMat[6] * temp[2]; + pxyz[1] = Q->transMat[1] * temp[0] + Q->transMat[4] * temp[1] + Q->transMat[7] * temp[2]; + pxyz[2] = Q->transMat[2] * temp[0] + Q->transMat[5] * temp[1] + Q->transMat[8] * temp[2]; + + /* Convert to local lat,lon */ + pj_Convert_Geocentric_To_Geodetic( &(Q->sph), pxyz[0], pxyz[1], pxyz[2], + temp, temp+1, temp+2); + + + /* Scale by radius */ + xyz.x = temp[1] * Q->rcurv / P->a; + xyz.y = temp[0] * Q->rcurv / P->a; + xyz.z = temp[2]; + + return xyz; +} + + +static PJ *setup(PJ *P) { /* general initialization */ + struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque); + double reast, rnorth; + double chdg, shdg; + double clt, slt; + double clo, slo; + double temp; + double pxyz[3]; + + temp = P->a * sqrt(1.0 - P->es); + + /* Setup original geocentric system */ + if ( pj_Set_Geocentric_Parameters(&(Q->elp_0), P->a, temp) != 0) + return pj_default_destructor(P, PJD_ERR_FAILED_TO_FIND_PROJ); + + clt = cos(Q->plat); + slt = sin(Q->plat); + clo = cos(Q->plon); + slo = sin(Q->plon); + + /* Estimate the radius of curvature for given peg */ + temp = sqrt(1.0 - (P->es) * slt * slt); + reast = (P->a)/temp; + rnorth = (P->a) * (1.0 - (P->es))/pow(temp,3); + + chdg = cos(Q->phdg); + shdg = sin(Q->phdg); + + Q->rcurv = Q->h0 + (reast*rnorth)/(reast * chdg * chdg + rnorth * shdg * shdg); + + /* Set up local sphere at the given peg point */ + if ( pj_Set_Geocentric_Parameters(&(Q->sph), Q->rcurv, Q->rcurv) != 0) + return pj_default_destructor(P, PJD_ERR_FAILED_TO_FIND_PROJ); + + /* Set up the transformation matrices */ + Q->transMat[0] = clt * clo; + Q->transMat[1] = -shdg*slo - slt*clo * chdg; + Q->transMat[2] = slo*chdg - slt*clo*shdg; + Q->transMat[3] = clt*slo; + Q->transMat[4] = clo*shdg - slt*slo*chdg; + Q->transMat[5] = -clo*chdg - slt*slo*shdg; + Q->transMat[6] = slt; + Q->transMat[7] = clt*chdg; + Q->transMat[8] = clt*shdg; + + + if( pj_Convert_Geodetic_To_Geocentric( &(Q->elp_0), Q->plat, Q->plon, Q->h0, + pxyz, pxyz+1, pxyz+2 ) != 0 ) + return pj_default_destructor(P, PJD_ERR_LAT_OR_LON_EXCEED_LIMIT); + + + Q->xyzoff[0] = pxyz[0] - (Q->rcurv) * clt * clo; + Q->xyzoff[1] = pxyz[1] - (Q->rcurv) * clt * slo; + Q->xyzoff[2] = pxyz[2] - (Q->rcurv) * slt; + + P->fwd3d = forward3d; + P->inv3d = inverse3d; + return P; +} + + +PJ *PROJECTION(sch) { + struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque))); + if (nullptr==Q) + return pj_default_destructor(P, ENOMEM); + P->opaque = Q; + + Q->h0 = 0.0; + + /* Check if peg latitude was defined */ + if (pj_param(P->ctx, P->params, "tplat_0").i) + Q->plat = pj_param(P->ctx, P->params, "rplat_0").f; + else { + return pj_default_destructor(P, PJD_ERR_FAILED_TO_FIND_PROJ); + } + + /* Check if peg longitude was defined */ + if (pj_param(P->ctx, P->params, "tplon_0").i) + Q->plon = pj_param(P->ctx, P->params, "rplon_0").f; + else { + return pj_default_destructor(P, PJD_ERR_FAILED_TO_FIND_PROJ); + } + + /* Check if peg latitude is defined */ + if (pj_param(P->ctx, P->params, "tphdg_0").i) + Q->phdg = pj_param(P->ctx, P->params, "rphdg_0").f; + else { + return pj_default_destructor(P, PJD_ERR_FAILED_TO_FIND_PROJ); + } + + + /* Check if average height was defined - If so read it in */ + if (pj_param(P->ctx, P->params, "th_0").i) + Q->h0 = pj_param(P->ctx, P->params, "dh_0").f; + + + return setup(P); +} |
