/[thuban]/branches/WIP-pyshapelib-bramz/libraries/pyshapelib/shapelibmodule.c
ViewVC logotype

Diff of /branches/WIP-pyshapelib-bramz/libraries/pyshapelib/shapelibmodule.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

trunk/thuban/libraries/pyshapelib/shapelib.i revision 2637 by bh, Thu Jun 30 14:20:46 2005 UTC branches/WIP-pyshapelib-bramz/libraries/pyshapelib/shapelibmodule.c revision 2744 by bramz, Thu Mar 15 13:48:58 2007 UTC
# Line 1  Line 1 
1  /* SWIG (www.swig.org) interface file for shapelib  #include "pyshapelib_common.h"
  *  
  * At the moment (Dec 2000) this file is only useful to generate Python  
  * bindings. Invoke swig as follows:  
  *  
  *      swig -python -shadow shapelib.i  
  *  
  * to generate shapelib_wrap.c and shapelib.py. shapelib_wrap.c  
  * defines a bunch of Python-functions that wrap the appripriate  
  * shapelib functions and shapelib.py contains an object oriented  
  * wrapper around shapelib_wrap.c.  
  *  
  * Shapelib, and hence this module too, defines two types of objects,  
  * shapes and shapefiles.  
  */  
2    
3  %module shapelib  /* --- SHPObject ----------------------------------------------------------------------------------------------------- */
4    
5  /*  typedef struct
6   * First, a %{,%}-Block. These blocks are copied verbatim to the  {
7   * shapelib_wrap.c file and are not parsed by SWIG. This is the place to          PyObject_HEAD
8   * import headerfiles and define helper-functions that are needed by the          SHPObject* shpObject;
9   * automatically generated wrappers.  }
10   */  SHPObjectObject;
11    
12  %{  enum {
13            vtXY,
14            vtXYM,
15            vtXYZM,
16            vtInvalid
17    } VertexType;
18    
19  /* import the shapelib headefile. */  int determine_vertex_type(int shape_type, int* has_z, int* has_m)
20  #include "shapefil.h"  {
21  #include "pyshapelib_api.h"          switch (shape_type)
22                {
23  /*          case SHPT_POINT:
24   * Rename a few shapelib functions that are effectively methods with          case SHPT_ARC:
25   * preprocessor macros so that they have the names that swig expects          case SHPT_POLYGON:
26   * (e.g. the destructor of SHPObject has to be called delete_SHPObject)          case SHPT_MULTIPOINT:
27                    if (has_z) *has_z = 0;
28                    if (has_m) *has_m = 0;
29                    return vtXY;
30            case SHPT_POINTM:
31            case SHPT_ARCM:
32            case SHPT_POLYGONM:
33            case SHPT_MULTIPOINTM:
34                    if (has_z) *has_z = 0;
35                    if (has_m) *has_m = 1;
36            case SHPT_POINTZ:
37            case SHPT_ARCZ:
38            case SHPT_POLYGONZ:
39            case SHPT_MULTIPOINTZ:
40            case SHPT_MULTIPATCH:
41                    if (has_z) *has_z = 1;
42                    if (has_m) *has_m = 1;
43                    return vtXYZM;
44            default:
45                    if (has_z) *has_z = 0;
46                    if (has_m) *has_m = 0;
47                    return vtInvalid;
48            }
49    }
50            
51    /* allocator
52   */   */
53    static PyObject* shpobject_new(PyTypeObject* type, PyObject* args, PyObject* kwds)
54    {
55            SHPObjectObject* self;  
56            self = (SHPObjectObject*) type->tp_alloc(type, 0);
57            self->shpObject = NULL;
58            return (PyObject*) self;
59    }
60    
61  #define delete_SHPObject SHPDestroyObject  /* deallocator
       
 /*  
  * The extents() method of SHPObject.  
  *  
  * Return the extents as a tuple of two 4-element lists with the min.  
  * and max. values of x, y, z, m.  
62   */   */
63  static PyObject *  static void shpobject_dealloc(SHPObjectObject* self)
 SHPObject_extents(SHPObject *object)  
64  {  {
65      return Py_BuildValue("[dddd][dddd]",          SHPDestroyObject(self->shpObject);
66                           object->dfXMin, object->dfYMin, object->dfZMin,          self->shpObject = NULL;
67                           object->dfMMin,          self->ob_type->tp_free((PyObject*)self);
                          object->dfXMax, object->dfYMax, object->dfZMax,  
                          object->dfMMax);  
68  }  }
69    
70    /* The constructor of SHPObject. parts is a list of lists of tuples
71    * describing the parts and their vertices just likethe output of the
72    * vertices() method. part_type_list is the list of part-types and may
73    * be NULL. For the meaning of the part-types and their default value
74    * see the Shaplib documentation.
75    */
76    static int shpobject_init(SHPObjectObject* self, PyObject* args, PyObject* kwds)
77    {
78            int type;
79            int id;
80            PyObject* parts = NULL;
81            PyObject* part_type_list = NULL;
82            
83            int num_parts;
84            int num_vertices;
85            int part_start;
86            
87            double* xs = NULL;
88            double* ys = NULL;
89            double* zs = NULL;
90            double* ms = NULL;
91            int* part_starts = NULL;
92            int* part_types = NULL;
93            
94            PyObject* part;
95            int vertex_type;
96            int has_z;
97            int has_m;
98            
99            int i;
100            int ok, return_code = -1;
101            
102            /* first, unpack parameters */
103            if (kwds != NULL && PyDict_Size(kwds) > 0)
104            {
105                    PyErr_Format(PyExc_TypeError, "shapelib.SHPObject.__init__ takes no keyword arguments");
106                    return -1;
107            }
108            if (!PyArg_ParseTuple(args, "iiO|O:__init__", &type, &id, &parts, &part_type_list)) return -1;
109    
110  /*          /* check parts */
111   * The vertices() method of SHPObject.          if (!PySequence_Check(parts))
112   *          {
113   * Return the x and y coords of the vertices as a list of lists of                  PyErr_SetString(PyExc_TypeError, "parts is not a sequence");
114   * tuples.                  return -1;
115   */          }
116            num_parts = PySequence_Length(parts);
117            if (num_parts < 0)
118            {
119                    PyErr_SetString(PyExc_TypeError, "cannot determine length of parts");
120                    return -1;
121            }
122            
123            /* parts and part_types have to have the same lengths */
124            if (part_type_list == Py_None)
125            {
126                    Py_DECREF(part_type_list);
127                    part_type_list = NULL;
128            }
129            if (part_type_list)
130            {
131                    if (!PySequence_Check(parts))
132                    {
133                            PyErr_SetString(PyExc_TypeError, "part_type_list is not a sequence");
134                            return -1;
135                    }
136                    if (PySequence_Length(part_type_list) != num_parts)
137                    {
138                            PyErr_SetString(PyExc_TypeError, "parts and part_types have to have the same lengths");
139                            return -1;
140                    }
141            }
142    
143  static PyObject* build_vertex_list(SHPObject *object, int index, int length);          /* determine how many vertices there are altogether */
144            num_vertices = 0;
145            for (i = 0; i < num_parts; ++i)
146            {
147                    PyObject* part = PySequence_ITEM(parts, i);
148                    if (!PySequence_Check(part))
149                    {
150                            PyErr_SetString(PyExc_TypeError, "at least one item in parts is not a sequence");
151                            Py_DECREF(part);
152                            return -1;
153                    }
154                    num_vertices += PySequence_Length(part);
155                    Py_DECREF(part);
156            }
157            
158            
159            vertex_type = determine_vertex_type(type, &has_z, &has_m);
160    
161            /* allocate the memory for the various arrays and check for memory errors */
162            xs = malloc(num_vertices * sizeof(double));
163            ys = malloc(num_vertices * sizeof(double));
164            zs = has_z ? malloc(num_vertices * sizeof(double)) : NULL;
165            ms = has_m ? malloc(num_vertices * sizeof(double)) : NULL;
166            part_starts = malloc(num_parts * sizeof(int));
167            part_types = part_type_list ? malloc(num_parts * sizeof(int)) : 0;
168    
169            if (!xs || !ys || (has_z && !zs) || (has_m && !ms) || !part_starts || (part_type_list && !part_types))
170            {
171                    PyErr_NoMemory();
172                    goto exit;
173            }
174    
175            /* convert the part types */
176            if (part_type_list)
177            {
178                    for (i = 0; i < num_parts; i++)
179                    {
180                            PyObject* otype = PySequence_ITEM(part_type_list, i);
181                            part_types[i] = PyInt_AsLong(otype);
182                            Py_DECREF(otype);
183                            if (part_types[i] < 0)
184                            {
185                                    PyErr_SetString(PyExc_TypeError, "at least one item in part_type_list is not an integer or is negative");
186                                    goto exit;
187                            }
188                    }
189            }
190    
191            /* convert the list of parts */
192            part_start = 0;
193            for (i = 0; i < num_parts; ++i)
194            {
195                    int j, length;
196                    
197                    part = PySequence_ITEM(parts, i);
198                    length = PySequence_Length(part);
199                    if (length < 0) goto exit;
200                    part_starts[i] = part_start;
201    
202                    for (j = 0; j < length; ++j)
203                    {
204                            PyObject* vertex = PySequence_ITEM(part, j);
205                            switch (vertex_type)
206                            {
207                            case vtXY:
208                                    ok = PyArg_ParseTuple(vertex, "dd:__init__", xs + part_start + j, ys + part_start + j);
209                                    break;
210                            case vtXYM:
211                                    ok = PyArg_ParseTuple(vertex, "ddd:__init__", xs + part_start + j, ys + part_start + j, ms + part_start + j);
212                                    break;
213                            case vtXYZM:
214                                    ms[part_start + j] = 0.;
215                                    ok = PyArg_ParseTuple(vertex, "ddd|d:__init__", xs + part_start + j, ys + part_start + j, zs + part_start + j,
216                                            ms + part_start + j);
217                                    break;
218                            }
219                            Py_DECREF(vertex);
220                            if (!ok)
221                            {
222                                    PyErr_SetString(PyExc_TypeError, "at least one vertex is of the wrong format");
223                                    goto exit;
224                            }
225                    }
226                    Py_DECREF(part);
227                    part = NULL;
228                    part_start += length;
229            }
230    
231  static PyObject*          self->shpObject = SHPCreateObject(type, id, num_parts, part_starts, part_types, num_vertices, xs, ys, zs, ms);
232  SHPObject_vertices(SHPObject *object)          return_code = 0;
233            
234    exit:
235            Py_XDECREF(part);
236            free(xs);
237            free(ys);
238            free(zs);
239            free(ms);
240            free(part_starts);
241            free(part_types);
242            return return_code;
243    }
244    
245    /*
246    * The extents() method of SHPObject.
247    *
248    * Return the extents as a tuple of two 4-element lists with the min.
249    * and max. values of x, y, z, m.
250    */
251    static PyObject* shpobject_extents(SHPObjectObject* self)
252  {  {
253      PyObject *result = NULL;          SHPObject* object = self->shpObject;
254      PyObject *part = NULL;          return Py_BuildValue("(dddd)(dddd)",
255      int part_idx, vertex_idx;                          object->dfXMin, object->dfYMin, object->dfZMin, object->dfMMin,
256      int length = 0;                          object->dfXMax, object->dfYMax, object->dfZMax, object->dfMMax);
257    }
258    
259    
260    /*
261    * The vertices() method of SHPObject.
262    *
263    * Return the x and y coords of the vertices as a list of lists of
264    * tuples.
265    */
266    
267    static PyObject* build_vertex_list(SHPObject *object, int index, int length, int vertex_type);
268    
269      if (object->nParts > 0)  static PyObject* shpobject_vertices(SHPObjectObject* self)
270      {  {
271          /* A multipart shape. Usual for SHPT_ARC and SHPT_POLYGON */          PyObject *result = NULL;
272            PyObject *part = NULL;
273            int part_idx, vertex_idx;
274            int length = 0;
275            int vertex_type;
276                    
277          result = PyList_New(object->nParts);          SHPObject* object = self->shpObject;
278          if (!result)          vertex_type = determine_vertex_type(object->nSHPType, NULL, NULL);
             return NULL;  
279    
280          for (part_idx = 0, vertex_idx = 0; part_idx < object->nParts;          if (object->nParts > 0)
              part_idx++)  
281          {          {
282              if (part_idx < object->nParts - 1)                  /* A multipart shape. Usual for SHPT_ARC and SHPT_POLYGON */
283                  length = (object->panPartStart[part_idx + 1]          
284                            - object->panPartStart[part_idx]);                  result = PyList_New(object->nParts);
285              else                  if (!result)
286                  length = object->nVertices - object->panPartStart[part_idx];                          return NULL;
287                
288              part = build_vertex_list(object, vertex_idx, length);                  for (part_idx = 0, vertex_idx = 0; part_idx < object->nParts; part_idx++)
289              if (!part)                  {
290                  goto fail;                          if (part_idx < object->nParts - 1)
291                                    length = (object->panPartStart[part_idx + 1]
292              if (PyList_SetItem(result, part_idx, part) < 0)                                          - object->panPartStart[part_idx]);
293                  goto fail;                          else
294                                    length = object->nVertices - object->panPartStart[part_idx];
295              vertex_idx += length;                          
296          }                          part = build_vertex_list(object, vertex_idx, length, vertex_type);
297      }                          if (!part) goto fail;
298      else  
299      {                          if (PyList_SetItem(result, part_idx, part) < 0) goto fail;
300          /* only one part. usual for SHPT_POINT */  
301          result = build_vertex_list(object, 0, object->nVertices);                          vertex_idx += length;
302      }                  }
303            }
304      return result;          else
305            {
306   fail:                  /* only one part. usual for SHPT_POINT */
307      Py_XDECREF(part);                  result = build_vertex_list(object, 0, object->nVertices, vertex_type);
308      Py_DECREF(result);          }
309      return NULL;  
310            return result;
311    
312    fail:
313            Py_XDECREF(part);
314            Py_DECREF(result);
315            return NULL;
316  }  }
317    
318    
319  /* Return the length coordinates of the shape object starting at vertex  /* Return the length coordinates of the shape object starting at vertex
320   * index as a Python-list of tuples. Helper function for  * index as a Python-list of tuples. Helper function for
321   * SHPObject_vertices.  * SHPObject_vertices.
322   */  */
323  static PyObject*  static PyObject* build_vertex_list(SHPObject *object, int index, int length, int vertex_type)
 build_vertex_list(SHPObject *object, int index, int length)  
324  {  {
325      int i;          int i;
326      PyObject * list;          PyObject * list;
327      PyObject * vertex = NULL;          PyObject * vertex = NULL;
328    
329      list = PyList_New(length);          list = PyList_New(length);
330      if (!list)          if (!list)
331          return NULL;                  return NULL;
332    
333      for (i = 0; i < length; i++, index++)          for (i = 0; i < length; i++, index++)
334      {          {
335          vertex = Py_BuildValue("dd", object->padfX[index],                  switch (vertex_type)
336                                 object->padfY[index]);                  {
337          if (!vertex)                  case vtXY:
338              goto fail;                          vertex = Py_BuildValue("dd", object->padfX[index], object->padfY[index]);
339          if (PyList_SetItem(list, i, vertex) < 0)                          break;                  
340              goto fail;                  case vtXYM:
341      }                          vertex = Py_BuildValue("ddd", object->padfX[index], object->padfY[index],
342                                    object->padfM[index]);
343      return list;                  case vtXYZM:
344                            vertex = Py_BuildValue("dddd", object->padfX[index], object->padfY[index],
345   fail:                                  object->padfZ[index], object->padfM[index]);
346      Py_XDECREF(vertex);                          break;                  
347      Py_DECREF(list);                  default:
348      return NULL;                          goto fail;
349  }                  }
350    
351                    if (!vertex || PyList_SetItem(list, i, vertex) < 0) goto fail;
352            }
353            
354            return list;
355    
356    fail:
357            Py_DECREF(list);
358            return NULL;
359    }
360    
361    
362    
363  /* The constructor of SHPObject. parts is a list of lists of tuples  static PyObject* shpobject_part_types(SHPObjectObject* self)
  * describing the parts and their vertices just likethe output of the  
  * vertices() method. part_type_list is the list of part-types and may  
  * be NULL. For the meaning of the part-types and their default value  
  * see the Shaplib documentation.  
  */  
 SHPObject * new_SHPObject(int type, int id, PyObject * parts,  
                           PyObject * part_type_list)  
364  {  {
365      /* arrays to hold thex and y coordinates of the  vertices */          int i;
366      double *xs = NULL, *ys = NULL;          PyObject* result = NULL;
367      /* number of all vertices of all parts */          SHPObject* object = self->shpObject;
368      int num_vertices;          
369      /* number of parts in the list parts */          if (object->nParts == 0 || object->panPartType == 0)
     int num_parts;  
     /* start index of in xs and ys of the part currently worked on */  
     int part_start;  
     /* array of start indices in xs and ys as expected by shapelib */  
     int *part_starts = NULL;  
   
     /* generic counter */  
     int i;  
   
     /* array of part types. holds the converted content of  
      * part_type_list. Stays NULL of part_type_list is NULL  
      */  
     int *part_types = NULL;  
   
     /* temporary python objects referring to the the list items being  
      * worked on.  
      */  
     PyObject * part = NULL, *tuple = NULL;  
   
     /* The result object */  
     SHPObject *result;  
   
     num_parts = PySequence_Length(parts);  
     num_vertices = 0;  
   
     /* parts and part_types have to have the same lengths */  
     if (part_type_list  
         && PySequence_Length(parts) != PySequence_Length(part_type_list))  
     {  
         PyErr_SetString(PyExc_TypeError,  
                         "parts and part_types have to have the same lengths");  
         return NULL;  
     }  
   
     /* determine how many vertices there are altogether */  
     for (i = 0; i < num_parts; i++)  
     {  
         PyObject * part = PySequence_GetItem(parts, i);  
         if (!part)  
             return NULL;  
         num_vertices += PySequence_Length(part);  
         Py_DECREF(part);  
     }  
   
     /* allocate the memory for the various arrays and check for memory  
        errors */  
     xs = malloc(num_vertices * sizeof(double));  
     ys = malloc(num_vertices * sizeof(double));  
     part_starts = malloc(num_parts * sizeof(int));  
     if (part_type_list)  
         part_types = malloc(num_parts * sizeof(int));  
   
     if (!xs || !ys || !part_starts || (part_type_list && !part_types))  
     {  
         PyErr_NoMemory();  
         goto fail;  
     }  
   
     /* convert the part types */  
     if (part_type_list)  
     {  
         for (i = 0; i < num_parts; i++)  
370          {          {
371              PyObject * otype = PySequence_GetItem(part_type_list, i);                  Py_RETURN_NONE;
             if (!otype)  
                 return NULL;  
             part_types[i] = PyInt_AsLong(otype);  
             Py_DECREF(otype);  
372          }          }
373      }          
374            result = PyTuple_New(object->nParts);
375      /* convert the list of parts */          if (!result) return NULL;
376      part_start = 0;          
377      for (i = 0; i < num_parts; i++)          for (i = 0; i < object->nParts; ++i)
378      {          {
379          int j, length;                  /* PyTuple_SetItem steals a reference */
380                    PyObject* part_type = PyInt_FromLong((long)object->panPartType[i]);
381          part = PySequence_GetItem(parts, i);                  if (!part_type || PyTuple_SetItem(result, i, part_type) < 0) goto fail;
382          length = PySequence_Length(part);          }      
383          part_starts[i] = part_start;          return result;
384            
385          for (j = 0; j < length; j++)  fail:
386          {          Py_DECREF(result);
387              tuple = PySequence_GetItem(part, j);          return NULL;
             if (!tuple)  
                 goto fail;  
   
             if (!PyArg_ParseTuple(tuple, "dd", xs + part_start + j,  
                                   ys + part_start + j))  
             {  
                 goto fail;  
             }  
             Py_DECREF(tuple);  
             tuple = NULL;  
         }  
         Py_DECREF(part);  
         part = NULL;  
         part_start += length;  
     }  
   
     result = SHPCreateObject(type, id, num_parts, part_starts, part_types,  
                              num_vertices, xs, ys, NULL, NULL);  
     free(xs);  
     free(ys);  
     free(part_starts);  
     free(part_types);  
     return result;  
   
  fail:  
     free(xs);  
     free(ys);  
     free(part_starts);  
     free(part_types);  
     Py_XDECREF(part);  
     Py_XDECREF(tuple);  
     return NULL;  
388  }  }
389    
 %}  
390    
391    
392    static PyObject* shpobject_type(SHPObjectObject* self, void* closure)
393    {
394            return PyInt_FromLong(self->shpObject->nSHPType);
395    }
396    
 /*  
  * The SWIG Interface definition.  
  */  
397    
 /* include some common SWIG type definitions and standard exception  
    handling code */  
 %include typemaps.i  
 %include exception.i  
398    
399    static PyObject* shpobject_id(SHPObjectObject* self, void* closure)
400    {
401            return PyInt_FromLong(self->shpObject->nShapeId);
402    }
403    
404  /*  
405   *  SHPObject -- Represents one shape  
406    /* return a string that can be feeded to eval() to reconstruct the object,
407     * assuming a proper context
408   */   */
409    static PyObject* shpobject_repr(SHPObjectObject* self)
410    {
411            PyObject* format = NULL;
412            PyObject* args = NULL;
413            PyObject* result = NULL;
414            
415            format = PyString_FromString("shapelib.SHPObject(%i, %i, %s, %s)");
416            if (!format) return NULL;
417    
418  /* Exception typemap for the SHPObject constructor. The constructor the          args = Py_BuildValue("iiNN",
419     the wrapper function defined above which returns NULL in case of                  self->shpObject->nSHPType,
420     error. */                  self->shpObject->nShapeId,
421                      shpobject_vertices(self),
422  %typemap(python,except) SHPObject*new_SHPObject {                  shpobject_part_types(self));
423      $function;          if (!args)
424      if (PyErr_Occurred())          {
425          return NULL;                  Py_DECREF(format);
426                    return NULL;
427            }
428            
429            result = PyString_Format(format, args);
430            Py_DECREF(args);
431            Py_DECREF(format);
432            return result;
433  }  }
434    
 /* Define the SHPObject struct for SWIG. This has to have the same name  
  * as the underlying C-struct in shapfil.h, but we don't have to repeat  
  * all the fields here, only those we want to access directly, and we  
  * can define methods for the object oriented interface.  
  */  
