svn-gvsig-desktop / tags / v1_9_Build_1222 / libraries / libjni-proj4 / src / pj_init.c @ 41849
History | View | Annotate | Download (12.8 KB)
1 |
/******************************************************************************
|
---|---|
2 |
* $Id: pj_init.c,v 1.16 2004/09/08 15:23:37 warmerda Exp $
|
3 |
*
|
4 |
* Project: PROJ.4
|
5 |
* Purpose: Initialize projection object from string definition. Includes
|
6 |
* pj_init(), pj_init_plus() and pj_free() function.
|
7 |
* Author: Gerald Evenden, Frank Warmerdam <warmerdam@pobox.com>
|
8 |
*
|
9 |
******************************************************************************
|
10 |
* Copyright (c) 1995, Gerald Evenden
|
11 |
* Copyright (c) 2002, Frank Warmerdam <warmerdam@pobox.com>
|
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_init.c,v $
|
33 |
* Revision 1.16 2004/09/08 15:23:37 warmerda
|
34 |
* added new error for unknown prime meridians
|
35 |
*
|
36 |
* Revision 1.15 2004/05/05 01:45:41 warmerda
|
37 |
* Made sword even longer.
|
38 |
*
|
39 |
* Revision 1.14 2004/05/05 01:45:00 warmerda
|
40 |
* Make sword buffer larger so long +towgs84 parameters don't get split.
|
41 |
*
|
42 |
* Revision 1.13 2003/09/16 03:46:21 warmerda
|
43 |
* dont use default ellps if any earth model info is set: bug 386
|
44 |
*
|
45 |
* Revision 1.12 2003/08/21 02:15:59 warmerda
|
46 |
* improve MAX_ARG checking
|
47 |
*
|
48 |
* Revision 1.11 2003/06/09 21:23:16 warmerda
|
49 |
* ensure start is initialized at very beginning of pj_init()
|
50 |
*
|
51 |
* Revision 1.10 2003/03/16 16:38:24 warmerda
|
52 |
* Modified get_opt() to terminate reading the definition when a new
|
53 |
* definition (a word starting with '<') is encountered, in addition to when
|
54 |
* the definition terminator '<>' is encountered, so that unterminated
|
55 |
* definitions like those in the distributed esri file will work properly.
|
56 |
* http://bugzilla.remotesensing.org/show_bug.cgi?id=302
|
57 |
*
|
58 |
* Revision 1.9 2002/12/14 20:15:02 warmerda
|
59 |
* added geocentric support, updated headers
|
60 |
*
|
61 |
*/
|
62 |
|
63 |
#define PJ_LIB__
|
64 |
#include <projects.h> |
65 |
#include <stdio.h> |
66 |
#include <string.h> |
67 |
#include <errno.h> |
68 |
|
69 |
PJ_CVSID("$Id: pj_init.c,v 1.16 2004/09/08 15:23:37 warmerda Exp $");
|
70 |
|
71 |
static paralist *start;
|
72 |
extern FILE *pj_open_lib(char *, char *); |
73 |
|
74 |
/************************************************************************/
|
75 |
/* get_opt() */
|
76 |
/************************************************************************/
|
77 |
static paralist *
|
78 |
get_opt(FILE *fid, char *name, paralist *next) {
|
79 |
char sword[302], *word = sword+1; |
80 |
int first = 1, len, c; |
81 |
|
82 |
len = strlen(name); |
83 |
*sword = 't';
|
84 |
while (fscanf(fid, "%300s", word) == 1) { |
85 |
if (*word == '#') /* skip comments */ |
86 |
while((c = fgetc(fid)) != EOF && c != '\n') ; |
87 |
else if (*word == '<') { /* control name */ |
88 |
if (first && !strncmp(name, word + 1, len) |
89 |
&& word[len + 1] == '>') |
90 |
first = 0;
|
91 |
else if (!first && *word == '<') { |
92 |
while((c = fgetc(fid)) != EOF && c != '\n') ; |
93 |
break;
|
94 |
} |
95 |
} else if (!first && !pj_param(start, sword).i) { |
96 |
/* don't default ellipse if datum, ellps or any earth model
|
97 |
information is set. */
|
98 |
if( strncmp(word,"ellps=",6) != 0 |
99 |
|| (!pj_param(start, "tdatum").i
|
100 |
&& !pj_param(start, "tellps").i
|
101 |
&& !pj_param(start, "ta").i
|
102 |
&& !pj_param(start, "tb").i
|
103 |
&& !pj_param(start, "trf").i
|
104 |
&& !pj_param(start, "tf").i) )
|
105 |
{ |
106 |
next = next->next = pj_mkparam(word); |
107 |
} |
108 |
} |
109 |
} |
110 |
|
111 |
if (errno == 25) |
112 |
errno = 0;
|
113 |
return next;
|
114 |
} |
115 |
|
116 |
/************************************************************************/
|
117 |
/* get_defaults() */
|
118 |
/************************************************************************/
|
119 |
static paralist *
|
120 |
get_defaults(paralist *next, char *name) {
|
121 |
FILE *fid; |
122 |
|
123 |
if (fid = pj_open_lib("proj_def.dat", "rt")) { |
124 |
next = get_opt(fid, "general", next);
|
125 |
rewind(fid); |
126 |
next = get_opt(fid, name, next); |
127 |
(void)fclose(fid);
|
128 |
} |
129 |
if (errno)
|
130 |
errno = 0; /* don't care if can't open file */ |
131 |
return next;
|
132 |
} |
133 |
|
134 |
/************************************************************************/
|
135 |
/* get_init() */
|
136 |
/************************************************************************/
|
137 |
static paralist *
|
138 |
get_init(paralist *next, char *name) {
|
139 |
char fname[MAX_PATH_FILENAME+ID_TAG_MAX+3], *opt; |
140 |
FILE *fid; |
141 |
|
142 |
(void)strncpy(fname, name, MAX_PATH_FILENAME + ID_TAG_MAX + 1); |
143 |
if (opt = strrchr(fname, ':')) |
144 |
*opt++ = '\0';
|
145 |
else { pj_errno = -3; return(0); } |
146 |
if (fid = pj_open_lib(fname, "rt")) |
147 |
next = get_opt(fid, opt, next); |
148 |
else
|
149 |
return(0); |
150 |
(void)fclose(fid);
|
151 |
if (errno == 25) |
152 |
errno = 0; /* unknown problem with some sys errno<-25 */ |
153 |
return next;
|
154 |
} |
155 |
|
156 |
/************************************************************************/
|
157 |
/* pj_init_plus() */
|
158 |
/* */
|
159 |
/* Same as pj_init() except it takes one argument string with */
|
160 |
/* individual arguments preceeded by '+', such as "+proj=utm */
|
161 |
/* +zone=11 +ellps=WGS84". */
|
162 |
/************************************************************************/
|
163 |
|
164 |
PJ * |
165 |
pj_init_plus( const char *definition ) |
166 |
|
167 |
{ |
168 |
#define MAX_ARG 200 |
169 |
char *argv[MAX_ARG];
|
170 |
char *defn_copy;
|
171 |
int argc = 0, i; |
172 |
PJ *result; |
173 |
|
174 |
/* make a copy that we can manipulate */
|
175 |
defn_copy = (char *) pj_malloc( strlen(definition)+1 ); |
176 |
strcpy( defn_copy, definition ); |
177 |
|
178 |
/* split into arguments based on '+' and trim white space */
|
179 |
|
180 |
for( i = 0; defn_copy[i] != '\0'; i++ ) |
181 |
{ |
182 |
switch( defn_copy[i] )
|
183 |
{ |
184 |
case '+': |
185 |
if( i == 0 || defn_copy[i-1] == '\0' ) |
186 |
{ |
187 |
if( argc+1 == MAX_ARG ) |
188 |
{ |
189 |
pj_errno = -44;
|
190 |
return NULL; |
191 |
} |
192 |
|
193 |
argv[argc++] = defn_copy + i + 1;
|
194 |
} |
195 |
break;
|
196 |
|
197 |
case ' ': |
198 |
case '\t': |
199 |
case '\n': |
200 |
defn_copy[i] = '\0';
|
201 |
break;
|
202 |
|
203 |
default:
|
204 |
/* do nothing */;
|
205 |
} |
206 |
} |
207 |
|
208 |
/* perform actual initialization */
|
209 |
result = pj_init( argc, argv ); |
210 |
|
211 |
pj_dalloc( defn_copy ); |
212 |
|
213 |
return result;
|
214 |
} |
215 |
|
216 |
/************************************************************************/
|
217 |
/* pj_init() */
|
218 |
/* */
|
219 |
/* Main entry point for initialing a PJ projections */
|
220 |
/* definition. Note that the projection specific function is */
|
221 |
/* called to do the initial allocation so it can be created */
|
222 |
/* large enough to hold projection specific parameters. */
|
223 |
/************************************************************************/
|
224 |
|
225 |
PJ * |
226 |
pj_init(int argc, char **argv) { |
227 |
char *s, *name;
|
228 |
PJ *(*proj)(PJ *); |
229 |
paralist *curr; |
230 |
int i;
|
231 |
PJ *PIN = 0;
|
232 |
|
233 |
errno = pj_errno = 0;
|
234 |
start = NULL;
|
235 |
|
236 |
/* put arguments into internal linked list */
|
237 |
if (argc <= 0) { pj_errno = -1; goto bum_call; } |
238 |
for (i = 0; i < argc; ++i) |
239 |
if (i)
|
240 |
curr = curr->next = pj_mkparam(argv[i]); |
241 |
else
|
242 |
start = curr = pj_mkparam(argv[i]); |
243 |
if (pj_errno) goto bum_call; |
244 |
|
245 |
/* check if +init present */
|
246 |
if (pj_param(start, "tinit").i) { |
247 |
paralist *last = curr; |
248 |
|
249 |
if (!(curr = get_init(curr, pj_param(start, "sinit").s))) |
250 |
goto bum_call;
|
251 |
if (curr == last) { pj_errno = -2; goto bum_call; } |
252 |
} |
253 |
|
254 |
/* find projection selection */
|
255 |
if (!(name = pj_param(start, "sproj").s)) |
256 |
{ pj_errno = -4; goto bum_call; } |
257 |
for (i = 0; (s = pj_list[i].id) && strcmp(name, s) ; ++i) ; |
258 |
if (!s) { pj_errno = -5; goto bum_call; } |
259 |
|
260 |
/* set defaults, unless inhibited */
|
261 |
if (!pj_param(start, "bno_defs").i) |
262 |
curr = get_defaults(curr, name); |
263 |
proj = (PJ *(*)(PJ *)) pj_list[i].proj; |
264 |
|
265 |
/* allocate projection structure */
|
266 |
if (!(PIN = (*proj)(0))) goto bum_call; |
267 |
PIN->params = start; |
268 |
PIN->is_latlong = 0;
|
269 |
PIN->is_geocent = 0;
|
270 |
|
271 |
/* set datum parameters */
|
272 |
if (pj_datum_set(start, PIN)) goto bum_call; |
273 |
|
274 |
/* set ellipsoid/sphere parameters */
|
275 |
if (pj_ell_set(start, &PIN->a, &PIN->es)) goto bum_call; |
276 |
|
277 |
PIN->e = sqrt(PIN->es); |
278 |
PIN->ra = 1. / PIN->a;
|
279 |
PIN->one_es = 1. - PIN->es;
|
280 |
if (PIN->one_es == 0.) { pj_errno = -6; goto bum_call; } |
281 |
PIN->rone_es = 1./PIN->one_es;
|
282 |
|
283 |
/* Now that we have ellipse information check for WGS84 datum */
|
284 |
if( PIN->datum_type == PJD_3PARAM
|
285 |
&& PIN->datum_params[0] == 0.0 |
286 |
&& PIN->datum_params[1] == 0.0 |
287 |
&& PIN->datum_params[2] == 0.0 |
288 |
&& PIN->a == 6378137.0 |
289 |
&& ABS(PIN->es - 0.006694379990) < 0.000000000050 )/*WGS84/GRS80*/ |
290 |
{ |
291 |
PIN->datum_type = PJD_WGS84; |
292 |
} |
293 |
|
294 |
/* set PIN->geoc coordinate system */
|
295 |
PIN->geoc = (PIN->es && pj_param(start, "bgeoc").i);
|
296 |
|
297 |
/* over-ranging flag */
|
298 |
PIN->over = pj_param(start, "bover").i;
|
299 |
|
300 |
/* central meridian */
|
301 |
PIN->lam0=pj_param(start, "rlon_0").f;
|
302 |
|
303 |
/* central latitude */
|
304 |
PIN->phi0 = pj_param(start, "rlat_0").f;
|
305 |
|
306 |
/* false easting and northing */
|
307 |
PIN->x0 = pj_param(start, "dx_0").f;
|
308 |
PIN->y0 = pj_param(start, "dy_0").f;
|
309 |
|
310 |
/* general scaling factor */
|
311 |
if (pj_param(start, "tk_0").i) |
312 |
PIN->k0 = pj_param(start, "dk_0").f;
|
313 |
else if (pj_param(start, "tk").i) |
314 |
PIN->k0 = pj_param(start, "dk").f;
|
315 |
else
|
316 |
PIN->k0 = 1.;
|
317 |
if (PIN->k0 <= 0.) { |
318 |
pj_errno = -31;
|
319 |
goto bum_call;
|
320 |
} |
321 |
|
322 |
/* set units */
|
323 |
s = 0;
|
324 |
if (name = pj_param(start, "sunits").s) { |
325 |
for (i = 0; (s = pj_units[i].id) && strcmp(name, s) ; ++i) ; |
326 |
if (!s) { pj_errno = -7; goto bum_call; } |
327 |
s = pj_units[i].to_meter; |
328 |
} |
329 |
if (s || (s = pj_param(start, "sto_meter").s)) { |
330 |
PIN->to_meter = strtod(s, &s); |
331 |
if (*s == '/') /* ratio number */ |
332 |
PIN->to_meter /= strtod(++s, 0);
|
333 |
PIN->fr_meter = 1. / PIN->to_meter;
|
334 |
} else
|
335 |
PIN->to_meter = PIN->fr_meter = 1.;
|
336 |
|
337 |
/* prime meridian */
|
338 |
s = 0;
|
339 |
if (name = pj_param(start, "spm").s) { |
340 |
const char *value = NULL; |
341 |
char *next_str = NULL; |
342 |
|
343 |
for (i = 0; pj_prime_meridians[i].id != NULL; ++i ) |
344 |
{ |
345 |
if( strcmp(name,pj_prime_meridians[i].id) == 0 ) |
346 |
{ |
347 |
value = pj_prime_meridians[i].defn; |
348 |
break;
|
349 |
} |
350 |
} |
351 |
|
352 |
if( value == NULL |
353 |
&& (dmstor(name,&next_str) != 0.0 || *name == '0') |
354 |
&& *next_str == '\0' )
|
355 |
value = name; |
356 |
|
357 |
if (!value) { pj_errno = -46; goto bum_call; } |
358 |
PIN->from_greenwich = dmstor(value,NULL);
|
359 |
} |
360 |
else
|
361 |
PIN->from_greenwich = 0.0; |
362 |
|
363 |
/* projection specific initialization */
|
364 |
if (!(PIN = (*proj)(PIN)) || errno || pj_errno) {
|
365 |
bum_call: /* cleanup error return */ |
366 |
if (!pj_errno)
|
367 |
pj_errno = errno; |
368 |
if (PIN)
|
369 |
pj_free(PIN); |
370 |
else
|
371 |
for ( ; start; start = curr) {
|
372 |
curr = start->next; |
373 |
pj_dalloc(start); |
374 |
} |
375 |
PIN = 0;
|
376 |
} |
377 |
return PIN;
|
378 |
} |
379 |
|
380 |
/************************************************************************/
|
381 |
/* pj_free() */
|
382 |
/* */
|
383 |
/* This is the application callable entry point for destroying */
|
384 |
/* a projection definition. It does work generic to all */
|
385 |
/* projection types, and then calls the projection specific */
|
386 |
/* free function (P->pfree()) to do local work. This maps to */
|
387 |
/* the FREEUP code in the individual projection source files. */
|
388 |
/************************************************************************/
|
389 |
|
390 |
void
|
391 |
pj_free(PJ *P) { |
392 |
if (P) {
|
393 |
paralist *t = P->params, *n; |
394 |
|
395 |
/* free parameter list elements */
|
396 |
for (t = P->params; t; t = n) {
|
397 |
n = t->next; |
398 |
pj_dalloc(t); |
399 |
} |
400 |
|
401 |
/* free projection parameters */
|
402 |
P->pfree(P); |
403 |
} |
404 |
} |
405 |
|
406 |
|