shapelib 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,86 @@
1
+ /* requires <shapefil.h> */
2
+ #define MONITOR_DETAIL 0
3
+
4
+ #define DBF_NAMELEN 12
5
+
6
+ typedef struct field_t {
7
+ DBFFieldType type;
8
+ char name[DBF_NAMELEN];
9
+ } field_t;
10
+
11
+ typedef struct {
12
+ SHPHandle hshp;
13
+ DBFHandle hdbf;
14
+ int nfields;
15
+ field_t *ftab;
16
+ /* for iterator */
17
+ int nrecs;
18
+ int irec;
19
+ } shapefile_t;
20
+
21
+ typedef struct {
22
+ DBFFieldType type;
23
+ char name[DBF_NAMELEN];
24
+ union ifs_t {
25
+ int ival;
26
+ double fval;
27
+ char *sval;
28
+ } val;
29
+ } attrib_t;
30
+
31
+ typedef struct {
32
+ SHPObject *obj;
33
+ int nattr;
34
+ attrib_t *attr;
35
+ } shape_t;
36
+
37
+ extern shapefile_t *shapefile_new(const char *filename, int shptype);
38
+ extern shapefile_t *shapefile_open(const char *filename, const char *mode);
39
+ extern int shapefile_add_field(shapefile_t *sfile, const char *name,
40
+ int atype, int width, int decimals);
41
+ extern void shapefile_bound(shapefile_t *sfile, double *minbound,
42
+ double *maxbound);
43
+ extern int shapefile_close(shapefile_t *sfile);
44
+ extern int shapefile_field_count(shapefile_t *sfile);
45
+ extern int shapefile_field_decimals(shapefile_t *sfile, unsigned ifield);
46
+ extern int shapefile_delete_shape(shapefile_t *sfile, int ishape);
47
+ extern int shapefile_field_index(shapefile_t *sfile, const char *name);
48
+ extern const char *shapefile_field_name(shapefile_t *sfile, unsigned ifield);
49
+ extern DBFFieldType shapefile_field_type(shapefile_t *sfile, unsigned ifield);
50
+ extern int shapefile_field_width(shapefile_t *sfile, unsigned ifield);
51
+ extern shape_t *shapefile_read(shapefile_t *sfile, int ishape);
52
+ extern int shapefile_size(shapefile_t *sfile);
53
+ extern int shapefile_shape_type(shapefile_t *sfile);
54
+ extern int shapefile_write(shapefile_t *sfile, int irec, shape_t *shape);
55
+
56
+ extern shape_t *shape_new(int shape_type, int shape_id,
57
+ int n_parts, int *part_type, int *part_start, int n_vertices,
58
+ double *xvals, double *yvals, double *zvals, double *mvals);
59
+ extern shape_t *shape_new_point(int shapetype,
60
+ double x, double y, double m, double z);
61
+ extern shape_t *shape_new_obj(int shapetype,
62
+ int n_parts, int *part_start, int *part_type, int n_vert,
63
+ double *x, double *y, double *m, double *z);
64
+ extern int shape_close(shape_t *shape);
65
+ extern int shape_attrib_index(shape_t *sh, const char *key, int extend);
66
+
67
+ /*
68
+ * MACRO AND MACRO-LIKE STATIC FUNCTION
69
+ */
70
+
71
+ #if MONITOR_DETAIL
72
+ # define monitor(args) rb_warning args
73
+ #else
74
+ # define monitor(args)
75
+ #endif
76
+ #define monitor_someday(args)
77
+
78
+ static char *StringDup(const char *str)
79
+ {
80
+ char *r;
81
+ size_t n;
82
+ n = strlen(str) + 1;
83
+ r = xmalloc(n);
84
+ memcpy(r, str, n);
85
+ return r;
86
+ }
@@ -0,0 +1,704 @@
1
+ /*
2
+ * constructors
3
+ */
4
+ #define NUM2DBLo(val) (NIL_P((val)) ? 0.0 : NUM2DBL((val)))
5
+
6
+ static int *IntPack(VALUE array, int decode_p)
7
+ {
8
+ int *buf;
9
+ int i;
10
+ Check_Type(array, T_ARRAY);
11
+ buf = xmalloc(sizeof(int) * RARRAY_LEN(array));
12
+ for (i = 0; i < RARRAY_LEN(array); i++) {
13
+ if (decode_p)
14
+ buf[i] = Ruby2PartType(RARRAY_PTR(array)[i]);
15
+ else
16
+ buf[i] = NUM2INT(RARRAY_PTR(array)[i]);
17
+ }
18
+ return buf;
19
+ }
20
+
21
+ static double *DoublePack(VALUE array, double nilval)
22
+ {
23
+ double *buf;
24
+ int i;
25
+ if (NIL_P(array))
26
+ return NULL;
27
+ Check_Type(array, T_ARRAY);
28
+ buf = xmalloc(sizeof(double) * RARRAY_LEN(array));
29
+ for (i = 0; i < RARRAY_LEN(array); i++) {
30
+ VALUE v;
31
+ v = RARRAY_PTR(array)[i];
32
+ buf[i] = (NIL_P(v) ? nilval : NUM2DBL(RARRAY_PTR(array)[i]));
33
+ }
34
+ return buf;
35
+ }
36
+
37
+ static VALUE HashDeref(VALUE hash, const char *key)
38
+ {
39
+ if (T_HASH == TYPE(hash)) {
40
+ return rb_hash_aref(hash, CSTR2SYM(key));
41
+ } else {
42
+ static ID op = 0;
43
+ if (op == 0)
44
+ op = rb_intern("[]");
45
+ return rb_funcall(hash, op, CSTR2SYM(key));
46
+ }
47
+ }
48
+
49
+ static VALUE sp_field_set(VALUE obj, VALUE name, VALUE val);
50
+
51
+ static void HashLoadAttrib(VALUE vshape, VALUE hash)
52
+ {
53
+ VALUE ary, *argv;
54
+ ID to_a = rb_intern("to_a");
55
+ int i;
56
+ if (!rb_respond_to(hash, to_a))
57
+ return;
58
+ ary = rb_funcall(hash, to_a, 0);
59
+ if (T_ARRAY != TYPE(ary))
60
+ return;
61
+ argv = RARRAY_PTR(ary);
62
+ for (i = 0; i < RARRAY_LEN(ary); i++) {
63
+ VALUE pair = argv[i];
64
+ VALUE key, val;
65
+ if (T_ARRAY != TYPE(pair))
66
+ continue;
67
+ if (RARRAY_LEN(pair) < 2)
68
+ continue;
69
+ key = RARRAY_PTR(pair)[0];
70
+ val = RARRAY_PTR(pair)[1];
71
+ if (T_STRING != TYPE(key))
72
+ continue;
73
+ sp_field_set(vshape, key, val);
74
+ }
75
+ }
76
+
77
+
78
+ static VALUE sp_s_new(VALUE klass, VALUE hash)
79
+ {
80
+ shape_t *shape;
81
+ VALUE qlass, vshape;
82
+ int shape_type, shape_id, n_parts, n_vertices;
83
+ int *part_type, *part_start;
84
+ double *xvals, *yvals, *zvals, *mvals;
85
+ shape_type = Ruby2ShapeType(HashDeref(hash, "shape_type"));
86
+ qlass = ShapeType2Class(shape_type, klass);
87
+ shape_id = NUM2INT_nil(HashDeref(hash, "shape_id"));
88
+ n_parts = NUM2INT(HashDeref(hash, "n_parts"));
89
+ n_vertices = NUM2INT(HashDeref(hash, "n_vertices"));
90
+ part_type = IntPack(HashDeref(hash, "part_type"), 1);
91
+ part_start = IntPack(HashDeref(hash, "part_start"), 0);
92
+ xvals = DoublePack(HashDeref(hash, "xvals"), 0.0);
93
+ yvals = DoublePack(HashDeref(hash, "yvals"), 0.0);
94
+ zvals = DoublePack(HashDeref(hash, "zvals"), 0.0);
95
+ mvals = DoublePack(HashDeref(hash, "mvals"), SHP_NODATA);
96
+ if (zvals == NULL) rb_raise(rb_eRuntimeError, "missing zvals");
97
+ if (mvals == NULL) rb_raise(rb_eRuntimeError, "missing mvals");
98
+ shape = shape_new(shape_type, shape_id,
99
+ n_parts, part_type, part_start, n_vertices,
100
+ xvals, yvals, zvals, mvals);
101
+ if (shape == NULL) rb_raise(rb_eRuntimeError, "SHPCreateObject fails");
102
+ free(part_type);
103
+ free(part_start);
104
+ if (xvals) free(xvals);
105
+ if (yvals) free(yvals);
106
+ if (zvals) free(zvals);
107
+ if (mvals) free(mvals);
108
+ vshape = Data_Wrap_Struct(qlass, 0, shape_close, shape);
109
+ HashLoadAttrib(vshape, hash);
110
+ return vshape;
111
+ }
112
+
113
+ static int CheckPartSize(int argc, VALUE *argv, int *part_start,
114
+ int *part_type)
115
+ {
116
+ int pstart = 0;
117
+ int i;
118
+ for (i = 0; i < argc; i++) {
119
+ VALUE first;
120
+ int partlen;
121
+ if (T_ARRAY != TYPE(argv[i])) {
122
+ rb_raise(rb_eArgError, "arg %d must be Array", i);
123
+ return -1;
124
+ }
125
+ partlen = RARRAY_LEN(argv[i]);
126
+ first = RARRAY_PTR(argv[i])[0];
127
+ switch (TYPE(first)) {
128
+ case T_SYMBOL: case T_STRING:
129
+ part_type[i] = Ruby2PartType(first);
130
+ partlen--;
131
+ break;
132
+ default:
133
+ part_type[i] = SHPP_RING;
134
+ ;
135
+ }
136
+ part_start[i] = pstart;
137
+ pstart += partlen;
138
+ }
139
+ /* returns total number of vertices */
140
+ return pstart;
141
+ }
142
+
143
+ static void ExtractXYMZ(VALUE v,
144
+ double *x, double *y, double *m, double *z)
145
+ {
146
+ static int idx = 0, idy, idz, idm;
147
+ if (idx == 0) {
148
+ idx = rb_intern("x"); idy = rb_intern("y");
149
+ idm = rb_intern("m"); idz = rb_intern("z");
150
+ }
151
+ if (T_ARRAY == TYPE(v)) {
152
+ int argc = RARRAY_LEN(v);
153
+ VALUE *argv = RARRAY_PTR(v);
154
+ *x = (argc > 0) ? NUM2DBLo(argv[0]) : 0.0;
155
+ *y = (argc > 1) ? NUM2DBLo(argv[1]) : 0.0;
156
+ *m = SHP_NUM2DBL((argc > 2) ? argv[2] : Qnil);
157
+ *z = (argc > 3) ? NUM2DBL(argv[3]) : 0.0;
158
+ } else {
159
+ *x = NUM2DBLo(rb_funcall(v, idx, 0));
160
+ *y = NUM2DBLo(rb_funcall(v, idy, 0));
161
+ if (rb_respond_to(v, idm)) {
162
+ *m = SHP_NUM2DBL(rb_funcall(v, idm, 0));
163
+ } else {
164
+ *m = SHP_NODATA;
165
+ }
166
+ if (rb_respond_to(v, idz)) {
167
+ *z = NUM2DBLo(rb_funcall(v, idz, 0));
168
+ } else {
169
+ *z = 0.0;
170
+ }
171
+ }
172
+ }
173
+
174
+ static void CollectPoints(int argc, const VALUE *argv,
175
+ double *x, double *y, double *m, double *z)
176
+ {
177
+ int i, ofs;
178
+ ofs = 0;
179
+ if (argc > 0) {
180
+ switch (TYPE(argv[0])) {
181
+ case T_SYMBOL: case T_STRING:
182
+ ofs++;
183
+ }
184
+ }
185
+ for (i = 0; i < argc - ofs; i++) {
186
+ ExtractXYMZ(argv[i + ofs], x + i, y + i, m + i, z + i);
187
+ }
188
+ }
189
+
190
+ static shape_t *NewMultiPart(int argc, VALUE *argv, VALUE klass, int shapetype)
191
+ {
192
+ shape_t *shape;
193
+ double *dblock, *x, *y, *m, *z;
194
+ int *part_start, *part_type;
195
+ int n_parts, n_vert;
196
+ int ipart;
197
+
198
+ n_parts = argc;
199
+ part_start = xmalloc(sizeof(int) * n_parts);
200
+ part_type = xmalloc(sizeof(int) * n_parts);
201
+ n_vert = CheckPartSize(argc, argv, part_start, part_type);
202
+ dblock = xmalloc(sizeof(double) * n_vert * 4);
203
+ x = dblock;
204
+ y = dblock + n_vert;
205
+ m = dblock + n_vert * 2;
206
+ z = dblock + n_vert * 3;
207
+ for (ipart = 0; ipart < argc; ipart++) {
208
+ CollectPoints(
209
+ RARRAY_LEN(argv[ipart]), RARRAY_PTR(argv[ipart]),
210
+ x + part_start[ipart], y + part_start[ipart],
211
+ m + part_start[ipart], z + part_start[ipart]);
212
+ }
213
+ shape = shape_new_obj(shapetype,
214
+ n_parts, part_start, part_type, n_vert,
215
+ x, y, m, z);
216
+ free(dblock);
217
+ free(part_start);
218
+ free(part_type);
219
+ return shape;
220
+ }
221
+
222
+ static shape_t *NewSinglePart(int argc, VALUE *argv, VALUE klass, int shapetype)
223
+ {
224
+ shape_t *shape;
225
+ double *dblock, *x, *y, *m, *z;
226
+ int n_vert, part_type_buf;
227
+ int part_start_buf = 0;
228
+ n_vert = argc;
229
+ switch (TYPE(argv[0])) {
230
+ case T_STRING: case T_SYMBOL:
231
+ part_type_buf = Ruby2PartType(argv[0]);
232
+ n_vert--;
233
+ break;
234
+ default:
235
+ part_type_buf = SHPP_RING;
236
+ }
237
+ dblock = xmalloc(sizeof(double) * n_vert * 4);
238
+ x = dblock;
239
+ y = dblock + n_vert;
240
+ m = dblock + n_vert * 2;
241
+ z = dblock + n_vert * 3;
242
+ CollectPoints(argc, argv, x, y, m, z);
243
+ shape = shape_new_obj(shapetype,
244
+ 1, &part_start_buf, &part_type_buf, n_vert, x, y, m, z);
245
+ free(dblock);
246
+ return shape;
247
+ }
248
+
249
+ /*
250
+ * == Single Part
251
+ * new [1, 2], [3, 4], ...
252
+ * new point, point, ...
253
+ * new :PartType, point, point, ...
254
+ * == Multi Part
255
+ * new [[1, 2], [3, 4], ...], ...
256
+ * new [point, point, ...], ...
257
+ * new [:PartType, point, point, ...], ...
258
+ */
259
+
260
+ static VALUE NewShape(int argc, VALUE *argv, VALUE klass, int shapetype)
261
+ {
262
+ shape_t *shape;
263
+ int multipart;
264
+ monitor(("NewShape"));
265
+ if (T_ARRAY == TYPE(argv[0])) {
266
+ switch (TYPE( RARRAY_PTR(argv[0])[0] )) {
267
+ case T_FIXNUM:
268
+ case T_FLOAT:
269
+ multipart = 0;
270
+ break;
271
+ default:
272
+ multipart = 1;
273
+ break;
274
+ }
275
+ } else {
276
+ multipart = 0;
277
+ }
278
+ if (multipart) {
279
+ shape = NewMultiPart(argc, argv, klass, shapetype);
280
+ } else {
281
+ shape = NewSinglePart(argc, argv, klass, shapetype);
282
+ }
283
+ return Data_Wrap_Struct(klass, 0, shape_close, shape);
284
+ }
285
+
286
+ static VALUE MultiPointNew(int argc, VALUE *argv, VALUE klass, int shapetype)
287
+ {
288
+ shape_t *shape;
289
+ double *dblock, *x, *y, *m, *z;
290
+ int *part_start;
291
+ int n_vert;
292
+ int part_start_buf = 0;
293
+ part_start = &part_start_buf;
294
+ n_vert = argc;
295
+ dblock = malloc(sizeof(double) * n_vert * 4);
296
+ x = dblock;
297
+ y = dblock + n_vert;
298
+ m = dblock + n_vert * 2;
299
+ z = dblock + n_vert * 3;
300
+ CollectPoints(argc, argv, x, y, m, z);
301
+ shape = shape_new_obj(shapetype, 1, part_start, NULL, n_vert, x, y, m, z);
302
+ free(dblock);
303
+ return Data_Wrap_Struct(klass, 0, shape_close, shape);
304
+ }
305
+
306
+ static VALUE arc_s_new(int argc, VALUE *argv, VALUE klass) {
307
+ return NewShape(argc, argv, klass, SHPT_ARC);
308
+ }
309
+
310
+ static VALUE arcm_s_new(int argc, VALUE *argv, VALUE klass) {
311
+ return NewShape(argc, argv, klass, SHPT_ARCM);
312
+ }
313
+
314
+ static VALUE arcz_s_new(int argc, VALUE *argv, VALUE klass) {
315
+ return NewShape(argc, argv, klass, SHPT_ARCZ);
316
+ }
317
+
318
+ static VALUE pl_s_new(int argc, VALUE *argv, VALUE klass) {
319
+ return NewShape(argc, argv, klass, SHPT_POLYGON);
320
+ }
321
+
322
+ static VALUE plm_s_new(int argc, VALUE *argv, VALUE klass) {
323
+ return NewShape(argc, argv, klass, SHPT_POLYGONM);
324
+ }
325
+
326
+ static VALUE plz_s_new(int argc, VALUE *argv, VALUE klass) {
327
+ return NewShape(argc, argv, klass, SHPT_POLYGONZ);
328
+ }
329
+
330
+ static VALUE mpatch_s_new(int argc, VALUE *argv, VALUE klass) {
331
+ return NewShape(argc, argv, klass, SHPT_MULTIPATCH);
332
+ }
333
+
334
+ static VALUE mp_s_new(int argc, VALUE *argv, VALUE klass) {
335
+ return MultiPointNew(argc, argv, klass, SHPT_MULTIPOINT);
336
+ }
337
+
338
+ static VALUE mpm_s_new(int argc, VALUE *argv, VALUE klass) {
339
+ return MultiPointNew(argc, argv, klass, SHPT_MULTIPOINTM);
340
+ }
341
+
342
+ static VALUE mpz_s_new(int argc, VALUE *argv, VALUE klass) {
343
+ return MultiPointNew(argc, argv, klass, SHPT_MULTIPOINTZ);
344
+ }
345
+
346
+
347
+ static void PointAddAttr(VALUE pt, VALUE attrs)
348
+ {
349
+ VALUE *argv;
350
+ VALUE ary;
351
+ int i, argc;
352
+ Check_Type(attrs, T_HASH);
353
+ ary = rb_funcall(attrs, rb_intern("to_a"), 0);
354
+ Check_Type(ary, T_ARRAY);
355
+ argv = RARRAY_PTR(ary);
356
+ argc = RARRAY_LEN(ary);
357
+ for (i = 0; i < argc; i++) {
358
+ VALUE *pair;
359
+ Check_Type(argv[i], T_ARRAY);
360
+ if (RARRAY_LEN(argv[i]) != 2)
361
+ rb_bug("hash.to_a member has weird size");
362
+ pair = RARRAY_PTR(argv[i]);
363
+ sp_field_set(pt, pair[0], pair[1]);
364
+ }
365
+ }
366
+
367
+
368
+ static VALUE pt_s_new(int argc, VALUE *argv, VALUE klass)
369
+ {
370
+ shape_t *shape;
371
+ VALUE vx, vy, attrs, pt;
372
+ rb_scan_args(argc, argv, "21", &vx, &vy, &attrs);
373
+ shape = shape_new_point(SHPT_POINT,
374
+ NUM2DBLo(vx), NUM2DBLo(vy), 0.0, 0.0);
375
+ pt = Data_Wrap_Struct(klass, 0, shape_close, shape);
376
+ if (!NIL_P(attrs)) {
377
+ PointAddAttr(pt, attrs);
378
+ }
379
+ return pt;
380
+ }
381
+
382
+ static VALUE ptm_s_new(int argc, VALUE *argv, VALUE klass)
383
+ {
384
+ shape_t *shape;
385
+ VALUE vx, vy, vm, attrs, pt;
386
+ rb_scan_args(argc, argv, "31", &vx, &vy, &vm, &attrs);
387
+ shape = shape_new_point(SHPT_POINTM,
388
+ NUM2DBLo(vx), NUM2DBLo(vy), SHP_NUM2DBL(vm), 0.0);
389
+ pt = Data_Wrap_Struct(klass, 0, shape_close, shape);
390
+ if (!NIL_P(attrs)) {
391
+ PointAddAttr(pt, attrs);
392
+ }
393
+ return pt;
394
+ }
395
+
396
+ static VALUE ptz_s_new(int argc, VALUE *argv, VALUE klass)
397
+ {
398
+ shape_t *shape;
399
+ VALUE vx, vy, vm, vz, attrs, pt;
400
+ rb_scan_args(argc, argv, "41", &vx, &vy, &vm, &vz, &attrs);
401
+ shape = shape_new_point(SHPT_POINTZ,
402
+ NUM2DBLo(vx), NUM2DBLo(vy), SHP_NUM2DBL(vm), NUM2DBLo(vz));
403
+ pt = Data_Wrap_Struct(klass, 0, shape_close, shape);
404
+ if (!NIL_P(attrs)) {
405
+ PointAddAttr(pt, attrs);
406
+ }
407
+ return pt;
408
+ }
409
+
410
+ /* ShapeLib.new_point */
411
+ static VALUE sl_m_new_point(int argc, VALUE *argv, VALUE klass)
412
+ {
413
+ if (2 == argc || (3 == argc && T_HASH == TYPE(argv[2]))) {
414
+ return pt_s_new(argc, argv, cPoint);
415
+ } else if (3 == argc || (4 == argc && T_HASH != TYPE(argv[3]))) {
416
+ return ptm_s_new(argc, argv, cPointM);
417
+ } else if (4 == argc || (5 == argc && T_HASH != TYPE(argv[4]))) {
418
+ return ptz_s_new(argc, argv, cPointZ);
419
+ } else {
420
+ rb_raise(rb_eArgError,
421
+ "usage: ShapeLib::Shape.new_point x, y, m, z, attr_array");
422
+ return Qnil;
423
+ }
424
+ }
425
+
426
+ /*
427
+ * instance methods of general Shape
428
+ */
429
+
430
+ static void Attr_to_Hash(VALUE h, VALUE obj)
431
+ {
432
+ shape_t *self;
433
+ int i;
434
+ Data_Get_Struct(obj, shape_t, self);
435
+ if (self->nattr <= 0)
436
+ return;
437
+ for (i = 0; i < self->nattr; i++) {
438
+ attrib_t *a;
439
+ VALUE v;
440
+ a = &(self->attr[i]);
441
+ switch (a->type) {
442
+ case -1:
443
+ v = Qnil;
444
+ break;
445
+ case FTInteger:
446
+ v = INT2NUM(a->val.ival);
447
+ break;
448
+ case FTDouble:
449
+ v = rb_float_new(a->val.fval);
450
+ break;
451
+ case FTString:
452
+ default:
453
+ v = rb_str_new2(a->val.sval);
454
+ break;
455
+ }
456
+ if (!NIL_P(v)) {
457
+ rb_hash_aset(h, rb_str_new2(a->name), v);
458
+ }
459
+ }
460
+ }
461
+
462
+ /* Shape#[] */
463
+ static VALUE sp_field_get(VALUE obj, VALUE name)
464
+ {
465
+ shape_t *self;
466
+ char *cname;
467
+ int ofs;
468
+
469
+ Data_Get_Struct(obj, shape_t, self);
470
+ cname = StringValuePtr(name);
471
+ ofs = shape_attrib_index(self, cname, 0);
472
+ if (ofs < 0) {
473
+ return Qnil;
474
+ }
475
+ switch (self->attr[ofs].type) {
476
+ case -1:
477
+ return Qnil;
478
+ case FTInteger:
479
+ return INT2NUM(self->attr[ofs].val.ival);
480
+ case FTDouble:
481
+ return rb_float_new(self->attr[ofs].val.fval);
482
+ case FTString:
483
+ case FTLogical:
484
+ return rb_str_new2(self->attr[ofs].val.sval);
485
+ default:
486
+ rb_raise(rb_eTypeError, "unacceptable field type");
487
+ }
488
+ }
489
+
490
+ /* Shape#[]= */
491
+ static VALUE sp_field_set(VALUE obj, VALUE name, VALUE val)
492
+ {
493
+ shape_t *self;
494
+ char *cname;
495
+ int ofs;
496
+
497
+ Data_Get_Struct(obj, shape_t, self);
498
+ cname = StringValuePtr(name);
499
+ ofs = shape_attrib_index(self, cname, 1);
500
+ if (ofs < 0) {
501
+ return Qnil;
502
+ }
503
+ switch (TYPE(val)) {
504
+ case T_STRING:
505
+ self->attr[ofs].type = FTString;
506
+ self->attr[ofs].val.sval = StringDup(StringValuePtr(val));
507
+ break;
508
+ case T_FIXNUM:
509
+ self->attr[ofs].type = FTInteger;
510
+ self->attr[ofs].val.ival = FIX2INT(val);
511
+ break;
512
+ case T_FLOAT:
513
+ self->attr[ofs].type = FTDouble;
514
+ self->attr[ofs].val.fval = RFLOAT_VALUE(val);
515
+ break;
516
+ case T_NIL:
517
+ self->attr[ofs].type = -1;
518
+ break;
519
+ default:
520
+ rb_raise(rb_eTypeError,
521
+ "give me String, Integer, or Float");
522
+ }
523
+ return obj;
524
+ }
525
+
526
+ static VALUE sp_maxbound(VALUE obj)
527
+ {
528
+ shape_t *self;
529
+ double buf[4];
530
+ Data_Get_Struct(obj, shape_t, self);
531
+ buf[0] = self->obj->dfXMax;
532
+ buf[1] = self->obj->dfYMax;
533
+ buf[2] = self->obj->dfMMax;
534
+ buf[3] = self->obj->dfZMax;
535
+ return DoubleUnpackM(buf, 4, 2);
536
+ }
537
+
538
+ static VALUE sp_minbound(VALUE obj)
539
+ {
540
+ shape_t *self;
541
+ double buf[4];
542
+ Data_Get_Struct(obj, shape_t, self);
543
+ buf[0] = self->obj->dfXMin;
544
+ buf[1] = self->obj->dfYMin;
545
+ buf[2] = self->obj->dfMMin;
546
+ buf[3] = self->obj->dfZMin;
547
+ return DoubleUnpackM(buf, 4, 2);
548
+ }
549
+
550
+ static VALUE sp_mvals(VALUE obj)
551
+ {
552
+ shape_t *self;
553
+ Data_Get_Struct(obj, shape_t, self);
554
+ return DoubleUnpackM(self->obj->padfM, self->obj->nVertices, -1);
555
+ }
556
+
557
+ static VALUE sp_n_parts(VALUE obj)
558
+ {
559
+ shape_t *self;
560
+ Data_Get_Struct(obj, shape_t, self);
561
+ return INT2NUM(self->obj->nParts);
562
+ }
563
+
564
+ static VALUE sp_n_vertices(VALUE obj)
565
+ {
566
+ shape_t *self;
567
+ Data_Get_Struct(obj, shape_t, self);
568
+ return INT2NUM(self->obj->nVertices);
569
+ }
570
+
571
+ static VALUE sp_part_start(VALUE obj)
572
+ {
573
+ shape_t *self;
574
+ Data_Get_Struct(obj, shape_t, self);
575
+ if (self->obj->nParts == 0)
576
+ return Qnil;
577
+ return IntUnpack(self->obj->panPartStart, self->obj->nParts);
578
+ }
579
+
580
+ static VALUE sp_part_type(VALUE obj)
581
+ {
582
+ shape_t *self;
583
+ VALUE ary;
584
+ int i;
585
+ Data_Get_Struct(obj, shape_t, self);
586
+ if (self->obj->nParts == 0)
587
+ return Qnil;
588
+ #if 0
589
+ return UintUnpack(self->obj->panPartType, self->obj->nParts);
590
+ #endif
591
+ ary = rb_ary_new2(self->obj->nParts);
592
+ for (i = 0; i < self->obj->nParts; i++) {
593
+ rb_ary_push(ary, PartType2Ruby(self->obj->panPartType[i]));
594
+ }
595
+ return ary;
596
+ }
597
+
598
+ static VALUE sp_shape_id(VALUE obj)
599
+ {
600
+ shape_t *self;
601
+ Data_Get_Struct(obj, shape_t, self);
602
+ return (self->obj->nShapeId < 0) ? Qnil : INT2NUM(self->obj->nShapeId);
603
+ }
604
+
605
+ static VALUE sp_shape_type(VALUE obj)
606
+ {
607
+ shape_t *self;
608
+ Data_Get_Struct(obj, shape_t, self);
609
+ return ShapeType2Ruby(self->obj->nSHPType);
610
+ }
611
+
612
+ static VALUE sp_rewind(VALUE obj)
613
+ {
614
+ shape_t *self;
615
+ Data_Get_Struct(obj, shape_t, self);
616
+ return SHPRewindObject(NULL, self->obj) ? Qtrue : Qfalse;
617
+ }
618
+
619
+ static VALUE sp_xvals(VALUE obj)
620
+ {
621
+ shape_t *self;
622
+ Data_Get_Struct(obj, shape_t, self);
623
+ return DoubleUnpack(self->obj->padfX, self->obj->nVertices);
624
+ }
625
+
626
+ static VALUE sp_yvals(VALUE obj)
627
+ {
628
+ shape_t *self;
629
+ Data_Get_Struct(obj, shape_t, self);
630
+ return DoubleUnpack(self->obj->padfY, self->obj->nVertices);
631
+ }
632
+
633
+ static VALUE sp_zvals(VALUE obj)
634
+ {
635
+ shape_t *self;
636
+ Data_Get_Struct(obj, shape_t, self);
637
+ return DoubleUnpack(self->obj->padfZ, self->obj->nVertices);
638
+ }
639
+
640
+ /*
641
+ * methods of Point/PointM/PointZ
642
+ */
643
+
644
+ static VALUE pt_x(VALUE obj)
645
+ {
646
+ shape_t *self;
647
+ Data_Get_Struct(obj, shape_t, self);
648
+ switch (self->obj->nSHPType) {
649
+ case SHPT_POINT:
650
+ case SHPT_POINTM:
651
+ case SHPT_POINTZ:
652
+ return rb_float_new(self->obj->padfX[0]);
653
+ default:
654
+ rb_bug("shape type %d is not Point", self->obj->nSHPType);
655
+ }
656
+ return Qnil;
657
+ }
658
+
659
+ static VALUE pt_y(VALUE obj)
660
+ {
661
+ shape_t *self;
662
+ Data_Get_Struct(obj, shape_t, self);
663
+ switch (self->obj->nSHPType) {
664
+ case SHPT_POINT:
665
+ case SHPT_POINTM:
666
+ case SHPT_POINTZ:
667
+ return rb_float_new(self->obj->padfY[0]);
668
+ default:
669
+ rb_bug("shape type %d is not Point", self->obj->nSHPType);
670
+ }
671
+ return Qnil;
672
+ }
673
+
674
+ static VALUE pt_m(VALUE obj)
675
+ {
676
+ shape_t *self;
677
+ Data_Get_Struct(obj, shape_t, self);
678
+ switch (self->obj->nSHPType) {
679
+ case SHPT_POINTM:
680
+ case SHPT_POINTZ:
681
+ return SHP_FLOAT_NEW(self->obj->padfM[0]);
682
+ case SHPT_POINT:
683
+ return Qnil;
684
+ default:
685
+ rb_bug("shape type %d is not Point", self->obj->nSHPType);
686
+ }
687
+ return Qnil;
688
+ }
689
+
690
+ static VALUE pt_z(VALUE obj)
691
+ {
692
+ shape_t *self;
693
+ Data_Get_Struct(obj, shape_t, self);
694
+ switch (self->obj->nSHPType) {
695
+ case SHPT_POINTZ:
696
+ return rb_float_new(self->obj->padfM[0]);
697
+ case SHPT_POINTM:
698
+ case SHPT_POINT:
699
+ return Qnil;
700
+ default:
701
+ rb_bug("shape type %d is not Point", self->obj->nSHPType);
702
+ }
703
+ return Qnil;
704
+ }