435    
 typedef struct {  
436    
437      /* The shape object has two read-only attributes: */  static struct PyMethodDef shpobject_methods[] =
438    {
439            {"extents", (PyCFunction)shpobject_extents, METH_NOARGS,
440                    "extents()\n"
441                    "returns ((x_min, y_min, z_min, m_min), (x_max, y_max, z_max, m_max)), the 4D bounding box of the SHPObject"},
442            {"vertices", (PyCFunction)shpobject_vertices, METH_NOARGS,
443                    "vertices()\n"
444                    "returns [[(x, y, ...), ...], ...], a list of object parts, where each part is again a list of vertices.\n"
445                    "each vertex is a tuple of two to four doubles, depending on the object type."},
446            {"part_types", (PyCFunction)shpobject_part_types, METH_NOARGS,
447                    "part_types()\n"
448                    "returns a tuple of integers, each integer indicating the type of the corresponding part in vertices()"},
449            {NULL}
450    };
451    
452      /* The type of the shape. In the c-struct defined the field is  static struct PyGetSetDef shpobject_getsetters[] =
453       * called 'nSHPType' but for the python bindings 'type' is more  {
454       * appropriate.          {"type", (getter)shpobject_type, NULL, "type of the object (read-only)" },
455       */          {"id", (getter)shpobject_id, NULL, "id of the object (read-only)" },
456      %readonly %name(type) int nSHPType;          {NULL}
457    };
     /* The id of the shape. Here 'id' is a better name than 'nShapeId'. */  
     %readonly %name(id) int nShapeId;  
   
     /* The methods */  
     %addmethods {  
   
         /* the constructor */  
         SHPObject(int type, int id, PyObject * parts,  
                   PyObject * part_types = NULL);  
   
         /* The destructor */  
         ~SHPObject();  
   
         /* extents and vertices correspond to the SHPObject_extents and  
          * SHPObject_vertices defined above  
          */  
         PyObject *extents();  
         PyObject *vertices();  
     }  
 } SHPObject;  
