/[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 1611 by jan, Tue Aug 19 21:24:20 2003 UTC branches/WIP-pyshapelib-bramz/libraries/pyshapelib/shapelibmodule.c revision 2751 by bramz, Wed Mar 28 23:30:15 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    static int unpack_vertex(PyObject* vertex, int vertex_type,
71                    double* xs, double* ys, double* zs, double* ms, int offset);
72    
73  /*  /* The constructor of SHPObject. parts is a list of lists of tuples
74   * The vertices() method of SHPObject.  * describing the parts and their vertices just likethe output of the
75   *  * vertices() method. part_type_list is the list of part-types and may
76   * Return the x and y coords of the vertices as a list of lists of  * be NULL. For the meaning of the part-types and their default value
77   * tuples.  * see the Shaplib documentation.
78    */
79    static int shpobject_init(SHPObjectObject* self, PyObject* args, PyObject* kwds)
80    {
81            int type;
82            int id;
83            PyObject* parts = NULL;
84            PyObject* part_type_list = NULL;
85            
86            int num_parts;
87            int num_vertices;
88            int part_start;
89            
90            double* xs = NULL;
91            double* ys = NULL;
92            double* zs = NULL;
93            double* ms = NULL;
94            int* part_starts = NULL;
95            int* part_types = NULL;
96            
97            PyObject* part;
98            int vertex_type;
99            int has_z;
100            int has_m;
101            
102            int i;
103            int return_code = -1;
104            
105            /* first, unpack parameters */
106            if (kwds != NULL && PyDict_Size(kwds) > 0)
107            {
108                    PyErr_Format(PyExc_TypeError, "shapelib.SHPObject.__init__ takes no keyword arguments");
109                    return -1;
110            }
111            if (!PyArg_ParseTuple(args, "iiO|O:__init__", &type, &id, &parts, &part_type_list)) return -1;
112    
113            /* check parts */
114            if (!PySequence_Check(parts))
115            {
116                    PyErr_SetString(PyExc_TypeError, "parts is not a sequence");
117                    return -1;
118            }
119            num_parts = PySequence_Length(parts);
120            if (num_parts < 0)
121            {
122                    PyErr_SetString(PyExc_TypeError, "cannot determine length of parts");
123                    return -1;
124            }
125            
126            /* parts and part_types have to have the same lengths */
127            if (part_type_list == Py_None)
128            {
129                    Py_DECREF(part_type_list);
130                    part_type_list = NULL;
131            }
132            if (part_type_list)
133            {
134                    if (!PySequence_Check(parts))
135                    {
136                            PyErr_SetString(PyExc_TypeError, "part_type_list is not a sequence");
137                            return -1;
138                    }
139                    if (PySequence_Length(part_type_list) != num_parts)
140                    {
141                            PyErr_SetString(PyExc_TypeError, "parts and part_types have to have the same lengths");
142                            return -1;
143                    }
144            }
145    
146            /* determine how many vertices there are altogether */
147            num_vertices = 0;
148            for (i = 0; i < num_parts; ++i)
149            {
150                    PyObject* part = PySequence_ITEM(parts, i);
151                    if (!PySequence_Check(part))
152                    {
153                            PyErr_SetString(PyExc_TypeError, "at least one item in parts is not a sequence");
154                            Py_DECREF(part);
155                            return -1;
156                    }
157                    num_vertices += PySequence_Length(part);
158                    Py_DECREF(part);
159            }
160            
161            
162            vertex_type = determine_vertex_type(type, &has_z, &has_m);
163    
164            /* allocate the memory for the various arrays and check for memory errors */
165            xs = malloc(num_vertices * sizeof(double));
166            ys = malloc(num_vertices * sizeof(double));
167            zs = has_z ? malloc(num_vertices * sizeof(double)) : NULL;
168            ms = has_m ? malloc(num_vertices * sizeof(double)) : NULL;
169            part_starts = malloc(num_parts * sizeof(int));
170            part_types = part_type_list ? malloc(num_parts * sizeof(int)) : 0;
171    
172            if (!xs || !ys || (has_z && !zs) || (has_m && !ms) || !part_starts || (part_type_list && !part_types))
173            {
174                    PyErr_NoMemory();
175                    goto exit;
176            }
177    
178            /* convert the part types */
179            if (part_type_list)
180            {
181                    for (i = 0; i < num_parts; i++)
182                    {
183                            PyObject* otype = PySequence_ITEM(part_type_list, i);
184                            part_types[i] = PyInt_AsLong(otype);
185                            Py_DECREF(otype);
186                            if (part_types[i] < 0)
187                            {
188                                    PyErr_SetString(PyExc_TypeError, "at least one item in part_type_list is not an integer or is negative");
189                                    goto exit;
190                            }
191                    }
192            }
193    
194            /* convert the list of parts */
195            part_start = 0;
196            for (i = 0; i < num_parts; ++i)
197            {
198                    int j, length;
199                    
200                    part = PySequence_ITEM(parts, i);
201                    length = PySequence_Length(part);
202                    if (length < 0) goto exit;
203                    part_starts[i] = part_start;
204    
205                    for (j = 0; j < length; ++j)
206                    {
207                            PyObject* vertex = PySequence_ITEM(part, j);
208                            if (!unpack_vertex(vertex, vertex_type, xs, ys, zs, ms, part_start + j))
209                            {
210                                    Py_DECREF(vertex);
211                                    PyErr_SetString(PyExc_TypeError, "at least one vertex is of the wrong format");
212                                    goto exit;
213                            }
214                            Py_DECREF(vertex);
215                    }
216                    Py_DECREF(part);
217                    part = NULL;
218                    part_start += length;
219            }
220    
221            self->shpObject = SHPCreateObject(type, id, num_parts, part_starts, part_types, num_vertices, xs, ys, zs, ms);
222            return_code = 0;
223            
224    exit:
225            Py_XDECREF(part);
226            free(xs);
227            free(ys);
228            free(zs);
229            free(ms);
230            free(part_starts);
231            free(part_types);
232            return return_code;
233    }
234    
235    /* helper for shpobject_init. Unpacks vertices
236   */   */
237    static int unpack_vertex(PyObject* vertex, int vertex_type,
238                    double* xs, double* ys, double* zs, double* ms, int offset)
239    {
240            int ok;
241            PyObject* m_object;
242            PyObject *err_type, *err_value, *err_traceback;
243    
244  static PyObject* build_vertex_list(SHPObject *object, int index, int length);          switch (vertex_type)
245            {
246            case vtXY:
247                    return PyArg_ParseTuple(vertex, "dd:__init__", xs + offset, ys + offset);
248    
249  static PyObject*          case vtXYM:
250  SHPObject_vertices(SHPObject *object)                  ms[offset] = PYSHAPELIB_NO_DATA;
251                    ok = PyArg_ParseTuple(vertex, "dd|d:__init__", xs + offset, ys + offset, ms + offset);
252                    if (!ok)
253                    {
254                            /* maybe they specified None as M value */
255                            PyErr_Fetch(&err_type, &err_value, &err_traceback);
256                            ok = PyArg_ParseTuple(vertex, "ddO:__init__", xs + offset, ys + offset, &m_object);
257                            if (ok && m_object == Py_None)
258                            {
259                                    Py_XDECREF(err_type);
260                                    Py_XDECREF(err_value);
261                                    Py_XDECREF(err_traceback);
262                            }
263                            else
264                            {
265                                    PyErr_Restore(err_type, err_value, err_traceback);
266                            }
267                    }
268                    return ok;
269    
270            case vtXYZM:
271                    zs[offset] = 0.;
272                    ms[offset] = PYSHAPELIB_NO_DATA;
273                    ok = PyArg_ParseTuple(vertex, "dd|dd:__init__", xs + offset, ys + offset,
274                                    zs + offset, ms + offset);
275                    if (!ok)
276                    {
277                            /* maybe they specified None as M value */
278                            PyErr_Fetch(&err_type, &err_value, &err_traceback);
279                            ok = PyArg_ParseTuple(vertex, "dddO:__init__", xs + offset, ys + offset,
280                                            zs + offset, &m_object);
281                            if (ok && m_object == Py_None)
282                            {
283                                    Py_XDECREF(err_type);
284                                    Py_XDECREF(err_value);
285                                    Py_XDECREF(err_traceback);
286                            }
287                            else
288                            {
289                                    PyErr_Restore(err_type, err_value, err_traceback);
290                            }
291                    }
292                    return ok;
293    
294            default:
295                    PyErr_SetString(PyExc_NotImplementedError, "vertex type not implemented");
296                    return 0;
297            }
298    }
299    
300    /*
301    * The extents() method of SHPObject.
302    *
303    * Return the extents as a tuple of two 4-element lists with the min.
304    * and max. values of x, y, z, m.
305    */
306    static PyObject* shpobject_extents(SHPObjectObject* self)
307  {  {
308      PyObject *result = NULL;          SHPObject* object = self->shpObject;
309      PyObject *part = NULL;          return Py_BuildValue("(dddd)(dddd)",
310      int part_idx, vertex_idx;                          object->dfXMin, object->dfYMin, object->dfZMin, object->dfMMin,
311      int length = 0;                          object->dfXMax, object->dfYMax, object->dfZMax, object->dfMMax);
312    }
313    
314    
315    /*
316    * The vertices() method of SHPObject.
317    *
318    * Return the x and y coords of the vertices as a list of lists of
319    * tuples.
320    */
321    
322    static PyObject* build_vertex_list(SHPObject *object, int index, int length, int vertex_type);
323    
324      if (object->nParts > 0)  static PyObject* shpobject_vertices(SHPObjectObject* self)
325      {  {
326          /* A multipart shape. Usual for SHPT_ARC and SHPT_POLYGON */          PyObject *result = NULL;
327            PyObject *part = NULL;
328            int part_idx, vertex_idx;
329            int length = 0;
330            int vertex_type;
331                    
332          result = PyList_New(object->nParts);          SHPObject* object = self->shpObject;
333          if (!result)          vertex_type = determine_vertex_type(object->nSHPType, NULL, NULL);
             return NULL;  
334    
335          for (part_idx = 0, vertex_idx = 0; part_idx < object->nParts;          if (object->nParts > 0)
              part_idx++)  
336          {          {
337              if (part_idx < object->nParts - 1)                  /* A multipart shape. Usual for SHPT_ARC and SHPT_POLYGON */
338                  length = (object->panPartStart[part_idx + 1]          
339                            - object->panPartStart[part_idx]);                  result = PyList_New(object->nParts);
340              else                  if (!result)
341                  length = object->nVertices - object->panPartStart[part_idx];                          return NULL;
342                
343              part = build_vertex_list(object, vertex_idx, length);                  for (part_idx = 0, vertex_idx = 0; part_idx < object->nParts; part_idx++)
344              if (!part)                  {
345                  goto fail;                          if (part_idx < object->nParts - 1)
346                                    length = (object->panPartStart[part_idx + 1]
347              if (PyList_SetItem(result, part_idx, part) < 0)                                          - object->panPartStart[part_idx]);
348                  goto fail;                          else
349                                    length = object->nVertices - object->panPartStart[part_idx];
350              vertex_idx += length;                          
351          }                          part = build_vertex_list(object, vertex_idx, length, vertex_type);
352      }                          if (!part) goto fail;
353      else  
354      {                          if (PyList_SetItem(result, part_idx, part) < 0) goto fail;
355          /* only one part. usual for SHPT_POINT */  
356          result = build_vertex_list(object, 0, object->nVertices);                          vertex_idx += length;
357      }                  }
358            }
359      return result;          else
360            {
361   fail:                  /* only one part. usual for SHPT_POINT */
362      Py_XDECREF(part);                  result = build_vertex_list(object, 0, object->nVertices, vertex_type);
363      Py_DECREF(result);          }
364      return NULL;  
365            return result;
366    
367    fail:
368            Py_XDECREF(part);
369            Py_DECREF(result);
370            return NULL;
371  }  }
372    
373    
374  /* Return the length coordinates of the shape object starting at vertex  /* Return the length coordinates of the shape object starting at vertex
375   * index as a Python-list of tuples. Helper function for  * index as a Python-list of tuples. Helper function for
376   * SHPObject_vertices.  * SHPObject_vertices.
377   */  */
378  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)  
379  {  {
380      int i;          int i;
381      PyObject * list;          PyObject * list;
382      PyObject * vertex = NULL;          PyObject * vertex = NULL;
383    
384            list = PyList_New(length);
385            if (!list)
386                    return NULL;
387    
388            for (i = 0; i < length; i++, index++)
389            {
390                    switch (vertex_type)
391                    {
392                    case vtXY:
393                            vertex = Py_BuildValue("dd", object->padfX[index], object->padfY[index]);
394                            break;                  
395                    case vtXYM:
396                            vertex = Py_BuildValue("ddd", object->padfX[index], object->padfY[index],
397                                    object->padfM[index]);
398                            break;
399                    case vtXYZM:
400                            vertex = Py_BuildValue("dddd", object->padfX[index], object->padfY[index],
401                                    object->padfZ[index], object->padfM[index]);
402                            break;                  
403                    default:
404                            goto fail;
405                    }
406    
407      list = PyList_New(length);                  if (!vertex || PyList_SetItem(list, i, vertex) < 0) goto fail;
408      if (!list)          }
409            
410            return list;
411    
412    fail:
413            Py_DECREF(list);
414            return NULL;
415    }
416    
417    
418    
419    static PyObject* shpobject_part_types(SHPObjectObject* self)
420    {
421            int i;
422            PyObject* result = NULL;
423            SHPObject* object = self->shpObject;
424            
425            if (object->nParts == 0 || object->panPartType == 0)
426            {
427                    Py_RETURN_NONE;
428            }
429            
430            result = PyTuple_New(object->nParts);
431            if (!result) return NULL;
432            
433            for (i = 0; i < object->nParts; ++i)
434            {
435                    /* PyTuple_SetItem steals a reference */
436                    PyObject* part_type = PyInt_FromLong((long)object->panPartType[i]);
437                    if (!part_type || PyTuple_SetItem(result, i, part_type) < 0) goto fail;
438            }      
439            return result;
440            
441    fail:
442            Py_DECREF(result);
443          return NULL;          return NULL;
444    }
445    
446      for (i = 0; i < length; i++, index++)  
447      {  
448          vertex = Py_BuildValue("dd", object->padfX[index],  static PyObject* shpobject_type(SHPObjectObject* self, void* closure)
449                                 object->padfY[index]);  {
450          if (!vertex)          return PyInt_FromLong(self->shpObject->nSHPType);
             goto fail;  
         if (PyList_SetItem(list, i, vertex) < 0)  
             goto fail;  
     }  
   
     return list;  
   
  fail:  
     Py_XDECREF(vertex);  
     Py_DECREF(list);  
     return NULL;  
451  }  }
452    
453    
454    
455    static PyObject* shpobject_id(SHPObjectObject* self, void* closure)
456    {
457            return PyInt_FromLong(self->shpObject->nShapeId);
458    }
459    
460    
461  /* The constructor of SHPObject. parts is a list of lists of tuples  
462   * describing the parts and their vertices just likethe output of the  /* return a string that can be feeded to eval() to reconstruct the object,
463   * vertices() method. part_type_list is the list of part-types and may   * assuming a proper context
  * be NULL. For the meaning of the part-types and their default value  
  * see the Shaplib documentation.  
464   */   */
465  SHPObject * new_SHPObject(int type, int id, PyObject * parts,  static PyObject* shpobject_repr(SHPObjectObject* self)
                           PyObject * part_type_list)  
466  {  {
467      /* arrays to hold thex and y coordinates of the  vertices */          PyObject* format = NULL;
468      double *xs = NULL, *ys = NULL;          PyObject* args = NULL;
469      /* number of all vertices of all parts */          PyObject* result = NULL;
470      int num_vertices;          
471      /* number of parts in the list parts */          format = PyString_FromString("shapelib.SHPObject(%i, %i, %s, %s)");
472      int num_parts;          if (!format) return NULL;
     /* 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(part) != PySequence_Length(part_type_list))  
     {  
         PyErr_SetString(PyExc_TypeError,  
                         "parts and part_types have to have the same lengths");  
         return NULL;  
     }  
473    
474      /* determine how many vertices there are altogether */          args = Py_BuildValue("iiNN",
475      for (i = 0; i < num_parts; i++)                  self->shpObject->nSHPType,
476      {                  self->shpObject->nShapeId,
477          PyObject * part = PySequence_GetItem(parts, i);                  shpobject_vertices(self),
478          if (!part)                  shpobject_part_types(self));
479              return NULL;          if (!args)
         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++)  
480          {          {
481              PyObject * otype = PySequence_GetItem(part_type_list, i);                  Py_DECREF(format);
             if (!otype)  
482                  return NULL;                  return NULL;
             part_types[i] = PyInt_AsLong(otype);  
             Py_DECREF(otype);  
483          }          }
484      }          
485            result = PyString_Format(format, args);
486      /* convert the list of parts */          Py_DECREF(args);
487      part_start = 0;          Py_DECREF(format);
488      for (i = 0; i < num_parts; i++)          return result;
     {  
         int j, length;  
   
         part = PySequence_GetItem(parts, i);  
         length = PySequence_Length(part);  
         part_starts[i] = part_start;  
   
         for (j = 0; j < length; j++)  
         {  
             tuple = PySequence_GetItem(part, j);  
             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;  
489  }  }
490    
 %}  
491    
492    
493    static struct PyMethodDef shpobject_methods[] =
494    {
495            {"extents", (PyCFunction)shpobject_extents, METH_NOARGS,
496                    "extents() -> ((x_min, y_min, z_min, m_min), (x_max, y_max, z_max, m_max))\n\n"
497                    "returns the 4D bounding box of the SHPObject"},
498            {"vertices", (PyCFunction)shpobject_vertices, METH_NOARGS,
499                    "vertices() ->  [[(x, y, ...), ...], ...]\n\n"
500                    "Returns a list of object parts, where each part is again a list of vertices. "
501                    "Each vertex is a tuple of two to four doubles, depending on the object type."},
502            {"part_types", (PyCFunction)shpobject_part_types, METH_NOARGS,
503                    "part_types() -> tuple\n\n"
504                    "returns a tuple of integers, each integer indicating the type of the "
505                    "corresponding part in vertices()"},
506            {NULL}
507    };
508    
509  /*  static struct PyGetSetDef shpobject_getsetters[] =
510   * The SWIG Interface definition.  {
511   */          {"type", (getter)shpobject_type, NULL, "type of the object (read-only)" },
512            {"id", (getter)shpobject_id, NULL, "id of the object (read-only)" },
513            {NULL}
514    };
515    
516  /* include some common SWIG type definitions and standard exception  static PyTypeObject SHPObjectType = PYSHAPELIB_DEFINE_TYPE(SHPObjectObject, shpobject, "shapelib.SHPObject", 0);
    handling code */  
 %include typemaps.i  
 %include exception.i  
517    
518    
519  /*  /* --- ShapeFile ----------------------------------------------------------------------------------------------------- */
  *  SHPObject -- Represents one shape  
  */  
520    
521  /* Exception typemap for the SHPObject constructor. The constructor the  typedef struct
522     the wrapper function defined above which returns NULL in case of  {
523     error. */          PyObject_HEAD
524              SHPHandle handle;
 %typemap(python,except) SHPObject*new_SHPObject {  
     $function;  
     if (PyErr_Occurred())  
         return NULL;  
525  }  }
526    ShapeFileObject;
527    
528  /* Define the SHPObject struct for SWIG. This has to have the same name  /* allocator
  * 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.  
529   */   */
530    static PyObject* shapefile_new(PyTypeObject* type, PyObject* args, PyObject* kwds)
531    {
532            ShapeFileObject* self;  
533            self = (ShapeFileObject*) type->tp_alloc(type, 0);
534            self->handle = NULL;
535            return (PyObject*) self;
536    }
537    
538  typedef struct {  /* destructor
539    */
540    static void shapefile_dealloc(ShapeFileObject* self)
541    {
542            SHPClose(self->handle);
543            self->ob_type->tp_free((PyObject*)self);
544    }
545    
546      /* The shape object has two read-only attributes: */  /* constructor
547     */
548    static int shapefile_init(ShapeFileObject* self, PyObject* args, PyObject* kwds)
549    {
550            char* file = NULL;
551            char* mode = "rb";
552            static char *kwlist[] = {"name", "mode", NULL};
553    
554            SHPClose(self->handle);
555            self->handle = NULL;
556    
557    #if defined(SHPAPI_HAS_WIDE) && defined(Py_WIN_WIDE_FILENAMES)
558            if (GetVersion() < 0x80000000) {    /* On NT, so wide API available */
559                    PyObject *wfile;
560                    if (PyArg_ParseTupleAndKeywords(args, kwds, "U|s:ShapeFile", kwlist, &wfile, &mode))
561                    {
562                            PyObject *wmode = PyUnicode_DecodeASCII(mode, strlen(mode), NULL);
563                            if (!wmode) return -1;
564                            self->handle = SHPOpenW(PyUnicode_AS_UNICODE(wfile), PyUnicode_AS_UNICODE(wmode));
565                            Py_DECREF(wmode);
566                            if (!self->handle)
567                            {
568                                    PyErr_SetFromErrnoWithFilenameObject(PyExc_IOError, wfile);
569                                    return -1;
570                            }
571                    }
572                    else
573                    {
574                            /* Drop the argument parsing error as narrow
575                               strings are also valid. */
576                            PyErr_Clear();
577                    }
578            }
579    #endif
580    
581      /* The type of the shape. In the c-struct defined the field is          if (!self->handle)
582       * called 'nSHPType' but for the python bindings 'type' is more          {
583       * appropriate.                  if (!PyArg_ParseTupleAndKeywords(args, kwds, "et|s:ShapeFile", kwlist,
584       */                          Py_FileSystemDefaultEncoding, &file, &mode)) return -1;
585      %readonly %name(type) int nSHPType;                  self->handle = SHPOpen(file, mode);
   
     /* 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;  
586    
587                    if (!self->handle)
588                    {
589                            PyErr_SetFromErrnoWithFilename(PyExc_IOError, file);
590                            PyMem_Free(file);
591                            return -1;
592                    }
593    
594  /*                  PyMem_Free(file);
595   * ShapeFile --  Represents the shape file          }
  */  
596    
597  /* Here we do things a little different. We define a new C-struct that          return 0;
598   * 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.  
  */  
599    
 /* First, define the C-struct */  
 %{  
     typedef struct {  
         SHPHandle handle;  
     } ShapeFile;  
 %}  
600    
 /* define and use some typemaps for the info() method whose  
  * 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:  
  */  
   
 %apply int * OUTPUT { int * output_entities }  
 %apply int * OUTPUT { int * output_type }  
601    
602  /* for the last two, the 4-element arrays of min- and max-values, we  static PyObject* shapefile_close(ShapeFileObject* self)
603   * have to define our own typemaps:  {
604   */          SHPClose(self->handle);
605  %typemap (python,ignore) double * extents(double temp[4]) {          self->handle = NULL;
606      $target = temp;          Py_RETURN_NONE;
607  }  }
608    
 %typemap (python,argout) double * extents {  
     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.  
  */  
609    
610    
611  %typemap(python,check) ShapeFile *{  static PyObject* shapefile_info(ShapeFileObject* self)
612      %#ifndef NOCHECK_$name  {
613      if (!$target || !$target->handle)          SHPHandle handle = self->handle;
614          SWIG_exception(SWIG_TypeError, "shapefile already closed");          return Py_BuildValue("ii(dddd)(dddd)",
615      %#endif                          handle->nRecords, handle->nShapeType,
616  }                          handle->adBoundsMin[0], handle->adBoundsMin[1], handle->adBoundsMin[2], handle->adBoundsMin[3],
617                            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");  
     }  
618  }  }
619    
620    
 /*  
  * The SWIG-version of the ShapeFile struct.  
  */  
621    
622  typedef struct  static PyObject* shapefile_read_object(ShapeFileObject* self, PyObject* args)
623  {  {
624      /* Only methods and no attributes here: */          int index;
625      %addmethods {          SHPObject* object;
626            SHPObjectObject* result;
627          /* The constructor. Takes two arguments, the filename and the          
628           * optinal mode which are passed through to SHPOpen (due to the          if (!PyArg_ParseTuple(args, "i:read_object", &index)) return NULL;
629           * renaming trick)          
630           */          object = SHPReadObject(self->handle, index);    
631          ShapeFile(char *file, char * mode = "rb") {          if (!object)
632              ShapeFile * self = malloc(sizeof(ShapeFile));          {
633              if (self)                  PyErr_SetString(PyExc_RuntimeError, "failed to read object");
634                  self->handle = SHPOpen(file, mode);                  return NULL;
             return self;  
635          }          }
636            
637          /* The destructor. Equivalent to SHPClose */          result = PyObject_New(SHPObjectObject, &SHPObjectType);
638          ~ShapeFile() {          if (!result)
639              if (self->handle)          {
640                  SHPClose(self->handle);                  return PyErr_NoMemory();
             free(self);  
641          }          }
642            
643            result->shpObject = object;
644            return (PyObject*) result;
645    }
646    
         /* close the shape file and set handle to NULL */  
         void close() {  
             if (self->handle)  
             {  
                 SHPClose(self->handle);  
                 self->handle = NULL;  
             }  
         }  
647    
         /* 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);  
         }  
648    
649          /* Return object number i */  static PyObject* shapefile_write_object(ShapeFileObject* self, PyObject* args)
650          %new SHPObject * read_object(int i) {  {
651              return SHPReadObject(self->handle, i);          int index, result;
652            PyObject* object;
653            
654            if (!PyArg_ParseTuple(args, "iO:write_object", &index, &object)) return NULL;
655            
656            if (!PyObject_IsInstance(object, (PyObject*)&SHPObjectType))
657            {
658                    PyErr_SetString(PyExc_TypeError, "object is not a SHPObject");
659                    return NULL;
660          }          }
661            
662          /* Write an object */          result = SHPWriteObject(self->handle, index, ((SHPObjectObject*)object)->shpObject);
663          int write_object(int iShape, SHPObject * psObject) {          if (result < 0)
664              return SHPWriteObject(self->handle, iShape, psObject);          {
665                    PyErr_SetString(PyExc_RuntimeError, "failed to write object");
666                    return NULL;
667          }          }
668            return PyInt_FromLong((long)result);
669    }
670    
671          /* Return the shapelib SHPHandle as a Python CObject */  static PyObject* shapefile_cobject(ShapeFileObject* self)
672          PyObject * cobject() {  {
673              return PyCObject_FromVoidPtr(self->handle, NULL);          return PyCObject_FromVoidPtr(self->handle, NULL);
674          }  }
     }  
675    
676  } ShapeFile;  static PyObject* shapefile_repr(ShapeFileObject* self)
677    {
678            /* TODO: it would be nice to do something like "shapelib.ShapeFile(filename, mode)" instead */
679            return PyString_FromFormat("<shapelib.ShapeFile object at %p>", self->handle);
680    }
681    
682    static struct PyMethodDef shapefile_methods[] =
683    {
684            {"close", (PyCFunction)shapefile_close, METH_NOARGS,
685                    "close() -> None\n\n"
686                    "close the shape file" },
687            {"info", (PyCFunction)shapefile_info, METH_NOARGS,
688                    "info() -> (num_shapes, type, (x_min, y_min, z_min, m_min), (x_max, y_max, z_max, m_max))\n\n"
689                    "returns info about ShapeFile with:\n"
690                    "- num_shapes: the number of the objects in the file\n"
691                    "- type: the type of the shape file (SHPT_POINT, SHPT_POLYGON, ...)\n"
692                    "- (x_min, ...), (x_max, ...): 4D bounding box of the data in the shape file" },
693            {"read_object", (PyCFunction)shapefile_read_object, METH_VARARGS,
694                    "read_object(id) -> SHPObject\n\n"
695                    "Returns shape indexed by id" },
696            {"write_object", (PyCFunction)shapefile_write_object, METH_VARARGS,
697                    "write_object(id, object) -> id\n\n"
698                    "Write an object at index id, and returns id."
699                    "If id == -1, the object is appended at the end of the shape file."},
700            {"cobject", (PyCFunction)shapefile_cobject, METH_NOARGS,
701                    "cobject() -> CObject\n\n"
702                    "Return the shapelib SHPHandle as a Python CObject"},
703            {NULL}
704    };
705    
706  /*  static struct PyGetSetDef shapefile_getsetters[] =
707   * Two module level functions, open() and create() that correspond to  {
708   * SHPOpen and SHPCreate respectively. open() is equivalent to the          {NULL}
709   * ShapeFile constructor.  };
  */  
710    
711  %{  static PyTypeObject ShapeFileType = PYSHAPELIB_DEFINE_TYPE(ShapeFileObject, shapefile, "shapelib.ShapeFile", 0);
712      ShapeFile * open_ShapeFile(const char *filename, const char * mode) {  
713          ShapeFile * self = malloc(sizeof(ShapeFile));  /* --- shapelib ------------------------------------------------------------------------------------------------------ */
714          if (self)  
715              self->handle = SHPOpen(filename, mode);  static PyObject* shapelib_open(PyObject* module, PyObject* args)
716          return self;  {
717      }          return PyObject_CallObject((PyObject*)&ShapeFileType, args);
718  %}  }
719    
720  %name(open) %new ShapeFile *open_ShapeFile(const char *filename,  static PyObject* shapelib_create(PyObject* module, PyObject* args)
721                                             const char * mode = "rb");  {
722            char* file;
723            int type;
724  %{          ShapeFileObject* result;
725      ShapeFile * create_ShapeFile(const char *filename, int type) {          SHPHandle handle = NULL;
726          ShapeFile * self = malloc(sizeof(ShapeFile));          int wideargument = 0;
727          if (self)  
728              self->handle = SHPCreate(filename, type);  #if defined(SHPAPI_HAS_WIDE) && defined(Py_WIN_WIDE_FILENAMES)
729          return self;          if (GetVersion() < 0x80000000) {    /* On NT, so wide API available */
730      }                  PyObject *wfile;
731  %}                      if (PyArg_ParseTuple(args, "Ui:create", &wfile, &type))
732                    {
733  %name(create) %new ShapeFile * create_ShapeFile(const char *filename,                          wideargument = 1;
734                                                  int type);                          handle = SHPCreateW(PyUnicode_AS_UNICODE(wfile), type);
735                                if (!handle)
736                            {
737  /* Module level function to expose some of the shapelib functions linked                                  PyErr_SetFromErrnoWithFilenameObject(PyExc_IOError, wfile);
738   * with the shapefile C-module to other Python extension modules. This                                  return NULL;
739   * is a kludge to make a Thuban extension work that reads shapes from                          }
740   * shapefiles opened by the shapefile module.                  }
741   */                  else
742                    {
743                            /* Drop the argument parsing error as narrow
744                               strings are also valid. */
745                            PyErr_Clear();
746                    }
747            }
748    #endif
749            
750            if (!handle)
751            {
752                    if (!PyArg_ParseTuple(args, "eti:create", Py_FileSystemDefaultEncoding, &file, &type)) return NULL;
753                    handle = SHPCreate(file, type);
754                    if (!handle)
755                    {
756                                    PyErr_SetFromErrnoWithFilename(PyExc_IOError, file);
757                                    PyMem_Free(file);
758                                    return NULL;
759                    }
760                    PyMem_Free(file);
761            }
762    
763  %{          result = PyObject_New(ShapeFileObject, &ShapeFileType);
764      static PyShapeLibAPI the_api = {          if (!result)
765            {
766                    SHPClose(handle);
767                    return PyErr_NoMemory();
768            }
769            
770            result->handle = handle;
771            return (PyObject*) result;
772    }
773            
774    static PyShapeLibAPI shapelib_the_api =
775    {
776          SHPReadObject,          SHPReadObject,
777          SHPDestroyObject,          SHPDestroyObject,
778          SHPCreateTree,          SHPCreateTree,
779          SHPDestroyTree,          SHPDestroyTree,
780          SHPTreeFindLikelyShapes          SHPTreeFindLikelyShapes
781      };  };
   
     PyObject * c_api() {  
         return PyCObject_FromVoidPtr(&the_api, NULL);  
     }  
 %}  
   
 PyObject * c_api();  
   
   
 /*  
  *  Module Level functions  
  */  
782    
783  /* convert shapefile types to names */  static PyObject* shapelib_c_api(PyObject* module)
784  %name(type_name) const char *SHPTypeName(int nSHPType);  {
785  %name(part_type_name) const char *SHPPartTypeName(int nPartType);          return PyCObject_FromVoidPtr(&shapelib_the_api, NULL);
786    }
787    
788    static PyObject* shapelib_type_name(PyObject* module, PyObject* args)
789    {
790            int type;
791            if (!PyArg_ParseTuple(args, "i:type_name", &type)) return NULL;
792            return PyString_FromString(SHPTypeName(type));
793    }
794    
795  /*  static PyObject* shapelib_part_type_name(PyObject* module, PyObject* args)
796   * Finally, constants copied from shapefil.h  {
797   */          int type;
798            if (!PyArg_ParseTuple(args, "i:part_type_name", &type)) return NULL;
799            return PyString_FromString(SHPPartTypeName(type));
800    }
801    
802  /* -------------------------------------------------------------------- */  static struct PyMethodDef shapelib_methods[] =
803  /*      Shape types (nSHPType)                                          */  {
804  /* -------------------------------------------------------------------- */          {"open", (PyCFunction)shapelib_open, METH_VARARGS,
805  #define SHPT_NULL       0                  "open(name [, mode='rb']) -> ShapeFile\n\n"
806  #define SHPT_POINT      1                  "opens a ShapeFile" },
807  #define SHPT_ARC        3          {"create", (PyCFunction)shapelib_create, METH_VARARGS,
808  #define SHPT_POLYGON    5                  "create(name, type) -> ShapeFile\n\n"
809  #define SHPT_MULTIPOINT 8                  "creates a ShapeFile of a certain type (one of SHPT_POINT, SHPT_POLYGON)" },
810  #define SHPT_POINTZ     11          {"c_api", (PyCFunction)shapelib_c_api, METH_NOARGS,
811  #define SHPT_ARCZ       13                  "c_api() -> CObject\n\n"
812  #define SHPT_POLYGONZ   15                  "get C API of shapelib as a CObject" },
813  #define SHPT_MULTIPOINTZ 18          {"type_name", (PyCFunction)shapelib_type_name, METH_VARARGS,
814  #define SHPT_POINTM     21                  "type_name(type) -> string\n\n"
815  #define SHPT_ARCM       23                  "return type as string" },
816  #define SHPT_POLYGONM   25          {"part_type_name", (PyCFunction)shapelib_part_type_name, METH_VARARGS,
817  #define SHPT_MULTIPOINTM 28                  "part_type_name(part_type) -> string\n\n"
818  #define SHPT_MULTIPATCH 31                  "return part type as string" },
819            {NULL}
820    };
 /* -------------------------------------------------------------------- */  
 /*      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  
821    
822    PyMODINIT_FUNC initshapelib(void)
823    {
824            PyObject* module = Py_InitModule("shapelib", shapelib_methods);
825            if (!module) return;
826            
827            PYSHAPELIB_ADD_TYPE(SHPObjectType, "SHPObject");
828            PYSHAPELIB_ADD_TYPE(ShapeFileType, "ShapeFile");
829            
830            PYSHAPELIB_ADD_CONSTANT(SHPT_NULL);
831            PYSHAPELIB_ADD_CONSTANT(SHPT_POINT);
832            PYSHAPELIB_ADD_CONSTANT(SHPT_ARC);
833            PYSHAPELIB_ADD_CONSTANT(SHPT_POLYGON);
834            PYSHAPELIB_ADD_CONSTANT(SHPT_MULTIPOINT);
835            PYSHAPELIB_ADD_CONSTANT(SHPT_POINTZ);
836            PYSHAPELIB_ADD_CONSTANT(SHPT_ARCZ);
837            PYSHAPELIB_ADD_CONSTANT(SHPT_POLYGONZ);
838            PYSHAPELIB_ADD_CONSTANT(SHPT_MULTIPOINTZ);
839            PYSHAPELIB_ADD_CONSTANT(SHPT_POINTM);
840            PYSHAPELIB_ADD_CONSTANT(SHPT_ARCM);
841            PYSHAPELIB_ADD_CONSTANT(SHPT_POLYGONM);
842            PYSHAPELIB_ADD_CONSTANT(SHPT_MULTIPOINTM);
843            PYSHAPELIB_ADD_CONSTANT(SHPT_MULTIPATCH);
844            PYSHAPELIB_ADD_CONSTANT(SHPP_TRISTRIP);
845            PYSHAPELIB_ADD_CONSTANT(SHPP_TRIFAN);
846            PYSHAPELIB_ADD_CONSTANT(SHPP_OUTERRING);
847            PYSHAPELIB_ADD_CONSTANT(SHPP_INNERRING);
848            PYSHAPELIB_ADD_CONSTANT(SHPP_FIRSTRING);
849            PYSHAPELIB_ADD_CONSTANT(SHPP_RING);
850    }
851    

Legend:
Removed from v.1611  
changed lines
  Added in v.2751

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26