librtree 0.8.4 → 0.8.8
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 +204 -90
- data/lib/rtree.rb +159 -11
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fc74390aa8eb79643f88f2c48f7408ef9dd17dd12ed1049e3bfe2961b7523e4b
|
4
|
+
data.tar.gz: 25488f67912344fcd69cb2c19ca6b4344cf708bfc07d9f8e1629b5893030a759
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4bc5ae0e333e077a8331164e87f3d4c60470bfadc046c86424b8147d59ecfdb32b212d7ae7ec0d3e834d62b0c564929723a56af988a5b5a05364ba9e841407ff
|
7
|
+
data.tar.gz: 2b5d8c0799fabb2085686f4c3eb23feb367201d6630d4ac7e0621cc76ba5dbc6422b0e4d5649aee33fc375cff3411308ef81d61567f1af6049f50b677aa198de
|
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
@@ -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);
|
@@ -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,102 +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(
|
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);
|
425
539
|
}
|
data/lib/rtree.rb
CHANGED
@@ -1,5 +1,13 @@
|
|
1
|
-
# The Ruby/C interface
|
2
|
-
|
1
|
+
# The internal Ruby/C interface for RTree, not documented in YARD.
|
2
|
+
#
|
3
|
+
class RTreeBase ; end
|
4
|
+
|
5
|
+
# The internal Ruby/C interface for RTree::Style, not documented in YARD.
|
6
|
+
#
|
7
|
+
class RTreeStyleBase ; end
|
8
|
+
|
9
|
+
require 'rtree/rtree'
|
10
|
+
require 'json'
|
3
11
|
|
4
12
|
# @author RTree J. J. Green
|
5
13
|
#
|
@@ -51,7 +59,7 @@ class RTreeC ; end
|
|
51
59
|
# determined at compile-time (with the RTREE_ID_TYPE variable) and by
|
52
60
|
# default this is a 64-bit unsigned integer.
|
53
61
|
#
|
54
|
-
class RTree <
|
62
|
+
class RTree < RTreeBase
|
55
63
|
|
56
64
|
class << self
|
57
65
|
|
@@ -61,6 +69,7 @@ class RTree < RTreeC
|
|
61
69
|
# @see #json_write
|
62
70
|
# @example Read from file
|
63
71
|
# rtree = File.open('rtree.json', 'r') { |io| RTree.json_read(io) }
|
72
|
+
#
|
64
73
|
def json_read(io)
|
65
74
|
super
|
66
75
|
end
|
@@ -69,6 +78,7 @@ class RTree < RTreeC
|
|
69
78
|
# @param json [String] a JSON string
|
70
79
|
# @return [RTree] the newly instantiated RTree
|
71
80
|
# @see #to_json
|
81
|
+
#
|
72
82
|
def from_json(json)
|
73
83
|
deserialise(json, Encoding::UTF_8) { |io| json_read(io) }
|
74
84
|
end
|
@@ -80,6 +90,7 @@ class RTree < RTreeC
|
|
80
90
|
# @see #bsrt_write
|
81
91
|
# @example Read from file
|
82
92
|
# rtree = File.open('rtree.bsrt', 'r') { |io| RTree.bsrt_read(io) }
|
93
|
+
#
|
83
94
|
def bsrt_read(io)
|
84
95
|
super
|
85
96
|
end
|
@@ -89,6 +100,7 @@ class RTree < RTreeC
|
|
89
100
|
# @param bsrt [String] a binary encoded string
|
90
101
|
# @return [RTree] the newly instantiated RTree
|
91
102
|
# @see #to_bsrt
|
103
|
+
#
|
92
104
|
def from_bsrt(bsrt)
|
93
105
|
deserialise(bsrt, Encoding::BINARY) { |io| bsrt_read(io) }
|
94
106
|
end
|
@@ -96,7 +108,7 @@ class RTree < RTreeC
|
|
96
108
|
# Build a new RTree instance from CSV stream
|
97
109
|
# @param io [IO] a readable stream object
|
98
110
|
# @param dim [Integer] the dimension of the tree
|
99
|
-
# @param split [:linear, :quadratic] See {#initialize}
|
111
|
+
# @param split [:linear, :quadratic, :greene] See {#initialize}
|
100
112
|
# @param node_page [Integer] See {#initialize}
|
101
113
|
# @return [RTree] the newly built RTree
|
102
114
|
# @note The CSV file (without header) should have the id in the
|
@@ -104,6 +116,7 @@ class RTree < RTreeC
|
|
104
116
|
# Extra columns may be present and will be ignored (this
|
105
117
|
# useful feature is the reason that the dimension is a required
|
106
118
|
# argument).
|
119
|
+
#
|
107
120
|
def csv_read(io, dim, split: :quadratic, node_page: 0)
|
108
121
|
flags = split_flag(split) | node_page_flag(node_page)
|
109
122
|
super(io, dim, flags)
|
@@ -114,6 +127,7 @@ class RTree < RTreeC
|
|
114
127
|
# @param dim [Integer] the dimension of the tree
|
115
128
|
# @param kwarg [Hash] As for {.csv_read}
|
116
129
|
# @return [RTree] the newly built RTree
|
130
|
+
#
|
117
131
|
def from_csv(csv, dim, **kwarg)
|
118
132
|
deserialise(csv, Encoding::UTF_8) do |io|
|
119
133
|
csv_read(io, dim, **kwarg)
|
@@ -121,33 +135,46 @@ class RTree < RTreeC
|
|
121
135
|
end
|
122
136
|
|
123
137
|
# @return [Array<Integer>] version of librtree
|
138
|
+
#
|
124
139
|
def version
|
125
140
|
@version ||= super.split('.').map(&:to_i)
|
126
141
|
end
|
127
142
|
|
128
143
|
# @return [String] email address for librtree bug reports
|
144
|
+
#
|
129
145
|
def bugreport
|
130
146
|
super
|
131
147
|
end
|
132
148
|
|
133
149
|
# @return [String] librtree homepage
|
150
|
+
#
|
134
151
|
def url
|
135
152
|
super
|
136
153
|
end
|
137
154
|
|
138
155
|
# @!visibility private
|
156
|
+
# This seems to need the self qualification on the constants,
|
157
|
+
# without them we get a NameError, not sure why so asked on SO
|
158
|
+
# https://stackoverflow.com/questions/68122256/ It's still not
|
159
|
+
# clear to me why this qualification is needed, but that's a
|
160
|
+
# problem with my understanding of the Ruby Eigenclass, it is
|
161
|
+
# the expected behaviour
|
162
|
+
#
|
139
163
|
def split_flag(split)
|
140
164
|
case split
|
141
165
|
when :quadratic
|
142
|
-
|
166
|
+
self::SPLIT_QUADRATIC
|
143
167
|
when :linear
|
144
|
-
|
168
|
+
self::SPLIT_LINEAR
|
169
|
+
when :greene
|
170
|
+
self::SPLIT_GREENE
|
145
171
|
else
|
146
172
|
raise ArgumentError, "bad split value: #{split}"
|
147
173
|
end
|
148
174
|
end
|
149
175
|
|
150
176
|
# @!visibility private
|
177
|
+
#
|
151
178
|
def node_page_flag(node_page)
|
152
179
|
node_page << 2
|
153
180
|
end
|
@@ -180,9 +207,10 @@ class RTree < RTreeC
|
|
180
207
|
|
181
208
|
# Initialize a new (empty) RTree
|
182
209
|
# @param dim [Integer] the dimension of the tree
|
183
|
-
# @param split [:linear, :quadratic] determines the splitting
|
184
|
-
# the linear strategy is faster to build, the quadratic
|
185
|
-
# better-quality R-
|
210
|
+
# @param split [:linear, :quadratic, :greene] determines the splitting
|
211
|
+
# strategy, the linear strategy is faster to build, the quadratic
|
212
|
+
# and greene strategies produce better-quality R-trees which are
|
213
|
+
# faster to query.
|
186
214
|
# @param node_page [Integer] the nodes-per-page value. This value can
|
187
215
|
# affect performance quite dramatically, particularly build time. A
|
188
216
|
# value which is too large would result in an infeasible branching
|
@@ -192,6 +220,7 @@ class RTree < RTreeC
|
|
192
220
|
# You may get better performance for your use-case by manual
|
193
221
|
# experimentation, but zero is a good place to start.
|
194
222
|
# @return [RTree] the newly instantiated RTree
|
223
|
+
#
|
195
224
|
def initialize(dim, split: :quadratic, node_page: 0)
|
196
225
|
@split = split
|
197
226
|
@node_page = node_page
|
@@ -200,6 +229,7 @@ class RTree < RTreeC
|
|
200
229
|
|
201
230
|
# Create a deep copy
|
202
231
|
# @return [RTree] a deep copy of the RTree
|
232
|
+
#
|
203
233
|
def clone
|
204
234
|
super
|
205
235
|
end
|
@@ -216,6 +246,7 @@ class RTree < RTreeC
|
|
216
246
|
# @example Add a rectangle to a dimension two RTree
|
217
247
|
# rtree = RTree.new(2)
|
218
248
|
# rtree.add_rect(7, [0, 0, 1, 1])
|
249
|
+
#
|
219
250
|
def add_rect(id, coords)
|
220
251
|
super
|
221
252
|
end
|
@@ -225,6 +256,7 @@ class RTree < RTreeC
|
|
225
256
|
# @return [Array<Integer>] the ids of all rectangles which intersect
|
226
257
|
# the search rectangle. If a block is given then these values will
|
227
258
|
# be yielded to the block (one at a time).
|
259
|
+
#
|
228
260
|
def search(coords)
|
229
261
|
if block_given? then
|
230
262
|
super
|
@@ -250,18 +282,21 @@ class RTree < RTreeC
|
|
250
282
|
# block and then convert the returned Ruby Floats to C; so we would
|
251
283
|
# expect that it loses much of its competitive advantage when
|
252
284
|
# compared to an R-tree rebuild.
|
285
|
+
#
|
253
286
|
def update!
|
254
287
|
super
|
255
288
|
end
|
256
289
|
|
257
290
|
# The height to the tree in the usual mathematical sense
|
258
291
|
# @return [Integer] the tree height
|
292
|
+
#
|
259
293
|
def height
|
260
294
|
super
|
261
295
|
end
|
262
296
|
|
263
297
|
# Whether the RTree has any rectangles or not
|
264
298
|
# @return [Boolean] true if the RTree is empty
|
299
|
+
#
|
265
300
|
def empty?
|
266
301
|
height == 0
|
267
302
|
end
|
@@ -272,6 +307,7 @@ class RTree < RTreeC
|
|
272
307
|
# @see .json_read
|
273
308
|
# @example Write to file
|
274
309
|
# File.open('rtree.json', 'w') { |io| rtree.json_write(io) }
|
310
|
+
#
|
275
311
|
def json_write(io)
|
276
312
|
super
|
277
313
|
end
|
@@ -282,6 +318,7 @@ class RTree < RTreeC
|
|
282
318
|
# @see .bsrt_read
|
283
319
|
# @example Write to file
|
284
320
|
# File.open('rtree.bsrt', 'w') { |io| rtree.bsrt_write(io) }
|
321
|
+
#
|
285
322
|
def bsrt_write(io)
|
286
323
|
super
|
287
324
|
end
|
@@ -289,6 +326,7 @@ class RTree < RTreeC
|
|
289
326
|
# Serialise to JSON string
|
290
327
|
# @return [String] the UTF-8 encoded JSON
|
291
328
|
# @see .from_json
|
329
|
+
#
|
292
330
|
def to_json
|
293
331
|
serialise(Encoding::UTF_8) { |io| json_write(io) }
|
294
332
|
end
|
@@ -296,12 +334,14 @@ class RTree < RTreeC
|
|
296
334
|
# Serialise to BSRT string
|
297
335
|
# @return [String] the binary encoded BSRT
|
298
336
|
# @see .from_bsrt
|
337
|
+
#
|
299
338
|
def to_bsrt
|
300
339
|
serialise(Encoding::BINARY) { |io| bsrt_write(io) }
|
301
340
|
end
|
302
341
|
|
303
342
|
# The RTree structure in hash form
|
304
343
|
# @return [Hash]
|
344
|
+
#
|
305
345
|
def to_h
|
306
346
|
JSON.parse(to_json, symbolize_names: true)
|
307
347
|
end
|
@@ -311,6 +351,7 @@ class RTree < RTreeC
|
|
311
351
|
# must be in the same order. Certainly {#clone} will produce
|
312
352
|
# an instance which is equal in this sense.
|
313
353
|
# @return [Boolean] true if the instances are identical
|
354
|
+
#
|
314
355
|
def eq?(other)
|
315
356
|
super
|
316
357
|
end
|
@@ -318,6 +359,7 @@ class RTree < RTreeC
|
|
318
359
|
alias_method(:==, :eq?)
|
319
360
|
|
320
361
|
# @return [Integer] the dimension of the R-tree
|
362
|
+
#
|
321
363
|
def dim
|
322
364
|
super
|
323
365
|
end
|
@@ -328,41 +370,74 @@ class RTree < RTreeC
|
|
328
370
|
# running count). Performance-minded users may wish to
|
329
371
|
# cache this value (invalidating the cache when calling
|
330
372
|
# {#add_rect} of course).
|
373
|
+
#
|
331
374
|
def size
|
332
375
|
super
|
333
376
|
end
|
334
377
|
|
335
378
|
# @return [Integer] the bytes in a page of memory
|
379
|
+
#
|
336
380
|
def page_size
|
337
381
|
super
|
338
382
|
end
|
339
383
|
|
340
384
|
# @return [Integer] the size in bytes of a node
|
385
|
+
#
|
341
386
|
def node_size
|
342
387
|
super
|
343
388
|
end
|
344
389
|
|
345
390
|
# @return [Integer] the size in bytes of a rectangle
|
391
|
+
#
|
346
392
|
def rect_size
|
347
393
|
super
|
348
394
|
end
|
349
395
|
|
350
396
|
# @return [Integer] the size in bytes of a branch
|
397
|
+
#
|
351
398
|
def branch_size
|
352
399
|
super
|
353
400
|
end
|
354
401
|
|
355
402
|
# @return [Integer] the number of branches from each node
|
403
|
+
#
|
356
404
|
def branching_factor
|
357
405
|
super
|
358
406
|
end
|
359
407
|
|
360
408
|
# @return [Float] the volume of the unit sphere in the R-tree's
|
361
409
|
# dimension
|
410
|
+
#
|
362
411
|
def unit_sphere_volume
|
363
412
|
super
|
364
413
|
end
|
365
414
|
|
415
|
+
# Create a PostScript plot of the RTree
|
416
|
+
# @param io [IO] a writeable stream object
|
417
|
+
# @param style [RTree::Style] a style object describing the fill
|
418
|
+
# colour and stroke width and colour for each level of the tree.
|
419
|
+
# @param height [Float] the height of the plot in units of PostScript
|
420
|
+
# point (1/72 inch)
|
421
|
+
# @param width [Float] the width of the plot in units of PostScript
|
422
|
+
# point (1/72 inch), if neither height nor width is given then a
|
423
|
+
# width of 216 (3 inches) will be taken as default
|
424
|
+
# @param margin [Float] extra space around the plot in units of
|
425
|
+
# PostScript point (1/72 inch), default zero
|
426
|
+
#
|
427
|
+
def postscript(io, style, height: nil, width: nil, margin: 0)
|
428
|
+
if height && width then
|
429
|
+
raise ArgumentError, 'cannot specify both height and width'
|
430
|
+
end
|
431
|
+
if height then
|
432
|
+
axis = AXIS_HEIGHT
|
433
|
+
extent = height
|
434
|
+
else
|
435
|
+
axis = AXIS_WIDTH
|
436
|
+
extent = width || 216
|
437
|
+
end
|
438
|
+
super(style, axis, extent, margin, io)
|
439
|
+
end
|
440
|
+
|
366
441
|
private
|
367
442
|
|
368
443
|
attr_reader :split, :node_page
|
@@ -394,8 +469,81 @@ class RTree < RTreeC
|
|
394
469
|
end
|
395
470
|
result
|
396
471
|
end
|
472
|
+
end
|
397
473
|
|
474
|
+
# @author RTree::Style J. J. Green
|
475
|
+
#
|
476
|
+
# A Ruby wrapper around RTree styles, used in PostScript plotting.
|
477
|
+
# in particular by {RTree#postscript}.
|
478
|
+
#
|
479
|
+
class RTree::Style < RTreeStyleBase
|
398
480
|
|
399
|
-
|
481
|
+
class << self
|
400
482
|
|
401
|
-
|
483
|
+
# Create a new Style instance from JSON stream
|
484
|
+
# @param io [IO] a readable stream object
|
485
|
+
# @return [RTree::Style] the newly instantiated Style
|
486
|
+
# @example Read from file
|
487
|
+
# style = File.open('some.style', 'r') do |io|
|
488
|
+
# RTree::Style.json_read(io)
|
489
|
+
# end
|
490
|
+
#
|
491
|
+
def json_read(io)
|
492
|
+
super
|
493
|
+
end
|
494
|
+
|
495
|
+
# Create a new Style instance from JSON string
|
496
|
+
# @param json [String] a JSON string
|
497
|
+
# @return [RTree::Style] the newly instantiated Style
|
498
|
+
# @see .json_read
|
499
|
+
#
|
500
|
+
def from_json(json)
|
501
|
+
raise TypeError unless json.is_a? String
|
502
|
+
rd, wr = IO.pipe(Encoding::UTF_8)
|
503
|
+
if fork then
|
504
|
+
wr.close
|
505
|
+
begin
|
506
|
+
result = json_read(rd)
|
507
|
+
ensure
|
508
|
+
rd.close
|
509
|
+
Process.wait
|
510
|
+
end
|
511
|
+
else
|
512
|
+
rd.close
|
513
|
+
begin
|
514
|
+
wr.write(json)
|
515
|
+
ensure
|
516
|
+
wr.close
|
517
|
+
exit!
|
518
|
+
end
|
519
|
+
end
|
520
|
+
result
|
521
|
+
end
|
522
|
+
|
523
|
+
# Create a new Style instance from array of Hash
|
524
|
+
# @param array [Array] an array of hash, this will be converted
|
525
|
+
# to JSON and read by .from_json
|
526
|
+
# @return [RTree::Style] the newly instantiated Style
|
527
|
+
# @see .from_json
|
528
|
+
# @example Create a simple one-level style:
|
529
|
+
# style = RTree::Style.from_a(
|
530
|
+
# [
|
531
|
+
# {
|
532
|
+
# fill: {
|
533
|
+
# rgb: [0.5, 0.5, 0.5]
|
534
|
+
# },
|
535
|
+
# stroke: {
|
536
|
+
# rgb: [0, 0, 1],
|
537
|
+
# width: 3
|
538
|
+
# }
|
539
|
+
# }
|
540
|
+
# ]
|
541
|
+
# )
|
542
|
+
#
|
543
|
+
def from_a(array)
|
544
|
+
from_json(array.to_json)
|
545
|
+
end
|
546
|
+
|
547
|
+
alias_method :from_array, :from_a
|
548
|
+
end
|
549
|
+
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.8.
|
4
|
+
version: 0.8.8
|
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-07-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -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 (1.0.
|
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
|