aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/PJ_qsc.c2
-rw-r--r--src/pj_inv.c4
-rw-r--r--src/pj_transform.c684
-rw-r--r--src/proj.h4
-rw-r--r--src/proj_4D_api.c30
-rw-r--r--src/proj_internal.h4
6 files changed, 410 insertions, 318 deletions
diff --git a/src/PJ_qsc.c b/src/PJ_qsc.c
index 36dabeb9..0f5d2299 100644
--- a/src/PJ_qsc.c
+++ b/src/PJ_qsc.c
@@ -14,7 +14,7 @@
* is described in
* [LK12]
* M. Lambers and A. Kolb, "Ellipsoidal Cube Maps for Accurate Rendering of
- * Planetary-Scale Terrain Data", Proc. Pacfic Graphics (Short Papers), Sep.
+ * Planetary-Scale Terrain Data", Proc. Pacific Graphics (Short Papers), Sep.
* 2012
*
* You have to choose one of the following projection centers,
diff --git a/src/pj_inv.c b/src/pj_inv.c
index 4ea88b69..9918c59d 100644
--- a/src/pj_inv.c
+++ b/src/pj_inv.c
@@ -115,9 +115,9 @@ static PJ_COORD pj_inv_prepare (PJ *P, PJ_COORD coo) {
return coo;
/* Classic proj.4 functions expect plane coordinates in units of the semimajor axis */
- /* Multiplying by ra, rather than dividing by a because the CALCOFI projection */
+ /* Multiplying by ra, rather than dividing by a because the CalCOFI projection */
/* stomps on a and hence (apparently) depends on this to roundtrip correctly */
- /* (CALCOFI avoids further scaling by stomping - but a better solution is possible) */
+ /* (CalCOFI avoids further scaling by stomping - but a better solution is possible) */
coo.xyz.x *= P->ra;
coo.xyz.y *= P->ra;
return coo;
diff --git a/src/pj_transform.c b/src/pj_transform.c
index c72df2e7..06a2dfb0 100644
--- a/src/pj_transform.c
+++ b/src/pj_transform.c
@@ -27,11 +27,23 @@
* DEALINGS IN THE SOFTWARE.
*****************************************************************************/
-#include <projects.h>
+#include "projects.h"
#include <string.h>
#include <math.h>
#include "geocent.h"
+
+/* Apply transformation to observation - in forward or inverse direction */
+/* Copied from proj.h */
+enum PJ_DIRECTION {
+ PJ_FWD = 1, /* Forward */
+ PJ_IDENT = 0, /* Do nothing */
+ PJ_INV = -1 /* Inverse */
+};
+typedef enum PJ_DIRECTION PJ_DIRECTION;
+
+
+
static int pj_adjust_axis( projCtx ctx, const char *axis, int denormalize_flag,
long point_count, int point_offset,
double *x, double *y, double *z );
@@ -81,388 +93,470 @@ static const int transient_error[60] = {
/* 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 };
-/************************************************************************/
-/* 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;
- srcdefn->ctx->last_errno = 0;
- dstdefn->ctx->last_errno = 0;
-
- if( point_offset == 0 )
- point_offset = 1;
/* -------------------------------------------------------------------- */
/* Transform unusual input coordinate axis orientation to */
/* standard form if needed. */
/* -------------------------------------------------------------------- */
- if( strcmp(srcdefn->axis,"enu") != 0 )
- {
- int err;
+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 pj_adjust_axis( P->ctx, P->axis,
+ dir==PJ_FWD ? 1: 0, n, dist, x, y, z );
+}
+
- err = pj_adjust_axis( srcdefn->ctx, srcdefn->axis,
- 0, point_count, point_offset, x, y, z );
- if( err != 0 )
- return err;
+
+/* ----------------------------------------------------------------------- */
+/* Transform cartesian ("geocentric") source coordinates to lat/long, */
+/* 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 == NULL ) {
+ 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 geocentric source coordinates to lat/long. */
+/* Transform destination points to projection coordinates, if */
+/* desired. */
+/* */
+/* Ought to fold this into projected_to_geographic */
/* -------------------------------------------------------------------- */
- if( srcdefn->is_geocent )
+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)
+ return 0;
+ if (P->is_geocent)
+ return 0;
+
+ if(P->fwd3d != NULL)
{
- int err;
- if( z == NULL )
+ /* Three dimensions must be defined */
+ if ( z == NULL)
{
- pj_ctx_set_errno( pj_get_ctx(srcdefn), PJD_ERR_GEOCENTRIC);
+ pj_ctx_set_errno( pj_get_ctx(P), PJD_ERR_GEOCENTRIC);
return PJD_ERR_GEOCENTRIC;
}
- if( srcdefn->to_meter != 1.0 )
+ for( i = 0; i < n; i++ )
{
- for( i = 0; i < point_count; i++ )
+ XYZ projected_loc;
+ LPZ geodetic_loc;
+
+ geodetic_loc.u = x[dist*i];
+ geodetic_loc.v = y[dist*i];
+ geodetic_loc.w = z[dist*i];
+
+ if (geodetic_loc.u == HUGE_VAL)
+ continue;
+
+ projected_loc = pj_fwd3d( geodetic_loc, P);
+ if( P->ctx->last_errno != 0 )
{
- if( x[point_offset*i] != HUGE_VAL )
+ if( (P->ctx->last_errno != 33 /*EDOM*/
+ && P->ctx->last_errno != 34 /*ERANGE*/ )
+ && (P->ctx->last_errno > 0
+ || P->ctx->last_errno < -44 || n == 1
+ || transient_error[-P->ctx->last_errno] == 0 ) )
+ return P->ctx->last_errno;
+ else
{
- x[point_offset*i] *= srcdefn->to_meter;
- y[point_offset*i] *= srcdefn->to_meter;
- z[point_offset*i] *= srcdefn->to_meter;
+ projected_loc.u = HUGE_VAL;
+ projected_loc.v = HUGE_VAL;
+ projected_loc.w = HUGE_VAL;
}
}
- }
- err = pj_geocentric_to_geodetic( srcdefn->a_orig, srcdefn->es_orig,
- point_count, point_offset,
- x, y, z );
- if( err != 0 )
- return err;
+ x[dist*i] = projected_loc.u;
+ y[dist*i] = projected_loc.v;
+ z[dist*i] = projected_loc.w;
+ }
+ return 0;
}
-/* -------------------------------------------------------------------- */
-/* Transform source points to lat/long, if they aren't */
-/* already. */
-/* -------------------------------------------------------------------- */
- else if( !srcdefn->is_latlong )
+ for( i = 0; i <n; i++ )
{
+ XY projected_loc;
+ LP geodetic_loc;
- /* Check first if projection is invertible. */
- if( (srcdefn->inv3d == NULL) && (srcdefn->inv == NULL))
- {
- pj_ctx_set_errno( pj_get_ctx(srcdefn), -17 );
- pj_log( pj_get_ctx(srcdefn), PJ_LOG_ERROR,
- "pj_transform(): source projection not invertable" );
- return -17;
- }
+ geodetic_loc.u = x[dist*i];
+ geodetic_loc.v = y[dist*i];
+
+ if( geodetic_loc.u == HUGE_VAL )
+ continue;
- /* If invertible - First try inv3d if defined */
- if (srcdefn->inv3d != NULL)
+ projected_loc = pj_fwd( geodetic_loc, P );
+ if( P->ctx->last_errno != 0 )
{
- /* Three dimensions must be defined */
- if ( z == NULL)
+ if( (P->ctx->last_errno != 33 /*EDOM*/
+ && P->ctx->last_errno != 34 /*ERANGE*/ )
+ && (P->ctx->last_errno > 0
+ || P->ctx->last_errno < -44 || n == 1
+ || transient_error[-P->ctx->last_errno] == 0 ) )
+ return P->ctx->last_errno;
+ else
{
- pj_ctx_set_errno( pj_get_ctx(srcdefn), PJD_ERR_GEOCENTRIC);
- return PJD_ERR_GEOCENTRIC;
+ projected_loc.u = HUGE_VAL;
+ projected_loc.v = HUGE_VAL;
}
+ }
- for (i=0; i < point_count; i++)
- {
- XYZ projected_loc;
- XYZ geodetic_loc;
+ x[dist*i] = projected_loc.u;
+ y[dist*i] = projected_loc.v;
+ }
+ return 0;
+}
- projected_loc.u = x[point_offset*i];
- projected_loc.v = y[point_offset*i];
- projected_loc.w = z[point_offset*i];
- if (projected_loc.u == HUGE_VAL)
- continue;
- geodetic_loc = pj_inv3d(projected_loc, srcdefn);
- if( srcdefn->ctx->last_errno != 0 )
- {
- if( (srcdefn->ctx->last_errno != 33 /*EDOM*/
- && srcdefn->ctx->last_errno != 34 /*ERANGE*/ )
- && (srcdefn->ctx->last_errno > 0
- || srcdefn->ctx->last_errno < -44 || point_count == 1
- || transient_error[-srcdefn->ctx->last_errno] == 0 ) )
- return srcdefn->ctx->last_errno;
- else
- {
- geodetic_loc.u = HUGE_VAL;
- geodetic_loc.v = HUGE_VAL;
- geodetic_loc.w = HUGE_VAL;
- }
- }
- x[point_offset*i] = geodetic_loc.u;
- y[point_offset*i] = geodetic_loc.v;
- z[point_offset*i] = geodetic_loc.w;
- }
+/* ----------------------------------------------------------------------- */
+/* 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)
+ return 0;
+
+ /* Check first if projection is invertible. */
+ if( (P->inv3d == NULL) && (P->inv == NULL))
+ {
+ pj_ctx_set_errno( pj_get_ctx(P), -17 );
+ pj_log( pj_get_ctx(P), PJ_LOG_ERROR,
+ "pj_transform(): source projection not invertable" );
+ return -17;
+ }
+ /* If invertible - First try inv3d if defined */
+ if (P->inv3d != NULL)
+ {
+ /* Three dimensions must be defined */
+ if ( z == NULL)
+ {
+ pj_ctx_set_errno( pj_get_ctx(P), PJD_ERR_GEOCENTRIC);
+ return PJD_ERR_GEOCENTRIC;
}
- else
+
+ for (i=0; i < n; i++)
{
- /* Fallback to the original PROJ.4 API 2d inversion - inv */
- for( i = 0; i < point_count; i++ )
- {
- XY projected_loc;
- LP geodetic_loc;
+ XYZ projected_loc;
+ XYZ geodetic_loc;
- projected_loc.u = x[point_offset*i];
- projected_loc.v = y[point_offset*i];
+ projected_loc.u = x[dist*i];
+ projected_loc.v = y[dist*i];
+ projected_loc.w = z[dist*i];
- if( projected_loc.u == HUGE_VAL )
- continue;
+ if (projected_loc.u == HUGE_VAL)
+ continue;
- geodetic_loc = pj_inv( projected_loc, srcdefn );
- if( srcdefn->ctx->last_errno != 0 )
+ geodetic_loc = pj_inv3d(projected_loc, P);
+ if( P->ctx->last_errno != 0 )
+ {
+ if( (P->ctx->last_errno != 33 /*EDOM*/
+ && P->ctx->last_errno != 34 /*ERANGE*/ )
+ && (P->ctx->last_errno > 0
+ || P->ctx->last_errno < -44 || n == 1
+ || transient_error[-P->ctx->last_errno] == 0 ) )
+ return P->ctx->last_errno;
+ else
{
- if( (srcdefn->ctx->last_errno != 33 /*EDOM*/
- && srcdefn->ctx->last_errno != 34 /*ERANGE*/ )
- && (srcdefn->ctx->last_errno > 0
- || srcdefn->ctx->last_errno < -44 || point_count == 1
- || transient_error[-srcdefn->ctx->last_errno] == 0 ) )
- return srcdefn->ctx->last_errno;
- else
- {
- geodetic_loc.u = HUGE_VAL;
- geodetic_loc.v = HUGE_VAL;
- }
+ geodetic_loc.u = HUGE_VAL;
+ geodetic_loc.v = HUGE_VAL;
+ geodetic_loc.w = HUGE_VAL;
}
-
- x[point_offset*i] = geodetic_loc.u;
- y[point_offset*i] = geodetic_loc.v;
}
+
+ x[dist*i] = geodetic_loc.u;
+ y[dist*i] = geodetic_loc.v;
+ z[dist*i] = geodetic_loc.w;
+
}
+ return 0;
}
-/* -------------------------------------------------------------------- */
-/* But if they are already lat long, adjust for the prime */
-/* meridian if there is one in effect. */
-/* -------------------------------------------------------------------- */
- if ((srcdefn->is_geocent || srcdefn->is_latlong) && ( srcdefn->from_greenwich != 0.0 ))
- {
- for( i = 0; i < point_count; i++ )
+ /* Fallback to the original PROJ.4 API 2d inversion - inv */
+ for( i = 0; i < n; i++ ) {
+ XY projected_loc;
+ LP geodetic_loc;
+
+ projected_loc.u = x[dist*i];
+ projected_loc.v = y[dist*i];
+
+ if( projected_loc.u == HUGE_VAL )
+ continue;
+
+ geodetic_loc = pj_inv( projected_loc, P );
+ if( P->ctx->last_errno != 0 )
{
- if( x[point_offset*i] != HUGE_VAL )
- x[point_offset*i] += srcdefn->from_greenwich;
+ if( (P->ctx->last_errno != 33 /*EDOM*/
+ && P->ctx->last_errno != 34 /*ERANGE*/ )
+ && (P->ctx->last_errno > 0
+ || P->ctx->last_errno < -44 || n == 1
+ || transient_error[-P->ctx->last_errno] == 0 ) )
+ return P->ctx->last_errno;
+ else
+ {
+ geodetic_loc.u = HUGE_VAL;
+ geodetic_loc.v = HUGE_VAL;
+ }
}
- }
-/* -------------------------------------------------------------------- */
-/* Do we need to translate from geoid to ellipsoidal vertical */
-/* datum? */
-/* -------------------------------------------------------------------- */
- if( srcdefn->has_geoid_vgrids && z != NULL )
- {
- if( pj_apply_vgridshift( srcdefn, "sgeoidgrids",
- &(srcdefn->vgridlist_geoid),
- &(srcdefn->vgridlist_geoid_count),
- 0, point_count, point_offset, x, y, z ) != 0 )
- return pj_ctx_get_errno(srcdefn->ctx);
+ x[dist*i] = geodetic_loc.u;
+ y[dist*i] = geodetic_loc.v;
}
+ return 0;
+}
-/* -------------------------------------------------------------------- */
-/* Convert datums if needed, and possible. */
-/* -------------------------------------------------------------------- */
- if( pj_datum_transform( srcdefn, dstdefn, point_count, point_offset,
- x, y, z ) != 0 )
- {
- if( srcdefn->ctx->last_errno != 0 )
- return srcdefn->ctx->last_errno;
- else
- return dstdefn->ctx->last_errno;
- }
-/* -------------------------------------------------------------------- */
-/* Do we need to translate from ellipsoidal to geoid vertical */
-/* datum? */
-/* -------------------------------------------------------------------- */
- if( dstdefn->has_geoid_vgrids && z != NULL )
- {
- if( pj_apply_vgridshift( dstdefn, "sgeoidgrids",
- &(dstdefn->vgridlist_geoid),
- &(dstdefn->vgridlist_geoid_count),
- 1, point_count, point_offset, x, y, z ) != 0 )
- return dstdefn->ctx->last_errno;
- }
/* -------------------------------------------------------------------- */
-/* But if they are staying lat long, adjust for the prime */
-/* meridian if there is one in effect. */
+/* Adjust for the prime meridian if needed. */
/* -------------------------------------------------------------------- */
- if ((dstdefn->is_geocent || dstdefn->is_latlong) && ( 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;
- }
+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;
}
+
+
/* -------------------------------------------------------------------- */
-/* Transform destination latlong to geocentric if required. */
+/* Adjust for vertical scale factor if needed */
/* -------------------------------------------------------------------- */
- if( dstdefn->is_geocent )
- {
- if( z == NULL )
- {
- pj_ctx_set_errno( dstdefn->ctx, PJD_ERR_GEOCENTRIC );
- return PJD_ERR_GEOCENTRIC;
- }
+static int height_unit (PJ *P, PJ_DIRECTION dir, long n, int dist, double *z) {
+ int i;
+ double fac = P->vto_meter;
- pj_geodetic_to_geocentric( dstdefn->a_orig, dstdefn->es_orig,
- point_count, point_offset, x, y, z );
+ if (PJ_FWD==dir)
+ fac = P->vfr_meter;
- 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;
- z[point_offset*i] *= srcdefn->fr_meter;
- }
- }
- }
- }
+ /* Nothing to do? */
+ if (fac==1.0)
+ return 0;
+ if (0==z)
+ return 0;
-/* -------------------------------------------------------------------- */
-/* Transform destination points to projection coordinates, if */
-/* desired. */
-/* -------------------------------------------------------------------- */
- else if( !dstdefn->is_latlong )
- {
+ for (i = 0; i < n; i++)
+ if (z[dist*i] != HUGE_VAL )
+ z[dist*i] *= fac;
- if( dstdefn->fwd3d != NULL)
- {
- /* Three dimensions must be defined */
- if ( z == NULL)
- {
- pj_ctx_set_errno( pj_get_ctx(dstdefn), PJD_ERR_GEOCENTRIC);
- return PJD_ERR_GEOCENTRIC;
- }
+ return 0;
+}
- for( i = 0; i < point_count; i++ )
- {
- XYZ projected_loc;
- LPZ geodetic_loc;
- geodetic_loc.u = x[point_offset*i];
- geodetic_loc.v = y[point_offset*i];
- geodetic_loc.w = z[point_offset*i];
- if (geodetic_loc.u == HUGE_VAL)
- continue;
+/* -------------------------------------------------------------------- */
+/* 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==0)
+ return PJD_ERR_GEOCENTRIC;
+ err = pj_apply_vgridshift (P, "sgeoidgrids",
+ &(P->vgridlist_geoid),
+ &(P->vgridlist_geoid_count),
+ dir==PJ_FWD ? 1 : 0, n, dist, x, y, z );
+ if (err)
+ return pj_ctx_get_errno(P->ctx);
+ return 0;
+}
- projected_loc = pj_fwd3d( geodetic_loc, dstdefn);
- if( dstdefn->ctx->last_errno != 0 )
- {
- if( (dstdefn->ctx->last_errno != 33 /*EDOM*/
- && dstdefn->ctx->last_errno != 34 /*ERANGE*/ )
- && (dstdefn->ctx->last_errno > 0
- || dstdefn->ctx->last_errno < -44 || point_count == 1
- || transient_error[-dstdefn->ctx->last_errno] == 0 ) )
- return dstdefn->ctx->last_errno;
- else
- {
- projected_loc.u = HUGE_VAL;
- projected_loc.v = HUGE_VAL;
- projected_loc.w = HUGE_VAL;
- }
- }
- x[point_offset*i] = projected_loc.u;
- y[point_offset*i] = projected_loc.v;
- z[point_offset*i] = projected_loc.w;
- }
- }
- else
- {
- for( i = 0; i < point_count; i++ )
- {
- XY projected_loc;
- LP geodetic_loc;
+/* -------------------------------------------------------------------- */
+/* 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;
+}
- 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( dstdefn->ctx->last_errno != 0 )
- {
- if( (dstdefn->ctx->last_errno != 33 /*EDOM*/
- && dstdefn->ctx->last_errno != 34 /*ERANGE*/ )
- && (dstdefn->ctx->last_errno > 0
- || dstdefn->ctx->last_errno < -44 || point_count == 1
- || transient_error[-dstdefn->ctx->last_errno] == 0 ) )
- return dstdefn->ctx->last_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;
- }
- }
- }
/* -------------------------------------------------------------------- */
/* If a wrapping center other than 0 is provided, rewrap around */
/* the suggested center (for latlong coordinate systems only). */
/* -------------------------------------------------------------------- */
- else if( dstdefn->is_latlong && dstdefn->is_long_wrap_set )
- {
- for( i = 0; i < point_count; i++ )
- {
- double val = x[point_offset*i];
- if( val == HUGE_VAL )
- continue;
+static int long_wrap (PJ *P, long n, int dist, double *x) {
+ long i;
- /* Get fast in ] -2 PI, 2 PI [ range */
- val = fmod(val, M_TWOPI);
- while( val < dstdefn->long_wrap_center - M_PI )
- val += M_TWOPI;
- while( val > dstdefn->long_wrap_center + M_PI )
- val -= M_TWOPI;
- x[point_offset*i] = val;
- }
- }
+ /* Nothing to do? */
+ if (P->is_geocent)
+ return 0;
+ if (!P->is_long_wrap_set)
+ return 0;
+ if (!P->is_latlong)
+ return 0;
-/* -------------------------------------------------------------------- */
-/* Transform normalized axes into unusual output coordinate axis */
-/* orientation if needed. */
-/* -------------------------------------------------------------------- */
- if( strcmp(dstdefn->axis,"enu") != 0 )
- {
- int err;
+ for (i = 0; i < n; i++ ) {
+ double val = x[dist*i];
+ if (val == HUGE_VAL)
+ continue;
- err = pj_adjust_axis( dstdefn->ctx, dstdefn->axis,
- 1, point_count, point_offset, x, y, z );
- if( err != 0 )
- return err;
+ /* 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 *srcdefn, PJ *dstdefn,
+ long point_count, int point_offset,
+ double *x, double *y, double *z
+){
+ int err;
+
+ srcdefn->ctx->last_errno = 0;
+ dstdefn->ctx->last_errno = 0;
+
+ if( point_offset == 0 )
+ point_offset = 1;
+
+ /* Bring input to "normal form": longitude, latitude, ellipsoidal height */
+
+ err = adjust_axes (srcdefn, PJ_INV, point_count, point_offset, x, y, z);
+ if (err)
+ return err;
+ err = geographic_to_cartesian (srcdefn, PJ_INV, point_count, point_offset, x, y, z);
+ if (err)
+ return err;
+ err = projected_to_geographic (srcdefn, point_count, point_offset, x, y, z);
+ if (err)
+ return err;
+ err = prime_meridian (srcdefn, PJ_INV, point_count, point_offset, x);
+ if (err)
+ return err;
+ err = height_unit (srcdefn, PJ_INV, point_count, point_offset, z);
+ if (err)
+ return err;
+ err = geometric_to_orthometric (srcdefn, 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(srcdefn, dstdefn, 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 (dstdefn, PJ_FWD, point_count, point_offset, x, y, z);
+ if (err)
+ return err;
+ err = height_unit (dstdefn, PJ_FWD, point_count, point_offset, z);
+ if (err)
+ return err;
+ err = prime_meridian (dstdefn, PJ_FWD, point_count, point_offset, x);
+ if (err)
+ return err;
+ err = geographic_to_cartesian (dstdefn, PJ_FWD, point_count, point_offset, x, y, z);
+ if (err)
+ return err;
+ err = geographic_to_projected (dstdefn, point_count, point_offset, x, y, z);
+ if (err)
+ return err;
+ err = long_wrap (dstdefn, point_count, point_offset, x);
+ if (err)
+ return err;
+ err = adjust_axes (dstdefn, PJ_FWD, point_count, point_offset, x, y, z);
+ if (err)
+ return err;
return 0;
}
+
+
/************************************************************************/
/* pj_geodetic_to_geocentric() */
/************************************************************************/
diff --git a/src/proj.h b/src/proj.h
index b938f586..0025f3ad 100644
--- a/src/proj.h
+++ b/src/proj.h
@@ -324,7 +324,7 @@ size_t proj_trans_generic (
PJ_COORD proj_coord (double x, double y, double z, double t);
/* Measure internal consistency - in forward or inverse direction */
-double proj_roundtrip (PJ *P, PJ_DIRECTION direction, int n, PJ_COORD *coo);
+double proj_roundtrip (PJ *P, PJ_DIRECTION direction, int n, PJ_COORD *coord);
/* Geodesic distance between two points with angular 2D coordinates */
double proj_lp_dist (const PJ *P, PJ_COORD a, PJ_COORD b);
@@ -374,7 +374,7 @@ double proj_torad (double angle_in_degrees);
double proj_todeg (double angle_in_radians);
/* Geographical to geocentric latitude - another of the "simple, but useful" */
-PJ_COORD proj_geocentric_latitude (const PJ *P, PJ_DIRECTION direction, PJ_COORD coo);
+PJ_COORD proj_geocentric_latitude (const PJ *P, PJ_DIRECTION direction, PJ_COORD coord);
double proj_dmstor(const char *is, char **rs);
char* proj_rtodms(char *s, double r, int pos, int neg);
diff --git a/src/proj_4D_api.c b/src/proj_4D_api.c
index fb20978b..f0ea7083 100644
--- a/src/proj_4D_api.c
+++ b/src/proj_4D_api.c
@@ -113,7 +113,7 @@ double proj_xyz_dist (PJ_COORD a, PJ_COORD b) {
/* Measure numerical deviation after n roundtrips fwd-inv (or inv-fwd) */
-double proj_roundtrip (PJ *P, PJ_DIRECTION direction, int n, PJ_COORD *coo) {
+double proj_roundtrip (PJ *P, PJ_DIRECTION direction, int n, PJ_COORD *coord) {
int i;
PJ_COORD t, org;
@@ -126,9 +126,9 @@ double proj_roundtrip (PJ *P, PJ_DIRECTION direction, int n, PJ_COORD *coo) {
}
/* in the first half-step, we generate the output value */
- org = *coo;
- *coo = proj_trans (P, direction, org);
- t = *coo;
+ org = *coord;
+ *coord = proj_trans (P, direction, org);
+ t = *coord;
/* now we take n-1 full steps in inverse direction: We are */
/* out of phase due to the half step already taken */
@@ -148,26 +148,26 @@ double proj_roundtrip (PJ *P, PJ_DIRECTION direction, int n, PJ_COORD *coo) {
/**************************************************************************************/
-PJ_COORD proj_trans (PJ *P, PJ_DIRECTION direction, PJ_COORD coo) {
+PJ_COORD proj_trans (PJ *P, PJ_DIRECTION direction, PJ_COORD coord) {
/***************************************************************************************
-Apply the transformation P to the coordinate coo, preferring the 4D interfaces if
+Apply the transformation P to the coordinate coord, preferring the 4D interfaces if
available.
See also pj_approx_2D_trans and pj_approx_3D_trans in pj_internal.c, which work
similarly, but prefers the 2D resp. 3D interfaces if available.
***************************************************************************************/
if (0==P)
- return coo;
+ return coord;
if (P->inverted)
direction = -direction;
switch (direction) {
case PJ_FWD:
- return pj_fwd4d (coo, P);
+ return pj_fwd4d (coord, P);
case PJ_INV:
- return pj_inv4d (coo, P);
+ return pj_inv4d (coord, P);
case PJ_IDENT:
- return coo;
+ return coord;
default:
break;
}
@@ -357,7 +357,7 @@ size_t proj_trans_generic (
/*************************************************************************************/
-PJ_COORD proj_geocentric_latitude (const PJ *P, PJ_DIRECTION direction, PJ_COORD coo) {
+PJ_COORD proj_geocentric_latitude (const PJ *P, PJ_DIRECTION direction, PJ_COORD coord) {
/**************************************************************************************
Convert geographical latitude to geocentric (or the other way round if
direction = PJ_INV)
@@ -373,13 +373,13 @@ PJ_COORD proj_geocentric_latitude (const PJ *P, PJ_DIRECTION direction, PJ_COORD
consequently, the input is copied directly to the output.
**************************************************************************************/
const double limit = M_HALFPI - 1e-9;
- PJ_COORD res = coo;
- if ((coo.lp.phi > limit) || (coo.lp.phi < -limit) || (P->es==0))
+ PJ_COORD res = coord;
+ if ((coord.lp.phi > limit) || (coord.lp.phi < -limit) || (P->es==0))
return res;
if (direction==PJ_FWD)
- res.lp.phi = atan (P->one_es * tan (coo.lp.phi) );
+ res.lp.phi = atan (P->one_es * tan (coord.lp.phi) );
else
- res.lp.phi = atan (P->rone_es * tan (coo.lp.phi) );
+ res.lp.phi = atan (P->rone_es * tan (coord.lp.phi) );
return res;
}
diff --git a/src/proj_internal.h b/src/proj_internal.h
index 071510c7..e72ce578 100644
--- a/src/proj_internal.h
+++ b/src/proj_internal.h
@@ -33,7 +33,7 @@
#endif
#include <math.h> /* For M_PI */
-#include <proj.h>
+#include "proj.h"
#ifdef PROJECTS_H
#error proj_internal.h must be included before projects.h
@@ -73,8 +73,6 @@ enum pj_io_units {
enum pj_io_units pj_left (PJ *P);
enum pj_io_units pj_right (PJ *P);
-PJ_COORD proj_trans (PJ *P, PJ_DIRECTION direction, PJ_COORD obs);
-
PJ_COORD proj_coord_error (void);
void proj_context_errno_set (PJ_CONTEXT *ctx, int err);