librtree 0.8.6 → 0.9.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.
- checksums.yaml +4 -4
- data/ext/rtree/rtree.c +206 -95
- data/lib/rtree.rb +224 -42
- metadata +12 -12
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 91ab938275be940bbe12869b5b95266bdd32a503c5aae74ef84e242db8b65cd2
|
|
4
|
+
data.tar.gz: 981f9d121d65cb94f3ca42cd09c3841471d9c9c6c4176416d8de639f2ffe9922
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 42764d0851e8ddab67468847fc08f8d148ad332a7b8e3d81f26a2eb50d8a79b0e2ac2cfb6e805c7f3d1bd2b17a5ed1bd52c89ed0001c88fb3c9c209fb879fe0f
|
|
7
|
+
data.tar.gz: a394efa120788677dbda6d409b07e1a1d6d234692f08ba6371dfbc99c0f82420e2f720214793c6944f0b652cc81739096b06ff5e8822ac5f18d8a0b3f70388ba
|
data/ext/rtree/rtree.c
CHANGED
|
@@ -4,48 +4,33 @@
|
|
|
4
4
|
|
|
5
5
|
#include <rtree.h>
|
|
6
6
|
#include <rtree/package.h>
|
|
7
|
+
#include <rtree/postscript.h>
|
|
7
8
|
|
|
8
9
|
#include <errno.h>
|
|
9
10
|
#include <stdint.h>
|
|
10
11
|
|
|
12
|
+
static rb_data_type_t style_type;
|
|
13
|
+
static rb_data_type_t rtree_type;
|
|
11
14
|
|
|
12
|
-
static void
|
|
15
|
+
static void rt_dfree(void *p)
|
|
13
16
|
{
|
|
14
17
|
rtree_destroy((rtree_t*)p);
|
|
15
18
|
}
|
|
16
19
|
|
|
17
|
-
static size_t
|
|
20
|
+
static size_t rt_dsize(const void *p)
|
|
18
21
|
{
|
|
19
22
|
return rtree_bytes((const rtree_t*)p);
|
|
20
23
|
}
|
|
21
24
|
|
|
22
|
-
static
|
|
23
|
-
.wrap_struct_name = "rtree-wrap",
|
|
24
|
-
.function = {
|
|
25
|
-
.dmark = NULL,
|
|
26
|
-
.dfree = lrt_dfree,
|
|
27
|
-
.dsize = lrt_dsize,
|
|
28
|
-
#if RUBY_API_VERSION_CODE < 20700
|
|
29
|
-
.reserved = { NULL, NULL }
|
|
30
|
-
#else
|
|
31
|
-
.dcompact = NULL,
|
|
32
|
-
.reserved = { NULL }
|
|
33
|
-
#endif
|
|
34
|
-
},
|
|
35
|
-
.parent = NULL,
|
|
36
|
-
.data = NULL,
|
|
37
|
-
.flags = RUBY_TYPED_FREE_IMMEDIATELY
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
static VALUE lrt_alloc(VALUE cls)
|
|
25
|
+
static VALUE rt_alloc(VALUE cls)
|
|
41
26
|
{
|
|
42
27
|
rtree_t *rtree;;
|
|
43
28
|
if ((rtree = rtree_alloc()) == NULL)
|
|
44
29
|
rb_raise(rb_eNoMemError, "failed to alloc rtree");
|
|
45
|
-
return TypedData_Wrap_Struct(cls, &
|
|
30
|
+
return TypedData_Wrap_Struct(cls, &rtree_type, rtree);
|
|
46
31
|
}
|
|
47
32
|
|
|
48
|
-
static VALUE
|
|
33
|
+
static VALUE rt_init(VALUE self, VALUE dim_obj, VALUE flags_obj)
|
|
49
34
|
{
|
|
50
35
|
Check_Type(dim_obj, T_FIXNUM);
|
|
51
36
|
size_t dim = FIX2ULONG(dim_obj);
|
|
@@ -54,7 +39,7 @@ static VALUE lrt_init(VALUE self, VALUE dim_obj, VALUE flags_obj)
|
|
|
54
39
|
state_flags_t flags = FIX2UINT(flags_obj);
|
|
55
40
|
|
|
56
41
|
rtree_t *rtree;
|
|
57
|
-
TypedData_Get_Struct(self, rtree_t, &
|
|
42
|
+
TypedData_Get_Struct(self, rtree_t, &rtree_type, rtree);
|
|
58
43
|
|
|
59
44
|
if ((rtree_init(rtree, dim, flags)) != 0)
|
|
60
45
|
rb_raise(rb_eNoMemError, "failed to init rtree");
|
|
@@ -62,28 +47,28 @@ static VALUE lrt_init(VALUE self, VALUE dim_obj, VALUE flags_obj)
|
|
|
62
47
|
return self;
|
|
63
48
|
}
|
|
64
49
|
|
|
65
|
-
static VALUE
|
|
50
|
+
static VALUE rt_release(VALUE self)
|
|
66
51
|
{
|
|
67
52
|
rtree_t *rtree;
|
|
68
|
-
TypedData_Get_Struct(self, rtree_t, &
|
|
53
|
+
TypedData_Get_Struct(self, rtree_t, &rtree_type, rtree);
|
|
69
54
|
rtree_destroy(rtree);
|
|
70
55
|
return self;
|
|
71
56
|
}
|
|
72
57
|
|
|
73
|
-
static VALUE
|
|
58
|
+
static VALUE rt_height(VALUE self)
|
|
74
59
|
{
|
|
75
60
|
rtree_t *rtree;
|
|
76
|
-
TypedData_Get_Struct(self, rtree_t, &
|
|
61
|
+
TypedData_Get_Struct(self, rtree_t, &rtree_type, rtree);
|
|
77
62
|
return INT2NUM(rtree_height(rtree));
|
|
78
63
|
}
|
|
79
64
|
|
|
80
|
-
static VALUE
|
|
65
|
+
static VALUE rt_add_rect(VALUE self, VALUE id_obj, VALUE coord_obj)
|
|
81
66
|
{
|
|
82
67
|
Check_Type(coord_obj, T_ARRAY);
|
|
83
68
|
Check_Type(id_obj, T_FIXNUM);
|
|
84
69
|
|
|
85
70
|
rtree_t *rtree;
|
|
86
|
-
TypedData_Get_Struct(self, rtree_t, &
|
|
71
|
+
TypedData_Get_Struct(self, rtree_t, &rtree_type, rtree);
|
|
87
72
|
|
|
88
73
|
rtree_id_t
|
|
89
74
|
id = FIX2ULONG(id_obj);
|
|
@@ -135,13 +120,13 @@ static int update_cb(rtree_id_t id, rtree_coord_t *coord, void *context)
|
|
|
135
120
|
return 0;
|
|
136
121
|
}
|
|
137
122
|
|
|
138
|
-
static VALUE
|
|
123
|
+
static VALUE rt_update(VALUE self)
|
|
139
124
|
{
|
|
140
125
|
if (!rb_block_given_p())
|
|
141
126
|
rb_raise(rb_eArgError, "Expected block");
|
|
142
127
|
|
|
143
128
|
rtree_t *rtree;
|
|
144
|
-
TypedData_Get_Struct(self, rtree_t, &
|
|
129
|
+
TypedData_Get_Struct(self, rtree_t, &rtree_type, rtree);
|
|
145
130
|
|
|
146
131
|
size_t len = 2 * state_dims(rtree->state);
|
|
147
132
|
int err = rtree_update(rtree, update_cb, &len);
|
|
@@ -154,10 +139,10 @@ static VALUE lrt_update(VALUE self)
|
|
|
154
139
|
|
|
155
140
|
/*
|
|
156
141
|
The librtree API expects the search callback to return zero to
|
|
157
|
-
continue the search, non-zero to terminate.
|
|
142
|
+
continue the search, non-zero to terminate. I was expecting to
|
|
158
143
|
need to wrap the 'yield' in 'rescue's and 'ensure's to handle
|
|
159
144
|
exceptions and breaks, but find that doing nothing actually does
|
|
160
|
-
the right thing (see specs). The search
|
|
145
|
+
the right thing (see specs). The search implementation is just
|
|
161
146
|
a recursive search through the tree (as you would expect) so
|
|
162
147
|
there is no end-of-search cleanup to do, so I think this is all
|
|
163
148
|
just fine ... wild
|
|
@@ -169,7 +154,7 @@ static int search_cb(rtree_id_t id, void *context)
|
|
|
169
154
|
return 0;
|
|
170
155
|
}
|
|
171
156
|
|
|
172
|
-
static VALUE
|
|
157
|
+
static VALUE rt_search(VALUE self, VALUE coord_obj)
|
|
173
158
|
{
|
|
174
159
|
if (!rb_block_given_p())
|
|
175
160
|
rb_raise(rb_eArgError, "Expected block");
|
|
@@ -177,7 +162,7 @@ static VALUE lrt_search(VALUE self, VALUE coord_obj)
|
|
|
177
162
|
Check_Type(coord_obj, T_ARRAY);
|
|
178
163
|
|
|
179
164
|
rtree_t *rtree;
|
|
180
|
-
TypedData_Get_Struct(self, rtree_t, &
|
|
165
|
+
TypedData_Get_Struct(self, rtree_t, &rtree_type, rtree);
|
|
181
166
|
|
|
182
167
|
size_t
|
|
183
168
|
len = RARRAY_LEN(coord_obj),
|
|
@@ -220,21 +205,21 @@ static VALUE deserialise(VALUE cls, VALUE io_obj, deserialise_t *f)
|
|
|
220
205
|
rb_raise(rb_eRuntimeError, "Failed read from stream");
|
|
221
206
|
}
|
|
222
207
|
|
|
223
|
-
return TypedData_Wrap_Struct(cls, &
|
|
208
|
+
return TypedData_Wrap_Struct(cls, &rtree_type, rtree);
|
|
224
209
|
}
|
|
225
210
|
|
|
226
|
-
static VALUE
|
|
211
|
+
static VALUE rt_json_read(VALUE cls, VALUE io_obj)
|
|
227
212
|
{
|
|
228
213
|
return deserialise(cls, io_obj, rtree_json_read);
|
|
229
214
|
}
|
|
230
215
|
|
|
231
|
-
static VALUE
|
|
216
|
+
static VALUE rt_bsrt_read(VALUE cls, VALUE io_obj)
|
|
232
217
|
{
|
|
233
218
|
return deserialise(cls, io_obj, rtree_bsrt_read);
|
|
234
219
|
}
|
|
235
220
|
|
|
236
|
-
static VALUE
|
|
237
|
-
|
|
221
|
+
static VALUE rt_csv_read(VALUE cls,
|
|
222
|
+
VALUE io_obj, VALUE dim_obj, VALUE flags_obj)
|
|
238
223
|
{
|
|
239
224
|
Check_Type(io_obj, T_FILE);
|
|
240
225
|
rb_io_t *io;
|
|
@@ -259,7 +244,7 @@ static VALUE lrt_csv_read(VALUE cls,
|
|
|
259
244
|
rb_raise(rb_eRuntimeError, "Failed read from stream");
|
|
260
245
|
}
|
|
261
246
|
|
|
262
|
-
return TypedData_Wrap_Struct(cls, &
|
|
247
|
+
return TypedData_Wrap_Struct(cls, &rtree_type, rtree);
|
|
263
248
|
}
|
|
264
249
|
|
|
265
250
|
/* serialisation */
|
|
@@ -277,7 +262,7 @@ static VALUE serialise(VALUE self, VALUE io_obj, serialise_t *f)
|
|
|
277
262
|
FILE *fp = rb_io_stdio_file(io);
|
|
278
263
|
|
|
279
264
|
rtree_t *rtree;
|
|
280
|
-
TypedData_Get_Struct(self, rtree_t, &
|
|
265
|
+
TypedData_Get_Struct(self, rtree_t, &rtree_type, rtree);
|
|
281
266
|
|
|
282
267
|
int err = f(rtree, fp);
|
|
283
268
|
if (err != 0)
|
|
@@ -286,22 +271,22 @@ static VALUE serialise(VALUE self, VALUE io_obj, serialise_t *f)
|
|
|
286
271
|
return self;
|
|
287
272
|
}
|
|
288
273
|
|
|
289
|
-
static VALUE
|
|
274
|
+
static VALUE rt_json_write(VALUE self, VALUE io_obj)
|
|
290
275
|
{
|
|
291
276
|
return serialise(self, io_obj, rtree_json_write);
|
|
292
277
|
}
|
|
293
278
|
|
|
294
|
-
static VALUE
|
|
279
|
+
static VALUE rt_bsrt_write(VALUE self, VALUE io_obj)
|
|
295
280
|
{
|
|
296
281
|
return serialise(self, io_obj, rtree_bsrt_write);
|
|
297
282
|
}
|
|
298
283
|
|
|
299
|
-
static VALUE
|
|
284
|
+
static VALUE rt_identical(VALUE self, VALUE other)
|
|
300
285
|
{
|
|
301
286
|
rtree_t *rtree_self, *rtree_other;
|
|
302
287
|
|
|
303
|
-
TypedData_Get_Struct(self, rtree_t, &
|
|
304
|
-
TypedData_Get_Struct(other, rtree_t, &
|
|
288
|
+
TypedData_Get_Struct(self, rtree_t, &rtree_type, rtree_self);
|
|
289
|
+
TypedData_Get_Struct(other, rtree_t, &rtree_type, rtree_other);
|
|
305
290
|
|
|
306
291
|
if (rtree_identical(rtree_self, rtree_other))
|
|
307
292
|
return Qtrue;
|
|
@@ -309,10 +294,10 @@ static VALUE lrt_identical(VALUE self, VALUE other)
|
|
|
309
294
|
return Qfalse;
|
|
310
295
|
}
|
|
311
296
|
|
|
312
|
-
static VALUE
|
|
297
|
+
static VALUE rt_clone(VALUE self)
|
|
313
298
|
{
|
|
314
299
|
rtree_t *rtree;
|
|
315
|
-
TypedData_Get_Struct(self, rtree_t, &
|
|
300
|
+
TypedData_Get_Struct(self, rtree_t, &rtree_type, rtree);
|
|
316
301
|
|
|
317
302
|
rtree_t *clone;
|
|
318
303
|
errno = 0;
|
|
@@ -324,105 +309,231 @@ static VALUE lrt_clone(VALUE self)
|
|
|
324
309
|
rb_raise(rb_eRuntimeError, "Failed clone");
|
|
325
310
|
}
|
|
326
311
|
|
|
327
|
-
return TypedData_Wrap_Struct(CLASS_OF(self), &
|
|
312
|
+
return TypedData_Wrap_Struct(CLASS_OF(self), &rtree_type, clone);
|
|
328
313
|
}
|
|
329
314
|
|
|
330
315
|
static VALUE state_size_access(VALUE self, size_t (*f)(const state_t*))
|
|
331
316
|
{
|
|
332
317
|
rtree_t *rtree;
|
|
333
|
-
TypedData_Get_Struct(self, rtree_t, &
|
|
318
|
+
TypedData_Get_Struct(self, rtree_t, &rtree_type, rtree);
|
|
334
319
|
return INT2NUM(f(rtree->state));
|
|
335
320
|
}
|
|
336
321
|
|
|
337
|
-
static VALUE
|
|
322
|
+
static VALUE rt_dim(VALUE self)
|
|
338
323
|
{
|
|
339
324
|
return state_size_access(self, state_dims);
|
|
340
325
|
}
|
|
341
326
|
|
|
342
|
-
static VALUE
|
|
327
|
+
static VALUE rt_page_size(VALUE self)
|
|
343
328
|
{
|
|
344
329
|
return state_size_access(self, state_page_size);
|
|
345
330
|
}
|
|
346
331
|
|
|
347
|
-
static VALUE
|
|
332
|
+
static VALUE rt_node_size(VALUE self)
|
|
348
333
|
{
|
|
349
334
|
return state_size_access(self, state_node_size);
|
|
350
335
|
}
|
|
351
336
|
|
|
352
|
-
static VALUE
|
|
337
|
+
static VALUE rt_rect_size(VALUE self)
|
|
353
338
|
{
|
|
354
339
|
return state_size_access(self, state_rect_size);
|
|
355
340
|
}
|
|
356
341
|
|
|
357
|
-
static VALUE
|
|
342
|
+
static VALUE rt_branch_size(VALUE self)
|
|
358
343
|
{
|
|
359
344
|
return state_size_access(self, state_branch_size);
|
|
360
345
|
}
|
|
361
346
|
|
|
362
|
-
static VALUE
|
|
347
|
+
static VALUE rt_branching_factor(VALUE self)
|
|
363
348
|
{
|
|
364
349
|
return state_size_access(self, state_branching_factor);
|
|
365
350
|
}
|
|
366
351
|
|
|
367
|
-
static VALUE
|
|
352
|
+
static VALUE rt_unit_sphere_volume(VALUE self)
|
|
368
353
|
{
|
|
369
354
|
rtree_t *rtree;
|
|
370
|
-
TypedData_Get_Struct(self, rtree_t, &
|
|
355
|
+
TypedData_Get_Struct(self, rtree_t, &rtree_type, rtree);
|
|
371
356
|
return DBL2NUM(state_unit_sphere_volume(rtree->state));
|
|
372
357
|
}
|
|
373
358
|
|
|
374
|
-
static VALUE
|
|
359
|
+
static VALUE rt_size(VALUE self)
|
|
375
360
|
{
|
|
376
361
|
rtree_t *rtree;
|
|
377
|
-
TypedData_Get_Struct(self, rtree_t, &
|
|
362
|
+
TypedData_Get_Struct(self, rtree_t, &rtree_type, rtree);
|
|
378
363
|
return INT2NUM(rtree_bytes(rtree));
|
|
379
364
|
}
|
|
380
365
|
|
|
381
|
-
static VALUE
|
|
366
|
+
static VALUE rt_version(VALUE self)
|
|
382
367
|
{
|
|
383
368
|
return rb_str_new_cstr(rtree_package_version);
|
|
384
369
|
}
|
|
385
370
|
|
|
386
|
-
static VALUE
|
|
371
|
+
static VALUE rt_bugreport(VALUE self)
|
|
387
372
|
{
|
|
388
373
|
return rb_str_new_cstr(rtree_package_bugreport);
|
|
389
374
|
}
|
|
390
375
|
|
|
391
|
-
static VALUE
|
|
376
|
+
static VALUE rt_url(VALUE self)
|
|
392
377
|
{
|
|
393
378
|
return rb_str_new_cstr(rtree_package_url);
|
|
394
379
|
}
|
|
395
380
|
|
|
381
|
+
static VALUE rt_postscript(VALUE self,
|
|
382
|
+
VALUE style_obj,
|
|
383
|
+
VALUE axis_obj,
|
|
384
|
+
VALUE extent_obj,
|
|
385
|
+
VALUE margin_obj,
|
|
386
|
+
VALUE io_obj)
|
|
387
|
+
{
|
|
388
|
+
rtree_t *rtree;
|
|
389
|
+
TypedData_Get_Struct(self, rtree_t, &rtree_type, rtree);
|
|
390
|
+
|
|
391
|
+
style_t *style;
|
|
392
|
+
TypedData_Get_Struct(style_obj, style_t, &style_type, style);
|
|
393
|
+
|
|
394
|
+
Check_Type(io_obj, T_FILE);
|
|
395
|
+
rb_io_t *io;
|
|
396
|
+
GetOpenFile(io_obj, io);
|
|
397
|
+
rb_io_check_initialized(io);
|
|
398
|
+
rb_io_check_writable(io);
|
|
399
|
+
FILE *fp = rb_io_stdio_file(io);
|
|
400
|
+
|
|
401
|
+
float
|
|
402
|
+
extent = NUM2DBL(extent_obj),
|
|
403
|
+
margin = NUM2DBL(margin_obj);
|
|
404
|
+
|
|
405
|
+
Check_Type(axis_obj, T_FIXNUM);
|
|
406
|
+
extent_axis_t axis = FIX2UINT(axis_obj);
|
|
407
|
+
|
|
408
|
+
rtree_postscript_t opt =
|
|
409
|
+
{
|
|
410
|
+
.style = style,
|
|
411
|
+
.axis = axis,
|
|
412
|
+
.extent = extent,
|
|
413
|
+
.margin = margin,
|
|
414
|
+
.title = "librtree-ruby output"
|
|
415
|
+
};
|
|
416
|
+
|
|
417
|
+
int err;
|
|
418
|
+
if ((err = rtree_postscript(rtree, &opt, fp)) != 0)
|
|
419
|
+
rb_raise(rb_eRuntimeError, "librtree: %s", rtree_strerror(err));
|
|
420
|
+
|
|
421
|
+
return Qnil;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
static rb_data_type_t rtree_type = {
|
|
425
|
+
.wrap_struct_name = "rtree-wrap",
|
|
426
|
+
.function = {
|
|
427
|
+
.dmark = NULL,
|
|
428
|
+
.dfree = rt_dfree,
|
|
429
|
+
.dsize = rt_dsize,
|
|
430
|
+
#if RUBY_API_VERSION_CODE < 20700
|
|
431
|
+
.reserved = { NULL, NULL }
|
|
432
|
+
#else
|
|
433
|
+
.dcompact = NULL,
|
|
434
|
+
.reserved = { NULL }
|
|
435
|
+
#endif
|
|
436
|
+
},
|
|
437
|
+
.parent = NULL,
|
|
438
|
+
.data = NULL,
|
|
439
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY
|
|
440
|
+
};
|
|
441
|
+
|
|
442
|
+
/* RTree::Style */
|
|
443
|
+
|
|
444
|
+
static void st_dfree(void *p)
|
|
445
|
+
{
|
|
446
|
+
postscript_style_destroy((style_t*)p);
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
static VALUE st_release(VALUE self)
|
|
450
|
+
{
|
|
451
|
+
style_t *style;
|
|
452
|
+
TypedData_Get_Struct(self, style_t, &style_type, style);
|
|
453
|
+
postscript_style_destroy(style);
|
|
454
|
+
return self;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
static VALUE st_json_read(VALUE cls, VALUE io_obj)
|
|
458
|
+
{
|
|
459
|
+
Check_Type(io_obj, T_FILE);
|
|
460
|
+
|
|
461
|
+
rb_io_t *io;
|
|
462
|
+
GetOpenFile(io_obj, io);
|
|
463
|
+
rb_io_check_initialized(io);
|
|
464
|
+
rb_io_check_readable(io);
|
|
465
|
+
FILE *fp = rb_io_stdio_file(io);
|
|
466
|
+
|
|
467
|
+
style_t *style;
|
|
468
|
+
errno = 0;
|
|
469
|
+
|
|
470
|
+
if ((style = postscript_style_read(fp)) == NULL)
|
|
471
|
+
{
|
|
472
|
+
if (errno)
|
|
473
|
+
rb_sys_fail(__func__);
|
|
474
|
+
else
|
|
475
|
+
rb_raise(rb_eRuntimeError, "Failed read from stream");
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
return TypedData_Wrap_Struct(cls, &style_type, style);
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
static rb_data_type_t style_type = {
|
|
482
|
+
.wrap_struct_name = "style-wrap",
|
|
483
|
+
.function = {
|
|
484
|
+
.dmark = NULL,
|
|
485
|
+
.dfree = st_dfree,
|
|
486
|
+
.dsize = NULL,
|
|
487
|
+
#if RUBY_API_VERSION_CODE < 20700
|
|
488
|
+
.reserved = { NULL, NULL }
|
|
489
|
+
#else
|
|
490
|
+
.dcompact = NULL,
|
|
491
|
+
.reserved = { NULL }
|
|
492
|
+
#endif
|
|
493
|
+
},
|
|
494
|
+
.parent = NULL,
|
|
495
|
+
.data = NULL,
|
|
496
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY
|
|
497
|
+
};
|
|
498
|
+
|
|
396
499
|
void Init_rtree(void)
|
|
397
500
|
{
|
|
398
|
-
VALUE
|
|
399
|
-
|
|
400
|
-
rb_define_alloc_func(
|
|
401
|
-
rb_define_method(
|
|
402
|
-
rb_define_method(
|
|
403
|
-
rb_define_method(
|
|
404
|
-
rb_define_method(
|
|
405
|
-
rb_define_method(
|
|
406
|
-
rb_define_method(
|
|
407
|
-
rb_define_method(
|
|
408
|
-
rb_define_method(
|
|
409
|
-
rb_define_method(
|
|
410
|
-
rb_define_method(
|
|
411
|
-
rb_define_method(
|
|
412
|
-
rb_define_method(
|
|
413
|
-
rb_define_method(
|
|
414
|
-
rb_define_method(
|
|
415
|
-
rb_define_method(
|
|
416
|
-
rb_define_method(
|
|
417
|
-
rb_define_method(
|
|
418
|
-
rb_define_method(
|
|
419
|
-
|
|
420
|
-
rb_define_singleton_method(
|
|
421
|
-
rb_define_singleton_method(
|
|
422
|
-
rb_define_singleton_method(
|
|
423
|
-
rb_define_singleton_method(
|
|
424
|
-
rb_define_singleton_method(
|
|
425
|
-
|
|
426
|
-
rb_define_const(
|
|
427
|
-
rb_define_const(
|
|
501
|
+
VALUE cRTreeBase = rb_const_get(rb_cObject, rb_intern("RTreeBase"));
|
|
502
|
+
|
|
503
|
+
rb_define_alloc_func(cRTreeBase, rt_alloc);
|
|
504
|
+
rb_define_method(cRTreeBase, "initialize", rt_init, 2);
|
|
505
|
+
rb_define_method(cRTreeBase, "free", rt_release, 0);
|
|
506
|
+
rb_define_method(cRTreeBase, "clone", rt_clone, 0);
|
|
507
|
+
rb_define_method(cRTreeBase, "update!", rt_update, 0);
|
|
508
|
+
rb_define_method(cRTreeBase, "height", rt_height, 0);
|
|
509
|
+
rb_define_method(cRTreeBase, "add_rect", rt_add_rect, 2);
|
|
510
|
+
rb_define_method(cRTreeBase, "search", rt_search, 1);
|
|
511
|
+
rb_define_method(cRTreeBase, "json_write", rt_json_write, 1);
|
|
512
|
+
rb_define_method(cRTreeBase, "bsrt_write", rt_bsrt_write, 1);
|
|
513
|
+
rb_define_method(cRTreeBase, "eq?", rt_identical, 1);
|
|
514
|
+
rb_define_method(cRTreeBase, "dim", rt_dim, 0);
|
|
515
|
+
rb_define_method(cRTreeBase, "size", rt_size, 0);
|
|
516
|
+
rb_define_method(cRTreeBase, "page_size", rt_page_size, 0);
|
|
517
|
+
rb_define_method(cRTreeBase, "node_size", rt_node_size, 0);
|
|
518
|
+
rb_define_method(cRTreeBase, "rect_size", rt_rect_size, 0);
|
|
519
|
+
rb_define_method(cRTreeBase, "branch_size", rt_branch_size, 0);
|
|
520
|
+
rb_define_method(cRTreeBase, "branching_factor", rt_branching_factor, 0);
|
|
521
|
+
rb_define_method(cRTreeBase, "unit_sphere_volume", rt_unit_sphere_volume, 0);
|
|
522
|
+
rb_define_method(cRTreeBase, "postscript", rt_postscript, 5);
|
|
523
|
+
rb_define_singleton_method(cRTreeBase, "version", rt_version, 0);
|
|
524
|
+
rb_define_singleton_method(cRTreeBase, "bugreport", rt_bugreport, 0);
|
|
525
|
+
rb_define_singleton_method(cRTreeBase, "url", rt_url, 0);
|
|
526
|
+
rb_define_singleton_method(cRTreeBase, "json_read", rt_json_read, 1);
|
|
527
|
+
rb_define_singleton_method(cRTreeBase, "bsrt_read", rt_bsrt_read, 1);
|
|
528
|
+
rb_define_singleton_method(cRTreeBase, "csv_read", rt_csv_read, 3);
|
|
529
|
+
rb_define_const(cRTreeBase, "SPLIT_QUADRATIC", INT2NUM(RTREE_SPLIT_QUADRATIC));
|
|
530
|
+
rb_define_const(cRTreeBase, "SPLIT_LINEAR", INT2NUM(RTREE_SPLIT_LINEAR));
|
|
531
|
+
rb_define_const(cRTreeBase, "SPLIT_GREENE", INT2NUM(RTREE_SPLIT_GREENE));
|
|
532
|
+
rb_define_const(cRTreeBase, "AXIS_HEIGHT", INT2NUM(axis_height));
|
|
533
|
+
rb_define_const(cRTreeBase, "AXIS_WIDTH", INT2NUM(axis_width));
|
|
534
|
+
|
|
535
|
+
VALUE cRTreeStyleBase = rb_const_get(rb_cObject, rb_intern("RTreeStyleBase"));
|
|
536
|
+
|
|
537
|
+
rb_define_method(cRTreeStyleBase, "free", st_release, 0);
|
|
538
|
+
rb_define_singleton_method(cRTreeStyleBase, "json_read", st_json_read, 1);
|
|
428
539
|
}
|
data/lib/rtree.rb
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# @!visibility private
|
|
4
|
+
#
|
|
5
|
+
class RTreeBase ; end
|
|
6
|
+
|
|
7
|
+
# @!visibility private
|
|
8
|
+
#
|
|
9
|
+
class RTreeStyleBase ; end
|
|
10
|
+
|
|
11
|
+
require 'rtree/rtree'
|
|
12
|
+
require 'json'
|
|
13
|
+
require 'fcntl'
|
|
3
14
|
|
|
4
15
|
# @author RTree J. J. Green
|
|
5
16
|
#
|
|
@@ -51,7 +62,79 @@ class RTreeC ; end
|
|
|
51
62
|
# determined at compile-time (with the RTREE_ID_TYPE variable) and by
|
|
52
63
|
# default this is a 64-bit unsigned integer.
|
|
53
64
|
#
|
|
54
|
-
class RTree <
|
|
65
|
+
class RTree < RTreeBase
|
|
66
|
+
|
|
67
|
+
# @!visibility private
|
|
68
|
+
#
|
|
69
|
+
module IOUtil
|
|
70
|
+
extend self
|
|
71
|
+
|
|
72
|
+
# @!visibility private
|
|
73
|
+
#
|
|
74
|
+
def deserialise(string, encoding)
|
|
75
|
+
raise TypeError unless string.is_a? String
|
|
76
|
+
rd, wr = IO.pipe(encoding)
|
|
77
|
+
if fork then
|
|
78
|
+
wr.close
|
|
79
|
+
unset_nonblock(rd)
|
|
80
|
+
begin
|
|
81
|
+
result = yield(rd)
|
|
82
|
+
ensure
|
|
83
|
+
rd.close
|
|
84
|
+
Process.wait
|
|
85
|
+
end
|
|
86
|
+
else
|
|
87
|
+
rd.close
|
|
88
|
+
begin
|
|
89
|
+
wr.write(string)
|
|
90
|
+
ensure
|
|
91
|
+
wr.close
|
|
92
|
+
exit!
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
result
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# @!visibility private
|
|
99
|
+
#
|
|
100
|
+
def serialise(encoding)
|
|
101
|
+
rd, wr = IO.pipe(encoding)
|
|
102
|
+
if fork then
|
|
103
|
+
wr.close
|
|
104
|
+
unset_nonblock(rd)
|
|
105
|
+
begin
|
|
106
|
+
result = rd.read
|
|
107
|
+
ensure
|
|
108
|
+
rd.close
|
|
109
|
+
Process.wait
|
|
110
|
+
end
|
|
111
|
+
else
|
|
112
|
+
rd.close
|
|
113
|
+
begin
|
|
114
|
+
yield(wr)
|
|
115
|
+
ensure
|
|
116
|
+
wr.close
|
|
117
|
+
exit!
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
result
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
private
|
|
124
|
+
|
|
125
|
+
# In Ruby 3, the Fibres facility exploits non-blocking IO and so pipes
|
|
126
|
+
# are non-blocking by default, this buggers-up the deserialise method
|
|
127
|
+
# since there is short delay forking here -- so we reinstate blocking
|
|
128
|
+
# with some fairly low-level fcntl(2) magic.
|
|
129
|
+
|
|
130
|
+
def unset_nonblock(fd)
|
|
131
|
+
fd.fcntl(
|
|
132
|
+
Fcntl::F_SETFL,
|
|
133
|
+
fd.fcntl(Fcntl::F_GETFL, 0) & ~Fcntl::O_NONBLOCK
|
|
134
|
+
)
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
end
|
|
55
138
|
|
|
56
139
|
class << self
|
|
57
140
|
|
|
@@ -61,6 +144,7 @@ class RTree < RTreeC
|
|
|
61
144
|
# @see #json_write
|
|
62
145
|
# @example Read from file
|
|
63
146
|
# rtree = File.open('rtree.json', 'r') { |io| RTree.json_read(io) }
|
|
147
|
+
#
|
|
64
148
|
def json_read(io)
|
|
65
149
|
super
|
|
66
150
|
end
|
|
@@ -69,6 +153,7 @@ class RTree < RTreeC
|
|
|
69
153
|
# @param json [String] a JSON string
|
|
70
154
|
# @return [RTree] the newly instantiated RTree
|
|
71
155
|
# @see #to_json
|
|
156
|
+
#
|
|
72
157
|
def from_json(json)
|
|
73
158
|
deserialise(json, Encoding::UTF_8) { |io| json_read(io) }
|
|
74
159
|
end
|
|
@@ -80,6 +165,7 @@ class RTree < RTreeC
|
|
|
80
165
|
# @see #bsrt_write
|
|
81
166
|
# @example Read from file
|
|
82
167
|
# rtree = File.open('rtree.bsrt', 'r') { |io| RTree.bsrt_read(io) }
|
|
168
|
+
#
|
|
83
169
|
def bsrt_read(io)
|
|
84
170
|
super
|
|
85
171
|
end
|
|
@@ -89,6 +175,7 @@ class RTree < RTreeC
|
|
|
89
175
|
# @param bsrt [String] a binary encoded string
|
|
90
176
|
# @return [RTree] the newly instantiated RTree
|
|
91
177
|
# @see #to_bsrt
|
|
178
|
+
#
|
|
92
179
|
def from_bsrt(bsrt)
|
|
93
180
|
deserialise(bsrt, Encoding::BINARY) { |io| bsrt_read(io) }
|
|
94
181
|
end
|
|
@@ -104,6 +191,7 @@ class RTree < RTreeC
|
|
|
104
191
|
# Extra columns may be present and will be ignored (this
|
|
105
192
|
# useful feature is the reason that the dimension is a required
|
|
106
193
|
# argument).
|
|
194
|
+
#
|
|
107
195
|
def csv_read(io, dim, split: :quadratic, node_page: 0)
|
|
108
196
|
flags = split_flag(split) | node_page_flag(node_page)
|
|
109
197
|
super(io, dim, flags)
|
|
@@ -114,6 +202,7 @@ class RTree < RTreeC
|
|
|
114
202
|
# @param dim [Integer] the dimension of the tree
|
|
115
203
|
# @param kwarg [Hash] As for {.csv_read}
|
|
116
204
|
# @return [RTree] the newly built RTree
|
|
205
|
+
#
|
|
117
206
|
def from_csv(csv, dim, **kwarg)
|
|
118
207
|
deserialise(csv, Encoding::UTF_8) do |io|
|
|
119
208
|
csv_read(io, dim, **kwarg)
|
|
@@ -121,21 +210,31 @@ class RTree < RTreeC
|
|
|
121
210
|
end
|
|
122
211
|
|
|
123
212
|
# @return [Array<Integer>] version of librtree
|
|
213
|
+
#
|
|
124
214
|
def version
|
|
125
215
|
@version ||= super.split('.').map(&:to_i)
|
|
126
216
|
end
|
|
127
217
|
|
|
128
218
|
# @return [String] email address for librtree bug reports
|
|
219
|
+
#
|
|
129
220
|
def bugreport
|
|
130
221
|
super
|
|
131
222
|
end
|
|
132
223
|
|
|
133
224
|
# @return [String] librtree homepage
|
|
225
|
+
#
|
|
134
226
|
def url
|
|
135
227
|
super
|
|
136
228
|
end
|
|
137
229
|
|
|
138
230
|
# @!visibility private
|
|
231
|
+
# This seems to need the self qualification on the constants,
|
|
232
|
+
# without them we get a NameError, not sure why so asked on SO
|
|
233
|
+
# https://stackoverflow.com/questions/68122256/ It's still not
|
|
234
|
+
# clear to me why this qualification is needed, but that's a
|
|
235
|
+
# problem with my understanding of the Ruby Eigenclass, it is
|
|
236
|
+
# the expected behaviour
|
|
237
|
+
#
|
|
139
238
|
def split_flag(split)
|
|
140
239
|
case split
|
|
141
240
|
when :quadratic
|
|
@@ -150,41 +249,24 @@ class RTree < RTreeC
|
|
|
150
249
|
end
|
|
151
250
|
|
|
152
251
|
# @!visibility private
|
|
252
|
+
#
|
|
153
253
|
def node_page_flag(node_page)
|
|
154
254
|
node_page << 2
|
|
155
255
|
end
|
|
156
256
|
|
|
157
257
|
private
|
|
158
258
|
|
|
159
|
-
def deserialise(
|
|
160
|
-
|
|
161
|
-
rd, wr = IO.pipe(encoding)
|
|
162
|
-
if fork then
|
|
163
|
-
wr.close
|
|
164
|
-
begin
|
|
165
|
-
result = yield(rd)
|
|
166
|
-
ensure
|
|
167
|
-
rd.close
|
|
168
|
-
Process.wait
|
|
169
|
-
end
|
|
170
|
-
else
|
|
171
|
-
rd.close
|
|
172
|
-
begin
|
|
173
|
-
wr.write(string)
|
|
174
|
-
ensure
|
|
175
|
-
wr.close
|
|
176
|
-
exit!
|
|
177
|
-
end
|
|
178
|
-
end
|
|
179
|
-
result
|
|
259
|
+
def deserialise(*args, &block)
|
|
260
|
+
RTree::IOUtil.deserialise(*args, &block)
|
|
180
261
|
end
|
|
262
|
+
|
|
181
263
|
end
|
|
182
264
|
|
|
183
265
|
# Initialize a new (empty) RTree
|
|
184
266
|
# @param dim [Integer] the dimension of the tree
|
|
185
267
|
# @param split [:linear, :quadratic, :greene] determines the splitting
|
|
186
268
|
# strategy, the linear strategy is faster to build, the quadratic
|
|
187
|
-
# and greene strategies
|
|
269
|
+
# and greene strategies produce better-quality R-trees which are
|
|
188
270
|
# faster to query.
|
|
189
271
|
# @param node_page [Integer] the nodes-per-page value. This value can
|
|
190
272
|
# affect performance quite dramatically, particularly build time. A
|
|
@@ -195,6 +277,7 @@ class RTree < RTreeC
|
|
|
195
277
|
# You may get better performance for your use-case by manual
|
|
196
278
|
# experimentation, but zero is a good place to start.
|
|
197
279
|
# @return [RTree] the newly instantiated RTree
|
|
280
|
+
#
|
|
198
281
|
def initialize(dim, split: :quadratic, node_page: 0)
|
|
199
282
|
@split = split
|
|
200
283
|
@node_page = node_page
|
|
@@ -203,6 +286,7 @@ class RTree < RTreeC
|
|
|
203
286
|
|
|
204
287
|
# Create a deep copy
|
|
205
288
|
# @return [RTree] a deep copy of the RTree
|
|
289
|
+
#
|
|
206
290
|
def clone
|
|
207
291
|
super
|
|
208
292
|
end
|
|
@@ -219,6 +303,7 @@ class RTree < RTreeC
|
|
|
219
303
|
# @example Add a rectangle to a dimension two RTree
|
|
220
304
|
# rtree = RTree.new(2)
|
|
221
305
|
# rtree.add_rect(7, [0, 0, 1, 1])
|
|
306
|
+
#
|
|
222
307
|
def add_rect(id, coords)
|
|
223
308
|
super
|
|
224
309
|
end
|
|
@@ -228,6 +313,7 @@ class RTree < RTreeC
|
|
|
228
313
|
# @return [Array<Integer>] the ids of all rectangles which intersect
|
|
229
314
|
# the search rectangle. If a block is given then these values will
|
|
230
315
|
# be yielded to the block (one at a time).
|
|
316
|
+
#
|
|
231
317
|
def search(coords)
|
|
232
318
|
if block_given? then
|
|
233
319
|
super
|
|
@@ -253,20 +339,23 @@ class RTree < RTreeC
|
|
|
253
339
|
# block and then convert the returned Ruby Floats to C; so we would
|
|
254
340
|
# expect that it loses much of its competitive advantage when
|
|
255
341
|
# compared to an R-tree rebuild.
|
|
342
|
+
#
|
|
256
343
|
def update!
|
|
257
344
|
super
|
|
258
345
|
end
|
|
259
346
|
|
|
260
347
|
# The height to the tree in the usual mathematical sense
|
|
261
348
|
# @return [Integer] the tree height
|
|
349
|
+
#
|
|
262
350
|
def height
|
|
263
351
|
super
|
|
264
352
|
end
|
|
265
353
|
|
|
266
354
|
# Whether the RTree has any rectangles or not
|
|
267
355
|
# @return [Boolean] true if the RTree is empty
|
|
356
|
+
#
|
|
268
357
|
def empty?
|
|
269
|
-
height
|
|
358
|
+
height.zero?
|
|
270
359
|
end
|
|
271
360
|
|
|
272
361
|
# Serialise to JSON stream
|
|
@@ -275,6 +364,7 @@ class RTree < RTreeC
|
|
|
275
364
|
# @see .json_read
|
|
276
365
|
# @example Write to file
|
|
277
366
|
# File.open('rtree.json', 'w') { |io| rtree.json_write(io) }
|
|
367
|
+
#
|
|
278
368
|
def json_write(io)
|
|
279
369
|
super
|
|
280
370
|
end
|
|
@@ -285,6 +375,7 @@ class RTree < RTreeC
|
|
|
285
375
|
# @see .bsrt_read
|
|
286
376
|
# @example Write to file
|
|
287
377
|
# File.open('rtree.bsrt', 'w') { |io| rtree.bsrt_write(io) }
|
|
378
|
+
#
|
|
288
379
|
def bsrt_write(io)
|
|
289
380
|
super
|
|
290
381
|
end
|
|
@@ -292,6 +383,7 @@ class RTree < RTreeC
|
|
|
292
383
|
# Serialise to JSON string
|
|
293
384
|
# @return [String] the UTF-8 encoded JSON
|
|
294
385
|
# @see .from_json
|
|
386
|
+
#
|
|
295
387
|
def to_json
|
|
296
388
|
serialise(Encoding::UTF_8) { |io| json_write(io) }
|
|
297
389
|
end
|
|
@@ -299,12 +391,14 @@ class RTree < RTreeC
|
|
|
299
391
|
# Serialise to BSRT string
|
|
300
392
|
# @return [String] the binary encoded BSRT
|
|
301
393
|
# @see .from_bsrt
|
|
394
|
+
#
|
|
302
395
|
def to_bsrt
|
|
303
396
|
serialise(Encoding::BINARY) { |io| bsrt_write(io) }
|
|
304
397
|
end
|
|
305
398
|
|
|
306
399
|
# The RTree structure in hash form
|
|
307
400
|
# @return [Hash]
|
|
401
|
+
#
|
|
308
402
|
def to_h
|
|
309
403
|
JSON.parse(to_json, symbolize_names: true)
|
|
310
404
|
end
|
|
@@ -314,6 +408,7 @@ class RTree < RTreeC
|
|
|
314
408
|
# must be in the same order. Certainly {#clone} will produce
|
|
315
409
|
# an instance which is equal in this sense.
|
|
316
410
|
# @return [Boolean] true if the instances are identical
|
|
411
|
+
#
|
|
317
412
|
def eq?(other)
|
|
318
413
|
super
|
|
319
414
|
end
|
|
@@ -321,6 +416,7 @@ class RTree < RTreeC
|
|
|
321
416
|
alias_method(:==, :eq?)
|
|
322
417
|
|
|
323
418
|
# @return [Integer] the dimension of the R-tree
|
|
419
|
+
#
|
|
324
420
|
def dim
|
|
325
421
|
super
|
|
326
422
|
end
|
|
@@ -331,41 +427,77 @@ class RTree < RTreeC
|
|
|
331
427
|
# running count). Performance-minded users may wish to
|
|
332
428
|
# cache this value (invalidating the cache when calling
|
|
333
429
|
# {#add_rect} of course).
|
|
430
|
+
#
|
|
334
431
|
def size
|
|
335
432
|
super
|
|
336
433
|
end
|
|
337
434
|
|
|
338
435
|
# @return [Integer] the bytes in a page of memory
|
|
436
|
+
#
|
|
339
437
|
def page_size
|
|
340
438
|
super
|
|
341
439
|
end
|
|
342
440
|
|
|
343
441
|
# @return [Integer] the size in bytes of a node
|
|
442
|
+
#
|
|
344
443
|
def node_size
|
|
345
444
|
super
|
|
346
445
|
end
|
|
347
446
|
|
|
348
447
|
# @return [Integer] the size in bytes of a rectangle
|
|
448
|
+
#
|
|
349
449
|
def rect_size
|
|
350
450
|
super
|
|
351
451
|
end
|
|
352
452
|
|
|
353
453
|
# @return [Integer] the size in bytes of a branch
|
|
454
|
+
#
|
|
354
455
|
def branch_size
|
|
355
456
|
super
|
|
356
457
|
end
|
|
357
458
|
|
|
358
459
|
# @return [Integer] the number of branches from each node
|
|
460
|
+
#
|
|
359
461
|
def branching_factor
|
|
360
462
|
super
|
|
361
463
|
end
|
|
362
464
|
|
|
363
465
|
# @return [Float] the volume of the unit sphere in the R-tree's
|
|
364
466
|
# dimension
|
|
467
|
+
#
|
|
365
468
|
def unit_sphere_volume
|
|
366
469
|
super
|
|
367
470
|
end
|
|
368
471
|
|
|
472
|
+
# Create a PostScript plot of the RTree
|
|
473
|
+
#
|
|
474
|
+
# @param io [IO] a writeable stream object
|
|
475
|
+
# @param style [RTree::Style] a style object describing the fill
|
|
476
|
+
# colour and stroke width and colour for each level of the tree.
|
|
477
|
+
# @param height [Float] the height of the plot in units of PostScript
|
|
478
|
+
# point (1/72 inch)
|
|
479
|
+
# @param width [Float] the width of the plot in units of PostScript
|
|
480
|
+
# point (1/72 inch), if neither height nor width is given then a
|
|
481
|
+
# width of 216 (3 inches) will be taken as default
|
|
482
|
+
# @param margin [Float] extra space around the plot in units of
|
|
483
|
+
# PostScript point (1/72 inch), default zero
|
|
484
|
+
#
|
|
485
|
+
# rdoc-image:img/cb-bupu3.png
|
|
486
|
+
#
|
|
487
|
+
def postscript(io, style, height: nil, width: nil, margin: 0)
|
|
488
|
+
if height && width then
|
|
489
|
+
raise ArgumentError, 'cannot specify both height and width'
|
|
490
|
+
end
|
|
491
|
+
if height then
|
|
492
|
+
axis = AXIS_HEIGHT
|
|
493
|
+
extent = height
|
|
494
|
+
else
|
|
495
|
+
axis = AXIS_WIDTH
|
|
496
|
+
extent = width || 216
|
|
497
|
+
end
|
|
498
|
+
super(style, axis, extent, margin, io)
|
|
499
|
+
end
|
|
500
|
+
|
|
369
501
|
private
|
|
370
502
|
|
|
371
503
|
attr_reader :split, :node_page
|
|
@@ -382,23 +514,73 @@ class RTree < RTreeC
|
|
|
382
514
|
node_page_flag | split_flag
|
|
383
515
|
end
|
|
384
516
|
|
|
385
|
-
def serialise(
|
|
386
|
-
|
|
387
|
-
if fork then
|
|
388
|
-
wr.close
|
|
389
|
-
result = rd.read
|
|
390
|
-
rd.close
|
|
391
|
-
Process.wait
|
|
392
|
-
else
|
|
393
|
-
rd.close
|
|
394
|
-
yield(wr)
|
|
395
|
-
wr.close
|
|
396
|
-
exit!
|
|
397
|
-
end
|
|
398
|
-
result
|
|
517
|
+
def serialise(*args, &block)
|
|
518
|
+
RTree::IOUtil.serialise(*args, &block)
|
|
399
519
|
end
|
|
400
520
|
|
|
401
|
-
|
|
402
521
|
end
|
|
403
522
|
|
|
404
|
-
|
|
523
|
+
# @author RTree::Style J. J. Green
|
|
524
|
+
#
|
|
525
|
+
# A Ruby wrapper around RTree styles, used in PostScript plotting.
|
|
526
|
+
# in particular by {RTree#postscript}.
|
|
527
|
+
#
|
|
528
|
+
class RTree::Style < RTreeStyleBase
|
|
529
|
+
|
|
530
|
+
class << self
|
|
531
|
+
|
|
532
|
+
# Create a new Style instance from JSON stream
|
|
533
|
+
# @param io [IO] a readable stream object
|
|
534
|
+
# @return [RTree::Style] the newly instantiated Style
|
|
535
|
+
# @example Read from file
|
|
536
|
+
# style = File.open('some.style', 'r') do |io|
|
|
537
|
+
# RTree::Style.json_read(io)
|
|
538
|
+
# end
|
|
539
|
+
#
|
|
540
|
+
def json_read(io)
|
|
541
|
+
super
|
|
542
|
+
end
|
|
543
|
+
|
|
544
|
+
# Create a new Style instance from JSON string
|
|
545
|
+
# @param json [String] a JSON string
|
|
546
|
+
# @return [RTree::Style] the newly instantiated Style
|
|
547
|
+
# @see .json_read
|
|
548
|
+
#
|
|
549
|
+
def from_json(json)
|
|
550
|
+
deserialise(json, Encoding::UTF_8) { |io| json_read(io) }
|
|
551
|
+
end
|
|
552
|
+
|
|
553
|
+
# Create a new Style instance from array of Hash
|
|
554
|
+
# @param array [Array] an array of hash, this will be converted
|
|
555
|
+
# to JSON and read by .from_json
|
|
556
|
+
# @return [RTree::Style] the newly instantiated Style
|
|
557
|
+
# @see .from_json
|
|
558
|
+
# @example Create a simple one-level style:
|
|
559
|
+
# style = RTree::Style.from_a(
|
|
560
|
+
# [
|
|
561
|
+
# {
|
|
562
|
+
# fill: {
|
|
563
|
+
# rgb: [0.5, 0.5, 0.5]
|
|
564
|
+
# },
|
|
565
|
+
# stroke: {
|
|
566
|
+
# rgb: [0, 0, 1],
|
|
567
|
+
# width: 3
|
|
568
|
+
# }
|
|
569
|
+
# }
|
|
570
|
+
# ]
|
|
571
|
+
# )
|
|
572
|
+
#
|
|
573
|
+
def from_a(array)
|
|
574
|
+
from_json(array.to_json)
|
|
575
|
+
end
|
|
576
|
+
|
|
577
|
+
alias_method :from_array, :from_a
|
|
578
|
+
|
|
579
|
+
private
|
|
580
|
+
|
|
581
|
+
def deserialise(*args, &block)
|
|
582
|
+
RTree::IOUtil.deserialise(*args, &block)
|
|
583
|
+
end
|
|
584
|
+
|
|
585
|
+
end
|
|
586
|
+
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: librtree
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.9.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- J.J. Green
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2021-
|
|
11
|
+
date: 2021-11-07 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -16,14 +16,14 @@ dependencies:
|
|
|
16
16
|
requirements:
|
|
17
17
|
- - "~>"
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: '2'
|
|
19
|
+
version: '2.1'
|
|
20
20
|
type: :development
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
24
|
- - "~>"
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: '2'
|
|
26
|
+
version: '2.1'
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: rake
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -44,14 +44,14 @@ dependencies:
|
|
|
44
44
|
requirements:
|
|
45
45
|
- - "~>"
|
|
46
46
|
- !ruby/object:Gem::Version
|
|
47
|
-
version: '3.
|
|
47
|
+
version: '3.10'
|
|
48
48
|
type: :development
|
|
49
49
|
prerelease: false
|
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
|
51
51
|
requirements:
|
|
52
52
|
- - "~>"
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
|
-
version: '3.
|
|
54
|
+
version: '3.10'
|
|
55
55
|
- !ruby/object:Gem::Dependency
|
|
56
56
|
name: yard
|
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -70,30 +70,30 @@ dependencies:
|
|
|
70
70
|
name: rubygems-tasks
|
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
|
72
72
|
requirements:
|
|
73
|
-
- - "
|
|
73
|
+
- - "~>"
|
|
74
74
|
- !ruby/object:Gem::Version
|
|
75
|
-
version: 0.2
|
|
75
|
+
version: '0.2'
|
|
76
76
|
type: :development
|
|
77
77
|
prerelease: false
|
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
|
79
79
|
requirements:
|
|
80
|
-
- - "
|
|
80
|
+
- - "~>"
|
|
81
81
|
- !ruby/object:Gem::Version
|
|
82
|
-
version: 0.2
|
|
82
|
+
version: '0.2'
|
|
83
83
|
- !ruby/object:Gem::Dependency
|
|
84
84
|
name: rake-compiler
|
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
|
86
86
|
requirements:
|
|
87
87
|
- - "~>"
|
|
88
88
|
- !ruby/object:Gem::Version
|
|
89
|
-
version: '1'
|
|
89
|
+
version: '1.1'
|
|
90
90
|
type: :development
|
|
91
91
|
prerelease: false
|
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
|
93
93
|
requirements:
|
|
94
94
|
- - "~>"
|
|
95
95
|
- !ruby/object:Gem::Version
|
|
96
|
-
version: '1'
|
|
96
|
+
version: '1.1'
|
|
97
97
|
description: |
|
|
98
98
|
A Ruby extension implementing the R-tree spatial-index of
|
|
99
99
|
Guttman-Green.
|