📄 pj_transform.c
字号:
/****************************************************************************** * $Id: pj_transform.c,v 1.9 2003/03/26 16:52:30 warmerda Exp $ * * 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. ****************************************************************************** * * $Log: pj_transform.c,v $ * Revision 1.9 2003/03/26 16:52:30 warmerda * added check that an inverse transformation func exists * * Revision 1.8 2002/12/14 20:35:43 warmerda * implement units support for geocentric coordinates * * Revision 1.7 2002/12/14 20:14:35 warmerda * added geocentric support * * Revision 1.6 2002/12/09 16:01:02 warmerda * added prime meridian support * * Revision 1.5 2002/12/01 19:25:26 warmerda * applied fix for 7 param shift in pj_geocentric_from_wgs84, see bug 194 * * Revision 1.4 2002/02/15 14:30:36 warmerda * provide default Z array if none passed in in pj_datum_transform() * * Revision 1.3 2001/04/04 21:13:21 warmerda * do arcsecond/radian and ppm datum parm transformation in pj_set_datum() * * Revision 1.2 2001/04/04 16:08:08 warmerda * rewrote 7 param datum shift to match EPSG:9606, now works with example * * Revision 1.1 2000/07/06 23:32:27 warmerda * New * */#include <projects.h>#include <string.h>#include <math.h>#include "geocent.h"PJ_CVSID("$Id: pj_transform.c,v 1.9 2003/03/26 16:52:30 warmerda Exp $");#ifndef SRS_WGS84_SEMIMAJOR#define SRS_WGS84_SEMIMAJOR 6378137.0#endif#ifndef SRS_WGS84_ESQUARED#define SRS_WGS84_ESQUARED 0.006694379990#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])/************************************************************************//* 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 *srcdefn, PJ *dstdefn, long point_count, int point_offset, double *x, double *y, double *z ){ long i; int need_datum_shift; pj_errno = 0; if( point_offset == 0 ) point_offset = 1;/* -------------------------------------------------------------------- *//* Transform geocentric source coordinates to lat/long. *//* -------------------------------------------------------------------- */ if( srcdefn->is_geocent ) { if( z == NULL ) { pj_errno = PJD_ERR_GEOCENTRIC; return PJD_ERR_GEOCENTRIC; } if( srcdefn->to_meter != 1.0 ) { for( i = 0; i < point_count; i++ ) { x[point_offset*i] *= srcdefn->to_meter; y[point_offset*i] *= srcdefn->to_meter; } } pj_geocentric_to_geodetic( srcdefn->a, srcdefn->es, point_count, point_offset, x, y, z ); }/* -------------------------------------------------------------------- *//* Transform source points to lat/long, if they aren't *//* already. *//* -------------------------------------------------------------------- */ else if( !srcdefn->is_latlong ) { if( srcdefn->inv == NULL ) { pj_errno = -17; /* this isn't correct, we need a no inverse err */ if( getenv( "PROJ_DEBUG" ) != NULL ) { fprintf( stderr, "pj_transform(): source projection not invertable\n" ); } return pj_errno; } for( i = 0; i < point_count; i++ ) { XY projected_loc; LP geodetic_loc; projected_loc.u = x[point_offset*i]; projected_loc.v = y[point_offset*i]; geodetic_loc = pj_inv( projected_loc, srcdefn ); if( pj_errno != 0 ) return pj_errno; x[point_offset*i] = geodetic_loc.u; y[point_offset*i] = geodetic_loc.v; } }/* -------------------------------------------------------------------- *//* But if they are already lat long, adjust for the prime *//* meridian if there is one in effect. *//* -------------------------------------------------------------------- */ else if( srcdefn->from_greenwich != 0.0 ) { for( i = 0; i < point_count; i++ ) x[point_offset*i] += srcdefn->from_greenwich; }/* -------------------------------------------------------------------- *//* Convert datums if needed, and possible. *//* -------------------------------------------------------------------- */ if( pj_datum_transform( srcdefn, dstdefn, point_count, point_offset, x, y, z ) != 0 ) return pj_errno;/* -------------------------------------------------------------------- *//* Transform destination latlong to geocentric if required. *//* -------------------------------------------------------------------- */ if( dstdefn->is_geocent ) { if( z == NULL ) { pj_errno = PJD_ERR_GEOCENTRIC; return PJD_ERR_GEOCENTRIC; } pj_geodetic_to_geocentric( dstdefn->a, dstdefn->es, point_count, point_offset, x, y, z ); if( dstdefn->fr_meter != 1.0 ) { for( i = 0; i < point_count; i++ ) { x[point_offset*i] *= dstdefn->fr_meter; y[point_offset*i] *= dstdefn->fr_meter; } } }/* -------------------------------------------------------------------- *//* Transform destination points to projection coordinates, if *//* desired. *//* -------------------------------------------------------------------- */ else if( !dstdefn->is_latlong ) { for( i = 0; i < point_count; i++ ) { XY projected_loc; LP geodetic_loc; geodetic_loc.u = x[point_offset*i]; geodetic_loc.v = y[point_offset*i]; projected_loc = pj_fwd( geodetic_loc, dstdefn ); if( pj_errno != 0 ) return pj_errno; x[point_offset*i] = projected_loc.u; y[point_offset*i] = projected_loc.v; } }/* -------------------------------------------------------------------- *//* But if they are staying lat long, adjust for the prime *//* meridian if there is one in effect. *//* -------------------------------------------------------------------- */ else if( dstdefn->from_greenwich != 0.0 ) { for( i = 0; i < point_count; i++ ) x[point_offset*i] -= dstdefn->from_greenwich; } 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; if( es == 0.0 ) b = a; else b = a * sqrt(1-es); if( Set_Geocentric_Parameters( a, b ) != 0 ) { pj_errno = PJD_ERR_GEOCENTRIC; return pj_errno; } for( i = 0; i < point_count; i++ ) { long io = i * point_offset; if( Convert_Geodetic_To_Geocentric( y[io], x[io], z[io], x+io, y+io, z+io ) != 0 ) { pj_errno = PJD_ERR_GEOCENTRIC; return PJD_ERR_GEOCENTRIC; } } return 0;}/************************************************************************//* pj_geodetic_to_geocentric() */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -