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

Annotation of /branches/WIP-pyshapelib-Unicode/thuban/libraries/pyshapelib/shapelibmodule.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2734 - (hide annotations)
Thu Mar 1 12:42:59 2007 UTC (18 years ago) by bramz
Original Path: branches/WIP-pyshapelib-bramz/libraries/pyshapelib/shapelib.i
File size: 15521 byte(s)
made a copy
1 jan 1611 /* SWIG (www.swig.org) interface file for shapelib
2     *
3     * At the moment (Dec 2000) this file is only useful to generate Python
4     * bindings. Invoke swig as follows:
5     *
6     * swig -python -shadow shapelib.i
7     *
8     * to generate shapelib_wrap.c and shapelib.py. shapelib_wrap.c
9     * defines a bunch of Python-functions that wrap the appripriate
10     * shapelib functions and shapelib.py contains an object oriented
11     * wrapper around shapelib_wrap.c.
12     *
13     * Shapelib, and hence this module too, defines two types of objects,
14     * shapes and shapefiles.
15     */
16    
17     %module shapelib
18    
19     /*
20     * First, a %{,%}-Block. These blocks are copied verbatim to the
21     * shapelib_wrap.c file and are not parsed by SWIG. This is the place to
22     * import headerfiles and define helper-functions that are needed by the
23     * automatically generated wrappers.
24     */
25    
26     %{
27    
28     /* import the shapelib headefile. */
29     #include "shapefil.h"
30     #include "pyshapelib_api.h"
31    
32     /*
33     * Rename a few shapelib functions that are effectively methods with
34     * preprocessor macros so that they have the names that swig expects
35     * (e.g. the destructor of SHPObject has to be called delete_SHPObject)
36     */
37    
38     #define delete_SHPObject SHPDestroyObject
39    
40     /*
41     * The extents() method of SHPObject.
42     *
43     * Return the extents as a tuple of two 4-element lists with the min.
44     * and max. values of x, y, z, m.
45     */
46     static PyObject *
47     SHPObject_extents(SHPObject *object)
48     {
49     return Py_BuildValue("[dddd][dddd]",
50     object->dfXMin, object->dfYMin, object->dfZMin,
51     object->dfMMin,
52     object->dfXMax, object->dfYMax, object->dfZMax,
53     object->dfMMax);
54     }
55    
56    
57     /*
58     * The vertices() method of SHPObject.
59     *
60     * Return the x and y coords of the vertices as a list of lists of
61     * tuples.
62     */
63    
64     static PyObject* build_vertex_list(SHPObject *object, int index, int length);
65    
66     static PyObject*
67     SHPObject_vertices(SHPObject *object)
68     {
69     PyObject *result = NULL;
70     PyObject *part = NULL;
71     int part_idx, vertex_idx;
72     int length = 0;
73    
74    
75     if (object->nParts > 0)
76     {
77     /* A multipart shape. Usual for SHPT_ARC and SHPT_POLYGON */
78    
79     result = PyList_New(object->nParts);
80     if (!result)
81     return NULL;
82    
83     for (part_idx = 0, vertex_idx = 0; part_idx < object->nParts;
84     part_idx++)
85     {
86     if (part_idx < object->nParts - 1)
87     length = (object->panPartStart[part_idx + 1]
88     - object->panPartStart[part_idx]);
89     else
90     length = object->nVertices - object->panPartStart[part_idx];
91    
92     part = build_vertex_list(object, vertex_idx, length);
93     if (!part)
94     goto fail;
95    
96     if (PyList_SetItem(result, part_idx, part) < 0)
97     goto fail;
98    
99     vertex_idx += length;
100     }
101     }
102     else
103     {
104     /* only one part. usual for SHPT_POINT */
105     result = build_vertex_list(object, 0, object->nVertices);
106     }
107    
108     return result;
109    
110     fail:
111     Py_XDECREF(part);
112     Py_DECREF(result);
113     return NULL;
114     }
115    
116    
117     /* Return the length coordinates of the shape object starting at vertex
118     * index as a Python-list of tuples. Helper function for
119     * SHPObject_vertices.
120     */
121     static PyObject*
122     build_vertex_list(SHPObject *object, int index, int length)
123     {
124     int i;
125     PyObject * list;
126     PyObject * vertex = NULL;
127    
128     list = PyList_New(length);
129     if (!list)
130     return NULL;
131    
132     for (i = 0; i < length; i++, index++)
133     {
134     vertex = Py_BuildValue("dd", object->padfX[index],
135     object->padfY[index]);
136     if (!vertex)
137     goto fail;
138     if (PyList_SetItem(list, i, vertex) < 0)
139     goto fail;
140     }
141    
142     return list;
143    
144     fail:
145     Py_XDECREF(vertex);
146     Py_DECREF(list);
147     return NULL;
148     }
149    
150    
151    
152    
153    
154     /* The constructor of SHPObject. parts is a list of lists of tuples
155     * describing the parts and their vertices just likethe output of the
156     * vertices() method. part_type_list is the list of part-types and may
157     * be NULL. For the meaning of the part-types and their default value
158     * see the Shaplib documentation.
159     */
160     SHPObject * new_SHPObject(int type, int id, PyObject * parts,
161     PyObject * part_type_list)
162     {
163     /* arrays to hold thex and y coordinates of the vertices */
164     double *xs = NULL, *ys = NULL;
165     /* number of all vertices of all parts */
166     int num_vertices;
167     /* number of parts in the list parts */
168     int num_parts;
169     /* start index of in xs and ys of the part currently worked on */
170     int part_start;
171     /* array of start indices in xs and ys as expected by shapelib */
172     int *part_starts = NULL;
173    
174     /* generic counter */
175     int i;
176    
177     /* array of part types. holds the converted content of
178     * part_type_list. Stays NULL of part_type_list is NULL
179     */
180     int *part_types = NULL;
181    
182     /* temporary python objects referring to the the list items being
183     * worked on.
184     */
185     PyObject * part = NULL, *tuple = NULL;
186    
187     /* The result object */
188     SHPObject *result;
189    
190     num_parts = PySequence_Length(parts);
191     num_vertices = 0;
192    
193     /* parts and part_types have to have the same lengths */
194     if (part_type_list
195 bh 2637 && PySequence_Length(parts) != PySequence_Length(part_type_list))
196 jan 1611 {
197     PyErr_SetString(PyExc_TypeError,
198     "parts and part_types have to have the same lengths");
199     return NULL;
200     }
201    
202     /* determine how many vertices there are altogether */
203     for (i = 0; i < num_parts; i++)
204     {
205     PyObject * part = PySequence_GetItem(parts, i);
206     if (!part)
207     return NULL;
208     num_vertices += PySequence_Length(part);
209     Py_DECREF(part);
210     }
211    
212     /* allocate the memory for the various arrays and check for memory
213     errors */
214     xs = malloc(num_vertices * sizeof(double));
215     ys = malloc(num_vertices * sizeof(double));
216     part_starts = malloc(num_parts * sizeof(int));
217     if (part_type_list)
218     part_types = malloc(num_parts * sizeof(int));
219    
220     if (!xs || !ys || !part_starts || (part_type_list && !part_types))
221     {
222     PyErr_NoMemory();
223     goto fail;
224     }
225    
226     /* convert the part types */
227     if (part_type_list)
228     {
229     for (i = 0; i < num_parts; i++)
230     {
231     PyObject * otype = PySequence_GetItem(part_type_list, i);
232     if (!otype)
233     return NULL;
234     part_types[i] = PyInt_AsLong(otype);
235     Py_DECREF(otype);
236     }
237     }
238    
239     /* convert the list of parts */
240     part_start = 0;
241     for (i = 0; i < num_parts; i++)
242     {
243     int j, length;
244    
245     part = PySequence_GetItem(parts, i);
246     length = PySequence_Length(part);
247     part_starts[i] = part_start;
248    
249     for (j = 0; j < length; j++)
250     {
251     tuple = PySequence_GetItem(part, j);
252     if (!tuple)
253     goto fail;
254    
255     if (!PyArg_ParseTuple(tuple, "dd", xs + part_start + j,
256     ys + part_start + j))
257     {
258     goto fail;
259     }
260     Py_DECREF(tuple);
261     tuple = NULL;
262     }
263     Py_DECREF(part);
264     part = NULL;
265     part_start += length;
266     }
267    
268     result = SHPCreateObject(type, id, num_parts, part_starts, part_types,
269     num_vertices, xs, ys, NULL, NULL);
270     free(xs);
271     free(ys);
272     free(part_starts);
273     free(part_types);
274     return result;
275    
276     fail:
277     free(xs);
278     free(ys);
279     free(part_starts);
280     free(part_types);
281     Py_XDECREF(part);
282     Py_XDECREF(tuple);
283     return NULL;
284     }
285    
286     %}
287    
288    
289    
290     /*
291     * The SWIG Interface definition.
292     */
293    
294     /* include some common SWIG type definitions and standard exception
295     handling code */
296     %include typemaps.i
297     %include exception.i
298    
299    
300     /*
301     * SHPObject -- Represents one shape
302     */
303    
304     /* Exception typemap for the SHPObject constructor. The constructor the
305     the wrapper function defined above which returns NULL in case of
306     error. */
307    
308     %typemap(python,except) SHPObject*new_SHPObject {
309     $function;
310     if (PyErr_Occurred())
311     return NULL;
312     }
313    
314     /* Define the SHPObject struct for SWIG. This has to have the same name
315     * as the underlying C-struct in shapfil.h, but we don't have to repeat
316     * all the fields here, only those we want to access directly, and we
317     * can define methods for the object oriented interface.
318     */
319    
320     typedef struct {
321    
322     /* The shape object has two read-only attributes: */
323    
324     /* The type of the shape. In the c-struct defined the field is
325     * called 'nSHPType' but for the python bindings 'type' is more
326     * appropriate.
327     */
328     %readonly %name(type) int nSHPType;
329    
330     /* The id of the shape. Here 'id' is a better name than 'nShapeId'. */
331     %readonly %name(id) int nShapeId;
332    
333     /* The methods */
334     %addmethods {
335    
336     /* the constructor */
337     SHPObject(int type, int id, PyObject * parts,
338     PyObject * part_types = NULL);
339    
340     /* The destructor */
341     ~SHPObject();
342    
343     /* extents and vertices correspond to the SHPObject_extents and
344     * SHPObject_vertices defined above
345     */
346     PyObject *extents();
347     PyObject *vertices();
348     }
349     } SHPObject;
350    
351    
352     /*
353     * ShapeFile -- Represents the shape file
354     */
355    
356     /* Here we do things a little different. We define a new C-struct that
357     * holds the SHPHandle. This is mainly done so we can separate the
358     * close() method from the destructor but it also helps with exception
359     * handling.
360     *
361     * After the ShapeFile has been opened or created the handle is not
362     * NULL. The close() method closes the file and sets handle to NULL as
363     * an indicator that the file has been closed.
364     */
365    
366     /* First, define the C-struct */
367     %{
368     typedef struct {
369     SHPHandle handle;
370     } ShapeFile;
371     %}
372    
373     /* define and use some typemaps for the info() method whose
374     * C-implementation has four output parameters that are returned through
375     * pointers passed into the function. SWIG already has definitions for
376     * common types such as int* and we can use those for the first two
377     * parameters:
378     */
379    
380     %apply int * OUTPUT { int * output_entities }
381     %apply int * OUTPUT { int * output_type }
382    
383     /* for the last two, the 4-element arrays of min- and max-values, we
384     * have to define our own typemaps:
385     */
386     %typemap (python,ignore) double * extents(double temp[4]) {
387     $target = temp;
388     }
389    
390     %typemap (python,argout) double * extents {
391     PyObject * list = Py_BuildValue("[dddd]",
392     $source[0], $source[1],
393     $source[2], $source[3]);
394     $target = t_output_helper($target,list);
395     }
396    
397     %apply double * extents { double * output_min_bounds }
398     %apply double * extents { double * output_max_bounds }
399    
400     /* The first argument to the ShapeFile methods is a ShapeFile pointer.
401     * We have to check whether handle is not NULL in most methods but not
402     * all. In the destructor and the close method, it's OK for handle to be
403     * NULL. We achieve this by checking whether the preprocessor macro
404     * NOCHECK_$name is defined. SWIG replaces $name with the name of the
405     * function for which the code is inserted. In the %{,%}-block below we
406     * define the macros for the destructor and the close() method.
407     */
408    
409    
410     %typemap(python,check) ShapeFile *{
411     %#ifndef NOCHECK_$name
412     if (!$target || !$target->handle)
413     SWIG_exception(SWIG_TypeError, "shapefile already closed");
414     %#endif
415     }
416    
417     %{
418     #define NOCHECK_delete_ShapeFile
419     #define NOCHECK_ShapeFile_close
420     %}
421    
422     /* An exception handle for the constructor and the module level open()
423     * and create() functions.
424     *
425     * Annoyingly, we *have* to put braces around the SWIG_exception()
426     * calls, at least in the python case, because of the way the macro is
427     * written. Of course, always putting braces around the branches of an
428     * if-statement is often considered good practice.
429     */
430     %typemap(python,except) ShapeFile * {
431     $function;
432     if (!$source)
433     {
434     SWIG_exception(SWIG_MemoryError, "no memory");
435     }
436     else if (!$source->handle)
437     {
438     SWIG_exception(SWIG_IOError, "$name failed");
439     }
440     }
441    
442    
443     /*
444     * The SWIG-version of the ShapeFile struct.
445     */
446    
447     typedef struct
448     {
449     /* Only methods and no attributes here: */
450     %addmethods {
451    
452     /* The constructor. Takes two arguments, the filename and the
453     * optinal mode which are passed through to SHPOpen (due to the
454     * renaming trick)
455     */
456     ShapeFile(char *file, char * mode = "rb") {
457     ShapeFile * self = malloc(sizeof(ShapeFile));
458     if (self)
459     self->handle = SHPOpen(file, mode);
460     return self;
461     }
462    
463     /* The destructor. Equivalent to SHPClose */
464     ~ShapeFile() {
465     if (self->handle)
466     SHPClose(self->handle);
467     free(self);
468     }
469    
470     /* close the shape file and set handle to NULL */
471     void close() {
472     if (self->handle)
473     {
474     SHPClose(self->handle);
475     self->handle = NULL;
476     }
477     }
478    
479     /* info() -- Return a tuple (NUM_SHAPES, TYPE, MIN, MAX) where
480     * NUM_SHAPES is the number of shapes in the file, TYPE is the
481     * shape type and MIN and MAX are 4-element lists with the min.
482     * and max. values of the data.
483     *
484     * The arguments of the underlying shapelib function SHPGetInfo
485     * are all output parameters. To tell SWIG this, we have defined
486     * some typemaps above
487     */
488     void info(int * output_entities, int * output_type,
489     double * output_min_bounds, double *output_max_bounds) {
490     SHPGetInfo(self->handle, output_entities, output_type,
491     output_min_bounds, output_max_bounds);
492     }
493    
494     /* Return object number i */
495     %new SHPObject * read_object(int i) {
496     return SHPReadObject(self->handle, i);
497     }
498    
499     /* Write an object */
500     int write_object(int iShape, SHPObject * psObject) {
501     return SHPWriteObject(self->handle, iShape, psObject);
502     }
503    
504     /* Return the shapelib SHPHandle as a Python CObject */
505     PyObject * cobject() {
506     return PyCObject_FromVoidPtr(self->handle, NULL);
507     }
508     }
509    
510     } ShapeFile;
511    
512    
513     /*
514     * Two module level functions, open() and create() that correspond to
515     * SHPOpen and SHPCreate respectively. open() is equivalent to the
516     * ShapeFile constructor.
517     */
518    
519     %{
520     ShapeFile * open_ShapeFile(const char *filename, const char * mode) {
521     ShapeFile * self = malloc(sizeof(ShapeFile));
522     if (self)
523     self->handle = SHPOpen(filename, mode);
524     return self;
525     }
526     %}
527    
528     %name(open) %new ShapeFile *open_ShapeFile(const char *filename,
529     const char * mode = "rb");
530    
531    
532     %{
533     ShapeFile * create_ShapeFile(const char *filename, int type) {
534     ShapeFile * self = malloc(sizeof(ShapeFile));
535     if (self)
536     self->handle = SHPCreate(filename, type);
537     return self;
538     }
539     %}
540    
541     %name(create) %new ShapeFile * create_ShapeFile(const char *filename,
542     int type);
543    
544    
545     /* Module level function to expose some of the shapelib functions linked
546     * with the shapefile C-module to other Python extension modules. This
547     * is a kludge to make a Thuban extension work that reads shapes from
548     * shapefiles opened by the shapefile module.
549     */
550    
551     %{
552     static PyShapeLibAPI the_api = {
553     SHPReadObject,
554     SHPDestroyObject,
555     SHPCreateTree,
556     SHPDestroyTree,
557     SHPTreeFindLikelyShapes
558     };
559    
560     PyObject * c_api() {
561     return PyCObject_FromVoidPtr(&the_api, NULL);
562     }
563     %}
564    
565     PyObject * c_api();
566    
567    
568     /*
569     * Module Level functions
570     */
571    
572     /* convert shapefile types to names */
573     %name(type_name) const char *SHPTypeName(int nSHPType);
574     %name(part_type_name) const char *SHPPartTypeName(int nPartType);
575    
576    
577     /*
578     * Finally, constants copied from shapefil.h
579     */
580    
581     /* -------------------------------------------------------------------- */
582     /* Shape types (nSHPType) */
583     /* -------------------------------------------------------------------- */
584     #define SHPT_NULL 0
585     #define SHPT_POINT 1
586     #define SHPT_ARC 3
587     #define SHPT_POLYGON 5
588     #define SHPT_MULTIPOINT 8
589     #define SHPT_POINTZ 11
590     #define SHPT_ARCZ 13
591     #define SHPT_POLYGONZ 15
592     #define SHPT_MULTIPOINTZ 18
593     #define SHPT_POINTM 21
594     #define SHPT_ARCM 23
595     #define SHPT_POLYGONM 25
596     #define SHPT_MULTIPOINTM 28
597     #define SHPT_MULTIPATCH 31
598    
599    
600     /* -------------------------------------------------------------------- */
601     /* Part types - everything but SHPT_MULTIPATCH just uses */
602     /* SHPP_RING. */
603     /* -------------------------------------------------------------------- */
604    
605     #define SHPP_TRISTRIP 0
606     #define SHPP_TRIFAN 1
607     #define SHPP_OUTERRING 2
608     #define SHPP_INNERRING 3
609     #define SHPP_FIRSTRING 4
610     #define SHPP_RING 5
611    
612    

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26