458    
459    static PyTypeObject SHPObjectType = PYSHAPELIB_DEFINE_TYPE(SHPObjectObject, shpobject, "shapelib.SHPObject", 0);
460    
 /*  
  * ShapeFile --  Represents the shape file  
  */  
461    
462  /* Here we do things a little different. We define a new C-struct that  /* --- ShapeFile ----------------------------------------------------------------------------------------------------- */
  * holds the SHPHandle. This is mainly done so we can separate the  
  * close() method from the destructor but it also helps with exception  
  * handling.  
  *  
  * After the ShapeFile has been opened or created the handle is not  
  * NULL. The close() method closes the file and sets handle to NULL as  
  * an indicator that the file has been closed.  
  */  
463    
464  /* First, define the C-struct */  typedef struct
465  %{  {
466      typedef struct {          PyObject_HEAD
467          SHPHandle handle;          SHPHandle handle;
468      } ShapeFile;  }
469  %}  ShapeFileObject;
470    
471  /* define and use some typemaps for the info() method whose  /* allocator
  * C-implementation has four output parameters that are returned through  
  * pointers passed into the function. SWIG already has definitions for  
  * common types such as int* and we can use those for the first two  
  * parameters:  
472   */   */
473    static PyObject* shapefile_new(PyTypeObject* type, PyObject* args, PyObject* kwds)
474  %apply int * OUTPUT { int * output_entities }  {
475  %apply int * OUTPUT { int * output_type }          ShapeFileObject* self;  
476            self = (ShapeFileObject*) type->tp_alloc(type, 0);
477            self->handle = NULL;
478            return (PyObject*) self;
479    }
480    
481  /* for the last two, the 4-element arrays of min- and max-values, we  /* destructor
482   * have to define our own typemaps:  */
483   */  static void shapefile_dealloc(ShapeFileObject* self)
484  %typemap (python,ignore) double * extents(double temp[4]) {  {
485      $target = temp;          SHPClose(self->handle);
486            self->ob_type->tp_free((PyObject*)self);
487  }  }
488    
489  %typemap (python,argout) double * extents {  /* constructor
     PyObject * list = Py_BuildValue("[dddd]",  
                                     $source[0], $source[1],  
                                     $source[2], $source[3]);  
     $target = t_output_helper($target,list);  
 }  
   
 %apply double * extents { double * output_min_bounds }  
 %apply double * extents { double * output_max_bounds }  
   
 /* The first argument to the ShapeFile methods is a ShapeFile pointer.  
  * We have to check whether handle is not NULL in most methods but not  
  * all. In the destructor and the close method, it's OK for handle to be  
  * NULL. We achieve this by checking whether the preprocessor macro  
  * NOCHECK_$name is defined. SWIG replaces $name with the name of the  
  * function for which the code is inserted. In the %{,%}-block below we  
  * define the macros for the destructor and the close() method.  
490   */   */
491    static int shapefile_init(ShapeFileObject* self, PyObject* args, PyObject* kwds)
492    {
493            char* file;
494            char* mode = "rb";
495            if (kwds != NULL && PyDict_Size(kwds) > 0)
496            {
497                    PyErr_Format(PyExc_TypeError, "shapelib.ShapeFile.__init__ takes no keyword arguments");
498                    return -1;
499            }
500            if (!PyArg_ParseTuple(args, "et|s:__init__", Py_FileSystemDefaultEncoding, &file, &mode)) return -1;
501            
502            self->handle = SHPOpen(file, mode);
503            return self->handle ? 0 : -1;
504    }
505    
506    static PyObject* shapefile_close(ShapeFileObject* self)
507    {
508            SHPClose(self->handle);
509            self->handle = NULL;
510            Py_RETURN_NONE;
511    }
512    
513  %typemap(python,check) ShapeFile *{  static PyObject* shapefile_info(ShapeFileObject* self)
514      %#ifndef NOCHECK_$name  {
515      if (!$target || !$target->handle)          SHPHandle handle = self->handle;
516          SWIG_exception(SWIG_TypeError, "shapefile already closed");          return Py_BuildValue("ii(dddd)(dddd)",
517      %#endif                          handle->nRecords, handle->nShapeType,
518  }                          handle->adBoundsMin[0], handle->adBoundsMin[1], handle->adBoundsMin[2], handle->adBoundsMin[3],
519                            handle->adBoundsMax[0], handle->adBoundsMax[1], handle->adBoundsMax[2], handle->adBoundsMax[3]);
 %{  
 #define NOCHECK_delete_ShapeFile  
 #define NOCHECK_ShapeFile_close  
 %}  
   
 /* An exception handle for the constructor and the module level open()  
  * and create() functions.  
  *  
  * Annoyingly, we *have* to put braces around the SWIG_exception()  
  * calls, at least in the python case, because of the way the macro is  
  * written. Of course, always putting braces around the branches of an  
  * if-statement is often considered good practice.  
  */  
 %typemap(python,except) ShapeFile * {  
     $function;  
     if (!$source)  
     {  
         SWIG_exception(SWIG_MemoryError, "no memory");  
     }  
     else if (!$source->handle)  
     {  
         SWIG_exception(SWIG_IOError, "$name failed");  
     }  
520  }  }
521    
522    static PyObject* shapefile_read_object(ShapeFileObject* self, PyObject* args)
523    {
524            int index;
525            SHPObject* object;
526            SHPObjectObject* result;
527            
528            if (!PyArg_ParseTuple(args, "i:read_object", &index)) return NULL;
529            
530            object = SHPReadObject(self->handle, index);    
531            if (!object)
532            {
533                    PyErr_SetString(PyExc_RuntimeError, "failed to read object");
534                    return NULL;
535            }
536            
537            result = PyObject_New(SHPObjectObject, &SHPObjectType);
538            if (!result)
539            {
540                    return PyErr_NoMemory();
541            }
542            
543            result->shpObject = object;
544            return (PyObject*) result;
545    }
546    
547  /*  static PyObject* shapefile_write_object(ShapeFileObject* self, PyObject* args)
548   * The SWIG-version of the ShapeFile struct.  {
549   */          int index, result;
550            PyObject* object;
551            
552            if (!PyArg_ParseTuple(args, "iO:write_object", &index, &object)) return NULL;
553            
554            if (!PyObject_IsInstance(object, (PyObject*)&SHPObjectType))
555            {
556                    PyErr_SetString(PyExc_TypeError, "object is not a SHPObject");
557                    return NULL;
558            }
559            
560            result = SHPWriteObject(self->handle, index, ((SHPObjectObject*)object)->shpObject);
561            if (result < 0)
562            {
563                    PyErr_SetString(PyExc_RuntimeError, "failed to write object");
564                    return NULL;
565            }
566            return PyInt_FromLong((long)result);
567    }
568    
569  typedef struct  static PyObject* shapefile_cobject(ShapeFileObject* self)
570  {  {
571      /* Only methods and no attributes here: */          return PyCObject_FromVoidPtr(self->handle, NULL);
572      %addmethods {  }
573    
574          /* The constructor. Takes two arguments, the filename and the  static PyObject* shapefile_repr(ShapeFileObject* self)
575           * optinal mode which are passed through to SHPOpen (due to the  {
576           * renaming trick)          /* TODO: it would be nice to do something like "shapelib.ShapeFile(filename, mode)" instead */
577           */          return PyString_FromFormat("<shapelib.ShapeFile object at %p>", self->handle);
578          ShapeFile(char *file, char * mode = "rb") {  }
             ShapeFile * self = malloc(sizeof(ShapeFile));  
             if (self)  
                 self->handle = SHPOpen(file, mode);  
             return self;  
         }  
   
         /* The destructor. Equivalent to SHPClose */  
         ~ShapeFile() {  
             if (self->handle)  
                 SHPClose(self->handle);  
             free(self);  
         }  
   
         /* close the shape file and set handle to NULL */  
         void close() {  
             if (self->handle)  
             {  
                 SHPClose(self->handle);  
                 self->handle = NULL;  
             }  
         }  
   
         /* info() -- Return a tuple (NUM_SHAPES, TYPE, MIN, MAX) where  
          * NUM_SHAPES is the number of shapes in the file, TYPE is the  
          * shape type and MIN and MAX are 4-element lists with the min.  
          * and max. values of the data.  
          *  
          * The arguments of the underlying shapelib function SHPGetInfo  
          * are all output parameters. To tell SWIG this, we have defined  
          * some typemaps above  
          */  
         void info(int * output_entities, int * output_type,  
                   double * output_min_bounds, double *output_max_bounds) {  
             SHPGetInfo(self->handle, output_entities, output_type,  
                        output_min_bounds, output_max_bounds);  
         }  
   
         /* Return object number i */  
         %new SHPObject * read_object(int i) {  
             return SHPReadObject(self->handle, i);  
         }  
   
         /* Write an object */  
         int write_object(int iShape, SHPObject * psObject) {  
             return SHPWriteObject(self->handle, iShape, psObject);  
         }  
   
         /* Return the shapelib SHPHandle as a Python CObject */  
         PyObject * cobject() {  
             return PyCObject_FromVoidPtr(self->handle, NULL);  
         }  
     }  
