librtree 0.8.2 → 0.8.7
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/extconf.rb +0 -2
- data/ext/rtree/rtree.c +249 -124
- data/lib/rtree.rb +182 -8
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b33e172341a9e44682c139df3a6b92198b3dd83059340da9fb8752444afbac70
|
4
|
+
data.tar.gz: 7ba6d8c71b6afeb8e5dedde55ff08074db758fa7ea150a67195ff07ca426a312
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d4440a12038bd07dcb458ff993269fd72ac3826753f6e2757b86f19913a1cc748d7af1f37a7355e015d5a6dd3a750b8335a6f87d2a1dbdc5e4ef5387f9424f6a
|
7
|
+
data.tar.gz: ce193b26ab45e5ca2cab29c0c145a9432440355585e5cc5e226bbe0e762b3d4c33bcd693626ccd3f60eaad11513c94d3e8246e86cf8b703a7d89f19b22090d1b
|
data/ext/rtree/extconf.rb
CHANGED
@@ -20,11 +20,9 @@ puts LIB_DIRS.inspect
|
|
20
20
|
|
21
21
|
dir_config('librtree', HEADER_DIRS, LIB_DIRS)
|
22
22
|
|
23
|
-
abort 'missing csv.h' unless find_header('csv.h')
|
24
23
|
abort 'missing jansson.h' unless find_header('jansson.h')
|
25
24
|
abort 'missing rtree.h' unless find_header('rtree.h')
|
26
25
|
|
27
|
-
abort "libcsv is missing" unless find_library('csv', 'csv_init')
|
28
26
|
abort "libjansson is missing" unless find_library('jansson', 'json_pack')
|
29
27
|
abort "librtree is missing" unless find_library('rtree', 'rtree_new')
|
30
28
|
|
data/ext/rtree/rtree.c
CHANGED
@@ -1,38 +1,36 @@
|
|
1
1
|
#include <ruby.h>
|
2
2
|
#include <ruby/io.h>
|
3
|
+
#include <ruby/version.h>
|
3
4
|
|
4
5
|
#include <rtree.h>
|
6
|
+
#include <rtree/package.h>
|
7
|
+
#include <rtree/postscript.h>
|
5
8
|
|
6
9
|
#include <errno.h>
|
7
10
|
#include <stdint.h>
|
8
11
|
|
9
|
-
|
10
|
-
|
11
|
-
rtree_t *rtree;
|
12
|
-
} lrt_t;
|
12
|
+
static rb_data_type_t style_type;
|
13
|
+
static rb_data_type_t rtree_type;
|
13
14
|
|
14
|
-
static void
|
15
|
+
static void rt_dfree(void *p)
|
15
16
|
{
|
16
|
-
|
17
|
-
|
18
|
-
if (lrt->rtree)
|
19
|
-
{
|
20
|
-
rtree_destroy(lrt->rtree);
|
21
|
-
lrt->rtree = NULL;
|
22
|
-
}
|
17
|
+
rtree_destroy((rtree_t*)p);
|
23
18
|
}
|
24
19
|
|
25
|
-
static
|
20
|
+
static size_t rt_dsize(const void *p)
|
26
21
|
{
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
lrt->rtree = NULL;
|
22
|
+
return rtree_bytes((const rtree_t*)p);
|
23
|
+
}
|
31
24
|
|
32
|
-
|
25
|
+
static VALUE rt_alloc(VALUE cls)
|
26
|
+
{
|
27
|
+
rtree_t *rtree;;
|
28
|
+
if ((rtree = rtree_alloc()) == NULL)
|
29
|
+
rb_raise(rb_eNoMemError, "failed to alloc rtree");
|
30
|
+
return TypedData_Wrap_Struct(cls, &rtree_type, rtree);
|
33
31
|
}
|
34
32
|
|
35
|
-
static VALUE
|
33
|
+
static VALUE rt_init(VALUE self, VALUE dim_obj, VALUE flags_obj)
|
36
34
|
{
|
37
35
|
Check_Type(dim_obj, T_FIXNUM);
|
38
36
|
size_t dim = FIX2ULONG(dim_obj);
|
@@ -40,43 +38,38 @@ static VALUE lrt_init(VALUE self, VALUE dim_obj, VALUE flags_obj)
|
|
40
38
|
Check_Type(dim_obj, T_FIXNUM);
|
41
39
|
state_flags_t flags = FIX2UINT(flags_obj);
|
42
40
|
|
43
|
-
|
44
|
-
|
41
|
+
rtree_t *rtree;
|
42
|
+
TypedData_Get_Struct(self, rtree_t, &rtree_type, rtree);
|
45
43
|
|
46
|
-
if ((
|
47
|
-
rb_raise(rb_eNoMemError, "failed to
|
44
|
+
if ((rtree_init(rtree, dim, flags)) != 0)
|
45
|
+
rb_raise(rb_eNoMemError, "failed to init rtree");
|
48
46
|
|
49
47
|
return self;
|
50
48
|
}
|
51
49
|
|
52
|
-
static VALUE
|
50
|
+
static VALUE rt_release(VALUE self)
|
53
51
|
{
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
free(lrt->rtree);
|
58
|
-
|
52
|
+
rtree_t *rtree;
|
53
|
+
TypedData_Get_Struct(self, rtree_t, &rtree_type, rtree);
|
54
|
+
rtree_destroy(rtree);
|
59
55
|
return self;
|
60
56
|
}
|
61
57
|
|
62
|
-
static VALUE
|
58
|
+
static VALUE rt_height(VALUE self)
|
63
59
|
{
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
return INT2NUM(rtree_height(lrt->rtree));
|
60
|
+
rtree_t *rtree;
|
61
|
+
TypedData_Get_Struct(self, rtree_t, &rtree_type, rtree);
|
62
|
+
return INT2NUM(rtree_height(rtree));
|
68
63
|
}
|
69
64
|
|
70
|
-
static VALUE
|
65
|
+
static VALUE rt_add_rect(VALUE self, VALUE id_obj, VALUE coord_obj)
|
71
66
|
{
|
72
67
|
Check_Type(coord_obj, T_ARRAY);
|
73
68
|
Check_Type(id_obj, T_FIXNUM);
|
74
69
|
|
75
|
-
|
76
|
-
|
70
|
+
rtree_t *rtree;
|
71
|
+
TypedData_Get_Struct(self, rtree_t, &rtree_type, rtree);
|
77
72
|
|
78
|
-
rtree_t
|
79
|
-
*rtree = lrt->rtree;
|
80
73
|
rtree_id_t
|
81
74
|
id = FIX2ULONG(id_obj);
|
82
75
|
size_t
|
@@ -127,16 +120,15 @@ static int update_cb(rtree_id_t id, rtree_coord_t *coord, void *context)
|
|
127
120
|
return 0;
|
128
121
|
}
|
129
122
|
|
130
|
-
static VALUE
|
123
|
+
static VALUE rt_update(VALUE self)
|
131
124
|
{
|
132
125
|
if (!rb_block_given_p())
|
133
126
|
rb_raise(rb_eArgError, "Expected block");
|
134
127
|
|
135
|
-
|
136
|
-
|
137
|
-
rtree_t *rtree = lrt->rtree;
|
138
|
-
size_t len = 2 * state_dims(rtree->state);
|
128
|
+
rtree_t *rtree;
|
129
|
+
TypedData_Get_Struct(self, rtree_t, &rtree_type, rtree);
|
139
130
|
|
131
|
+
size_t len = 2 * state_dims(rtree->state);
|
140
132
|
int err = rtree_update(rtree, update_cb, &len);
|
141
133
|
|
142
134
|
if (err != 0)
|
@@ -162,18 +154,16 @@ static int search_cb(rtree_id_t id, void *context)
|
|
162
154
|
return 0;
|
163
155
|
}
|
164
156
|
|
165
|
-
static VALUE
|
157
|
+
static VALUE rt_search(VALUE self, VALUE coord_obj)
|
166
158
|
{
|
167
159
|
if (!rb_block_given_p())
|
168
160
|
rb_raise(rb_eArgError, "Expected block");
|
169
161
|
|
170
162
|
Check_Type(coord_obj, T_ARRAY);
|
171
163
|
|
172
|
-
|
173
|
-
|
164
|
+
rtree_t *rtree;
|
165
|
+
TypedData_Get_Struct(self, rtree_t, &rtree_type, rtree);
|
174
166
|
|
175
|
-
rtree_t
|
176
|
-
*rtree = lrt->rtree;
|
177
167
|
size_t
|
178
168
|
len = RARRAY_LEN(coord_obj),
|
179
169
|
dim = state_dims(rtree->state);
|
@@ -215,26 +205,21 @@ static VALUE deserialise(VALUE cls, VALUE io_obj, deserialise_t *f)
|
|
215
205
|
rb_raise(rb_eRuntimeError, "Failed read from stream");
|
216
206
|
}
|
217
207
|
|
218
|
-
|
219
|
-
VALUE obj = Data_Make_Struct(cls, lrt_t, NULL, lrt_free, lrt);
|
220
|
-
|
221
|
-
lrt->rtree = rtree;
|
222
|
-
|
223
|
-
return obj;
|
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,12 +244,7 @@ static VALUE lrt_csv_read(VALUE cls,
|
|
259
244
|
rb_raise(rb_eRuntimeError, "Failed read from stream");
|
260
245
|
}
|
261
246
|
|
262
|
-
|
263
|
-
VALUE obj = Data_Make_Struct(cls, lrt_t, NULL, lrt_free, lrt);
|
264
|
-
|
265
|
-
lrt->rtree = rtree;
|
266
|
-
|
267
|
-
return obj;
|
247
|
+
return TypedData_Wrap_Struct(cls, &rtree_type, rtree);
|
268
248
|
}
|
269
249
|
|
270
250
|
/* serialisation */
|
@@ -281,9 +261,8 @@ static VALUE serialise(VALUE self, VALUE io_obj, serialise_t *f)
|
|
281
261
|
rb_io_check_writable(io);
|
282
262
|
FILE *fp = rb_io_stdio_file(io);
|
283
263
|
|
284
|
-
|
285
|
-
|
286
|
-
rtree_t *rtree = lrt->rtree;
|
264
|
+
rtree_t *rtree;
|
265
|
+
TypedData_Get_Struct(self, rtree_t, &rtree_type, rtree);
|
287
266
|
|
288
267
|
int err = f(rtree, fp);
|
289
268
|
if (err != 0)
|
@@ -292,24 +271,22 @@ static VALUE serialise(VALUE self, VALUE io_obj, serialise_t *f)
|
|
292
271
|
return self;
|
293
272
|
}
|
294
273
|
|
295
|
-
static VALUE
|
274
|
+
static VALUE rt_json_write(VALUE self, VALUE io_obj)
|
296
275
|
{
|
297
276
|
return serialise(self, io_obj, rtree_json_write);
|
298
277
|
}
|
299
278
|
|
300
|
-
static VALUE
|
279
|
+
static VALUE rt_bsrt_write(VALUE self, VALUE io_obj)
|
301
280
|
{
|
302
281
|
return serialise(self, io_obj, rtree_bsrt_write);
|
303
282
|
}
|
304
283
|
|
305
|
-
static VALUE
|
284
|
+
static VALUE rt_identical(VALUE self, VALUE other)
|
306
285
|
{
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
rtree_t
|
311
|
-
*rtree_self = lrt_self->rtree,
|
312
|
-
*rtree_other = lrt_other->rtree;
|
286
|
+
rtree_t *rtree_self, *rtree_other;
|
287
|
+
|
288
|
+
TypedData_Get_Struct(self, rtree_t, &rtree_type, rtree_self);
|
289
|
+
TypedData_Get_Struct(other, rtree_t, &rtree_type, rtree_other);
|
313
290
|
|
314
291
|
if (rtree_identical(rtree_self, rtree_other))
|
315
292
|
return Qtrue;
|
@@ -317,14 +294,14 @@ static VALUE lrt_identical(VALUE self, VALUE other)
|
|
317
294
|
return Qfalse;
|
318
295
|
}
|
319
296
|
|
320
|
-
static VALUE
|
297
|
+
static VALUE rt_clone(VALUE self)
|
321
298
|
{
|
322
|
-
lrt_t *lrt;
|
323
|
-
Data_Get_Struct(self, lrt_t, lrt);
|
324
299
|
rtree_t *rtree;
|
300
|
+
TypedData_Get_Struct(self, rtree_t, &rtree_type, rtree);
|
325
301
|
|
302
|
+
rtree_t *clone;
|
326
303
|
errno = 0;
|
327
|
-
if ((
|
304
|
+
if ((clone = rtree_clone(rtree)) == NULL)
|
328
305
|
{
|
329
306
|
if (errno)
|
330
307
|
rb_sys_fail(__func__);
|
@@ -332,83 +309,231 @@ static VALUE lrt_clone(VALUE self)
|
|
332
309
|
rb_raise(rb_eRuntimeError, "Failed clone");
|
333
310
|
}
|
334
311
|
|
335
|
-
|
336
|
-
VALUE cls = CLASS_OF(self);
|
337
|
-
VALUE obj = Data_Make_Struct(cls, lrt_t, NULL, lrt_free, lrt_cloned);
|
338
|
-
|
339
|
-
lrt_cloned->rtree = rtree;
|
340
|
-
|
341
|
-
return obj;
|
312
|
+
return TypedData_Wrap_Struct(CLASS_OF(self), &rtree_type, clone);
|
342
313
|
}
|
343
314
|
|
344
315
|
static VALUE state_size_access(VALUE self, size_t (*f)(const state_t*))
|
345
316
|
{
|
346
|
-
|
347
|
-
|
348
|
-
return INT2NUM(f(
|
317
|
+
rtree_t *rtree;
|
318
|
+
TypedData_Get_Struct(self, rtree_t, &rtree_type, rtree);
|
319
|
+
return INT2NUM(f(rtree->state));
|
349
320
|
}
|
350
321
|
|
351
|
-
static VALUE
|
322
|
+
static VALUE rt_dim(VALUE self)
|
352
323
|
{
|
353
324
|
return state_size_access(self, state_dims);
|
354
325
|
}
|
355
326
|
|
356
|
-
static VALUE
|
327
|
+
static VALUE rt_page_size(VALUE self)
|
357
328
|
{
|
358
329
|
return state_size_access(self, state_page_size);
|
359
330
|
}
|
360
331
|
|
361
|
-
static VALUE
|
332
|
+
static VALUE rt_node_size(VALUE self)
|
362
333
|
{
|
363
334
|
return state_size_access(self, state_node_size);
|
364
335
|
}
|
365
336
|
|
366
|
-
static VALUE
|
337
|
+
static VALUE rt_rect_size(VALUE self)
|
367
338
|
{
|
368
339
|
return state_size_access(self, state_rect_size);
|
369
340
|
}
|
370
341
|
|
371
|
-
static VALUE
|
342
|
+
static VALUE rt_branch_size(VALUE self)
|
372
343
|
{
|
373
344
|
return state_size_access(self, state_branch_size);
|
374
345
|
}
|
375
346
|
|
376
|
-
static VALUE
|
347
|
+
static VALUE rt_branching_factor(VALUE self)
|
377
348
|
{
|
378
349
|
return state_size_access(self, state_branching_factor);
|
379
350
|
}
|
380
351
|
|
381
|
-
static VALUE
|
352
|
+
static VALUE rt_unit_sphere_volume(VALUE self)
|
353
|
+
{
|
354
|
+
rtree_t *rtree;
|
355
|
+
TypedData_Get_Struct(self, rtree_t, &rtree_type, rtree);
|
356
|
+
return DBL2NUM(state_unit_sphere_volume(rtree->state));
|
357
|
+
}
|
358
|
+
|
359
|
+
static VALUE rt_size(VALUE self)
|
360
|
+
{
|
361
|
+
rtree_t *rtree;
|
362
|
+
TypedData_Get_Struct(self, rtree_t, &rtree_type, rtree);
|
363
|
+
return INT2NUM(rtree_bytes(rtree));
|
364
|
+
}
|
365
|
+
|
366
|
+
static VALUE rt_version(VALUE self)
|
367
|
+
{
|
368
|
+
return rb_str_new_cstr(rtree_package_version);
|
369
|
+
}
|
370
|
+
|
371
|
+
static VALUE rt_bugreport(VALUE self)
|
372
|
+
{
|
373
|
+
return rb_str_new_cstr(rtree_package_bugreport);
|
374
|
+
}
|
375
|
+
|
376
|
+
static VALUE rt_url(VALUE self)
|
377
|
+
{
|
378
|
+
return rb_str_new_cstr(rtree_package_url);
|
379
|
+
}
|
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)
|
382
387
|
{
|
383
|
-
|
384
|
-
|
385
|
-
|
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);
|
386
479
|
}
|
387
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
|
+
};
|
388
498
|
|
389
499
|
void Init_rtree(void)
|
390
500
|
{
|
391
|
-
VALUE
|
392
|
-
|
393
|
-
rb_define_alloc_func(
|
394
|
-
rb_define_method(
|
395
|
-
rb_define_method(
|
396
|
-
rb_define_method(
|
397
|
-
rb_define_method(
|
398
|
-
rb_define_method(
|
399
|
-
rb_define_method(
|
400
|
-
rb_define_method(
|
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
|
-
|
412
|
-
|
413
|
-
rb_define_singleton_method(
|
501
|
+
VALUE cRTree = rb_const_get(rb_cObject, rb_intern("RTreeC"));
|
502
|
+
|
503
|
+
rb_define_alloc_func(cRTree, rt_alloc);
|
504
|
+
rb_define_method(cRTree, "initialize", rt_init, 2);
|
505
|
+
rb_define_method(cRTree, "free", rt_release, 0);
|
506
|
+
rb_define_method(cRTree, "clone", rt_clone, 0);
|
507
|
+
rb_define_method(cRTree, "update!", rt_update, 0);
|
508
|
+
rb_define_method(cRTree, "height", rt_height, 0);
|
509
|
+
rb_define_method(cRTree, "add_rect", rt_add_rect, 2);
|
510
|
+
rb_define_method(cRTree, "search", rt_search, 1);
|
511
|
+
rb_define_method(cRTree, "json_write", rt_json_write, 1);
|
512
|
+
rb_define_method(cRTree, "bsrt_write", rt_bsrt_write, 1);
|
513
|
+
rb_define_method(cRTree, "eq?", rt_identical, 1);
|
514
|
+
rb_define_method(cRTree, "dim", rt_dim, 0);
|
515
|
+
rb_define_method(cRTree, "size", rt_size, 0);
|
516
|
+
rb_define_method(cRTree, "page_size", rt_page_size, 0);
|
517
|
+
rb_define_method(cRTree, "node_size", rt_node_size, 0);
|
518
|
+
rb_define_method(cRTree, "rect_size", rt_rect_size, 0);
|
519
|
+
rb_define_method(cRTree, "branch_size", rt_branch_size, 0);
|
520
|
+
rb_define_method(cRTree, "branching_factor", rt_branching_factor, 0);
|
521
|
+
rb_define_method(cRTree, "unit_sphere_volume", rt_unit_sphere_volume, 0);
|
522
|
+
rb_define_method(cRTree, "postscript", rt_postscript, 5);
|
523
|
+
rb_define_singleton_method(cRTree, "version", rt_version, 0);
|
524
|
+
rb_define_singleton_method(cRTree, "bugreport", rt_bugreport, 0);
|
525
|
+
rb_define_singleton_method(cRTree, "url", rt_url, 0);
|
526
|
+
rb_define_singleton_method(cRTree, "json_read", rt_json_read, 1);
|
527
|
+
rb_define_singleton_method(cRTree, "bsrt_read", rt_bsrt_read, 1);
|
528
|
+
rb_define_singleton_method(cRTree, "csv_read", rt_csv_read, 3);
|
529
|
+
rb_define_const(cRTree, "SPLIT_QUADRATIC", INT2NUM(RTREE_SPLIT_QUADRATIC));
|
530
|
+
rb_define_const(cRTree, "SPLIT_LINEAR", INT2NUM(RTREE_SPLIT_LINEAR));
|
531
|
+
rb_define_const(cRTree, "SPLIT_GREENE", INT2NUM(RTREE_SPLIT_GREENE));
|
532
|
+
rb_define_const(cRTree, "AXIS_HEIGHT", INT2NUM(axis_height));
|
533
|
+
rb_define_const(cRTree, "AXIS_WIDTH", INT2NUM(axis_width));
|
534
|
+
|
535
|
+
VALUE cStyle = rb_define_class_under(cRTree, "StyleC", rb_cObject);
|
536
|
+
|
537
|
+
rb_define_method(cStyle, "free", st_release, 0);
|
538
|
+
rb_define_singleton_method(cStyle, "json_read", st_json_read, 1);
|
414
539
|
}
|
data/lib/rtree.rb
CHANGED
@@ -1,5 +1,12 @@
|
|
1
|
-
# The Ruby/C interface
|
2
|
-
|
1
|
+
# The Ruby/C interface to RTree, not documented in YARD.
|
2
|
+
#
|
3
|
+
class RTreeC
|
4
|
+
# The Ruby/C interface to RTree::Style, not documented in YARD.
|
5
|
+
#
|
6
|
+
class StyleC ; end
|
7
|
+
end
|
8
|
+
|
9
|
+
require 'json'
|
3
10
|
|
4
11
|
# @author RTree J. J. Green
|
5
12
|
#
|
@@ -61,6 +68,7 @@ class RTree < RTreeC
|
|
61
68
|
# @see #json_write
|
62
69
|
# @example Read from file
|
63
70
|
# rtree = File.open('rtree.json', 'r') { |io| RTree.json_read(io) }
|
71
|
+
#
|
64
72
|
def json_read(io)
|
65
73
|
super
|
66
74
|
end
|
@@ -69,6 +77,7 @@ class RTree < RTreeC
|
|
69
77
|
# @param json [String] a JSON string
|
70
78
|
# @return [RTree] the newly instantiated RTree
|
71
79
|
# @see #to_json
|
80
|
+
#
|
72
81
|
def from_json(json)
|
73
82
|
deserialise(json, Encoding::UTF_8) { |io| json_read(io) }
|
74
83
|
end
|
@@ -80,6 +89,7 @@ class RTree < RTreeC
|
|
80
89
|
# @see #bsrt_write
|
81
90
|
# @example Read from file
|
82
91
|
# rtree = File.open('rtree.bsrt', 'r') { |io| RTree.bsrt_read(io) }
|
92
|
+
#
|
83
93
|
def bsrt_read(io)
|
84
94
|
super
|
85
95
|
end
|
@@ -89,6 +99,7 @@ class RTree < RTreeC
|
|
89
99
|
# @param bsrt [String] a binary encoded string
|
90
100
|
# @return [RTree] the newly instantiated RTree
|
91
101
|
# @see #to_bsrt
|
102
|
+
#
|
92
103
|
def from_bsrt(bsrt)
|
93
104
|
deserialise(bsrt, Encoding::BINARY) { |io| bsrt_read(io) }
|
94
105
|
end
|
@@ -96,7 +107,7 @@ class RTree < RTreeC
|
|
96
107
|
# Build a new RTree instance from CSV stream
|
97
108
|
# @param io [IO] a readable stream object
|
98
109
|
# @param dim [Integer] the dimension of the tree
|
99
|
-
# @param split [:linear, :quadratic] See {#initialize}
|
110
|
+
# @param split [:linear, :quadratic, :greene] See {#initialize}
|
100
111
|
# @param node_page [Integer] See {#initialize}
|
101
112
|
# @return [RTree] the newly built RTree
|
102
113
|
# @note The CSV file (without header) should have the id in the
|
@@ -104,6 +115,7 @@ class RTree < RTreeC
|
|
104
115
|
# Extra columns may be present and will be ignored (this
|
105
116
|
# useful feature is the reason that the dimension is a required
|
106
117
|
# argument).
|
118
|
+
#
|
107
119
|
def csv_read(io, dim, split: :quadratic, node_page: 0)
|
108
120
|
flags = split_flag(split) | node_page_flag(node_page)
|
109
121
|
super(io, dim, flags)
|
@@ -114,25 +126,48 @@ class RTree < RTreeC
|
|
114
126
|
# @param dim [Integer] the dimension of the tree
|
115
127
|
# @param kwarg [Hash] As for {.csv_read}
|
116
128
|
# @return [RTree] the newly built RTree
|
129
|
+
#
|
117
130
|
def from_csv(csv, dim, **kwarg)
|
118
131
|
deserialise(csv, Encoding::UTF_8) do |io|
|
119
132
|
csv_read(io, dim, **kwarg)
|
120
133
|
end
|
121
134
|
end
|
122
135
|
|
136
|
+
# @return [Array<Integer>] version of librtree
|
137
|
+
#
|
138
|
+
def version
|
139
|
+
@version ||= super.split('.').map(&:to_i)
|
140
|
+
end
|
141
|
+
|
142
|
+
# @return [String] email address for librtree bug reports
|
143
|
+
#
|
144
|
+
def bugreport
|
145
|
+
super
|
146
|
+
end
|
147
|
+
|
148
|
+
# @return [String] librtree homepage
|
149
|
+
#
|
150
|
+
def url
|
151
|
+
super
|
152
|
+
end
|
153
|
+
|
123
154
|
# @!visibility private
|
155
|
+
#
|
124
156
|
def split_flag(split)
|
125
157
|
case split
|
126
158
|
when :quadratic
|
127
|
-
|
159
|
+
self::SPLIT_QUADRATIC
|
128
160
|
when :linear
|
129
|
-
|
161
|
+
self::SPLIT_LINEAR
|
162
|
+
when :greene
|
163
|
+
self::SPLIT_GREENE
|
130
164
|
else
|
131
165
|
raise ArgumentError, "bad split value: #{split}"
|
132
166
|
end
|
133
167
|
end
|
134
168
|
|
135
169
|
# @!visibility private
|
170
|
+
#
|
136
171
|
def node_page_flag(node_page)
|
137
172
|
node_page << 2
|
138
173
|
end
|
@@ -165,9 +200,10 @@ class RTree < RTreeC
|
|
165
200
|
|
166
201
|
# Initialize a new (empty) RTree
|
167
202
|
# @param dim [Integer] the dimension of the tree
|
168
|
-
# @param split [:linear, :quadratic] determines the splitting
|
169
|
-
# the linear strategy is faster to build, the quadratic
|
170
|
-
# better-quality R-
|
203
|
+
# @param split [:linear, :quadratic, :greene] determines the splitting
|
204
|
+
# strategy, the linear strategy is faster to build, the quadratic
|
205
|
+
# and greene strategies produce better-quality R-trees which are
|
206
|
+
# faster to query.
|
171
207
|
# @param node_page [Integer] the nodes-per-page value. This value can
|
172
208
|
# affect performance quite dramatically, particularly build time. A
|
173
209
|
# value which is too large would result in an infeasible branching
|
@@ -177,6 +213,7 @@ class RTree < RTreeC
|
|
177
213
|
# You may get better performance for your use-case by manual
|
178
214
|
# experimentation, but zero is a good place to start.
|
179
215
|
# @return [RTree] the newly instantiated RTree
|
216
|
+
#
|
180
217
|
def initialize(dim, split: :quadratic, node_page: 0)
|
181
218
|
@split = split
|
182
219
|
@node_page = node_page
|
@@ -185,6 +222,7 @@ class RTree < RTreeC
|
|
185
222
|
|
186
223
|
# Create a deep copy
|
187
224
|
# @return [RTree] a deep copy of the RTree
|
225
|
+
#
|
188
226
|
def clone
|
189
227
|
super
|
190
228
|
end
|
@@ -201,6 +239,7 @@ class RTree < RTreeC
|
|
201
239
|
# @example Add a rectangle to a dimension two RTree
|
202
240
|
# rtree = RTree.new(2)
|
203
241
|
# rtree.add_rect(7, [0, 0, 1, 1])
|
242
|
+
#
|
204
243
|
def add_rect(id, coords)
|
205
244
|
super
|
206
245
|
end
|
@@ -210,6 +249,7 @@ class RTree < RTreeC
|
|
210
249
|
# @return [Array<Integer>] the ids of all rectangles which intersect
|
211
250
|
# the search rectangle. If a block is given then these values will
|
212
251
|
# be yielded to the block (one at a time).
|
252
|
+
#
|
213
253
|
def search(coords)
|
214
254
|
if block_given? then
|
215
255
|
super
|
@@ -235,18 +275,21 @@ class RTree < RTreeC
|
|
235
275
|
# block and then convert the returned Ruby Floats to C; so we would
|
236
276
|
# expect that it loses much of its competitive advantage when
|
237
277
|
# compared to an R-tree rebuild.
|
278
|
+
#
|
238
279
|
def update!
|
239
280
|
super
|
240
281
|
end
|
241
282
|
|
242
283
|
# The height to the tree in the usual mathematical sense
|
243
284
|
# @return [Integer] the tree height
|
285
|
+
#
|
244
286
|
def height
|
245
287
|
super
|
246
288
|
end
|
247
289
|
|
248
290
|
# Whether the RTree has any rectangles or not
|
249
291
|
# @return [Boolean] true if the RTree is empty
|
292
|
+
#
|
250
293
|
def empty?
|
251
294
|
height == 0
|
252
295
|
end
|
@@ -257,6 +300,7 @@ class RTree < RTreeC
|
|
257
300
|
# @see .json_read
|
258
301
|
# @example Write to file
|
259
302
|
# File.open('rtree.json', 'w') { |io| rtree.json_write(io) }
|
303
|
+
#
|
260
304
|
def json_write(io)
|
261
305
|
super
|
262
306
|
end
|
@@ -267,6 +311,7 @@ class RTree < RTreeC
|
|
267
311
|
# @see .bsrt_read
|
268
312
|
# @example Write to file
|
269
313
|
# File.open('rtree.bsrt', 'w') { |io| rtree.bsrt_write(io) }
|
314
|
+
#
|
270
315
|
def bsrt_write(io)
|
271
316
|
super
|
272
317
|
end
|
@@ -274,6 +319,7 @@ class RTree < RTreeC
|
|
274
319
|
# Serialise to JSON string
|
275
320
|
# @return [String] the UTF-8 encoded JSON
|
276
321
|
# @see .from_json
|
322
|
+
#
|
277
323
|
def to_json
|
278
324
|
serialise(Encoding::UTF_8) { |io| json_write(io) }
|
279
325
|
end
|
@@ -281,12 +327,14 @@ class RTree < RTreeC
|
|
281
327
|
# Serialise to BSRT string
|
282
328
|
# @return [String] the binary encoded BSRT
|
283
329
|
# @see .from_bsrt
|
330
|
+
#
|
284
331
|
def to_bsrt
|
285
332
|
serialise(Encoding::BINARY) { |io| bsrt_write(io) }
|
286
333
|
end
|
287
334
|
|
288
335
|
# The RTree structure in hash form
|
289
336
|
# @return [Hash]
|
337
|
+
#
|
290
338
|
def to_h
|
291
339
|
JSON.parse(to_json, symbolize_names: true)
|
292
340
|
end
|
@@ -296,6 +344,7 @@ class RTree < RTreeC
|
|
296
344
|
# must be in the same order. Certainly {#clone} will produce
|
297
345
|
# an instance which is equal in this sense.
|
298
346
|
# @return [Boolean] true if the instances are identical
|
347
|
+
#
|
299
348
|
def eq?(other)
|
300
349
|
super
|
301
350
|
end
|
@@ -303,41 +352,85 @@ class RTree < RTreeC
|
|
303
352
|
alias_method(:==, :eq?)
|
304
353
|
|
305
354
|
# @return [Integer] the dimension of the R-tree
|
355
|
+
#
|
306
356
|
def dim
|
307
357
|
super
|
308
358
|
end
|
309
359
|
|
360
|
+
# @return [Integer] the total bytes allocated for the instance
|
361
|
+
# @note This method traverses the entire tree summing the
|
362
|
+
# contributions for each node (rather than maintaining a
|
363
|
+
# running count). Performance-minded users may wish to
|
364
|
+
# cache this value (invalidating the cache when calling
|
365
|
+
# {#add_rect} of course).
|
366
|
+
#
|
367
|
+
def size
|
368
|
+
super
|
369
|
+
end
|
370
|
+
|
310
371
|
# @return [Integer] the bytes in a page of memory
|
372
|
+
#
|
311
373
|
def page_size
|
312
374
|
super
|
313
375
|
end
|
314
376
|
|
315
377
|
# @return [Integer] the size in bytes of a node
|
378
|
+
#
|
316
379
|
def node_size
|
317
380
|
super
|
318
381
|
end
|
319
382
|
|
320
383
|
# @return [Integer] the size in bytes of a rectangle
|
384
|
+
#
|
321
385
|
def rect_size
|
322
386
|
super
|
323
387
|
end
|
324
388
|
|
325
389
|
# @return [Integer] the size in bytes of a branch
|
390
|
+
#
|
326
391
|
def branch_size
|
327
392
|
super
|
328
393
|
end
|
329
394
|
|
330
395
|
# @return [Integer] the number of branches from each node
|
396
|
+
#
|
331
397
|
def branching_factor
|
332
398
|
super
|
333
399
|
end
|
334
400
|
|
335
401
|
# @return [Float] the volume of the unit sphere in the R-tree's
|
336
402
|
# dimension
|
403
|
+
#
|
337
404
|
def unit_sphere_volume
|
338
405
|
super
|
339
406
|
end
|
340
407
|
|
408
|
+
# Create a PostScript plot of the RTree
|
409
|
+
# @param io [IO] a writeable stream object
|
410
|
+
# @param style [RTree::Style] a style object describing the fill
|
411
|
+
# colour and stroke width and colour for each level of the tree.
|
412
|
+
# @param height [Float] the height of the plot in units of PostScript
|
413
|
+
# point (1/72 inch)
|
414
|
+
# @param width [Float] the width of the plot in units of PostScript
|
415
|
+
# point (1/72 inch), if neither height nor width is given then a
|
416
|
+
# width of 216 (3 inches) will be taken as default
|
417
|
+
# @param margin [Float] extra space around the plot in units of
|
418
|
+
# PostScript point (1/72 inch), default zero
|
419
|
+
#
|
420
|
+
def postscript(io, style, height: nil, width: nil, margin: 0)
|
421
|
+
if height && width then
|
422
|
+
raise ArgumentError, 'cannot specify both height and width'
|
423
|
+
end
|
424
|
+
if height then
|
425
|
+
axis = AXIS_HEIGHT
|
426
|
+
extent = height
|
427
|
+
else
|
428
|
+
axis = AXIS_WIDTH
|
429
|
+
extent = width || 216
|
430
|
+
end
|
431
|
+
super(style, axis, extent, margin, io)
|
432
|
+
end
|
433
|
+
|
341
434
|
private
|
342
435
|
|
343
436
|
attr_reader :split, :node_page
|
@@ -369,8 +462,89 @@ class RTree < RTreeC
|
|
369
462
|
end
|
370
463
|
result
|
371
464
|
end
|
465
|
+
end
|
466
|
+
|
467
|
+
|
468
|
+
class RTree < RTreeC
|
469
|
+
class Style < RTreeC::StyleC
|
470
|
+
end
|
471
|
+
end
|
472
|
+
|
473
|
+
# @author RTree::Style J. J. Green
|
474
|
+
#
|
475
|
+
# A Ruby wrapper around RTree styles, used in PostScript plotting.
|
476
|
+
# in particular by {RTree#postscript}.
|
477
|
+
#
|
478
|
+
class RTree::Style
|
479
|
+
|
480
|
+
class << self
|
372
481
|
|
482
|
+
# Create a new Style instance from JSON stream
|
483
|
+
# @param io [IO] a readable stream object
|
484
|
+
# @return [RTree::Style] the newly instantiated Style
|
485
|
+
# @example Read from file
|
486
|
+
# style = File.open('some.style', 'r') do |io|
|
487
|
+
# RTree::Style.json_read(io)
|
488
|
+
# end
|
489
|
+
#
|
490
|
+
def json_read(io)
|
491
|
+
super
|
492
|
+
end
|
373
493
|
|
494
|
+
# Create a new Style instance from JSON string
|
495
|
+
# @param json [String] a JSON string
|
496
|
+
# @return [RTree::Style] the newly instantiated Style
|
497
|
+
# @see .json_read
|
498
|
+
#
|
499
|
+
def from_json(json)
|
500
|
+
raise TypeError unless json.is_a? String
|
501
|
+
rd, wr = IO.pipe(Encoding::UTF_8)
|
502
|
+
if fork then
|
503
|
+
wr.close
|
504
|
+
begin
|
505
|
+
result = json_read(rd)
|
506
|
+
ensure
|
507
|
+
rd.close
|
508
|
+
Process.wait
|
509
|
+
end
|
510
|
+
else
|
511
|
+
rd.close
|
512
|
+
begin
|
513
|
+
wr.write(json)
|
514
|
+
ensure
|
515
|
+
wr.close
|
516
|
+
exit!
|
517
|
+
end
|
518
|
+
end
|
519
|
+
result
|
520
|
+
end
|
521
|
+
|
522
|
+
# Create a new Style instance from array of Hash
|
523
|
+
# @param array [Array] an array of hash, this will be converted
|
524
|
+
# to JSON and read by .from_json
|
525
|
+
# @return [RTree::Style] the newly instantiated Style
|
526
|
+
# @see .from_json
|
527
|
+
# @example Create a simple one-level style:
|
528
|
+
# style = RTree::Style.from_a(
|
529
|
+
# [
|
530
|
+
# {
|
531
|
+
# fill: {
|
532
|
+
# rgb: [0.5, 0.5, 0.5]
|
533
|
+
# },
|
534
|
+
# stroke: {
|
535
|
+
# rgb: [0, 0, 1],
|
536
|
+
# width: 3
|
537
|
+
# }
|
538
|
+
# }
|
539
|
+
# ]
|
540
|
+
# )
|
541
|
+
#
|
542
|
+
def from_a(array)
|
543
|
+
from_json(array.to_json)
|
544
|
+
end
|
545
|
+
|
546
|
+
alias_method :from_array, :from_a
|
547
|
+
end
|
374
548
|
end
|
375
549
|
|
376
550
|
require 'rtree/rtree'
|
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.8.
|
4
|
+
version: 0.8.7
|
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-06-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -95,8 +95,8 @@ dependencies:
|
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '1'
|
97
97
|
description: |
|
98
|
-
A Ruby extension
|
99
|
-
|
98
|
+
A Ruby extension implementing the R-tree spatial-index of
|
99
|
+
Guttman-Green.
|
100
100
|
email: j.j.green@gmx.co.uk
|
101
101
|
executables: []
|
102
102
|
extensions:
|
@@ -119,14 +119,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
119
119
|
requirements:
|
120
120
|
- - ">="
|
121
121
|
- !ruby/object:Gem::Version
|
122
|
-
version: '0'
|
122
|
+
version: '2.0'
|
123
123
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
124
124
|
requirements:
|
125
125
|
- - ">="
|
126
126
|
- !ruby/object:Gem::Version
|
127
127
|
version: '0'
|
128
128
|
requirements:
|
129
|
-
- The librtree library
|
129
|
+
- The librtree library (1.0.6 or later)
|
130
130
|
rubygems_version: 3.1.2
|
131
131
|
signing_key:
|
132
132
|
specification_version: 4
|