// This looks most like -*- c -*- code // // Projection.i: SWIG interface file for PROJ.4 projection library. // // Copyright (c) 2001 Meridian Environmental Technology, Inc // All rights reserved. // // Author: Douglas K. Rand // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // 1. Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF // SUCH DAMAGE. // // %module Projection %{ #include // We wrap the PJ structure in our own so we can keep the // type of units the user wants to operate in along. typedef enum {DEGREES, RADIANS} Units; typedef struct { Units units; PJ *proj; } Projection; %} %include typemaps.i %include constraints.i %include array.i typedef enum {DEGREES, RADIANS} Units; // Because that stupid pj_init() function requires a count of the args, // we have to do a typemap for EACH language terminating it with a null // so we can count the items in our wrapper. Sigh. %typemap(python, in) char **argv { /* Check if is a list */ if (PyList_Check($source)) { int size = PyList_Size($source); int i = 0; $target = (char **) malloc((size+1)*sizeof(char *)); for (i = 0; i < size; i++) { PyObject *o = PyList_GetItem($source,i); if (PyString_Check(o)) $target[i] = PyString_AsString(PyList_GetItem($source,i)); else { PyErr_SetString(PyExc_TypeError,"list must contain strings"); free($target); return NULL; } } $target[i] = 0; } else { PyErr_SetString(PyExc_TypeError,"not a list"); return NULL; } } // Free up the argv structure created above %typemap(python, freearg) char **argv { free((char *) $source); } /* Assign the pointer to a local variable */ %typemap(python, ignore) double *outvalue(double temp) { $target = &temp; } // This tells SWIG to treat an double * argument with name 'outvalue' as // an output value. We'll append the value to the current result which // is guaranteed to be a List object by SWIG. %typemap(python,argout) double *outvalue { PyObject *o; o = PyFloat_FromDouble(*$source); if ((!$target) || ($target == Py_None)) { $target = o; } else { if (!PyList_Check($target)) { PyObject *o2 = $target; $target = PyList_New(0); PyList_Append($target,o2); Py_XDECREF(o2); } PyList_Append($target,o); Py_XDECREF(o); } } //%typemap(perl5, argout) double *outvalue { // $target = sv_newmortal(); // sv_setnv($target, *$source); // argvi++; //} /* Assign the pointer to a local variable */ %typemap(python,in) double *outvalue { static double junk; $target = &junk; } //%typemap(perl5, in) double *outvalue { // static double junk; // $target = &junk; //} /* Exception handler for the Projection constructor */ %typemap(python,except) Projection * { /* Use pj_get_errno_ref to access the pj_errno because directly * accessing pj_errno doesn't work on windows if the proj library is * in a DLL */ *pj_get_errno_ref() = 0; $function; if (!$source) { /* FIXME: There's a case where $source is NULL and pj_errno is * not set, namely when memory allocation of the Projection * struct fails. */ SWIG_exception(SWIG_IOError, pj_strerrno(*pj_get_errno_ref())); } } typedef struct { Units units; PJ *proj; %addmethods { Projection(char **argv, Units units = DEGREES); ~Projection(); void Forward(double lat, double lon, double *outvalue, double *outvalue); void Inverse(double u, double v, double *outvalue, double *outvalue); PyObject * cobject() { return PyCObject_FromVoidPtr(self->proj, NULL); } /* The __del__ method generated by the old SWIG version we're * tries to access self.thisown which may not be set at all when * there was an exception during construction. Therefore we * override it with our own version. * FIXME: It would be better to upgrade to a newer SWIG version * or to get rid of SWIG entirely. */ %pragma(python) addtoclass = " def __del__(self,Projectionc=Projectionc): if getattr(self, 'thisown', 0): Projectionc.delete_Projection(self) " } } Projection; %{ // Make a brand new projection Projection *new_Projection(char **argv, Units units) { int argc = 0; char **p; PJ *proj; Projection *pj = NULL; for(p = argv; p != NULL && *p != NULL; p++) argc++; proj = pj_init(argc, argv); if(proj != NULL) { pj = (Projection *) malloc(sizeof(Projection)); pj->units = units; pj->proj = proj; } return pj; } // Get rid of a projection void delete_Projection(Projection *self) { if(self != NULL) { if(self->proj != NULL) pj_free(self->proj); free(self); } } // Do a forward (lat/lon --> world) translation void Projection_Forward(Projection *self, double lat, double lon, double *u, double *v) { projUV latlon, result; latlon.u = lat; latlon.v = lon; if(self->units == DEGREES) { latlon.u *= DEG_TO_RAD; latlon.v *= DEG_TO_RAD; } result = pj_fwd(latlon, self->proj); *u = result.u; *v = result.v; } // Do a reverse (world --> lat/lon) translation void Projection_Inverse(Projection *self, double u, double v, double *lat, double *lon) { projUV world, result; world.u = u; world.v = v; result = pj_inv(world, self->proj); if(self->units == DEGREES) { result.u *= RAD_TO_DEG; result.v *= RAD_TO_DEG; } *lat = result.u; *lon = result.v; } %}