579    
580  } ShapeFile;  static struct PyMethodDef shapefile_methods[] =
581    {
582            {"close", (PyCFunction)shapefile_close, METH_NOARGS,
583                    "close()\n"
584                    "close the shape file" },
585            {"info", (PyCFunction)shapefile_info, METH_NOARGS,
586                    "info()\n"
587                    "returns (num_shapes, type, (x_min, y_min, z_min, m_min), (x_max, y_max, z_max, m_max)) with:\n"
588                    "-num_shapes: the number of the objects in the file\n"
589                    "-type: the type of the shape file (SHPT_POINT, SHPT_POLYGON, ...)\n"
590                    "-(x_min, y_min, z_min, m_min), (x_max, y_max, z_max, m_max): 4D bounding box of the data in the shape file" },
591            {"read_object", (PyCFunction)shapefile_read_object, METH_VARARGS,
592                    "read_object(id)\n"
593                    "Return object indexed by id" },
594            {"write_object", (PyCFunction)shapefile_write_object, METH_VARARGS,
595                    "write_object(id, object)\n"
596                    "Write an object at index id.\n"
597                    "If id == -1, the object is appended at the end of the shape file"},
598            {"cobject", (PyCFunction)shapefile_cobject, METH_NOARGS,
599                    "cobject()\n"
600                    "Return the shapelib SHPHandle as a Python CObject"},
601            {NULL}
602    };
603    
604    static struct PyGetSetDef shapefile_getsetters[] =
605    {
606            {NULL}
607    };
608    
609  /*  static PyTypeObject ShapeFileType = PYSHAPELIB_DEFINE_TYPE(ShapeFileObject, shapefile, "shapelib.ShapeFile", 0);
  * Two module level functions, open() and create() that correspond to  
  * SHPOpen and SHPCreate respectively. open() is equivalent to the  
  * ShapeFile constructor.  
  */  
