svn-gvsig-desktop / tags / v1_1_2_Build_1045 / libraries / libjni-proj4 / src / pj_transform.c @ 38629
History | View | Annotate | Download (22.5 KB)
1 |
/******************************************************************************
|
---|---|
2 |
* $Id: pj_transform.c,v 1.13 2004/10/25 15:34:36 fwarmerdam Exp $
|
3 |
*
|
4 |
* Project: PROJ.4
|
5 |
* Purpose: Perform overall coordinate system to coordinate system
|
6 |
* transformations (pj_transform() function) including reprojection
|
7 |
* and datum shifting.
|
8 |
* Author: Frank Warmerdam, warmerdam@pobox.com
|
9 |
*
|
10 |
******************************************************************************
|
11 |
* Copyright (c) 2000, Frank Warmerdam
|
12 |
*
|
13 |
* Permission is hereby granted, free of charge, to any person obtaining a
|
14 |
* copy of this software and associated documentation files (the "Software"),
|
15 |
* to deal in the Software without restriction, including without limitation
|
16 |
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
17 |
* and/or sell copies of the Software, and to permit persons to whom the
|
18 |
* Software is furnished to do so, subject to the following conditions:
|
19 |
*
|
20 |
* The above copyright notice and this permission notice shall be included
|
21 |
* in all copies or substantial portions of the Software.
|
22 |
*
|
23 |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
24 |
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
25 |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
26 |
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
27 |
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
28 |
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
29 |
* DEALINGS IN THE SOFTWARE.
|
30 |
******************************************************************************
|
31 |
*
|
32 |
* $Log: pj_transform.c,v $
|
33 |
* Revision 1.13 2004/10/25 15:34:36 fwarmerdam
|
34 |
* make names of geodetic funcs from geotrans unique
|
35 |
*
|
36 |
* Revision 1.12 2004/05/03 19:45:23 warmerda
|
37 |
* Altered so that raw ellpses are treated as a essentially having a
|
38 |
* +towgs84=0,0,0 specification so ellpisoid shifts are applied.
|
39 |
* Fixed so that prime meridian shifts are applied if the coordinate system is
|
40 |
* not lat/long (ie. if it is projected). This fixes:
|
41 |
* http://bugzilla.remotesensing.org/show_bug.cgi?id=510
|
42 |
*
|
43 |
* Revision 1.11 2004/01/24 09:37:19 warmerda
|
44 |
* pj_transform() will no longer return an error code if any of the points are
|
45 |
* transformable. In this case the application is expected to check for
|
46 |
* HUGE_VAL to identify failed points.
|
47 |
* As part of the implementation, I added a list of pj_errno values that
|
48 |
* are transient (ie per-point) rather than indicating global failure for the
|
49 |
* coordinate system definition. We use this in deciding which pj_fwd and
|
50 |
* pj_inv error codes are really fatal and should be reported.
|
51 |
*
|
52 |
* Revision 1.10 2003/08/21 02:09:06 warmerda
|
53 |
* added a bunch of HUGE_VAL checking
|
54 |
*
|
55 |
* Revision 1.9 2003/03/26 16:52:30 warmerda
|
56 |
* added check that an inverse transformation func exists
|
57 |
*
|
58 |
* Revision 1.8 2002/12/14 20:35:43 warmerda
|
59 |
* implement units support for geocentric coordinates
|
60 |
*
|
61 |
* Revision 1.7 2002/12/14 20:14:35 warmerda
|
62 |
* added geocentric support
|
63 |
*
|
64 |
* Revision 1.6 2002/12/09 16:01:02 warmerda
|
65 |
* added prime meridian support
|
66 |
*
|
67 |
* Revision 1.5 2002/12/01 19:25:26 warmerda
|
68 |
* applied fix for 7 param shift in pj_geocentric_from_wgs84, see bug 194
|
69 |
*
|
70 |
* Revision 1.4 2002/02/15 14:30:36 warmerda
|
71 |
* provide default Z array if none passed in in pj_datum_transform()
|
72 |
*
|
73 |
* Revision 1.3 2001/04/04 21:13:21 warmerda
|
74 |
* do arcsecond/radian and ppm datum parm transformation in pj_set_datum()
|
75 |
*
|
76 |
* Revision 1.2 2001/04/04 16:08:08 warmerda
|
77 |
* rewrote 7 param datum shift to match EPSG:9606, now works with example
|
78 |
*
|
79 |
* Revision 1.1 2000/07/06 23:32:27 warmerda
|
80 |
* New
|
81 |
*
|
82 |
*/
|
83 |
|
84 |
#include <projects.h> |
85 |
#include <string.h> |
86 |
#include <math.h> |
87 |
#include "geocent.h" |
88 |
|
89 |
PJ_CVSID("$Id: pj_transform.c,v 1.13 2004/10/25 15:34:36 fwarmerdam Exp $");
|
90 |
|
91 |
#ifndef SRS_WGS84_SEMIMAJOR
|
92 |
#define SRS_WGS84_SEMIMAJOR 6378137.0 |
93 |
#endif
|
94 |
|
95 |
#ifndef SRS_WGS84_ESQUARED
|
96 |
#define SRS_WGS84_ESQUARED 0.006694379990 |
97 |
#endif
|
98 |
|
99 |
#define Dx_BF (defn->datum_params[0]) |
100 |
#define Dy_BF (defn->datum_params[1]) |
101 |
#define Dz_BF (defn->datum_params[2]) |
102 |
#define Rx_BF (defn->datum_params[3]) |
103 |
#define Ry_BF (defn->datum_params[4]) |
104 |
#define Rz_BF (defn->datum_params[5]) |
105 |
#define M_BF (defn->datum_params[6]) |
106 |
|
107 |
/*
|
108 |
** This table is intended to indicate for any given error code in
|
109 |
** the range 0 to -44, whether that error will occur for all locations (ie.
|
110 |
** it is a problem with the coordinate system as a whole) in which case the
|
111 |
** value would be 0, or if the problem is with the point being transformed
|
112 |
** in which case the value is 1.
|
113 |
**
|
114 |
** At some point we might want to move this array in with the error message
|
115 |
** list or something, but while experimenting with it this should be fine.
|
116 |
*/
|
117 |
|
118 |
static int transient_error[45] = { |
119 |
/* 0 1 2 3 4 5 6 7 8 9 */
|
120 |
/* 0 to 9 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
121 |
/* 10 to 19 */ 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, |
122 |
/* 20 to 29 */ 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, |
123 |
/* 30 to 39 */ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, |
124 |
/* 40 to 44 */ 0, 0, 0, 0, 0 }; |
125 |
|
126 |
/************************************************************************/
|
127 |
/* pj_transform() */
|
128 |
/* */
|
129 |
/* Currently this function doesn't recognise if two projections */
|
130 |
/* are identical (to short circuit reprojection) because it is */
|
131 |
/* difficult to compare PJ structures (since there are some */
|
132 |
/* projection specific components). */
|
133 |
/************************************************************************/
|
134 |
|
135 |
int pj_transform( PJ *srcdefn, PJ *dstdefn, long point_count, int point_offset, |
136 |
double *x, double *y, double *z ) |
137 |
|
138 |
{ |
139 |
long i;
|
140 |
int need_datum_shift;
|
141 |
|
142 |
pj_errno = 0;
|
143 |
|
144 |
if( point_offset == 0 ) |
145 |
point_offset = 1;
|
146 |
|
147 |
/* -------------------------------------------------------------------- */
|
148 |
/* Transform geocentric source coordinates to lat/long. */
|
149 |
/* -------------------------------------------------------------------- */
|
150 |
if( srcdefn->is_geocent )
|
151 |
{ |
152 |
if( z == NULL ) |
153 |
{ |
154 |
pj_errno = PJD_ERR_GEOCENTRIC; |
155 |
return PJD_ERR_GEOCENTRIC;
|
156 |
} |
157 |
|
158 |
if( srcdefn->to_meter != 1.0 ) |
159 |
{ |
160 |
for( i = 0; i < point_count; i++ ) |
161 |
{ |
162 |
x[point_offset*i] *= srcdefn->to_meter; |
163 |
y[point_offset*i] *= srcdefn->to_meter; |
164 |
} |
165 |
} |
166 |
|
167 |
if( pj_geocentric_to_geodetic( srcdefn->a, srcdefn->es,
|
168 |
point_count, point_offset, |
169 |
x, y, z ) != 0)
|
170 |
return pj_errno;
|
171 |
} |
172 |
|
173 |
/* -------------------------------------------------------------------- */
|
174 |
/* Transform source points to lat/long, if they aren't */
|
175 |
/* already. */
|
176 |
/* -------------------------------------------------------------------- */
|
177 |
else if( !srcdefn->is_latlong ) |
178 |
{ |
179 |
if( srcdefn->inv == NULL ) |
180 |
{ |
181 |
pj_errno = -17; /* this isn't correct, we need a no inverse err */ |
182 |
if( getenv( "PROJ_DEBUG" ) != NULL ) |
183 |
{ |
184 |
fprintf( stderr, |
185 |
"pj_transform(): source projection not invertable\n" );
|
186 |
} |
187 |
return pj_errno;
|
188 |
} |
189 |
|
190 |
for( i = 0; i < point_count; i++ ) |
191 |
{ |
192 |
XY projected_loc; |
193 |
LP geodetic_loc; |
194 |
|
195 |
projected_loc.u = x[point_offset*i]; |
196 |
projected_loc.v = y[point_offset*i]; |
197 |
|
198 |
if( projected_loc.u == HUGE_VAL )
|
199 |
continue;
|
200 |
|
201 |
geodetic_loc = pj_inv( projected_loc, srcdefn ); |
202 |
if( pj_errno != 0 ) |
203 |
{ |
204 |
if( pj_errno > 0 || pj_errno < -44 || point_count == 1 |
205 |
|| transient_error[-pj_errno] == 0 )
|
206 |
return pj_errno;
|
207 |
else
|
208 |
{ |
209 |
geodetic_loc.u = HUGE_VAL; |
210 |
geodetic_loc.v = HUGE_VAL; |
211 |
} |
212 |
} |
213 |
|
214 |
x[point_offset*i] = geodetic_loc.u; |
215 |
y[point_offset*i] = geodetic_loc.v; |
216 |
} |
217 |
} |
218 |
/* -------------------------------------------------------------------- */
|
219 |
/* But if they are already lat long, adjust for the prime */
|
220 |
/* meridian if there is one in effect. */
|
221 |
/* -------------------------------------------------------------------- */
|
222 |
if( srcdefn->from_greenwich != 0.0 ) |
223 |
{ |
224 |
for( i = 0; i < point_count; i++ ) |
225 |
{ |
226 |
if( x[point_offset*i] != HUGE_VAL )
|
227 |
x[point_offset*i] += srcdefn->from_greenwich; |
228 |
} |
229 |
} |
230 |
|
231 |
/* -------------------------------------------------------------------- */
|
232 |
/* Convert datums if needed, and possible. */
|
233 |
/* -------------------------------------------------------------------- */
|
234 |
if( pj_datum_transform( srcdefn, dstdefn, point_count, point_offset,
|
235 |
x, y, z ) != 0 )
|
236 |
return pj_errno;
|
237 |
|
238 |
/* -------------------------------------------------------------------- */
|
239 |
/* But if they are staying lat long, adjust for the prime */
|
240 |
/* meridian if there is one in effect. */
|
241 |
/* -------------------------------------------------------------------- */
|
242 |
if( dstdefn->from_greenwich != 0.0 ) |
243 |
{ |
244 |
for( i = 0; i < point_count; i++ ) |
245 |
{ |
246 |
if( x[point_offset*i] != HUGE_VAL )
|
247 |
x[point_offset*i] -= dstdefn->from_greenwich; |
248 |
} |
249 |
} |
250 |
|
251 |
|
252 |
/* -------------------------------------------------------------------- */
|
253 |
/* Transform destination latlong to geocentric if required. */
|
254 |
/* -------------------------------------------------------------------- */
|
255 |
if( dstdefn->is_geocent )
|
256 |
{ |
257 |
if( z == NULL ) |
258 |
{ |
259 |
pj_errno = PJD_ERR_GEOCENTRIC; |
260 |
return PJD_ERR_GEOCENTRIC;
|
261 |
} |
262 |
|
263 |
pj_geodetic_to_geocentric( dstdefn->a, dstdefn->es, |
264 |
point_count, point_offset, x, y, z ); |
265 |
|
266 |
if( dstdefn->fr_meter != 1.0 ) |
267 |
{ |
268 |
for( i = 0; i < point_count; i++ ) |
269 |
{ |
270 |
if( x[point_offset*i] != HUGE_VAL )
|
271 |
{ |
272 |
x[point_offset*i] *= dstdefn->fr_meter; |
273 |
y[point_offset*i] *= dstdefn->fr_meter; |
274 |
} |
275 |
} |
276 |
} |
277 |
} |
278 |
|
279 |
/* -------------------------------------------------------------------- */
|
280 |
/* Transform destination points to projection coordinates, if */
|
281 |
/* desired. */
|
282 |
/* -------------------------------------------------------------------- */
|
283 |
else if( !dstdefn->is_latlong ) |
284 |
{ |
285 |
for( i = 0; i < point_count; i++ ) |
286 |
{ |
287 |
XY projected_loc; |
288 |
LP geodetic_loc; |
289 |
|
290 |
geodetic_loc.u = x[point_offset*i]; |
291 |
geodetic_loc.v = y[point_offset*i]; |
292 |
|
293 |
if( geodetic_loc.u == HUGE_VAL )
|
294 |
continue;
|
295 |
|
296 |
projected_loc = pj_fwd( geodetic_loc, dstdefn ); |
297 |
if( pj_errno != 0 ) |
298 |
{ |
299 |
if( pj_errno > 0 || pj_errno < -44 || point_count == 1 |
300 |
|| transient_error[-pj_errno] == 0 )
|
301 |
return pj_errno;
|
302 |
else
|
303 |
{ |
304 |
projected_loc.u = HUGE_VAL; |
305 |
projected_loc.v = HUGE_VAL; |
306 |
} |
307 |
} |
308 |
|
309 |
x[point_offset*i] = projected_loc.u; |
310 |
y[point_offset*i] = projected_loc.v; |
311 |
} |
312 |
} |
313 |
|
314 |
return 0; |
315 |
} |
316 |
|
317 |
/************************************************************************/
|
318 |
/* pj_geodetic_to_geocentric() */
|
319 |
/************************************************************************/
|
320 |
|
321 |
int pj_geodetic_to_geocentric( double a, double es, |
322 |
long point_count, int point_offset, |
323 |
double *x, double *y, double *z ) |
324 |
|
325 |
{ |
326 |
double b;
|
327 |
int i;
|
328 |
|
329 |
if( es == 0.0 ) |
330 |
b = a; |
331 |
else
|
332 |
b = a * sqrt(1-es);
|
333 |
|
334 |
if( pj_Set_Geocentric_Parameters( a, b ) != 0 ) |
335 |
{ |
336 |
pj_errno = PJD_ERR_GEOCENTRIC; |
337 |
return pj_errno;
|
338 |
} |
339 |
|
340 |
for( i = 0; i < point_count; i++ ) |
341 |
{ |
342 |
long io = i * point_offset;
|
343 |
|
344 |
if( pj_Convert_Geodetic_To_Geocentric( y[io], x[io], z[io],
|
345 |
x+io, y+io, z+io ) != 0 )
|
346 |
{ |
347 |
pj_errno = PJD_ERR_GEOCENTRIC; |
348 |
return PJD_ERR_GEOCENTRIC;
|
349 |
} |
350 |
} |
351 |
|
352 |
return 0; |
353 |
} |
354 |
|
355 |
/************************************************************************/
|
356 |
/* pj_geodetic_to_geocentric() */
|
357 |
/************************************************************************/
|
358 |
|
359 |
int pj_geocentric_to_geodetic( double a, double es, |
360 |
long point_count, int point_offset, |
361 |
double *x, double *y, double *z ) |
362 |
|
363 |
{ |
364 |
double b;
|
365 |
int i;
|
366 |
|
367 |
if( es == 0.0 ) |
368 |
b = a; |
369 |
else
|
370 |
b = a * sqrt(1-es);
|
371 |
|
372 |
if( pj_Set_Geocentric_Parameters( a, b ) != 0 ) |
373 |
{ |
374 |
pj_errno = PJD_ERR_GEOCENTRIC; |
375 |
return pj_errno;
|
376 |
} |
377 |
|
378 |
for( i = 0; i < point_count; i++ ) |
379 |
{ |
380 |
long io = i * point_offset;
|
381 |
|
382 |
if( x[io] == HUGE_VAL )
|
383 |
continue;
|
384 |
|
385 |
pj_Convert_Geocentric_To_Geodetic( x[io], y[io], z[io], |
386 |
y+io, x+io, z+io ); |
387 |
} |
388 |
|
389 |
return 0; |
390 |
} |
391 |
|
392 |
/************************************************************************/
|
393 |
/* pj_compare_datums() */
|
394 |
/* */
|
395 |
/* Returns TRUE if the two datums are identical, otherwise */
|
396 |
/* FALSE. */
|
397 |
/************************************************************************/
|
398 |
|
399 |
int pj_compare_datums( PJ *srcdefn, PJ *dstdefn )
|
400 |
|
401 |
{ |
402 |
if( srcdefn->datum_type != dstdefn->datum_type )
|
403 |
{ |
404 |
return 0; |
405 |
} |
406 |
else if( srcdefn->a != dstdefn->a |
407 |
|| ABS(srcdefn->es - dstdefn->es) > 0.000000000050 ) |
408 |
{ |
409 |
/* the tolerence for es is to ensure that GRS80 and WGS84 are
|
410 |
considered identical */
|
411 |
return 0; |
412 |
} |
413 |
else if( srcdefn->datum_type == PJD_3PARAM ) |
414 |
{ |
415 |
return (srcdefn->datum_params[0] == dstdefn->datum_params[0] |
416 |
&& srcdefn->datum_params[1] == dstdefn->datum_params[1] |
417 |
&& srcdefn->datum_params[2] == dstdefn->datum_params[2]); |
418 |
} |
419 |
else if( srcdefn->datum_type == PJD_7PARAM ) |
420 |
{ |
421 |
return (srcdefn->datum_params[0] == dstdefn->datum_params[0] |
422 |
&& srcdefn->datum_params[1] == dstdefn->datum_params[1] |
423 |
&& srcdefn->datum_params[2] == dstdefn->datum_params[2] |
424 |
&& srcdefn->datum_params[3] == dstdefn->datum_params[3] |
425 |
&& srcdefn->datum_params[4] == dstdefn->datum_params[4] |
426 |
&& srcdefn->datum_params[5] == dstdefn->datum_params[5] |
427 |
&& srcdefn->datum_params[6] == dstdefn->datum_params[6]); |
428 |
} |
429 |
else if( srcdefn->datum_type == PJD_GRIDSHIFT ) |
430 |
{ |
431 |
return strcmp( pj_param(srcdefn->params,"snadgrids").s, |
432 |
pj_param(dstdefn->params,"snadgrids").s ) == 0; |
433 |
} |
434 |
else
|
435 |
return 1; |
436 |
} |
437 |
|
438 |
/************************************************************************/
|
439 |
/* pj_geocentic_to_wgs84() */
|
440 |
/************************************************************************/
|
441 |
|
442 |
int pj_geocentric_to_wgs84( PJ *defn,
|
443 |
long point_count, int point_offset, |
444 |
double *x, double *y, double *z ) |
445 |
|
446 |
{ |
447 |
int i;
|
448 |
|
449 |
pj_errno = 0;
|
450 |
|
451 |
if( defn->datum_type == PJD_3PARAM )
|
452 |
{ |
453 |
for( i = 0; i < point_count; i++ ) |
454 |
{ |
455 |
long io = i * point_offset;
|
456 |
|
457 |
if( x[io] == HUGE_VAL )
|
458 |
continue;
|
459 |
|
460 |
x[io] = x[io] + defn->datum_params[0];
|
461 |
y[io] = y[io] + defn->datum_params[1];
|
462 |
z[io] = z[io] + defn->datum_params[2];
|
463 |
} |
464 |
} |
465 |
else if( defn->datum_type == PJD_7PARAM ) |
466 |
{ |
467 |
for( i = 0; i < point_count; i++ ) |
468 |
{ |
469 |
long io = i * point_offset;
|
470 |
double x_out, y_out, z_out;
|
471 |
|
472 |
if( x[io] == HUGE_VAL )
|
473 |
continue;
|
474 |
|
475 |
x_out = M_BF*( x[io] - Rz_BF*y[io] + Ry_BF*z[io]) + Dx_BF; |
476 |
y_out = M_BF*( Rz_BF*x[io] + y[io] - Rx_BF*z[io]) + Dy_BF; |
477 |
z_out = M_BF*(-Ry_BF*x[io] + Rx_BF*y[io] + z[io]) + Dz_BF; |
478 |
|
479 |
x[io] = x_out; |
480 |
y[io] = y_out; |
481 |
z[io] = z_out; |
482 |
} |
483 |
} |
484 |
|
485 |
return 0; |
486 |
} |
487 |
|
488 |
/************************************************************************/
|
489 |
/* pj_geocentic_from_wgs84() */
|
490 |
/************************************************************************/
|
491 |
|
492 |
int pj_geocentric_from_wgs84( PJ *defn,
|
493 |
long point_count, int point_offset, |
494 |
double *x, double *y, double *z ) |
495 |
|
496 |
{ |
497 |
int i;
|
498 |
|
499 |
pj_errno = 0;
|
500 |
|
501 |
if( defn->datum_type == PJD_3PARAM )
|
502 |
{ |
503 |
for( i = 0; i < point_count; i++ ) |
504 |
{ |
505 |
long io = i * point_offset;
|
506 |
|
507 |
if( x[io] == HUGE_VAL )
|
508 |
continue;
|
509 |
|
510 |
x[io] = x[io] - defn->datum_params[0];
|
511 |
y[io] = y[io] - defn->datum_params[1];
|
512 |
z[io] = z[io] - defn->datum_params[2];
|
513 |
} |
514 |
} |
515 |
else if( defn->datum_type == PJD_7PARAM ) |
516 |
{ |
517 |
for( i = 0; i < point_count; i++ ) |
518 |
{ |
519 |
long io = i * point_offset;
|
520 |
double x_tmp, y_tmp, z_tmp;
|
521 |
|
522 |
if( x[io] == HUGE_VAL )
|
523 |
continue;
|
524 |
|
525 |
x_tmp = (x[io] - Dx_BF) / M_BF; |
526 |
y_tmp = (y[io] - Dy_BF) / M_BF; |
527 |
z_tmp = (z[io] - Dz_BF) / M_BF; |
528 |
|
529 |
x[io] = x_tmp + Rz_BF*y_tmp - Ry_BF*z_tmp; |
530 |
y[io] = -Rz_BF*x_tmp + y_tmp + Rx_BF*z_tmp; |
531 |
z[io] = Ry_BF*x_tmp - Rx_BF*y_tmp + z_tmp; |
532 |
} |
533 |
} |
534 |
|
535 |
return 0; |
536 |
} |
537 |
|
538 |
/************************************************************************/
|
539 |
/* pj_datum_transform() */
|
540 |
/************************************************************************/
|
541 |
|
542 |
int pj_datum_transform( PJ *srcdefn, PJ *dstdefn,
|
543 |
long point_count, int point_offset, |
544 |
double *x, double *y, double *z ) |
545 |
|
546 |
{ |
547 |
double src_a, src_es, dst_a, dst_es;
|
548 |
int z_is_temp = FALSE;
|
549 |
|
550 |
pj_errno = 0;
|
551 |
|
552 |
/* -------------------------------------------------------------------- */
|
553 |
/* Short cut if the datums are identical. */
|
554 |
/* -------------------------------------------------------------------- */
|
555 |
if( pj_compare_datums( srcdefn, dstdefn ) )
|
556 |
return 0; |
557 |
|
558 |
src_a = srcdefn->a; |
559 |
src_es = srcdefn->es; |
560 |
|
561 |
dst_a = dstdefn->a; |
562 |
dst_es = dstdefn->es; |
563 |
|
564 |
/* -------------------------------------------------------------------- */
|
565 |
/* Create a temporary Z array if one is not provided. */
|
566 |
/* -------------------------------------------------------------------- */
|
567 |
if( z == NULL ) |
568 |
{ |
569 |
int bytes = sizeof(double) * point_count * point_offset; |
570 |
z = (double *) pj_malloc(bytes);
|
571 |
memset( z, 0, bytes );
|
572 |
z_is_temp = TRUE; |
573 |
} |
574 |
|
575 |
#define CHECK_RETURN {if( pj_errno != 0 ) { if( z_is_temp ) pj_dalloc(z); return pj_errno; }} |
576 |
|
577 |
/* -------------------------------------------------------------------- */
|
578 |
/* If this datum requires grid shifts, then apply it to geodetic */
|
579 |
/* coordinates. */
|
580 |
/* -------------------------------------------------------------------- */
|
581 |
if( srcdefn->datum_type == PJD_GRIDSHIFT )
|
582 |
{ |
583 |
pj_apply_gridshift( pj_param(srcdefn->params,"snadgrids").s, 0, |
584 |
point_count, point_offset, x, y, z ); |
585 |
CHECK_RETURN; |
586 |
|
587 |
src_a = SRS_WGS84_SEMIMAJOR; |
588 |
src_es = 0.006694379990; |
589 |
} |
590 |
|
591 |
if( dstdefn->datum_type == PJD_GRIDSHIFT )
|
592 |
{ |
593 |
dst_a = SRS_WGS84_SEMIMAJOR; |
594 |
dst_es = 0.006694379990; |
595 |
} |
596 |
|
597 |
/* ==================================================================== */
|
598 |
/* Do we need to go through geocentric coordinates? */
|
599 |
/* ==================================================================== */
|
600 |
if( src_es != dst_es || src_a != dst_a
|
601 |
|| srcdefn->datum_type == PJD_3PARAM |
602 |
|| srcdefn->datum_type == PJD_7PARAM |
603 |
|| dstdefn->datum_type == PJD_3PARAM |
604 |
|| dstdefn->datum_type == PJD_7PARAM) |
605 |
{ |
606 |
/* -------------------------------------------------------------------- */
|
607 |
/* Convert to geocentric coordinates. */
|
608 |
/* -------------------------------------------------------------------- */
|
609 |
pj_geodetic_to_geocentric( src_a, src_es, |
610 |
point_count, point_offset, x, y, z ); |
611 |
CHECK_RETURN; |
612 |
|
613 |
/* -------------------------------------------------------------------- */
|
614 |
/* Convert between datums. */
|
615 |
/* -------------------------------------------------------------------- */
|
616 |
if( srcdefn->datum_type == PJD_3PARAM
|
617 |
|| srcdefn->datum_type == PJD_7PARAM ) |
618 |
{ |
619 |
pj_geocentric_to_wgs84( srcdefn, point_count, point_offset,x,y,z); |
620 |
CHECK_RETURN; |
621 |
} |
622 |
|
623 |
if( dstdefn->datum_type == PJD_3PARAM
|
624 |
|| dstdefn->datum_type == PJD_7PARAM ) |
625 |
{ |
626 |
pj_geocentric_from_wgs84( dstdefn, point_count,point_offset,x,y,z); |
627 |
CHECK_RETURN; |
628 |
} |
629 |
|
630 |
/* -------------------------------------------------------------------- */
|
631 |
/* Convert back to geodetic coordinates. */
|
632 |
/* -------------------------------------------------------------------- */
|
633 |
pj_geocentric_to_geodetic( dst_a, dst_es, |
634 |
point_count, point_offset, x, y, z ); |
635 |
CHECK_RETURN; |
636 |
} |
637 |
|
638 |
/* -------------------------------------------------------------------- */
|
639 |
/* Apply grid shift to destination if required. */
|
640 |
/* -------------------------------------------------------------------- */
|
641 |
if( dstdefn->datum_type == PJD_GRIDSHIFT )
|
642 |
{ |
643 |
pj_apply_gridshift( pj_param(dstdefn->params,"snadgrids").s, 1, |
644 |
point_count, point_offset, x, y, z ); |
645 |
CHECK_RETURN; |
646 |
} |
647 |
|
648 |
if( z_is_temp )
|
649 |
pj_dalloc( z ); |
650 |
|
651 |
return 0; |
652 |
} |
653 |
|