1 |
// This looks most like -*- c -*- code |
2 |
|
3 |
// |
4 |
// Projection.i: SWIG interface file for PROJ.4 projection library. |
5 |
// |
6 |
// Copyright (c) 2001 Meridian Environmental Technology, Inc |
7 |
// All rights reserved. |
8 |
// |
9 |
// Author: Douglas K. Rand <[email protected]> |
10 |
// |
11 |
// Redistribution and use in source and binary forms, with or without |
12 |
// modification, are permitted provided that the following conditions |
13 |
// are met: |
14 |
// 1. Redistributions of source code must retain the above copyright |
15 |
// notice, this list of conditions and the following disclaimer. |
16 |
// 2. Redistributions in binary form must reproduce the above copyright |
17 |
// notice, this list of conditions and the following disclaimer in the |
18 |
// documentation and/or other materials provided with the distribution. |
19 |
// |
20 |
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
21 |
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
22 |
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
23 |
// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
24 |
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
25 |
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
26 |
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
27 |
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
28 |
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
29 |
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
30 |
// SUCH DAMAGE. |
31 |
// |
32 |
// |
33 |
|
34 |
|
35 |
%module Projection |
36 |
%{ |
37 |
#include <projects.h> |
38 |
|
39 |
// We wrap the PJ structure in our own so we can keep the |
40 |
// type of units the user wants to operate in along. |
41 |
typedef enum {DEGREES, RADIANS} Units; |
42 |
typedef struct { |
43 |
Units units; |
44 |
PJ *proj; |
45 |
} Projection; |
46 |
%} |
47 |
|
48 |
%include typemaps.i |
49 |
%include constraints.i |
50 |
%include array.i |
51 |
|
52 |
typedef enum {DEGREES, RADIANS} Units; |
53 |
|
54 |
// Because that stupid pj_init() function requires a count of the args, |
55 |
// we have to do a typemap for EACH language terminating it with a null |
56 |
// so we can count the items in our wrapper. Sigh. |
57 |
%typemap(python, in) char **argv { |
58 |
/* Check if is a list */ |
59 |
if (PyList_Check($source)) { |
60 |
int size = PyList_Size($source); |
61 |
int i = 0; |
62 |
$target = (char **) malloc((size+1)*sizeof(char *)); |
63 |
for (i = 0; i < size; i++) { |
64 |
PyObject *o = PyList_GetItem($source,i); |
65 |
if (PyString_Check(o)) |
66 |
$target[i] = PyString_AsString(PyList_GetItem($source,i)); |
67 |
else { |
68 |
PyErr_SetString(PyExc_TypeError,"list must contain strings"); |
69 |
free($target); |
70 |
return NULL; |
71 |
} |
72 |
} |
73 |
$target[i] = 0; |
74 |
} else { |
75 |
PyErr_SetString(PyExc_TypeError,"not a list"); return NULL; |
76 |
} |
77 |
} |
78 |
|
79 |
// Free up the argv structure created above |
80 |
%typemap(python, freearg) char **argv { |
81 |
free((char *) $source); |
82 |
} |
83 |
|
84 |
/* Assign the pointer to a local variable */ |
85 |
%typemap(python, ignore) double *outvalue(double temp) { |
86 |
$target = &temp; |
87 |
} |
88 |
|
89 |
// This tells SWIG to treat an double * argument with name 'outvalue' as |
90 |
// an output value. We'll append the value to the current result which |
91 |
// is guaranteed to be a List object by SWIG. |
92 |
%typemap(python,argout) double *outvalue { |
93 |
PyObject *o; |
94 |
o = PyFloat_FromDouble(*$source); |
95 |
if ((!$target) || ($target == Py_None)) { |
96 |
$target = o; |
97 |
} else { |
98 |
if (!PyList_Check($target)) { |
99 |
PyObject *o2 = $target; |
100 |
$target = PyList_New(0); |
101 |
PyList_Append($target,o2); |
102 |
Py_XDECREF(o2); |
103 |
} |
104 |
PyList_Append($target,o); |
105 |
Py_XDECREF(o); |
106 |
} |
107 |
} |
108 |
|
109 |
//%typemap(perl5, argout) double *outvalue { |
110 |
// $target = sv_newmortal(); |
111 |
// sv_setnv($target, *$source); |
112 |
// argvi++; |
113 |
//} |
114 |
|
115 |
/* Assign the pointer to a local variable */ |
116 |
%typemap(python,in) double *outvalue { |
117 |
static double junk; |
118 |
$target = &junk; |
119 |
} |
120 |
|
121 |
//%typemap(perl5, in) double *outvalue { |
122 |
// static double junk; |
123 |
// $target = &junk; |
124 |
//} |
125 |
|
126 |
|
127 |
/* Exception handler for the Projection constructor */ |
128 |
%typemap(python,except) Projection * { |
129 |
/* Use pj_get_errno_ref to access the pj_errno because directly |
130 |
* accessing pj_errno doesn't work on windows if the proj library is |
131 |
* in a DLL */ |
132 |
*pj_get_errno_ref() = 0; |
133 |
$function; |
134 |
if (!$source) |
135 |
{ |
136 |
/* FIXME: There's a case where $source is NULL and pj_errno is |
137 |
* not set, namely when memory allocation of the Projection |
138 |
* struct fails. */ |
139 |
SWIG_exception(SWIG_IOError, pj_strerrno(*pj_get_errno_ref())); |
140 |
} |
141 |
} |
142 |
|
143 |
|
144 |
typedef struct { |
145 |
Units units; |
146 |
PJ *proj; |
147 |
|
148 |
%addmethods { |
149 |
Projection(char **argv, Units units = DEGREES); |
150 |
~Projection(); |
151 |
void Forward(double lat, double lon, double *outvalue, double *outvalue); |
152 |
void Inverse(double u, double v, double *outvalue, double *outvalue); |
153 |
|
154 |
PyObject * cobject() { |
155 |
return PyCObject_FromVoidPtr(self->proj, NULL); |
156 |
} |
157 |
|
158 |
|
159 |
/* The __del__ method generated by the old SWIG version we're |
160 |
* tries to access self.thisown which may not be set at all when |
161 |
* there was an exception during construction. Therefore we |
162 |
* override it with our own version. |
163 |
* FIXME: It would be better to upgrade to a newer SWIG version |
164 |
* or to get rid of SWIG entirely. |
165 |
*/ |
166 |
%pragma(python) addtoclass = " |
167 |
def __del__(self,Projectionc=Projectionc): |
168 |
if getattr(self, 'thisown', 0): |
169 |
Projectionc.delete_Projection(self) |
170 |
" |
171 |
|
172 |
} |
173 |
} Projection; |
174 |
|
175 |
%{ |
176 |
// Make a brand new projection |
177 |
Projection *new_Projection(char **argv, Units units) { |
178 |
int argc = 0; |
179 |
char **p; |
180 |
PJ *proj; |
181 |
Projection *pj = NULL; |
182 |
|
183 |
for(p = argv; p != NULL && *p != NULL; p++) argc++; |
184 |
proj = pj_init(argc, argv); |
185 |
if(proj != NULL) { |
186 |
pj = (Projection *) malloc(sizeof(Projection)); |
187 |
pj->units = units; |
188 |
pj->proj = proj; |
189 |
} |
190 |
return pj; |
191 |
} |
192 |
|
193 |
// Get rid of a projection |
194 |
void delete_Projection(Projection *self) { |
195 |
if(self != NULL) { |
196 |
if(self->proj != NULL) |
197 |
pj_free(self->proj); |
198 |
free(self); |
199 |
} |
200 |
} |
201 |
|
202 |
// Do a forward (lat/lon --> world) translation |
203 |
void Projection_Forward(Projection *self, double lat, double lon, double *u, double *v) { |
204 |
projUV latlon, result; |
205 |
latlon.u = lat; |
206 |
latlon.v = lon; |
207 |
if(self->units == DEGREES) { |
208 |
latlon.u *= DEG_TO_RAD; |
209 |
latlon.v *= DEG_TO_RAD; |
210 |
} |
211 |
result = pj_fwd(latlon, self->proj); |
212 |
*u = result.u; |
213 |
*v = result.v; |
214 |
} |
215 |
|
216 |
// Do a reverse (world --> lat/lon) translation |
217 |
void Projection_Inverse(Projection *self, double u, double v, double *lat, double *lon) { |
218 |
projUV world, result; |
219 |
world.u = u; |
220 |
world.v = v; |
221 |
result = pj_inv(world, self->proj); |
222 |
if(self->units == DEGREES) { |
223 |
result.u *= RAD_TO_DEG; |
224 |
result.v *= RAD_TO_DEG; |
225 |
} |
226 |
*lat = result.u; |
227 |
*lon = result.v; |
228 |
} |
229 |
%} |