610    
611  %{  /* --- shapelib ------------------------------------------------------------------------------------------------------ */
     ShapeFile * open_ShapeFile(const char *filename, const char * mode) {  
         ShapeFile * self = malloc(sizeof(ShapeFile));  
         if (self)  
             self->handle = SHPOpen(filename, mode);  
         return self;  
     }  
 %}  
   
 %name(open) %new ShapeFile *open_ShapeFile(const char *filename,  
                                            const char * mode = "rb");  
   
   
 %{  
     ShapeFile * create_ShapeFile(const char *filename, int type) {  
         ShapeFile * self = malloc(sizeof(ShapeFile));  
         if (self)  
             self->handle = SHPCreate(filename, type);  
         return self;  
     }  
 %}      
   
 %name(create) %new ShapeFile * create_ShapeFile(const char *filename,  
                                                 int type);  
       
   
 /* Module level function to expose some of the shapelib functions linked  
  * with the shapefile C-module to other Python extension modules. This  
  * is a kludge to make a Thuban extension work that reads shapes from  
  * shapefiles opened by the shapefile module.  
  */  
612    
613  %{  static PyObject* shapelib_open(PyObject* module, PyObject* args)
614      static PyShapeLibAPI the_api = {  {
615            return PyObject_CallObject((PyObject*)&ShapeFileType, args);
616    }
617    
618    static PyObject* shapelib_create(PyObject* module, PyObject* args)
619    {
620            char* file;
621            int type;
622            ShapeFileObject* result;
623            
624            if (!PyArg_ParseTuple(args, "eti:create", Py_FileSystemDefaultEncoding, &file, &type)) return NULL;
625            
626            result = PyObject_New(ShapeFileObject, &ShapeFileType);
627            if (!result)
628            {
629                    return PyErr_NoMemory();
630            }
631            
632            result->handle = SHPCreate(file, type);
633            if (!result->handle)
634            {
635                    PyObject_Del((PyObject*)result);
636                    PyErr_SetString(PyExc_RuntimeError, "Failed to create ShapeFile");
637                    return NULL;
638            }
639            
640            return (PyObject*) result;
641    }
642            
643    static PyShapeLibAPI shapelib_the_api =
644    {
645          SHPReadObject,          SHPReadObject,
646          SHPDestroyObject,          SHPDestroyObject,
647          SHPCreateTree,          SHPCreateTree,
648          SHPDestroyTree,          SHPDestroyTree,
649          SHPTreeFindLikelyShapes          SHPTreeFindLikelyShapes
650      };  };
   
     PyObject * c_api() {  
         return PyCObject_FromVoidPtr(&the_api, NULL);  
     }  
 %}  
