📄 pj_transform.cpp
字号:
#include "stdafx.h"
#include "projects.h"
#include <string.h>
#include "geocent.h"
#include <math.h>
PJ_CVSID("$Id: pj_transform.c,v 1.12 2004/05/03 19:45:23 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])
/*
** This table is intended to indicate for any given error code in
** the range 0 to -44, 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.
*/
static int transient_error[45] = {
/* 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, 1, 0,
/* 40 to 44 */ 0, 0, 0, 0, 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 *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;
}
}
if( pj_geocentric_to_geodetic( srcdefn->a, srcdefn->es,
point_count, point_offset,
x, y, z ) != 0)
return pj_errno;
}
/* -------------------------------------------------------------------- */
/* 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 */
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];
if( projected_loc.u == HUGE_VAL )
continue;
geodetic_loc = pj_inv( projected_loc, srcdefn );
if( pj_errno != 0 )
{
if( pj_errno > 0 || pj_errno < -44 || point_count == 1
|| transient_error[-pj_errno] == 0 )
return pj_errno;
else
{
geodetic_loc.u = HUGE_VAL;
geodetic_loc.v = HUGE_VAL;
}
}
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. */
/* -------------------------------------------------------------------- */
if( srcdefn->from_greenwich != 0.0 )
{
for( i = 0; i < point_count; i++ )
{
if( x[point_offset*i] != HUGE_VAL )
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;
/* -------------------------------------------------------------------- */
/* But if they are staying lat long, adjust for the prime */
/* meridian if there is one in effect. */
/* -------------------------------------------------------------------- */
if( dstdefn->from_greenwich != 0.0 )
{
for( i = 0; i < point_count; i++ )
{
if( x[point_offset*i] != HUGE_VAL )
x[point_offset*i] -= dstdefn->from_greenwich;
}
}
/* -------------------------------------------------------------------- */
/* 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++ )
{
if( x[point_offset*i] != HUGE_VAL )
{
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];
if( geodetic_loc.u == HUGE_VAL )
continue;
projected_loc = pj_fwd( geodetic_loc, dstdefn );
if( pj_errno != 0 )
{
if( pj_errno > 0 || pj_errno < -44 || point_count == 1
|| transient_error[-pj_errno] == 0 )
return pj_errno;
else
{
projected_loc.u = HUGE_VAL;
projected_loc.v = HUGE_VAL;
}
}
x[point_offset*i] = projected_loc.u;
y[point_offset*i] = projected_loc.v;
}
}
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() */
/************************************************************************/
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;
if( es == 0.0 )
b = a;
else
b = a * sqrt(1-es);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -