/[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 2751 - (hide annotations)
Wed Mar 28 23:30:15 2007 UTC (17 years, 11 months ago) by bramz
Original Path: branches/WIP-pyshapelib-bramz/libraries/pyshapelib/shapelibmodule.c
File MIME type: text/plain
File size: 21428 byte(s)
Added support for Win32 wide character file API.  Unicode filenames are now fully supported on the windows platform: for example exotic filenames like the greek letter pi (u"\u03c0").  However, this needed unofficial modifications in the C++ shapelib library.
1 bramz 2735 #include "pyshapelib_common.h"
2 jan 1611
3 bramz 2735 /* --- SHPObject ----------------------------------------------------------------------------------------------------- */
4 jan 1611
5 bramz 2735 typedef struct
6     {
7     PyObject_HEAD
8     SHPObject* shpObject;
9     }
10 bramz 2742 SHPObjectObject;
11 jan 1611
12 bramz 2743 enum {
13     vtXY,
14     vtXYM,
15     vtXYZM,
16     vtInvalid
17     } VertexType;
18    
19     int determine_vertex_type(int shape_type, int* has_z, int* has_m)
20     {
21     switch (shape_type)
22     {
23     case SHPT_POINT:
24     case SHPT_ARC:
25     case SHPT_POLYGON:
26     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 bramz 2741 /* allocator
52     */
53 bramz 2742 static PyObject* shpobject_new(PyTypeObject* type, PyObject* args, PyObject* kwds)
54 bramz 2735 {
55 bramz 2742 SHPObjectObject* self;
56     self = (SHPObjectObject*) type->tp_alloc(type, 0);
57 bramz 2735 self->shpObject = NULL;
58     return (PyObject*) self;
59     }
60 jan 1611
61 bramz 2741 /* deallocator
62     */
63 bramz 2742 static void shpobject_dealloc(SHPObjectObject* self)
64 bramz 2735 {
65     SHPDestroyObject(self->shpObject);
66     self->shpObject = NULL;
67     self->ob_type->tp_free((PyObject*)self);
68     }
69 jan 1611
70 bramz 2745 static int unpack_vertex(PyObject* vertex, int vertex_type,
71     double* xs, double* ys, double* zs, double* ms, int offset);
72    
73 bramz 2735 /* The constructor of SHPObject. parts is a list of lists of tuples
74     * 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     * be NULL. For the meaning of the part-types and their default value
77     * see the Shaplib documentation.
78     */
79 bramz 2742 static int shpobject_init(SHPObjectObject* self, PyObject* args, PyObject* kwds)
80 bramz 2735 {
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 bramz 2743 double* zs = NULL;
93     double* ms = NULL;
94 bramz 2735 int* part_starts = NULL;
95     int* part_types = NULL;
96    
97 bramz 2743 PyObject* part;
98     int vertex_type;
99     int has_z;
100     int has_m;
101    
102 bramz 2735 int i;
103 bramz 2745 int return_code = -1;
104 bramz 2735
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 bramz 2744 if (!PyArg_ParseTuple(args, "iiO|O:__init__", &type, &id, &parts, &part_type_list)) return -1;
112 bramz 2735
113 bramz 2743 /* check parts */
114 bramz 2735 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 bramz 2741 if (part_type_list == Py_None)
128     {
129     Py_DECREF(part_type_list);
130     part_type_list = NULL;
131     }
132 bramz 2735 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 bramz 2743
161    
162     vertex_type = determine_vertex_type(type, &has_z, &has_m);
163 bramz 2735
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 bramz 2743 zs = has_z ? malloc(num_vertices * sizeof(double)) : NULL;
168     ms = has_m ? malloc(num_vertices * sizeof(double)) : NULL;
169 bramz 2735 part_starts = malloc(num_parts * sizeof(int));
170     part_types = part_type_list ? malloc(num_parts * sizeof(int)) : 0;
171    
172 bramz 2743 if (!xs || !ys || (has_z && !zs) || (has_m && !ms) || !part_starts || (part_type_list && !part_types))
173 bramz 2735 {
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 bramz 2743 part = PySequence_ITEM(parts, i);
201 bramz 2735 length = PySequence_Length(part);
202 bramz 2743 if (length < 0) goto exit;
203 bramz 2735 part_starts[i] = part_start;
204    
205     for (j = 0; j < length; ++j)
206     {
207     PyObject* vertex = PySequence_ITEM(part, j);
208 bramz 2745 if (!unpack_vertex(vertex, vertex_type, xs, ys, zs, ms, part_start + j))
209 bramz 2735 {
210 bramz 2745 Py_DECREF(vertex);
211 bramz 2743 PyErr_SetString(PyExc_TypeError, "at least one vertex is of the wrong format");
212 bramz 2735 goto exit;
213     }
214 bramz 2745 Py_DECREF(vertex);
215 bramz 2735 }
216     Py_DECREF(part);
217 bramz 2743 part = NULL;
218 bramz 2735 part_start += length;
219     }
220    
221 bramz 2743 self->shpObject = SHPCreateObject(type, id, num_parts, part_starts, part_types, num_vertices, xs, ys, zs, ms);
222 bramz 2735 return_code = 0;
223    
224     exit:
225 bramz 2743 Py_XDECREF(part);
226 bramz 2735 free(xs);
227     free(ys);
228 bramz 2743 free(zs);
229     free(ms);
230 bramz 2735 free(part_starts);
231     free(part_types);
232     return return_code;
233     }
234    
235 bramz 2745 /* 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     switch (vertex_type)
245     {
246     case vtXY:
247     return PyArg_ParseTuple(vertex, "dd:__init__", xs + offset, ys + offset);
248    
249     case vtXYM:
250     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 jan 1611 /*
301 bramz 2735 * 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 bramz 2742 static PyObject* shpobject_extents(SHPObjectObject* self)
307 jan 1611 {
308 bramz 2735 SHPObject* object = self->shpObject;
309     return Py_BuildValue("(dddd)(dddd)",
310     object->dfXMin, object->dfYMin, object->dfZMin, object->dfMMin,
311     object->dfXMax, object->dfYMax, object->dfZMax, object->dfMMax);
312 jan 1611 }
313    
314    
315     /*
316 bramz 2735 * 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 jan 1611
322 bramz 2743 static PyObject* build_vertex_list(SHPObject *object, int index, int length, int vertex_type);
323 jan 1611
324 bramz 2742 static PyObject* shpobject_vertices(SHPObjectObject* self)
325 jan 1611 {
326 bramz 2735 PyObject *result = NULL;
327     PyObject *part = NULL;
328     int part_idx, vertex_idx;
329     int length = 0;
330 bramz 2743 int vertex_type;
331    
332 bramz 2735 SHPObject* object = self->shpObject;
333 bramz 2743 vertex_type = determine_vertex_type(object->nSHPType, NULL, NULL);
334 jan 1611
335 bramz 2735 if (object->nParts > 0)
336     {
337     /* A multipart shape. Usual for SHPT_ARC and SHPT_POLYGON */
338 jan 1611
339 bramz 2735 result = PyList_New(object->nParts);
340 bramz 2741 if (!result)
341     return NULL;
342 jan 1611
343 bramz 2741 for (part_idx = 0, vertex_idx = 0; part_idx < object->nParts; part_idx++)
344     {
345     if (part_idx < object->nParts - 1)
346 bramz 2743 length = (object->panPartStart[part_idx + 1]
347     - object->panPartStart[part_idx]);
348 bramz 2741 else
349 bramz 2743 length = object->nVertices - object->panPartStart[part_idx];
350 bramz 2741
351 bramz 2743 part = build_vertex_list(object, vertex_idx, length, vertex_type);
352     if (!part) goto fail;
353 jan 1611
354 bramz 2743 if (PyList_SetItem(result, part_idx, part) < 0) goto fail;
355 jan 1611
356 bramz 2741 vertex_idx += length;
357     }
358 jan 1611 }
359 bramz 2735 else
360     {
361 bramz 2741 /* only one part. usual for SHPT_POINT */
362 bramz 2743 result = build_vertex_list(object, 0, object->nVertices, vertex_type);
363 bramz 2735 }
364 jan 1611
365 bramz 2735 return result;
366 jan 1611
367 bramz 2735 fail:
368     Py_XDECREF(part);
369     Py_DECREF(result);
370     return NULL;
371 jan 1611 }
372    
373    
374     /* Return the length coordinates of the shape object starting at vertex
375 bramz 2735 * index as a Python-list of tuples. Helper function for
376     * SHPObject_vertices.
377     */
378 bramz 2743 static PyObject* build_vertex_list(SHPObject *object, int index, int length, int vertex_type)
379 jan 1611 {
380 bramz 2735 int i;
381     PyObject * list;
382     PyObject * vertex = NULL;
383 jan 1611
384 bramz 2735 list = PyList_New(length);
385     if (!list)
386 bramz 2741 return NULL;
387 jan 1611
388 bramz 2735 for (i = 0; i < length; i++, index++)
389     {
390 bramz 2743 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 bramz 2745 break;
399 bramz 2743 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 bramz 2741 goto fail;
405 bramz 2743 }
406    
407     if (!vertex || PyList_SetItem(list, i, vertex) < 0) goto fail;
408 bramz 2735 }
409 bramz 2743
410 bramz 2735 return list;
411 jan 1611
412 bramz 2735 fail:
413     Py_DECREF(list);
414     return NULL;
415 jan 1611 }
416    
417 bramz 2741
418    
419 bramz 2742 static PyObject* shpobject_part_types(SHPObjectObject* self)
420 bramz 2741 {
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;
444     }
445    
446    
447    
448 bramz 2742 static PyObject* shpobject_type(SHPObjectObject* self, void* closure)
449 bramz 2735 {
450     return PyInt_FromLong(self->shpObject->nSHPType);
451     }
452 jan 1611
453 bramz 2741
454    
455 bramz 2742 static PyObject* shpobject_id(SHPObjectObject* self, void* closure)
456 bramz 2735 {
457     return PyInt_FromLong(self->shpObject->nShapeId);
458     }
459 jan 1611
460 bramz 2741
461    
462     /* return a string that can be feeded to eval() to reconstruct the object,
463     * assuming a proper context
464     */
465 bramz 2742 static PyObject* shpobject_repr(SHPObjectObject* self)
466 bramz 2741 {
467     PyObject* format = NULL;
468     PyObject* args = NULL;
469     PyObject* result = NULL;
470    
471     format = PyString_FromString("shapelib.SHPObject(%i, %i, %s, %s)");
472     if (!format) return NULL;
473    
474     args = Py_BuildValue("iiNN",
475     self->shpObject->nSHPType,
476     self->shpObject->nShapeId,
477 bramz 2742 shpobject_vertices(self),
478     shpobject_part_types(self));
479 bramz 2741 if (!args)
480     {
481     Py_DECREF(format);
482     return NULL;
483     }
484    
485     result = PyString_Format(format, args);
486     Py_DECREF(args);
487     Py_DECREF(format);
488     return result;
489     }
490    
491    
492    
493 bramz 2742 static struct PyMethodDef shpobject_methods[] =
494 bramz 2735 {
495 bramz 2744 {"extents", (PyCFunction)shpobject_extents, METH_NOARGS,
496 bramz 2745 "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 bramz 2744 {"vertices", (PyCFunction)shpobject_vertices, METH_NOARGS,
499 bramz 2745 "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 bramz 2744 {"part_types", (PyCFunction)shpobject_part_types, METH_NOARGS,
503 bramz 2745 "part_types() -> tuple\n\n"
504     "returns a tuple of integers, each integer indicating the type of the "
505     "corresponding part in vertices()"},
506 bramz 2735 {NULL}
507     };
508 jan 1611
509 bramz 2742 static struct PyGetSetDef shpobject_getsetters[] =
510 jan 1611 {
511 bramz 2744 {"type", (getter)shpobject_type, NULL, "type of the object (read-only)" },
512     {"id", (getter)shpobject_id, NULL, "id of the object (read-only)" },
513 bramz 2735 {NULL}
514     };
515 jan 1611
516 bramz 2742 static PyTypeObject SHPObjectType = PYSHAPELIB_DEFINE_TYPE(SHPObjectObject, shpobject, "shapelib.SHPObject", 0);
517 jan 1611
518    
519 bramz 2735 /* --- ShapeFile ----------------------------------------------------------------------------------------------------- */
520 jan 1611
521 bramz 2735 typedef struct
522     {
523     PyObject_HEAD
524     SHPHandle handle;
525     }
526 bramz 2742 ShapeFileObject;
527 jan 1611
528 bramz 2741 /* allocator
529     */
530 bramz 2742 static PyObject* shapefile_new(PyTypeObject* type, PyObject* args, PyObject* kwds)
531 bramz 2735 {
532 bramz 2742 ShapeFileObject* self;
533     self = (ShapeFileObject*) type->tp_alloc(type, 0);
534 bramz 2735 self->handle = NULL;
535     return (PyObject*) self;
536     }
537 jan 1611
538 bramz 2742 /* 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 bramz 2741 /* constructor
547     */
548 bramz 2742 static int shapefile_init(ShapeFileObject* self, PyObject* args, PyObject* kwds)
549 bramz 2735 {
550 bramz 2751 char* file = NULL;
551 bramz 2735 char* mode = "rb";
552 bramz 2745 static char *kwlist[] = {"name", "mode", NULL};
553 bramz 2751
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 bramz 2749 if (!self->handle)
582     {
583 bramz 2751 if (!PyArg_ParseTupleAndKeywords(args, kwds, "et|s:ShapeFile", kwlist,
584     Py_FileSystemDefaultEncoding, &file, &mode)) return -1;
585     self->handle = SHPOpen(file, mode);
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 bramz 2749 }
596    
597 bramz 2751 return 0;
598 bramz 2735 }
599 jan 1611
600 bramz 2751
601    
602 bramz 2742 static PyObject* shapefile_close(ShapeFileObject* self)
603 bramz 2735 {
604     SHPClose(self->handle);
605     self->handle = NULL;
606     Py_RETURN_NONE;
607     }
608 jan 1611
609 bramz 2751
610    
611 bramz 2742 static PyObject* shapefile_info(ShapeFileObject* self)
612 bramz 2735 {
613     SHPHandle handle = self->handle;
614     return Py_BuildValue("ii(dddd)(dddd)",
615     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]);
618     }
619 jan 1611
620 bramz 2751
621    
622 bramz 2742 static PyObject* shapefile_read_object(ShapeFileObject* self, PyObject* args)
623 bramz 2735 {
624     int index;
625     SHPObject* object;
626 bramz 2742 SHPObjectObject* result;
627 bramz 2735
628 bramz 2744 if (!PyArg_ParseTuple(args, "i:read_object", &index)) return NULL;
629 bramz 2735
630     object = SHPReadObject(self->handle, index);
631     if (!object)
632 jan 1611 {
633 bramz 2735 PyErr_SetString(PyExc_RuntimeError, "failed to read object");
634 jan 1611 return NULL;
635     }
636 bramz 2735
637 bramz 2742 result = PyObject_New(SHPObjectObject, &SHPObjectType);
638 bramz 2735 if (!result)
639 jan 1611 {
640 bramz 2735 return PyErr_NoMemory();
641 jan 1611 }
642 bramz 2735
643     result->shpObject = object;
644     return (PyObject*) result;
645 jan 1611 }
646    
647 bramz 2751
648    
649 bramz 2742 static PyObject* shapefile_write_object(ShapeFileObject* self, PyObject* args)
650 bramz 2735 {
651     int index, result;
652     PyObject* object;
653    
654 bramz 2744 if (!PyArg_ParseTuple(args, "iO:write_object", &index, &object)) return NULL;
655 bramz 2735
656 bramz 2742 if (!PyObject_IsInstance(object, (PyObject*)&SHPObjectType))
657 bramz 2735 {
658     PyErr_SetString(PyExc_TypeError, "object is not a SHPObject");
659     return NULL;
660     }
661    
662 bramz 2742 result = SHPWriteObject(self->handle, index, ((SHPObjectObject*)object)->shpObject);
663 bramz 2735 if (result < 0)
664     {
665     PyErr_SetString(PyExc_RuntimeError, "failed to write object");
666     return NULL;
667     }
668     return PyInt_FromLong((long)result);
669 jan 1611 }
670    
671 bramz 2742 static PyObject* shapefile_cobject(ShapeFileObject* self)
672 bramz 2735 {
673     return PyCObject_FromVoidPtr(self->handle, NULL);
674 jan 1611 }
675    
676 bramz 2742 static PyObject* shapefile_repr(ShapeFileObject* self)
677 bramz 2741 {
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 bramz 2742 static struct PyMethodDef shapefile_methods[] =
683 bramz 2735 {
684 bramz 2744 {"close", (PyCFunction)shapefile_close, METH_NOARGS,
685 bramz 2745 "close() -> None\n\n"
686 bramz 2744 "close the shape file" },
687     {"info", (PyCFunction)shapefile_info, METH_NOARGS,
688 bramz 2745 "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 bramz 2744 {"read_object", (PyCFunction)shapefile_read_object, METH_VARARGS,
694 bramz 2745 "read_object(id) -> SHPObject\n\n"
695     "Returns shape indexed by id" },
696 bramz 2744 {"write_object", (PyCFunction)shapefile_write_object, METH_VARARGS,
697 bramz 2745 "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 bramz 2744 {"cobject", (PyCFunction)shapefile_cobject, METH_NOARGS,
701 bramz 2745 "cobject() -> CObject\n\n"
702 bramz 2744 "Return the shapelib SHPHandle as a Python CObject"},
703 bramz 2735 {NULL}
704     };
705 jan 1611
706 bramz 2742 static struct PyGetSetDef shapefile_getsetters[] =
707 bramz 2735 {
708     {NULL}
709     };
710 jan 1611
711 bramz 2742 static PyTypeObject ShapeFileType = PYSHAPELIB_DEFINE_TYPE(ShapeFileObject, shapefile, "shapelib.ShapeFile", 0);
712 jan 1611
713 bramz 2735 /* --- shapelib ------------------------------------------------------------------------------------------------------ */
714 jan 1611
715 bramz 2735 static PyObject* shapelib_open(PyObject* module, PyObject* args)
716     {
717 bramz 2742 return PyObject_CallObject((PyObject*)&ShapeFileType, args);
718 jan 1611 }
719    
720 bramz 2735 static PyObject* shapelib_create(PyObject* module, PyObject* args)
721 jan 1611 {
722 bramz 2735 char* file;
723     int type;
724 bramz 2742 ShapeFileObject* result;
725 bramz 2751 SHPHandle handle = NULL;
726     int wideargument = 0;
727    
728     #if defined(SHPAPI_HAS_WIDE) && defined(Py_WIN_WIDE_FILENAMES)
729     if (GetVersion() < 0x80000000) { /* On NT, so wide API available */
730     PyObject *wfile;
731     if (PyArg_ParseTuple(args, "Ui:create", &wfile, &type))
732     {
733     wideargument = 1;
734     handle = SHPCreateW(PyUnicode_AS_UNICODE(wfile), type);
735     if (!handle)
736     {
737     PyErr_SetFromErrnoWithFilenameObject(PyExc_IOError, wfile);
738     return NULL;
739     }
740     }
741     else
742     {
743     /* Drop the argument parsing error as narrow
744     strings are also valid. */
745     PyErr_Clear();
746     }
747     }
748     #endif
749 bramz 2735
750 bramz 2751 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 bramz 2742 result = PyObject_New(ShapeFileObject, &ShapeFileType);
764 bramz 2735 if (!result)
765     {
766 bramz 2751 SHPClose(handle);
767 bramz 2735 return PyErr_NoMemory();
768 jan 1611 }
769 bramz 2735
770 bramz 2751 result->handle = handle;
771 bramz 2735 return (PyObject*) result;
772     }
773    
774     static PyShapeLibAPI shapelib_the_api =
775     {
776 jan 1611 SHPReadObject,
777     SHPDestroyObject,
778     SHPCreateTree,
779     SHPDestroyTree,
780     SHPTreeFindLikelyShapes
781 bramz 2735 };
782 jan 1611
783 bramz 2735 static PyObject* shapelib_c_api(PyObject* module)
784     {
785     return PyCObject_FromVoidPtr(&shapelib_the_api, NULL);
786     }
787 jan 1611
788 bramz 2735 static PyObject* shapelib_type_name(PyObject* module, PyObject* args)
789     {
790     int type;
791 bramz 2744 if (!PyArg_ParseTuple(args, "i:type_name", &type)) return NULL;
792 bramz 2735 return PyString_FromString(SHPTypeName(type));
793     }
794 jan 1611
795 bramz 2735 static PyObject* shapelib_part_type_name(PyObject* module, PyObject* args)
796     {
797     int type;
798 bramz 2744 if (!PyArg_ParseTuple(args, "i:part_type_name", &type)) return NULL;
799 bramz 2735 return PyString_FromString(SHPPartTypeName(type));
800     }
801 jan 1611
802 bramz 2742 static struct PyMethodDef shapelib_methods[] =
803 bramz 2735 {
804 bramz 2744 {"open", (PyCFunction)shapelib_open, METH_VARARGS,
805 bramz 2745 "open(name [, mode='rb']) -> ShapeFile\n\n"
806     "opens a ShapeFile" },
807 bramz 2744 {"create", (PyCFunction)shapelib_create, METH_VARARGS,
808 bramz 2745 "create(name, type) -> ShapeFile\n\n"
809     "creates a ShapeFile of a certain type (one of SHPT_POINT, SHPT_POLYGON)" },
810 bramz 2744 {"c_api", (PyCFunction)shapelib_c_api, METH_NOARGS,
811 bramz 2745 "c_api() -> CObject\n\n"
812     "get C API of shapelib as a CObject" },
813 bramz 2744 {"type_name", (PyCFunction)shapelib_type_name, METH_VARARGS,
814 bramz 2745 "type_name(type) -> string\n\n"
815 bramz 2744 "return type as string" },
816     {"part_type_name", (PyCFunction)shapelib_part_type_name, METH_VARARGS,
817 bramz 2745 "part_type_name(part_type) -> string\n\n"
818 bramz 2744 "return part type as string" },
819 bramz 2735 {NULL}
820     };
821 jan 1611
822 bramz 2735 PyMODINIT_FUNC initshapelib(void)
823     {
824     PyObject* module = Py_InitModule("shapelib", shapelib_methods);
825     if (!module) return;
826    
827 bramz 2742 PYSHAPELIB_ADD_TYPE(SHPObjectType, "SHPObject");
828     PYSHAPELIB_ADD_TYPE(ShapeFileType, "ShapeFile");
829 bramz 2735
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 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