shapelib 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +59 -0
- data/Rakefile +47 -0
- data/doc/Interface.html +558 -0
- data/doc/Interface.rd +498 -0
- data/doc/style.css +136 -0
- data/ext/shapelib_ext/depend +49 -0
- data/ext/shapelib_ext/extconf.rb +19 -0
- data/ext/shapelib_ext/main.c +102 -0
- data/ext/shapelib_ext/sfcode.h +284 -0
- data/ext/shapelib_ext/sflist.h +21 -0
- data/ext/shapelib_ext/shpplus.c +588 -0
- data/ext/shapelib_ext/shpplus.h +86 -0
- data/ext/shapelib_ext/spcode.h +704 -0
- data/ext/shapelib_ext/splist.h +71 -0
- data/ext/shapelib_ext/spwkt.h +219 -0
- data/ext/shapelib_ext/valconv.h +313 -0
- data/lib/shapelib.rb +2 -0
- data/lib/shapelib/shape.rb +14 -0
- data/lib/shapelib/version.rb +3 -0
- data/test/libtest.rb +80 -0
- data/test/zsample1.rb +168 -0
- data/test/ztest1.rb +253 -0
- metadata +103 -0
@@ -0,0 +1,21 @@
|
|
1
|
+
static method_table_entry sf_methods[] = {
|
2
|
+
{ "add_field", sf_add_field, -1 },
|
3
|
+
{ "close", sf_close, 0 },
|
4
|
+
{ "delete_shape", sf_delete_shape, 1 },
|
5
|
+
{ "each", sf_each, 0 },
|
6
|
+
{ "field_count", sf_field_count, 0 },
|
7
|
+
{ "field_index", sf_field_index, 1 },
|
8
|
+
{ "field_name", sf_field_name, 1 },
|
9
|
+
{ "field_type", sf_field_type, 1 },
|
10
|
+
{ "field_width", sf_field_width, 1 },
|
11
|
+
{ "field_decimals", sf_field_decimals, 1 },
|
12
|
+
{ "fields", sf_fields, 0 },
|
13
|
+
{ "minbound", sf_minbound, 0 },
|
14
|
+
{ "maxbound", sf_maxbound, 0 },
|
15
|
+
{ "read", sf_read, -1 },
|
16
|
+
{ "rewind", sf_rewind, 0 },
|
17
|
+
{ "shape_type", sf_shape_type, 0 },
|
18
|
+
{ "size", sf_size, 0 },
|
19
|
+
{ "write", sf_write, -1 },
|
20
|
+
{ NULL, NULL, 0 }
|
21
|
+
};
|
@@ -0,0 +1,588 @@
|
|
1
|
+
#include <stdlib.h>
|
2
|
+
#include <ctype.h>
|
3
|
+
#include <string.h>
|
4
|
+
#if defined(HAVE_SHAPEFIL_H)
|
5
|
+
#include <shapefil.h>
|
6
|
+
#endif
|
7
|
+
#if defined(HAVE_LIBSHP_SHAPEFIL_H)
|
8
|
+
#include <libshp/shapefil.h>
|
9
|
+
#endif
|
10
|
+
#include <ruby.h>
|
11
|
+
#include "shpplus.h"
|
12
|
+
|
13
|
+
#define HAS_DBFMARKRECORDDELETED 0
|
14
|
+
#define ATTR_TABLE_DEFAULT 16
|
15
|
+
|
16
|
+
/*
|
17
|
+
* === static functions ===
|
18
|
+
*/
|
19
|
+
|
20
|
+
static shape_t *shape_init(SHPObject *objp);
|
21
|
+
|
22
|
+
/*--- lower level routines ---*/
|
23
|
+
|
24
|
+
static int FieldNameEquiv(const char *a, const char *b)
|
25
|
+
{
|
26
|
+
int i;
|
27
|
+
monitor_someday(("FNE <%s> <%s>", a, b));
|
28
|
+
for (i = 0; i < 11; i++) {
|
29
|
+
int ca, cb;
|
30
|
+
if (a[i] == '\0' && b[i] == '\0') {
|
31
|
+
return 1;
|
32
|
+
} else if (a[i] == '\0' || b[i] == '\0') {
|
33
|
+
return 0;
|
34
|
+
}
|
35
|
+
ca = (isalpha(a[i]) ? toupper(a[i]) : (a[i]));
|
36
|
+
cb = (isalpha(b[i]) ? toupper(b[i]) : (b[i]));
|
37
|
+
if (ca != cb) {
|
38
|
+
return 0;
|
39
|
+
}
|
40
|
+
}
|
41
|
+
return 1;
|
42
|
+
}
|
43
|
+
|
44
|
+
static void AttribClear(attrib_t *pa)
|
45
|
+
{
|
46
|
+
pa->type = -1;
|
47
|
+
pa->val.fval = 0.0;
|
48
|
+
memset(pa->name, '\0', DBF_NAMELEN);
|
49
|
+
}
|
50
|
+
|
51
|
+
/*--- related to struct shape_t ---*/
|
52
|
+
|
53
|
+
static int ShapeSetAttrTable(shape_t *sh, int newsize)
|
54
|
+
{
|
55
|
+
int oldsize;
|
56
|
+
int i;
|
57
|
+
if (newsize == 0) {
|
58
|
+
if (sh->nattr != 0)
|
59
|
+
rb_bug("trying to emptify attr table with %d entries", sh->nattr);
|
60
|
+
return -1;
|
61
|
+
}
|
62
|
+
if (sh->attr == NULL) {
|
63
|
+
sh->attr = xmalloc(sizeof(attrib_t) * newsize);
|
64
|
+
} else {
|
65
|
+
sh->attr = xrealloc(sh->attr, sizeof(attrib_t) * newsize);
|
66
|
+
}
|
67
|
+
oldsize = sh->nattr;
|
68
|
+
sh->nattr = newsize;
|
69
|
+
for (i = oldsize; i < newsize; i++) {
|
70
|
+
AttribClear(&(sh->attr[i]));
|
71
|
+
}
|
72
|
+
return 0;
|
73
|
+
}
|
74
|
+
|
75
|
+
/*--- related to struct shapefile_t ---*/
|
76
|
+
|
77
|
+
static shapefile_t *ShapefileInit(void)
|
78
|
+
{
|
79
|
+
shapefile_t *sfile;
|
80
|
+
sfile = xmalloc(sizeof(shapefile_t));
|
81
|
+
if (sfile == NULL)
|
82
|
+
return NULL;
|
83
|
+
sfile->nrecs = sfile->nfields = -1;
|
84
|
+
sfile->ftab = NULL;
|
85
|
+
sfile->irec = 0;
|
86
|
+
return sfile;
|
87
|
+
}
|
88
|
+
|
89
|
+
static void ShapefileBuildFieldTable(shapefile_t *sfile)
|
90
|
+
{
|
91
|
+
int i;
|
92
|
+
if (sfile->ftab)
|
93
|
+
return;
|
94
|
+
sfile->nfields = shapefile_field_count(sfile);
|
95
|
+
sfile->ftab = xmalloc(sizeof(field_t) * sfile->nfields);
|
96
|
+
if (sfile->ftab == NULL)
|
97
|
+
return;
|
98
|
+
for (i = 0; i < sfile->nfields; i++) {
|
99
|
+
memset(sfile->ftab[i].name, '\0', DBF_NAMELEN);
|
100
|
+
}
|
101
|
+
for (i = 0; i < sfile->nfields; i++) {
|
102
|
+
field_t *f;
|
103
|
+
f = &(sfile->ftab[i]);
|
104
|
+
f->type = DBFGetFieldInfo(sfile->hdbf, i, f->name, NULL, NULL);
|
105
|
+
monitor(("DBFGetFieldInfo(%p, %d) => %d, \"%s\"", sfile->hdbf, i,
|
106
|
+
(int)f->type, f->name));
|
107
|
+
}
|
108
|
+
}
|
109
|
+
|
110
|
+
static void ShapefileWriteAttribute(shapefile_t *sfile,
|
111
|
+
int irec, int ifield, attrib_t *a)
|
112
|
+
{
|
113
|
+
int s;
|
114
|
+
if (a->type == -1) {
|
115
|
+
rb_bug("supposed to be rejected in shapefile_write");
|
116
|
+
} else if (a->type == FTInteger) {
|
117
|
+
s = DBFWriteIntegerAttribute(sfile->hdbf, irec, ifield,
|
118
|
+
a->val.ival);
|
119
|
+
monitor(("DBFWriteIntegerAttribute(%p %d %d %d) -> %d",
|
120
|
+
sfile->hdbf, irec, ifield, a->val.ival, s));
|
121
|
+
} else if (a->type == FTDouble) {
|
122
|
+
s = DBFWriteDoubleAttribute(sfile->hdbf, irec, ifield,
|
123
|
+
a->val.fval);
|
124
|
+
monitor(("DBFWriteDoubleAttribute(%p %d %d %g) -> %d",
|
125
|
+
sfile->hdbf, irec, ifield, a->val.fval, s));
|
126
|
+
} else {
|
127
|
+
s = DBFWriteStringAttribute(sfile->hdbf, irec, ifield,
|
128
|
+
a->val.sval);
|
129
|
+
monitor(("DBFWriteStringAttribute(%p %d %d %s) -> %d",
|
130
|
+
sfile->hdbf, irec, ifield, a->val.sval, s));
|
131
|
+
}
|
132
|
+
if (s == 0) {
|
133
|
+
rb_raise(rb_eRuntimeError, "write error or overflow");
|
134
|
+
}
|
135
|
+
}
|
136
|
+
|
137
|
+
/*
|
138
|
+
* === methods of class ShapeFile ===
|
139
|
+
*/
|
140
|
+
|
141
|
+
shapefile_t *shapefile_open(const char *filename, const char *mode)
|
142
|
+
{
|
143
|
+
shapefile_t *sfile;
|
144
|
+
sfile = ShapefileInit();
|
145
|
+
sfile->hshp = SHPOpen(filename, mode);
|
146
|
+
monitor(("SHPOpen(\"%s\", \"%s\") -> %p", filename, mode, sfile->hshp));
|
147
|
+
sfile->hdbf = DBFOpen(filename, mode);
|
148
|
+
monitor(("DBFOpen(\"%s\", \"%s\") -> %p", filename, mode, sfile->hdbf));
|
149
|
+
ShapefileBuildFieldTable(sfile);
|
150
|
+
return sfile;
|
151
|
+
}
|
152
|
+
|
153
|
+
shapefile_t *shapefile_new(const char *filename, int shptype)
|
154
|
+
{
|
155
|
+
shapefile_t *sfile;
|
156
|
+
sfile = ShapefileInit();
|
157
|
+
sfile->hshp = SHPCreate(filename, shptype);
|
158
|
+
monitor(("SHPCreate(\"%s\", %d) -> %p", filename, shptype, sfile->hshp));
|
159
|
+
sfile->hdbf = DBFCreate(filename);
|
160
|
+
monitor(("DBFCreate(\"%s\") -> %p", filename, sfile->hdbf));
|
161
|
+
return sfile;
|
162
|
+
}
|
163
|
+
|
164
|
+
int shapefile_add_field(shapefile_t *sfile, const char *name,
|
165
|
+
int atype, int width, int decimals)
|
166
|
+
{
|
167
|
+
int r;
|
168
|
+
if (sfile->hdbf == NULL) {
|
169
|
+
rb_raise(rb_eRuntimeError, "dbf closed");
|
170
|
+
return -1;
|
171
|
+
}
|
172
|
+
if (sfile->ftab) {
|
173
|
+
rb_raise(rb_eRuntimeError, "add field before you write a record");
|
174
|
+
return -1;
|
175
|
+
}
|
176
|
+
monitor(("DBFAddField(%p, %s, %d, %d, %d)", sfile->hdbf, name,
|
177
|
+
atype, width, decimals));
|
178
|
+
r = DBFAddField(sfile->hdbf, name, (DBFFieldType)atype, width, decimals);
|
179
|
+
if (r == -1) {
|
180
|
+
rb_raise(rb_eRuntimeError, "DBFAddField fail");
|
181
|
+
}
|
182
|
+
return r;
|
183
|
+
}
|
184
|
+
|
185
|
+
int shapefile_close(shapefile_t *sfile)
|
186
|
+
{
|
187
|
+
if (sfile->hshp) {
|
188
|
+
monitor(("SHPClose(%p)", sfile->hshp));
|
189
|
+
SHPClose(sfile->hshp);
|
190
|
+
sfile->hshp = NULL;
|
191
|
+
}
|
192
|
+
if (sfile->hdbf) {
|
193
|
+
monitor(("DBFClose(%p)", sfile->hdbf));
|
194
|
+
DBFClose(sfile->hdbf);
|
195
|
+
sfile->hdbf = NULL;
|
196
|
+
}
|
197
|
+
if (sfile->ftab) {
|
198
|
+
xfree(sfile->ftab);
|
199
|
+
sfile->ftab = NULL;
|
200
|
+
}
|
201
|
+
return 0;
|
202
|
+
}
|
203
|
+
|
204
|
+
int shapefile_field_decimals(shapefile_t *sfile, unsigned ifield)
|
205
|
+
{
|
206
|
+
int decimals;
|
207
|
+
if (NULL == sfile->hdbf)
|
208
|
+
return -1;
|
209
|
+
DBFGetFieldInfo(sfile->hdbf, ifield, NULL, NULL, &decimals);
|
210
|
+
return decimals;
|
211
|
+
}
|
212
|
+
|
213
|
+
int shapefile_delete_shape(shapefile_t *sfile, int ishape)
|
214
|
+
{
|
215
|
+
#if HAS_DBFMARKRECORDDELETED
|
216
|
+
int r;
|
217
|
+
if (ishape < 0) {
|
218
|
+
rb_raise(rb_eArgError, "shape number %d must be nonnegative", ishape);
|
219
|
+
}
|
220
|
+
if (sfile->hshp) {
|
221
|
+
SHPObject *shape;
|
222
|
+
double d;
|
223
|
+
shape = SHPCreateSimpleObject(SHPT_NULL, 0, &d, &d, &d);
|
224
|
+
if (shape == NULL) {
|
225
|
+
rb_raise(rb_eRuntimeError,
|
226
|
+
"SHPCreateSimpleObject(SHPT_NULL, ...)");
|
227
|
+
}
|
228
|
+
r = SHPWriteObject(sfile->hshp, ishape, shape);
|
229
|
+
if (r != ishape) {
|
230
|
+
rb_raise(rb_eRuntimeError,
|
231
|
+
"SHPWriteObject(NullObj, %d) -> %d", ishape, r);
|
232
|
+
}
|
233
|
+
SHPDestroyObject(shape);
|
234
|
+
}
|
235
|
+
if (sfile->hdbf) {
|
236
|
+
r = DBFMarkRecordDeleted(sfile->hdbf, ishape, 1);
|
237
|
+
if (r) {
|
238
|
+
rb_raise(rb_eRuntimeError,
|
239
|
+
"DBFMarkRecordDeleted %d -> %d", ishape, r);
|
240
|
+
}
|
241
|
+
}
|
242
|
+
#else
|
243
|
+
rb_raise(rb_eRuntimeError, "DBFMarkRecordDeleted is disabled");
|
244
|
+
#endif
|
245
|
+
return 0;
|
246
|
+
}
|
247
|
+
|
248
|
+
int shapefile_field_index(shapefile_t *sfile, const char *name)
|
249
|
+
{
|
250
|
+
if (NULL == sfile->hdbf)
|
251
|
+
return -1;
|
252
|
+
return DBFGetFieldIndex(sfile->hdbf, name);
|
253
|
+
}
|
254
|
+
|
255
|
+
/* WARNING: result of this function is not valid after next call.
|
256
|
+
*/
|
257
|
+
const char *shapefile_field_name(shapefile_t *sfile, unsigned ifield)
|
258
|
+
{
|
259
|
+
static char buf[DBF_NAMELEN];
|
260
|
+
if (NULL == sfile->hdbf)
|
261
|
+
return NULL;
|
262
|
+
DBFGetFieldInfo(sfile->hdbf, ifield, buf, NULL, NULL);
|
263
|
+
return buf;
|
264
|
+
}
|
265
|
+
|
266
|
+
DBFFieldType shapefile_field_type(shapefile_t *sfile, unsigned ifield)
|
267
|
+
{
|
268
|
+
if (NULL == sfile->hdbf) {
|
269
|
+
return -1;
|
270
|
+
}
|
271
|
+
if (sfile->ftab) {
|
272
|
+
if (ifield >= sfile->nfields) {
|
273
|
+
return -1;
|
274
|
+
}
|
275
|
+
return sfile->ftab[ifield].type;
|
276
|
+
}
|
277
|
+
return DBFGetFieldInfo(sfile->hdbf, ifield, NULL, NULL, NULL);
|
278
|
+
}
|
279
|
+
|
280
|
+
int shapefile_field_width(shapefile_t *sfile, unsigned ifield)
|
281
|
+
{
|
282
|
+
int width;
|
283
|
+
if (NULL == sfile->hdbf)
|
284
|
+
return -1;
|
285
|
+
DBFGetFieldInfo(sfile->hdbf, ifield, NULL, &width, NULL);
|
286
|
+
return width;
|
287
|
+
}
|
288
|
+
|
289
|
+
int shapefile_field_count(shapefile_t *sfile)
|
290
|
+
{
|
291
|
+
int r;
|
292
|
+
if (NULL == sfile->hdbf) {
|
293
|
+
return -1;
|
294
|
+
}
|
295
|
+
if (sfile->ftab) {
|
296
|
+
return sfile->nfields;
|
297
|
+
}
|
298
|
+
/*
|
299
|
+
* Field table is not built here
|
300
|
+
* because it would prohibit field_add() afterwards.
|
301
|
+
*/
|
302
|
+
r = DBFGetFieldCount(sfile->hdbf);
|
303
|
+
monitor(("DBFGetFieldCount(%p) -> %d", sfile->hdbf, r));
|
304
|
+
return r;
|
305
|
+
}
|
306
|
+
|
307
|
+
void shapefile_bound(shapefile_t *sfile, double *minbound, double *maxbound)
|
308
|
+
{
|
309
|
+
if (NULL == sfile->hshp) {
|
310
|
+
int i;
|
311
|
+
/*
|
312
|
+
* is that right? I guess NaN should be filled - if there is
|
313
|
+
* a portable and safe way to generate it.
|
314
|
+
*/
|
315
|
+
if (minbound) { for (i = 0; i < 4; i++) minbound[i] = 0.0; }
|
316
|
+
if (maxbound) { for (i = 0; i < 4; i++) maxbound[i] = 0.0; }
|
317
|
+
return;
|
318
|
+
}
|
319
|
+
SHPGetInfo(sfile->hshp, NULL, NULL, minbound, maxbound);
|
320
|
+
}
|
321
|
+
|
322
|
+
shape_t *shapefile_read(shapefile_t *sfile, int ishape)
|
323
|
+
{
|
324
|
+
shape_t *shape;
|
325
|
+
int i, iattr;
|
326
|
+
if (NULL == sfile->hshp)
|
327
|
+
return NULL;
|
328
|
+
if (ishape < 0) {
|
329
|
+
if (sfile->nrecs < 0) {
|
330
|
+
shapefile_size(sfile);
|
331
|
+
sfile->irec = 0;
|
332
|
+
}
|
333
|
+
ishape = (sfile->irec)++;
|
334
|
+
} else {
|
335
|
+
sfile->irec = ishape + 1;
|
336
|
+
}
|
337
|
+
shape = shape_init(SHPReadObject(sfile->hshp, ishape));
|
338
|
+
if (shape == NULL)
|
339
|
+
return NULL;
|
340
|
+
monitor(("SHPReadObject(%p) -> %p", sfile->hshp, shape));
|
341
|
+
if (shape->obj->nSHPType == SHPT_NULL) {
|
342
|
+
monitor(("shape type NULL"));
|
343
|
+
return NULL;
|
344
|
+
}
|
345
|
+
ShapefileBuildFieldTable(sfile);
|
346
|
+
if (NULL == sfile->hdbf)
|
347
|
+
goto no_dbf;
|
348
|
+
#if HAS_DBFMARKRECORDDELETED
|
349
|
+
if (DBFIsRecordDeleted(sfile->hdbf, ishape)) {
|
350
|
+
monitor(("DBF record %d deleted", ishape))
|
351
|
+
goto no_dbf;
|
352
|
+
}
|
353
|
+
#endif
|
354
|
+
ShapeSetAttrTable(shape, sfile->nfields);
|
355
|
+
for (i = iattr = 0; i < sfile->nfields; i++) {
|
356
|
+
attrib_t *a;
|
357
|
+
field_t *f;
|
358
|
+
if (DBFIsAttributeNULL(sfile->hdbf, ishape, i)) {
|
359
|
+
goto next_field;
|
360
|
+
}
|
361
|
+
a = &(shape->attr[iattr]);
|
362
|
+
f = &(sfile->ftab[i]);
|
363
|
+
monitor(("attrib %s type %d", f->name, f->type));
|
364
|
+
if (f->type == FTInteger) {
|
365
|
+
a->val.ival = DBFReadIntegerAttribute(sfile->hdbf, ishape, i);
|
366
|
+
} else if (f->type == FTDouble) {
|
367
|
+
a->val.fval = DBFReadDoubleAttribute(sfile->hdbf, ishape, i);
|
368
|
+
#if 0
|
369
|
+
} else if (f->type == FTLogical) {
|
370
|
+
a->val.ival = DBFReadLogicalAttribute(sfile->hdbf, ishape, i);
|
371
|
+
#endif
|
372
|
+
} else {
|
373
|
+
a->val.sval = StringDup(
|
374
|
+
DBFReadStringAttribute(sfile->hdbf, ishape, i)
|
375
|
+
);
|
376
|
+
}
|
377
|
+
a->type = f->type;
|
378
|
+
memcpy(a->name, f->name, DBF_NAMELEN);
|
379
|
+
iattr++;
|
380
|
+
next_field:
|
381
|
+
;
|
382
|
+
}
|
383
|
+
no_dbf:
|
384
|
+
return shape;
|
385
|
+
}
|
386
|
+
|
387
|
+
int shapefile_shape_type(shapefile_t *sfile)
|
388
|
+
{
|
389
|
+
int r;
|
390
|
+
if (NULL == sfile->hshp)
|
391
|
+
return -1;
|
392
|
+
SHPGetInfo(sfile->hshp, NULL, &r, NULL, NULL);
|
393
|
+
return r;
|
394
|
+
}
|
395
|
+
|
396
|
+
int shapefile_size(shapefile_t *sfile)
|
397
|
+
{
|
398
|
+
int sd, ss;
|
399
|
+
if (NULL == sfile->hshp) {
|
400
|
+
return -1;
|
401
|
+
}
|
402
|
+
SHPGetInfo(sfile->hshp, &ss, NULL, NULL, NULL);
|
403
|
+
monitor(("SHPGetInfo(%p) -> %d", sfile->hshp, ss));
|
404
|
+
if (sfile->hdbf) {
|
405
|
+
sd = DBFGetRecordCount(sfile->hdbf);
|
406
|
+
monitor(("DBFGetRecordCount(%p) -> %d", sfile->hdbf, sd));
|
407
|
+
if (sd != ss) {
|
408
|
+
if (DBFGetFieldCount(sfile->hdbf) > 0) {
|
409
|
+
rb_warn("ShapeFile/DBF size mismatch %d %d", ss, sd);
|
410
|
+
}
|
411
|
+
}
|
412
|
+
}
|
413
|
+
sfile->nrecs = ss;
|
414
|
+
return ss;
|
415
|
+
}
|
416
|
+
|
417
|
+
int shapefile_write(shapefile_t *sfile, int irec, shape_t *shape)
|
418
|
+
{
|
419
|
+
int r;
|
420
|
+
int ifield;
|
421
|
+
int iattr;
|
422
|
+
int *usedfield;
|
423
|
+
/* precondition */
|
424
|
+
if (!sfile->hshp || !shape->obj)
|
425
|
+
return -1;
|
426
|
+
ShapefileBuildFieldTable(sfile);
|
427
|
+
/* write the object */
|
428
|
+
r = SHPWriteObject(sfile->hshp, irec, shape->obj);
|
429
|
+
monitor(("SHPWriteObject(%p, %d, %p) -> %d", sfile->hshp, irec,
|
430
|
+
shape->obj, r));
|
431
|
+
if (r < 0)
|
432
|
+
return -1;
|
433
|
+
/* make field table */
|
434
|
+
usedfield = xmalloc(sizeof(int) * sfile->nfields);
|
435
|
+
for (ifield = 0; ifield < sfile->nfields; ifield++) {
|
436
|
+
usedfield[ifield] = 0;
|
437
|
+
}
|
438
|
+
for (iattr = 0; iattr < shape->nattr; iattr++) {
|
439
|
+
attrib_t *a;
|
440
|
+
a = &(shape->attr[iattr]);
|
441
|
+
if (a->type == -1) {
|
442
|
+
continue;
|
443
|
+
}
|
444
|
+
ifield = DBFGetFieldIndex(sfile->hdbf, a->name);
|
445
|
+
if (ifield == -1) {
|
446
|
+
rb_raise(rb_eArgError,
|
447
|
+
"attribute %s not defined in ShapeFile", a->name);
|
448
|
+
}
|
449
|
+
ShapefileWriteAttribute(sfile, r, ifield, a);
|
450
|
+
usedfield[ifield] = 1;
|
451
|
+
}
|
452
|
+
for (ifield = 0; ifield < sfile->nfields; ifield++) {
|
453
|
+
int r2;
|
454
|
+
if (usedfield[ifield] == 0) {
|
455
|
+
r2 = DBFWriteNULLAttribute(sfile->hdbf, r, ifield);
|
456
|
+
monitor(("DBFWriteNULLAttribute(%p %d %d -> %d",
|
457
|
+
sfile->hdbf, r, ifield, r2));
|
458
|
+
if (r2 == 0)
|
459
|
+
rb_raise(rb_eRuntimeError, "write error");
|
460
|
+
}
|
461
|
+
}
|
462
|
+
free(usedfield);
|
463
|
+
return r;
|
464
|
+
}
|
465
|
+
|
466
|
+
static shape_t *shape_init(SHPObject *objp)
|
467
|
+
{
|
468
|
+
shape_t *sh;
|
469
|
+
if (objp == NULL)
|
470
|
+
return NULL;
|
471
|
+
sh = xmalloc(sizeof(shape_t));
|
472
|
+
if (sh == NULL) {
|
473
|
+
SHPDestroyObject(objp);
|
474
|
+
return NULL;
|
475
|
+
}
|
476
|
+
sh->obj = objp;
|
477
|
+
sh->attr = NULL;
|
478
|
+
sh->nattr = 0;
|
479
|
+
return sh;
|
480
|
+
}
|
481
|
+
|
482
|
+
shape_t *shape_new(int shape_type, int shape_id,
|
483
|
+
int n_parts, int *part_type, int *part_start, int n_vertices,
|
484
|
+
double *xvals, double *yvals, double *zvals, double *mvals)
|
485
|
+
{
|
486
|
+
SHPObject *objp;
|
487
|
+
shape_t *sh;
|
488
|
+
objp = SHPCreateObject(shape_type, shape_id,
|
489
|
+
n_parts, part_start, part_type, n_vertices,
|
490
|
+
xvals, yvals, zvals, mvals);
|
491
|
+
monitor(("SHPCreateObject(%d, %d, ...) -> %p",
|
492
|
+
shape_type, shape_id, objp));
|
493
|
+
sh = shape_init(objp);
|
494
|
+
return sh;
|
495
|
+
}
|
496
|
+
|
497
|
+
shape_t *shape_new_point(int shapetype, double x, double y, double m, double z)
|
498
|
+
{
|
499
|
+
shape_t *sh;
|
500
|
+
if (m == 0.0) {
|
501
|
+
sh = shape_init(SHPCreateSimpleObject(shapetype, 1, &x, &y, &z));
|
502
|
+
monitor(("SHPCreateSimpleObject(%d, 1 %g, %g, %g) -> %p",
|
503
|
+
shapetype, x, y, z, sh));
|
504
|
+
} else {
|
505
|
+
sh = shape_init(SHPCreateObject(shapetype,
|
506
|
+
-1, /* iShape: dummy because shapefile_write determines it */
|
507
|
+
0, /* nParts: 0 indicates panPartStart is not given */
|
508
|
+
NULL, /* panPartStart: list of part start address */
|
509
|
+
NULL, /* panPartType: list of MultiPatch part type */
|
510
|
+
1, /* nVertices */
|
511
|
+
&x, &y, &z, &m));
|
512
|
+
monitor(("SHPCreateObject(%d, ..., 1 %g, %g, %g, %g) -> %p",
|
513
|
+
shapetype, x, y, m, z, sh));
|
514
|
+
}
|
515
|
+
return sh;
|
516
|
+
}
|
517
|
+
|
518
|
+
shape_t *shape_new_obj(int shapetype,
|
519
|
+
int n_parts, int *part_start, int *part_type, int n_vert,
|
520
|
+
double *x, double *y, double *m, double *z)
|
521
|
+
{
|
522
|
+
shape_t *sh;
|
523
|
+
sh = shape_init(SHPCreateObject(shapetype,
|
524
|
+
-1, /* iShape: dummy because shapefile_write determines it */
|
525
|
+
n_parts, part_start, part_type, n_vert, x, y, z, m));
|
526
|
+
monitor(("SHPCreateObject(%d, -1, %d, ... %d, [%g, %g, %g, %g], ...) -> %p",
|
527
|
+
shapetype, n_parts, n_vert, x, y, m, z, sh));
|
528
|
+
return sh;
|
529
|
+
}
|
530
|
+
|
531
|
+
int shape_attrib_index(shape_t *sh, const char *key, int extend)
|
532
|
+
{
|
533
|
+
int i;
|
534
|
+
monitor(("shape_attrib_index(%p, %s)", sh, key));
|
535
|
+
if (sh->attr == NULL || sh->nattr == 0) {
|
536
|
+
if (!extend) {
|
537
|
+
return -1;
|
538
|
+
}
|
539
|
+
ShapeSetAttrTable(sh, ATTR_TABLE_DEFAULT);
|
540
|
+
}
|
541
|
+
for (i = 0; i < sh->nattr; i++) {
|
542
|
+
if (FieldNameEquiv(sh->attr[i].name, key)) {
|
543
|
+
return i;
|
544
|
+
}
|
545
|
+
}
|
546
|
+
for (i = 0; i < sh->nattr; i++) {
|
547
|
+
if (sh->attr[i].type == -1) {
|
548
|
+
strcpy(sh->attr[i].name, key);
|
549
|
+
return i;
|
550
|
+
}
|
551
|
+
}
|
552
|
+
if (extend) {
|
553
|
+
i = sh->nattr;
|
554
|
+
ShapeSetAttrTable(sh, sh->nattr * 2);
|
555
|
+
strcpy(sh->attr[i].name, key);
|
556
|
+
return i;
|
557
|
+
} else {
|
558
|
+
return -1;
|
559
|
+
}
|
560
|
+
}
|
561
|
+
|
562
|
+
int shape_close(shape_t *shape)
|
563
|
+
{
|
564
|
+
if (shape->obj) {
|
565
|
+
monitor(("SHPDestroyObject(%p)", shape->obj));
|
566
|
+
SHPDestroyObject(shape->obj);
|
567
|
+
shape->obj = NULL;
|
568
|
+
}
|
569
|
+
if (shape->attr) {
|
570
|
+
int i;
|
571
|
+
for (i = 0; i < shape->nattr; i++) {
|
572
|
+
switch (shape->attr[i].type) {
|
573
|
+
case FTInteger:
|
574
|
+
case FTDouble:
|
575
|
+
break;
|
576
|
+
case FTString:
|
577
|
+
default:
|
578
|
+
free(shape->attr[i].val.sval);
|
579
|
+
shape->attr[i].val.ival = 0;
|
580
|
+
break;
|
581
|
+
}
|
582
|
+
}
|
583
|
+
free(shape->attr);
|
584
|
+
shape->attr = NULL;
|
585
|
+
}
|
586
|
+
xfree(shape);
|
587
|
+
return 0;
|
588
|
+
}
|