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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2751 - (show annotations)
Wed Mar 28 23:30:15 2007 UTC (17 years, 11 months ago) by bramz
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 #include "pyshapelib_common.h"
2
3 /* --- SHPObject ----------------------------------------------------------------------------------------------------- */
4
5 typedef struct
6 {
7 PyObject_HEAD
8 SHPObject* shpObject;
9 }
10 SHPObjectObject;
11
12 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 /* 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 /* deallocator
62 */
63 static void shpobject_dealloc(SHPObjectObject* self)
64 {
65 SHPDestroyObject(self->shpObject);
66 self->shpObject = NULL;
67 self->ob_type->tp_free((PyObject*)self);
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 * 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 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 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 /*
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 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 }
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 static PyObject* shpobject_vertices(SHPObjectObject* self)
325 {
326 PyObject *result = NULL;
327 PyObject *part = NULL;
328 int part_idx, vertex_idx;
329 int length = 0;
330 int vertex_type;
331
332 SHPObject* object = self->shpObject;
333 vertex_type = determine_vertex_type(object->nSHPType, NULL, NULL);
334
335 if (object->nParts > 0)
336 {
337 /* A multipart shape. Usual for SHPT_ARC and SHPT_POLYGON */
338
339 result = PyList_New(object->nParts);
340 if (!result)
341 return NULL;
342
343 for (part_idx = 0, vertex_idx = 0; part_idx < object->nParts; part_idx++)
344 {
345 if (part_idx < object->nParts - 1)
346 length = (object->panPartStart[part_idx + 1]
347 - object->panPartStart[part_idx]);
348 else
349 length = object->nVertices - object->panPartStart[part_idx];
350
351 part = build_vertex_list(object, vertex_idx, length, vertex_type);
352 if (!part) goto fail;
353
354 if (PyList_SetItem(result, part_idx, part) < 0) goto fail;
355
356 vertex_idx += length;
357 }
358 }
359 else
360 {
361 /* only one part. usual for SHPT_POINT */
362 result = build_vertex_list(object, 0, object->nVertices, vertex_type);
363 }
364
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
375 * index as a Python-list of tuples. Helper function for
376 * SHPObject_vertices.
377 */
378 static PyObject* build_vertex_list(SHPObject *object, int index, int length, int vertex_type)
379 {
380 int i;
381 PyObject * list;
382 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 if (!vertex || PyList_SetItem(list, i, vertex) < 0) goto fail;
408 }
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;
444 }
445
446
447
448 static PyObject* shpobject_type(SHPObjectObject* self, void* closure)
449 {
450 return PyInt_FromLong(self->shpObject->nSHPType);
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
462 /* return a string that can be feeded to eval() to reconstruct the object,
463 * assuming a proper context
464 */
465 static PyObject* shpobject_repr(SHPObjectObject* self)
466 {
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 shpobject_vertices(self),
478 shpobject_part_types(self));
479 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 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 {
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 static PyTypeObject SHPObjectType = PYSHAPELIB_DEFINE_TYPE(SHPObjectObject, shpobject, "shapelib.SHPObject", 0);
517
518
519 /* --- ShapeFile ----------------------------------------------------------------------------------------------------- */
520
521 typedef struct
522 {
523 PyObject_HEAD
524 SHPHandle handle;
525 }
526 ShapeFileObject;
527
528 /* allocator
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 /* 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 /* 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 if (!self->handle)
582 {
583 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 }
596
597 return 0;
598 }
599
600
601
602 static PyObject* shapefile_close(ShapeFileObject* self)
603 {
604 SHPClose(self->handle);
605 self->handle = NULL;
606 Py_RETURN_NONE;
607 }
608
609
610
611 static PyObject* shapefile_info(ShapeFileObject* self)
612 {
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
620
621
622 static PyObject* shapefile_read_object(ShapeFileObject* self, PyObject* args)
623 {
624 int index;
625 SHPObject* object;
626 SHPObjectObject* result;
627
628 if (!PyArg_ParseTuple(args, "i:read_object", &index)) return NULL;
629
630 object = SHPReadObject(self->handle, index);
631 if (!object)
632 {
633 PyErr_SetString(PyExc_RuntimeError, "failed to read object");
634 return NULL;
635 }
636
637 result = PyObject_New(SHPObjectObject, &SHPObjectType);
638 if (!result)
639 {
640 return PyErr_NoMemory();
641 }
642
643 result->shpObject = object;
644 return (PyObject*) result;
645 }
646
647
648
649 static PyObject* shapefile_write_object(ShapeFileObject* self, PyObject* args)
650 {
651 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 result = SHPWriteObject(self->handle, index, ((SHPObjectObject*)object)->shpObject);
663 if (result < 0)
664 {
665 PyErr_SetString(PyExc_RuntimeError, "failed to write object");
666 return NULL;
667 }
668 return PyInt_FromLong((long)result);
669 }
670
671 static PyObject* shapefile_cobject(ShapeFileObject* self)
672 {
673 return PyCObject_FromVoidPtr(self->handle, NULL);
674 }
675
676 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 {
708 {NULL}
709 };
710
711 static PyTypeObject ShapeFileType = PYSHAPELIB_DEFINE_TYPE(ShapeFileObject, shapefile, "shapelib.ShapeFile", 0);
712
713 /* --- shapelib ------------------------------------------------------------------------------------------------------ */
714
715 static PyObject* shapelib_open(PyObject* module, PyObject* args)
716 {
717 return PyObject_CallObject((PyObject*)&ShapeFileType, args);
718 }
719
720 static PyObject* shapelib_create(PyObject* module, PyObject* args)
721 {
722 char* file;
723 int type;
724 ShapeFileObject* result;
725 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
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 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,
777 SHPDestroyObject,
778 SHPCreateTree,
779 SHPDestroyTree,
780 SHPTreeFindLikelyShapes
781 };
782
783 static PyObject* shapelib_c_api(PyObject* module)
784 {
785 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 {
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 {
804 {"open", (PyCFunction)shapelib_open, METH_VARARGS,
805 "open(name [, mode='rb']) -> ShapeFile\n\n"
806 "opens a ShapeFile" },
807 {"create", (PyCFunction)shapelib_create, METH_VARARGS,
808 "create(name, type) -> ShapeFile\n\n"
809 "creates a ShapeFile of a certain type (one of SHPT_POINT, SHPT_POLYGON)" },
810 {"c_api", (PyCFunction)shapelib_c_api, METH_NOARGS,
811 "c_api() -> CObject\n\n"
812 "get C API of shapelib as a CObject" },
813 {"type_name", (PyCFunction)shapelib_type_name, METH_VARARGS,
814 "type_name(type) -> string\n\n"
815 "return type as string" },
816 {"part_type_name", (PyCFunction)shapelib_part_type_name, METH_VARARGS,
817 "part_type_name(part_type) -> string\n\n"
818 "return part type as string" },
819 {NULL}
820 };
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

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26