651    
652  PyObject * c_api();  static PyObject* shapelib_c_api(PyObject* module)
653    {
654            return PyCObject_FromVoidPtr(&shapelib_the_api, NULL);
655  /*  }
  *  Module Level functions  
  */  
   
 /* convert shapefile types to names */  
 %name(type_name) const char *SHPTypeName(int nSHPType);  
 %name(part_type_name) const char *SHPPartTypeName(int nPartType);  
656    
657    static PyObject* shapelib_type_name(PyObject* module, PyObject* args)
658    {
659            int type;
660            if (!PyArg_ParseTuple(args, "i:type_name", &type)) return NULL;
661            return PyString_FromString(SHPTypeName(type));
662    }
663    
664  /*  static PyObject* shapelib_part_type_name(PyObject* module, PyObject* args)
665   * Finally, constants copied from shapefil.h  {
666   */          int type;
667            if (!PyArg_ParseTuple(args, "i:part_type_name", &type)) return NULL;
668            return PyString_FromString(SHPPartTypeName(type));
669    }
670    
671  /* -------------------------------------------------------------------- */  static struct PyMethodDef shapelib_methods[] =
672  /*      Shape types (nSHPType)                                          */  {
673  /* -------------------------------------------------------------------- */          {"open", (PyCFunction)shapelib_open, METH_VARARGS,
674  #define SHPT_NULL       0                  "open(filename [, mode='rb'])\n"
675  #define SHPT_POINT      1                  "open a ShapeFile" },
676  #define SHPT_ARC        3          {"create", (PyCFunction)shapelib_create, METH_VARARGS,
677  #define SHPT_POLYGON    5                  "create(filename, type)\n"
678  #define SHPT_MULTIPOINT 8                  "create a ShapeFile of a certain type (one of SHPT_POINT, SHPT_POLYGON)" },
679  #define SHPT_POINTZ     11          {"c_api", (PyCFunction)shapelib_c_api, METH_NOARGS,
680  #define SHPT_ARCZ       13                  "c_api()\n"
681  #define SHPT_POLYGONZ   15                  "get C API of shapelib" },
682  #define SHPT_MULTIPOINTZ 18          {"type_name", (PyCFunction)shapelib_type_name, METH_VARARGS,
683  #define SHPT_POINTM     21                  "type_name(type)\n"
684  #define SHPT_ARCM       23                  "return type as string" },
685  #define SHPT_POLYGONM   25          {"part_type_name", (PyCFunction)shapelib_part_type_name, METH_VARARGS,
686  #define SHPT_MULTIPOINTM 28                  "part_type_name(part_type)\n"
687  #define SHPT_MULTIPATCH 31                  "return part type as string" },
688            {NULL}
689    };
 /* -------------------------------------------------------------------- */  
 /*      Part types - everything but SHPT_MULTIPATCH just uses           */  
 /*      SHPP_RING.                                                      */  
 /* -------------------------------------------------------------------- */  
   
 #define SHPP_TRISTRIP   0  
 #define SHPP_TRIFAN     1  
 #define SHPP_OUTERRING  2  
 #define SHPP_INNERRING  3  
 #define SHPP_FIRSTRING  4  
 #define SHPP_RING       5  
690    
691    PyMODINIT_FUNC initshapelib(void)
692    {
693            PyObject* module = Py_InitModule("shapelib", shapelib_methods);
694            if (!module) return;
695            
696            PYSHAPELIB_ADD_TYPE(SHPObjectType, "SHPObject");
697            PYSHAPELIB_ADD_TYPE(ShapeFileType, "ShapeFile");
698            
699            PYSHAPELIB_ADD_CONSTANT(SHPT_NULL);
700            PYSHAPELIB_ADD_CONSTANT(SHPT_POINT);
701            PYSHAPELIB_ADD_CONSTANT(SHPT_ARC);
702            PYSHAPELIB_ADD_CONSTANT(SHPT_POLYGON);
703            PYSHAPELIB_ADD_CONSTANT(SHPT_MULTIPOINT);
704            PYSHAPELIB_ADD_CONSTANT(SHPT_POINTZ);
705            PYSHAPELIB_ADD_CONSTANT(SHPT_ARCZ);
706            PYSHAPELIB_ADD_CONSTANT(SHPT_POLYGONZ);
707            PYSHAPELIB_ADD_CONSTANT(SHPT_MULTIPOINTZ);
708            PYSHAPELIB_ADD_CONSTANT(SHPT_POINTM);
709            PYSHAPELIB_ADD_CONSTANT(SHPT_ARCM);
710            PYSHAPELIB_ADD_CONSTANT(SHPT_POLYGONM);
711            PYSHAPELIB_ADD_CONSTANT(SHPT_MULTIPOINTM);
712            PYSHAPELIB_ADD_CONSTANT(SHPT_MULTIPATCH);
713            PYSHAPELIB_ADD_CONSTANT(SHPP_TRISTRIP);
714            PYSHAPELIB_ADD_CONSTANT(SHPP_TRIFAN);
715            PYSHAPELIB_ADD_CONSTANT(SHPP_OUTERRING);
716            PYSHAPELIB_ADD_CONSTANT(SHPP_INNERRING);
717            PYSHAPELIB_ADD_CONSTANT(SHPP_FIRSTRING);
718            PYSHAPELIB_ADD_CONSTANT(SHPP_RING);
719    }
720    

Legend:
Removed from v.2637  
changed lines
  Added in v.2744

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26