9 |
} |
} |
10 |
SHPObjectObject; |
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 |
/* allocator |
52 |
*/ |
*/ |
53 |
static PyObject* shpobject_new(PyTypeObject* type, PyObject* args, PyObject* kwds) |
static PyObject* shpobject_new(PyTypeObject* type, PyObject* args, PyObject* kwds) |
86 |
|
|
87 |
double* xs = NULL; |
double* xs = NULL; |
88 |
double* ys = NULL; |
double* ys = NULL; |
89 |
|
double* zs = NULL; |
90 |
|
double* ms = NULL; |
91 |
int* part_starts = NULL; |
int* part_starts = NULL; |
92 |
int* part_types = NULL; |
int* part_types = NULL; |
93 |
|
|
94 |
|
PyObject* part; |
95 |
|
int vertex_type; |
96 |
|
int has_z; |
97 |
|
int has_m; |
98 |
|
|
99 |
int i; |
int i; |
100 |
int return_code = -1; |
int ok, return_code = -1; |
101 |
|
|
102 |
/* first, unpack parameters */ |
/* first, unpack parameters */ |
103 |
if (kwds != NULL && PyDict_Size(kwds) > 0) |
if (kwds != NULL && PyDict_Size(kwds) > 0) |
107 |
} |
} |
108 |
if (!PyArg_ParseTuple(args, "iiO|O", &type, &id, &parts, &part_type_list)) return -1; |
if (!PyArg_ParseTuple(args, "iiO|O", &type, &id, &parts, &part_type_list)) return -1; |
109 |
|
|
110 |
|
/* check parts */ |
111 |
if (!PySequence_Check(parts)) |
if (!PySequence_Check(parts)) |
112 |
{ |
{ |
113 |
PyErr_SetString(PyExc_TypeError, "parts is not a sequence"); |
PyErr_SetString(PyExc_TypeError, "parts is not a sequence"); |
154 |
num_vertices += PySequence_Length(part); |
num_vertices += PySequence_Length(part); |
155 |
Py_DECREF(part); |
Py_DECREF(part); |
156 |
} |
} |
157 |
|
|
158 |
|
|
159 |
|
vertex_type = determine_vertex_type(type, &has_z, &has_m); |
160 |
|
|
161 |
/* allocate the memory for the various arrays and check for memory errors */ |
/* allocate the memory for the various arrays and check for memory errors */ |
162 |
xs = malloc(num_vertices * sizeof(double)); |
xs = malloc(num_vertices * sizeof(double)); |
163 |
ys = malloc(num_vertices * sizeof(double)); |
ys = malloc(num_vertices * sizeof(double)); |
164 |
|
zs = has_z ? malloc(num_vertices * sizeof(double)) : NULL; |
165 |
|
ms = has_m ? malloc(num_vertices * sizeof(double)) : NULL; |
166 |
part_starts = malloc(num_parts * sizeof(int)); |
part_starts = malloc(num_parts * sizeof(int)); |
167 |
part_types = part_type_list ? malloc(num_parts * sizeof(int)) : 0; |
part_types = part_type_list ? malloc(num_parts * sizeof(int)) : 0; |
168 |
|
|
169 |
if (!xs || !ys || !part_starts || (part_type_list && !part_types)) |
if (!xs || !ys || (has_z && !zs) || (has_m && !ms) || !part_starts || (part_type_list && !part_types)) |
170 |
{ |
{ |
171 |
PyErr_NoMemory(); |
PyErr_NoMemory(); |
172 |
goto exit; |
goto exit; |
194 |
{ |
{ |
195 |
int j, length; |
int j, length; |
196 |
|
|
197 |
PyObject* part = PySequence_ITEM(parts, i); |
part = PySequence_ITEM(parts, i); |
198 |
length = PySequence_Length(part); |
length = PySequence_Length(part); |
199 |
|
if (length < 0) goto exit; |
200 |
part_starts[i] = part_start; |
part_starts[i] = part_start; |
201 |
|
|
202 |
for (j = 0; j < length; ++j) |
for (j = 0; j < length; ++j) |
203 |
{ |
{ |
204 |
PyObject* vertex = PySequence_ITEM(part, j); |
PyObject* vertex = PySequence_ITEM(part, j); |
205 |
if (!PyArg_ParseTuple(vertex, "dd", xs + part_start + j, ys + part_start + j)) |
switch (vertex_type) |
206 |
{ |
{ |
207 |
PyErr_SetString(PyExc_TypeError, "at least one part contains an vertex that's not a tuple of two doubles"); |
case vtXY: |
208 |
Py_DECREF(vertex); |
ok = PyArg_ParseTuple(vertex, "dd", xs + part_start + j, ys + part_start + j); |
209 |
Py_DECREF(part); |
break; |
210 |
goto exit; |
case vtXYM: |
211 |
|
ok = PyArg_ParseTuple(vertex, "ddd", xs + part_start + j, ys + part_start + j, ms + part_start + j); |
212 |
|
break; |
213 |
|
case vtXYZM: |
214 |
|
ms[part_start + j] = 0.; |
215 |
|
ok = PyArg_ParseTuple(vertex, "ddd|d", xs + part_start + j, ys + part_start + j, zs + part_start + j, |
216 |
|
ms + part_start + j); |
217 |
|
break; |
218 |
} |
} |
219 |
Py_DECREF(vertex); |
Py_DECREF(vertex); |
220 |
|
if (!ok) |
221 |
|
{ |
222 |
|
PyErr_SetString(PyExc_TypeError, "at least one vertex is of the wrong format"); |
223 |
|
goto exit; |
224 |
|
} |
225 |
} |
} |
226 |
Py_DECREF(part); |
Py_DECREF(part); |
227 |
|
part = NULL; |
228 |
part_start += length; |
part_start += length; |
229 |
} |
} |
230 |
|
|
231 |
self->shpObject = SHPCreateObject(type, id, num_parts, part_starts, part_types, num_vertices, xs, ys, NULL, NULL); |
self->shpObject = SHPCreateObject(type, id, num_parts, part_starts, part_types, num_vertices, xs, ys, zs, ms); |
232 |
return_code = 0; |
return_code = 0; |
233 |
|
|
234 |
exit: |
exit: |
235 |
|
Py_XDECREF(part); |
236 |
free(xs); |
free(xs); |
237 |
free(ys); |
free(ys); |
238 |
|
free(zs); |
239 |
|
free(ms); |
240 |
free(part_starts); |
free(part_starts); |
241 |
free(part_types); |
free(part_types); |
242 |
return return_code; |
return return_code; |
264 |
* tuples. |
* tuples. |
265 |
*/ |
*/ |
266 |
|
|
267 |
static PyObject* build_vertex_list(SHPObject *object, int index, int length); |
static PyObject* build_vertex_list(SHPObject *object, int index, int length, int vertex_type); |
268 |
|
|
269 |
static PyObject* shpobject_vertices(SHPObjectObject* self) |
static PyObject* shpobject_vertices(SHPObjectObject* self) |
270 |
{ |
{ |
272 |
PyObject *part = NULL; |
PyObject *part = NULL; |
273 |
int part_idx, vertex_idx; |
int part_idx, vertex_idx; |
274 |
int length = 0; |
int length = 0; |
275 |
|
int vertex_type; |
276 |
|
|
277 |
SHPObject* object = self->shpObject; |
SHPObject* object = self->shpObject; |
278 |
|
vertex_type = determine_vertex_type(object->nSHPType, NULL, NULL); |
279 |
|
|
280 |
if (object->nParts > 0) |
if (object->nParts > 0) |
281 |
{ |
{ |
288 |
for (part_idx = 0, vertex_idx = 0; part_idx < object->nParts; part_idx++) |
for (part_idx = 0, vertex_idx = 0; part_idx < object->nParts; part_idx++) |
289 |
{ |
{ |
290 |
if (part_idx < object->nParts - 1) |
if (part_idx < object->nParts - 1) |
291 |
length = (object->panPartStart[part_idx + 1] |
length = (object->panPartStart[part_idx + 1] |
292 |
- object->panPartStart[part_idx]); |
- object->panPartStart[part_idx]); |
293 |
else |
else |
294 |
length = object->nVertices - object->panPartStart[part_idx]; |
length = object->nVertices - object->panPartStart[part_idx]; |
295 |
|
|
296 |
part = build_vertex_list(object, vertex_idx, length); |
part = build_vertex_list(object, vertex_idx, length, vertex_type); |
297 |
if (!part) |
if (!part) goto fail; |
|
goto fail; |
|
298 |
|
|
299 |
if (PyList_SetItem(result, part_idx, part) < 0) |
if (PyList_SetItem(result, part_idx, part) < 0) goto fail; |
|
goto fail; |
|
300 |
|
|
301 |
vertex_idx += length; |
vertex_idx += length; |
302 |
} |
} |
304 |
else |
else |
305 |
{ |
{ |
306 |
/* only one part. usual for SHPT_POINT */ |
/* only one part. usual for SHPT_POINT */ |
307 |
result = build_vertex_list(object, 0, object->nVertices); |
result = build_vertex_list(object, 0, object->nVertices, vertex_type); |
308 |
} |
} |
309 |
|
|
310 |
return result; |
return result; |
320 |
* index as a Python-list of tuples. Helper function for |
* index as a Python-list of tuples. Helper function for |
321 |
* SHPObject_vertices. |
* SHPObject_vertices. |
322 |
*/ |
*/ |
323 |
static PyObject* build_vertex_list(SHPObject *object, int index, int length) |
static PyObject* build_vertex_list(SHPObject *object, int index, int length, int vertex_type) |
324 |
{ |
{ |
325 |
int i; |
int i; |
326 |
PyObject * list; |
PyObject * list; |
332 |
|
|
333 |
for (i = 0; i < length; i++, index++) |
for (i = 0; i < length; i++, index++) |
334 |
{ |
{ |
335 |
vertex = Py_BuildValue("dd", object->padfX[index], |
switch (vertex_type) |
336 |
object->padfY[index]); |
{ |
337 |
if (!vertex) |
case vtXY: |
338 |
goto fail; |
vertex = Py_BuildValue("dd", object->padfX[index], object->padfY[index]); |
339 |
if (PyList_SetItem(list, i, vertex) < 0) |
break; |
340 |
|
case vtXYM: |
341 |
|
vertex = Py_BuildValue("ddd", object->padfX[index], object->padfY[index], |
342 |
|
object->padfM[index]); |
343 |
|
case vtXYZM: |
344 |
|
vertex = Py_BuildValue("dddd", object->padfX[index], object->padfY[index], |
345 |
|
object->padfZ[index], object->padfM[index]); |
346 |
|
break; |
347 |
|
default: |
348 |
goto fail; |
goto fail; |
349 |
} |
} |
350 |
|
|
351 |
|
if (!vertex || PyList_SetItem(list, i, vertex) < 0) goto fail; |
352 |
|
} |
353 |
|
|
354 |
return list; |
return list; |
355 |
|
|
356 |
fail: |
fail: |
|
Py_XDECREF(vertex); |
|
357 |
Py_DECREF(list); |
Py_DECREF(list); |
358 |
return NULL; |
return NULL; |
359 |
} |
} |