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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 636adac7b1df4b79407c5d7402aa101d4362379dc7c325e7283c81eb2faeb94e
4
- data.tar.gz: ee8da51ba25d5e5648ee9b511a0507beb0b1bb5325b1c5dcfbb499e01cf9fb77
3
+ metadata.gz: fc74390aa8eb79643f88f2c48f7408ef9dd17dd12ed1049e3bfe2961b7523e4b
4
+ data.tar.gz: 25488f67912344fcd69cb2c19ca6b4344cf708bfc07d9f8e1629b5893030a759
5
5
  SHA512:
6
- metadata.gz: c6a7c7d731a9d09caf84e9e9c1b7133cdbadad297efe09af3875f5f97352740c7c9786c6ceb3c74665110b2b248b2c59ab712b9e3bb3b8e195e946745648f840
7
- data.tar.gz: 2be108c80ff14fc3d2d5ba0ebead91a07e0a537d8a7a4ded460fdec4645ff41eb3412a765d02edc3d7fff87dc04b9dc7c2d0af4516b70e14464e51c556f379f9
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 lrt_dfree(void *p)
15
+ static void rt_dfree(void *p)
13
16
  {
14
17
  rtree_destroy((rtree_t*)p);
15
18
  }
16
19
 
17
- static size_t lrt_dsize(const void *p)
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 rb_data_type_t type = {
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, &type, rtree);
30
+ return TypedData_Wrap_Struct(cls, &rtree_type, rtree);
46
31
  }
47
32
 
48
- static VALUE lrt_init(VALUE self, VALUE dim_obj, VALUE flags_obj)
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, &type, rtree);
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 lrt_release(VALUE self)
50
+ static VALUE rt_release(VALUE self)
66
51
  {
67
52
  rtree_t *rtree;
68
- TypedData_Get_Struct(self, rtree_t, &type, rtree);
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 lrt_height(VALUE self)
58
+ static VALUE rt_height(VALUE self)
74
59
  {
75
60
  rtree_t *rtree;
76
- TypedData_Get_Struct(self, rtree_t, &type, rtree);
61
+ TypedData_Get_Struct(self, rtree_t, &rtree_type, rtree);
77
62
  return INT2NUM(rtree_height(rtree));
78
63
  }
79
64
 
80
- static VALUE lrt_add_rect(VALUE self, VALUE id_obj, VALUE coord_obj)
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, &type, rtree);
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 lrt_update(VALUE self)
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, &type, rtree);
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 lrt_search(VALUE self, VALUE coord_obj)
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, &type, rtree);
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, &type, rtree);
208
+ return TypedData_Wrap_Struct(cls, &rtree_type, rtree);
224
209
  }
225
210
 
226
- static VALUE lrt_json_read(VALUE cls, VALUE io_obj)
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 lrt_bsrt_read(VALUE cls, VALUE io_obj)
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 lrt_csv_read(VALUE cls,
237
- VALUE io_obj, VALUE dim_obj, VALUE flags_obj)
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, &type, rtree);
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, &type, rtree);
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 lrt_json_write(VALUE self, VALUE io_obj)
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 lrt_bsrt_write(VALUE self, VALUE io_obj)
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 lrt_identical(VALUE self, VALUE other)
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, &type, rtree_self);
304
- TypedData_Get_Struct(other, rtree_t, &type, rtree_other);
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 lrt_clone(VALUE self)
297
+ static VALUE rt_clone(VALUE self)
313
298
  {
314
299
  rtree_t *rtree;
315
- TypedData_Get_Struct(self, rtree_t, &type, rtree);
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), &type, clone);
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, &type, rtree);
318
+ TypedData_Get_Struct(self, rtree_t, &rtree_type, rtree);
334
319
  return INT2NUM(f(rtree->state));
335
320
  }
336
321
 
337
- static VALUE lrt_dim(VALUE self)
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 lrt_page_size(VALUE self)
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 lrt_node_size(VALUE self)
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 lrt_rect_size(VALUE self)
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 lrt_branch_size(VALUE self)
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 lrt_branching_factor(VALUE self)
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 lrt_unit_sphere_volume(VALUE self)
352
+ static VALUE rt_unit_sphere_volume(VALUE self)
368
353
  {
369
354
  rtree_t *rtree;
370
- TypedData_Get_Struct(self, rtree_t, &type, rtree);
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 lrt_size(VALUE self)
359
+ static VALUE rt_size(VALUE self)
375
360
  {
376
361
  rtree_t *rtree;
377
- TypedData_Get_Struct(self, rtree_t, &type, rtree);
362
+ TypedData_Get_Struct(self, rtree_t, &rtree_type, rtree);
378
363
  return INT2NUM(rtree_bytes(rtree));
379
364
  }
380
365
 
381
- static VALUE lrt_version(VALUE self)
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 lrt_bugreport(VALUE self)
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 lrt_url(VALUE self)
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 cls = rb_const_get(rb_cObject, rb_intern("RTreeC"));
399
-
400
- rb_define_alloc_func(cls, lrt_alloc);
401
- rb_define_method(cls, "initialize", lrt_init, 2);
402
- rb_define_method(cls, "free", lrt_release, 0);
403
- rb_define_method(cls, "clone", lrt_clone, 0);
404
- rb_define_method(cls, "update!", lrt_update, 0);
405
- rb_define_method(cls, "height", lrt_height, 0);
406
- rb_define_method(cls, "add_rect", lrt_add_rect, 2);
407
- rb_define_method(cls, "search", lrt_search, 1);
408
- rb_define_method(cls, "json_write", lrt_json_write, 1);
409
- rb_define_method(cls, "bsrt_write", lrt_bsrt_write, 1);
410
- rb_define_method(cls, "eq?", lrt_identical, 1);
411
- rb_define_method(cls, "dim", lrt_dim, 0);
412
- rb_define_method(cls, "size", lrt_size, 0);
413
- rb_define_method(cls, "page_size", lrt_page_size, 0);
414
- rb_define_method(cls, "node_size", lrt_node_size, 0);
415
- rb_define_method(cls, "rect_size", lrt_rect_size, 0);
416
- rb_define_method(cls, "branch_size", lrt_branch_size, 0);
417
- rb_define_method(cls, "branching_factor", lrt_branching_factor, 0);
418
- rb_define_method(cls, "unit_sphere_volume", lrt_unit_sphere_volume, 0);
419
- rb_define_singleton_method(cls, "version", lrt_version, 0);
420
- rb_define_singleton_method(cls, "bugreport", lrt_bugreport, 0);
421
- rb_define_singleton_method(cls, "url", lrt_url, 0);
422
- rb_define_singleton_method(cls, "json_read", lrt_json_read, 1);
423
- rb_define_singleton_method(cls, "bsrt_read", lrt_bsrt_read, 1);
424
- rb_define_singleton_method(cls, "csv_read", lrt_csv_read, 3);
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, which is not documented in YARD.
2
- class RTreeC ; end
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 < RTreeC
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
- 0
166
+ self::SPLIT_QUADRATIC
143
167
  when :linear
144
- 1
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 strategy,
184
- # the linear strategy is faster to build, the quadratic produces a
185
- # better-quality R-tree which is faster to query.
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
- end
481
+ class << self
400
482
 
401
- require 'rtree/rtree'
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
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-05-24 00:00:00.000000000 Z
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.3 or later)
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