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,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
|
+
}
|