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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2735 - (hide annotations)
Mon Mar 12 23:24:35 2007 UTC (17 years, 11 months ago) by bramz
Original Path: branches/WIP-pyshapelib-bramz/libraries/pyshapelib/shapelib.c
File MIME type: text/plain
File size: 13581 byte(s)
rewritten shapelib to use hand-crafted Python bindings instead of SWIG generated ones.
1 bramz 2735 #include "shapefil.h"
2     #include "pyshapelib_common.h"
3     #include "pyshapelib_api.h"
4 jan 1611
5 bramz 2735 /* --- SHPObject ----------------------------------------------------------------------------------------------------- */
6 jan 1611
7 bramz 2735 typedef struct
8     {
9     PyObject_HEAD
10     SHPObject* shpObject;
11     }
12     PySHPObject;
13 jan 1611
14 bramz 2735 static PyObject* PySHPObject_new(PyTypeObject* type, PyObject* args, PyObject* kwds)
15     {
16     PySHPObject* self;
17     self = (PySHPObject*) type->tp_alloc(type, 0);
18     self->shpObject = NULL;
19     return (PyObject*) self;
20     }
21 jan 1611
22 bramz 2735 static void PySHPObject_dealloc(PySHPObject* self)
23     {
24     SHPDestroyObject(self->shpObject);
25     self->shpObject = NULL;
26     self->ob_type->tp_free((PyObject*)self);
27     }
28 jan 1611
29 bramz 2735 /* The constructor of SHPObject. parts is a list of lists of tuples
30     * describing the parts and their vertices just likethe output of the
31     * vertices() method. part_type_list is the list of part-types and may
32     * be NULL. For the meaning of the part-types and their default value
33     * see the Shaplib documentation.
34     */
35     static int PySHPObject_init(PySHPObject* self, PyObject* args, PyObject* kwds)
36     {
37     int type;
38     int id;
39     PyObject* parts = NULL;
40     PyObject* part_type_list = NULL;
41    
42     int num_parts;
43     int num_vertices;
44     int part_start;
45    
46     double* xs = NULL;
47     double* ys = NULL;
48     int* part_starts = NULL;
49     int* part_types = NULL;
50    
51     int i;
52     int return_code = -1;
53    
54     /* first, unpack parameters */
55     if (kwds != NULL && PyDict_Size(kwds) > 0)
56     {
57     PyErr_Format(PyExc_TypeError, "shapelib.SHPObject.__init__ takes no keyword arguments");
58     return -1;
59     }
60     if (!PyArg_ParseTuple(args, "iiO|O", &type, &id, &parts, &part_type_list)) return -1;
61    
62     if (!PySequence_Check(parts))
63     {
64     PyErr_SetString(PyExc_TypeError, "parts is not a sequence");
65     return -1;
66     }
67     num_parts = PySequence_Length(parts);
68     if (num_parts < 0)
69     {
70     PyErr_SetString(PyExc_TypeError, "cannot determine length of parts");
71     return -1;
72     }
73    
74     /* parts and part_types have to have the same lengths */
75     if (part_type_list)
76     {
77     if (!PySequence_Check(parts))
78     {
79     PyErr_SetString(PyExc_TypeError, "part_type_list is not a sequence");
80     return -1;
81     }
82     if (PySequence_Length(part_type_list) != num_parts)
83     {
84     PyErr_SetString(PyExc_TypeError, "parts and part_types have to have the same lengths");
85     return -1;
86     }
87     }
88    
89     /* determine how many vertices there are altogether */
90     num_vertices = 0;
91     for (i = 0; i < num_parts; ++i)
92     {
93     PyObject* part = PySequence_ITEM(parts, i);
94     if (!PySequence_Check(part))
95     {
96     PyErr_SetString(PyExc_TypeError, "at least one item in parts is not a sequence");
97     Py_DECREF(part);
98     return -1;
99     }
100     num_vertices += PySequence_Length(part);
101     Py_DECREF(part);
102     }
103    
104     /* allocate the memory for the various arrays and check for memory errors */
105     xs = malloc(num_vertices * sizeof(double));
106     ys = malloc(num_vertices * sizeof(double));
107     part_starts = malloc(num_parts * sizeof(int));
108     part_types = part_type_list ? malloc(num_parts * sizeof(int)) : 0;
109    
110     if (!xs || !ys || !part_starts || (part_type_list && !part_types))
111     {
112     PyErr_NoMemory();
113     goto exit;
114     }
115    
116     /* convert the part types */
117     if (part_type_list)
118     {
119     for (i = 0; i < num_parts; i++)
120     {
121     PyObject* otype = PySequence_ITEM(part_type_list, i);
122     part_types[i] = PyInt_AsLong(otype);
123     Py_DECREF(otype);
124     if (part_types[i] < 0)
125     {
126     PyErr_SetString(PyExc_TypeError, "at least one item in part_type_list is not an integer or is negative");
127     goto exit;
128     }
129     }
130     }
131    
132     /* convert the list of parts */
133     part_start = 0;
134     for (i = 0; i < num_parts; ++i)
135     {
136     int j, length;
137    
138     PyObject* part = PySequence_ITEM(parts, i);
139     length = PySequence_Length(part);
140     part_starts[i] = part_start;
141    
142     for (j = 0; j < length; ++j)
143     {
144     PyObject* vertex = PySequence_ITEM(part, j);
145     if (!PyArg_ParseTuple(vertex, "dd", xs + part_start + j, ys + part_start + j))
146     {
147     PyErr_SetString(PyExc_TypeError, "at least one part contains an vertex that's not a tuple of two doubles");
148     Py_DECREF(vertex);
149     Py_DECREF(part);
150     goto exit;
151     }
152     Py_DECREF(vertex);
153     }
154     Py_DECREF(part);
155     part_start += length;
156     }
157    
158     self->shpObject = SHPCreateObject(type, id, num_parts, part_starts, part_types, num_vertices, xs, ys, NULL, NULL);
159     return_code = 0;
160    
161     exit:
162     free(xs);
163     free(ys);
164     free(part_starts);
165     free(part_types);
166     return return_code;
167     }
168    
169 jan 1611 /*
170 bramz 2735 * The extents() method of SHPObject.
171     *
172     * Return the extents as a tuple of two 4-element lists with the min.
173     * and max. values of x, y, z, m.
174     */
175     static PyObject* PySHPObject_extents(PySHPObject* self)
176 jan 1611 {
177 bramz 2735 SHPObject* object = self->shpObject;
178     return Py_BuildValue("(dddd)(dddd)",
179     object->dfXMin, object->dfYMin, object->dfZMin, object->dfMMin,
180     object->dfXMax, object->dfYMax, object->dfZMax, object->dfMMax);
181 jan 1611 }
182    
183    
184     /*
185 bramz 2735 * The vertices() method of SHPObject.
186     *
187     * Return the x and y coords of the vertices as a list of lists of
188     * tuples.
189     */
190 jan 1611
191     static PyObject* build_vertex_list(SHPObject *object, int index, int length);
192    
193 bramz 2735 static PyObject* PySHPObject_vertices(PySHPObject* self)
194 jan 1611 {
195 bramz 2735 PyObject *result = NULL;
196     PyObject *part = NULL;
197     int part_idx, vertex_idx;
198     int length = 0;
199     SHPObject* object = self->shpObject;
200 jan 1611
201 bramz 2735 if (object->nParts > 0)
202     {
203     /* A multipart shape. Usual for SHPT_ARC and SHPT_POLYGON */
204 jan 1611
205 bramz 2735 result = PyList_New(object->nParts);
206 jan 1611 if (!result)
207 bramz 2735 return NULL;
208 jan 1611
209     for (part_idx = 0, vertex_idx = 0; part_idx < object->nParts;
210 bramz 2735 part_idx++)
211 jan 1611 {
212 bramz 2735 if (part_idx < object->nParts - 1)
213 jan 1611 length = (object->panPartStart[part_idx + 1]
214 bramz 2735 - object->panPartStart[part_idx]);
215     else
216 jan 1611 length = object->nVertices - object->panPartStart[part_idx];
217 bramz 2735
218     part = build_vertex_list(object, vertex_idx, length);
219     if (!part)
220 jan 1611 goto fail;
221    
222 bramz 2735 if (PyList_SetItem(result, part_idx, part) < 0)
223 jan 1611 goto fail;
224    
225 bramz 2735 vertex_idx += length;
226 jan 1611 }
227 bramz 2735 }
228     else
229     {
230 jan 1611 /* only one part. usual for SHPT_POINT */
231     result = build_vertex_list(object, 0, object->nVertices);
232 bramz 2735 }
233 jan 1611
234 bramz 2735 return result;
235 jan 1611
236 bramz 2735 fail:
237     Py_XDECREF(part);
238     Py_DECREF(result);
239     return NULL;
240 jan 1611 }
241    
242    
243     /* Return the length coordinates of the shape object starting at vertex
244 bramz 2735 * index as a Python-list of tuples. Helper function for
245     * SHPObject_vertices.
246     */
247     static PyObject* build_vertex_list(SHPObject *object, int index, int length)
248 jan 1611 {
249 bramz 2735 int i;
250     PyObject * list;
251     PyObject * vertex = NULL;
252 jan 1611
253 bramz 2735 list = PyList_New(length);
254     if (!list)
255 jan 1611 return NULL;
256    
257 bramz 2735 for (i = 0; i < length; i++, index++)
258     {
259 jan 1611 vertex = Py_BuildValue("dd", object->padfX[index],
260 bramz 2735 object->padfY[index]);
261 jan 1611 if (!vertex)
262 bramz 2735 goto fail;
263 jan 1611 if (PyList_SetItem(list, i, vertex) < 0)
264 bramz 2735 goto fail;
265     }
266 jan 1611
267 bramz 2735 return list;
268 jan 1611
269 bramz 2735 fail:
270     Py_XDECREF(vertex);
271     Py_DECREF(list);
272     return NULL;
273 jan 1611 }
274    
275 bramz 2735 static PyObject* PySHPObject_type(PySHPObject* self, void* closure)
276     {
277     return PyInt_FromLong(self->shpObject->nSHPType);
278     }
279 jan 1611
280 bramz 2735 static PyObject* PySHPObject_id(PySHPObject* self, void* closure)
281     {
282     return PyInt_FromLong(self->shpObject->nShapeId);
283     }
284 jan 1611
285 bramz 2735 static PyMethodDef PySHPObject_methods[] =
286     {
287     {"extents", (PyCFunction)PySHPObject_extents, METH_NOARGS, NULL},
288     {"vertices", (PyCFunction)PySHPObject_vertices, METH_NOARGS, NULL},
289     {NULL}
290     };
291 jan 1611
292 bramz 2735 static PyGetSetDef PySHPObject_getsetters[] =
293 jan 1611 {
294 bramz 2735 {"type", (getter)PySHPObject_type, NULL, NULL },
295     {"id", (getter)PySHPObject_id, NULL, NULL },
296     {NULL}
297     };
298 jan 1611
299 bramz 2735 static PyTypeObject PySHPObjectType = PYSHAPELIB_DEFINE_TYPE(PySHPObject, "shapelib.SHPObject", 0);
300 jan 1611
301    
302 bramz 2735 /* --- ShapeFile ----------------------------------------------------------------------------------------------------- */
303 jan 1611
304 bramz 2735 typedef struct
305     {
306     PyObject_HEAD
307     SHPHandle handle;
308     }
309     PyShapeFile;
310 jan 1611
311 bramz 2735 static PyObject* PyShapeFile_new(PyTypeObject* type, PyObject* args, PyObject* kwds)
312     {
313     PyShapeFile* self;
314     self = (PyShapeFile*) type->tp_alloc(type, 0);
315     self->handle = NULL;
316     return (PyObject*) self;
317     }
318 jan 1611
319 bramz 2735 static int PyShapeFile_init(PyShapeFile* self, PyObject* args, PyObject* kwds)
320     {
321     char* file;
322     char* mode = "rb";
323     if (kwds != NULL && PyDict_Size(kwds) > 0)
324     {
325     PyErr_Format(PyExc_TypeError, "shapelib.ShapeFile.__init__ takes no keyword arguments");
326     return -1;
327     }
328     if (!PyArg_ParseTuple(args, "s|s", &file, &mode)) return -1;
329    
330     self->handle = SHPOpen(file, mode);
331     return self->handle ? 0 : -1;
332     }
333 jan 1611
334 bramz 2735 static PyObject* PyShapeFile_close(PyShapeFile* self)
335     {
336     SHPClose(self->handle);
337     self->handle = NULL;
338     Py_RETURN_NONE;
339     }
340 jan 1611
341 bramz 2735 static void PyShapeFile_dealloc(PyShapeFile* self)
342     {
343     PyShapeFile_close(self);
344     self->ob_type->tp_free((PyObject*)self);
345     }
346 jan 1611
347 bramz 2735 static PyObject* PyShapeFile_info(PyShapeFile* self)
348     {
349     SHPHandle handle = self->handle;
350     return Py_BuildValue("ii(dddd)(dddd)",
351     handle->nRecords, handle->nShapeType,
352     handle->adBoundsMin[0], handle->adBoundsMin[1], handle->adBoundsMin[2], handle->adBoundsMin[3],
353     handle->adBoundsMax[0], handle->adBoundsMax[1], handle->adBoundsMax[2], handle->adBoundsMax[3]);
354     }
355 jan 1611
356 bramz 2735 static PyObject* PyShapeFile_read_object(PyShapeFile* self, PyObject* args)
357     {
358     int index;
359     SHPObject* object;
360     PySHPObject* result;
361    
362     if (!PyArg_ParseTuple(args, "i", &index)) return NULL;
363    
364     object = SHPReadObject(self->handle, index);
365     if (!object)
366 jan 1611 {
367 bramz 2735 PyErr_SetString(PyExc_RuntimeError, "failed to read object");
368 jan 1611 return NULL;
369     }
370 bramz 2735
371     result = PyObject_New(PySHPObject, &PySHPObjectType);
372     if (!result)
373 jan 1611 {
374 bramz 2735 return PyErr_NoMemory();
375 jan 1611 }
376 bramz 2735
377     result->shpObject = object;
378     return (PyObject*) result;
379 jan 1611 }
380    
381 bramz 2735 static PyObject* PyShapeFile_write_object(PyShapeFile* self, PyObject* args)
382     {
383     int index, result;
384     PyObject* object;
385    
386     if (!PyArg_ParseTuple(args, "iO", &index, &object)) return NULL;
387    
388     if (!PyObject_IsInstance(object, (PyObject*)&PySHPObjectType))
389     {
390     PyErr_SetString(PyExc_TypeError, "object is not a SHPObject");
391     return NULL;
392     }
393    
394     result = SHPWriteObject(self->handle, index, ((PySHPObject*)object)->shpObject);
395     if (result < 0)
396     {
397     PyErr_SetString(PyExc_RuntimeError, "failed to write object");
398     return NULL;
399     }
400     return PyInt_FromLong((long)result);
401 jan 1611 }
402    
403 bramz 2735 static PyObject* PyShapeFile_cobject(PyShapeFile* self)
404     {
405     return PyCObject_FromVoidPtr(self->handle, NULL);
406 jan 1611 }
407    
408 bramz 2735 static PyMethodDef PyShapeFile_methods[] =
409     {
410     {"close", (PyCFunction)PyShapeFile_close, METH_NOARGS, "close the shape file" },
411     {"info", (PyCFunction)PyShapeFile_info, METH_NOARGS,
412     "Return a tuple (NUM_SHAPES, TYPE, MIN, MAX) where NUM_SHAPES is the number of shapes in the file, TYPE is the "
413     "shape type and MIN and MAX are 4-element tuples with the min. and max. values of the data." },
414     {"read_object", (PyCFunction)PyShapeFile_read_object, METH_VARARGS, "Return object number i" },
415     {"write_object", (PyCFunction)PyShapeFile_write_object, METH_VARARGS, "Write an object"},
416     {"cobject", (PyCFunction)PyShapeFile_cobject, METH_NOARGS, "Return the shapelib SHPHandle as a Python CObject"},
417     {NULL}
418     };
419 jan 1611
420 bramz 2735 static PyGetSetDef PyShapeFile_getsetters[] =
421     {
422     {NULL}
423     };
424 jan 1611
425 bramz 2735 static PyTypeObject PyShapeFileType = PYSHAPELIB_DEFINE_TYPE(PyShapeFile, "shapelib.ShapeFile", 0);
426 jan 1611
427 bramz 2735 /* --- shapelib ------------------------------------------------------------------------------------------------------ */
428 jan 1611
429 bramz 2735 static PyObject* shapelib_open(PyObject* module, PyObject* args)
430     {
431     return PyObject_CallObject((PyObject*)&PyShapeFileType, args);
432 jan 1611 }
433    
434 bramz 2735 static PyObject* shapelib_create(PyObject* module, PyObject* args)
435 jan 1611 {
436 bramz 2735 char* file;
437     int type;
438     PyShapeFile* result;
439    
440     if (!PyArg_ParseTuple(args, "si", &file, &type)) return NULL;
441    
442     result = PyObject_New(PyShapeFile, &PyShapeFileType);
443     if (!result)
444     {
445     return PyErr_NoMemory();
446 jan 1611 }
447 bramz 2735
448     result->handle = SHPCreate(file, type);
449     if (!result->handle)
450     {
451     PyObject_Del((PyObject*)result);
452     PyErr_SetString(PyExc_RuntimeError, "Failed to create ShapeFile");
453     return NULL;
454 jan 1611 }
455 bramz 2735
456     return (PyObject*) result;
457     }
458    
459     static PyShapeLibAPI shapelib_the_api =
460     {
461 jan 1611 SHPReadObject,
462     SHPDestroyObject,
463     SHPCreateTree,
464     SHPDestroyTree,
465     SHPTreeFindLikelyShapes
466 bramz 2735 };
467 jan 1611
468 bramz 2735 static PyObject* shapelib_c_api(PyObject* module)
469     {
470     return PyCObject_FromVoidPtr(&shapelib_the_api, NULL);
471     }
472 jan 1611
473 bramz 2735 static PyObject* shapelib_type_name(PyObject* module, PyObject* args)
474     {
475     int type;
476     if (!PyArg_ParseTuple(args, "i", &type)) return NULL;
477     return PyString_FromString(SHPTypeName(type));
478     }
479 jan 1611
480 bramz 2735 static PyObject* shapelib_part_type_name(PyObject* module, PyObject* args)
481     {
482     int type;
483     if (!PyArg_ParseTuple(args, "i", &type)) return NULL;
484     return PyString_FromString(SHPPartTypeName(type));
485     }
486 jan 1611
487 bramz 2735 static PyMethodDef shapelib_methods[] =
488     {
489     {"open", (PyCFunction)shapelib_open, METH_VARARGS, "open a ShapeFile" },
490     {"create", (PyCFunction)shapelib_create, METH_VARARGS, "create a ShapeFile" },
491     {"c_api", (PyCFunction)shapelib_c_api, METH_NOARGS, "get C API of shapelib" },
492     {"type_name", (PyCFunction)shapelib_type_name, METH_VARARGS, "return type as string" },
493     {"part_type_name", (PyCFunction)shapelib_part_type_name, METH_VARARGS, "return part type as string" },
494     {NULL}
495     };
496 jan 1611
497 bramz 2735 PyMODINIT_FUNC initshapelib(void)
498     {
499     PyObject* module = Py_InitModule("shapelib", shapelib_methods);
500     if (!module) return;
501    
502     PYSHAPELIB_ADD_TYPE(PySHPObjectType, "SHPObject");
503     PYSHAPELIB_ADD_TYPE(PyShapeFileType, "ShapeFile");
504    
505     PYSHAPELIB_ADD_CONSTANT(SHPT_NULL);
506     PYSHAPELIB_ADD_CONSTANT(SHPT_POINT);
507     PYSHAPELIB_ADD_CONSTANT(SHPT_ARC);
508     PYSHAPELIB_ADD_CONSTANT(SHPT_POLYGON);
509     PYSHAPELIB_ADD_CONSTANT(SHPT_MULTIPOINT);
510     PYSHAPELIB_ADD_CONSTANT(SHPT_POINTZ);
511     PYSHAPELIB_ADD_CONSTANT(SHPT_ARCZ);
512     PYSHAPELIB_ADD_CONSTANT(SHPT_POLYGONZ);
513     PYSHAPELIB_ADD_CONSTANT(SHPT_MULTIPOINTZ);
514     PYSHAPELIB_ADD_CONSTANT(SHPT_POINTM);
515     PYSHAPELIB_ADD_CONSTANT(SHPT_ARCM);
516     PYSHAPELIB_ADD_CONSTANT(SHPT_POLYGONM);
517     PYSHAPELIB_ADD_CONSTANT(SHPT_MULTIPOINTM);
518     PYSHAPELIB_ADD_CONSTANT(SHPT_MULTIPATCH);
519     PYSHAPELIB_ADD_CONSTANT(SHPP_TRISTRIP);
520     PYSHAPELIB_ADD_CONSTANT(SHPP_TRIFAN);
521     PYSHAPELIB_ADD_CONSTANT(SHPP_OUTERRING);
522     PYSHAPELIB_ADD_CONSTANT(SHPP_INNERRING);
523     PYSHAPELIB_ADD_CONSTANT(SHPP_FIRSTRING);
524     PYSHAPELIB_ADD_CONSTANT(SHPP_RING);
525     }
526 jan 1611

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26