librtree 0.8.6 → 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.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/ext/rtree/rtree.c +204 -93
  3. data/lib/rtree.rb +149 -3
  4. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ad62e4e446f6fb4571d33f6498bf9df26d5b360a0325cde40ead187ebcb0be04
4
- data.tar.gz: d462f690013c36933961206659026af7fe9b50ea6d23198f15a0965247390192
3
+ metadata.gz: b33e172341a9e44682c139df3a6b92198b3dd83059340da9fb8752444afbac70
4
+ data.tar.gz: 7ba6d8c71b6afeb8e5dedde55ff08074db758fa7ea150a67195ff07ca426a312
5
5
  SHA512:
6
- metadata.gz: 19e997efe8519f2db02e10f69f8d60af57c376e9a6de7f38bc8f3613cbd8287800e096816f1c37361c122c0a7c99e41bd97f7842ddebdf0357395e31a666739b
7
- data.tar.gz: bf1911bade3fcba763aee1f4a451dd9638f8e9c3b06577482b09bc134942282d031538d8a436ee161ec4334c7f2dfdadfcf8ac1349dc3d32b053c69390e5eb7f
6
+ metadata.gz: d4440a12038bd07dcb458ff993269fd72ac3826753f6e2757b86f19913a1cc748d7af1f37a7355e015d5a6dd3a750b8335a6f87d2a1dbdc5e4ef5387f9424f6a
7
+ data.tar.gz: ce193b26ab45e5ca2cab29c0c145a9432440355585e5cc5e226bbe0e762b3d4c33bcd693626ccd3f60eaad11513c94d3e8246e86cf8b703a7d89f19b22090d1b
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,105 +309,231 @@ static VALUE lrt_clone(VALUE self)
324
309
  rb_raise(rb_eRuntimeError, "Failed clone");
325
310
  }
326
311
 
327
- return TypedData_Wrap_Struct(CLASS_OF(self), &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);
425
- rb_define_const(cls, "SPLIT_QUADRATIC", INT2NUM(RTREE_SPLIT_QUADRATIC));
426
- rb_define_const(cls, "SPLIT_LINEAR", INT2NUM(RTREE_SPLIT_LINEAR));
427
- rb_define_const(cls, "SPLIT_GREENE", INT2NUM(RTREE_SPLIT_GREENE));
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);
428
539
  }
data/lib/rtree.rb CHANGED
@@ -1,5 +1,12 @@
1
- # The Ruby/C interface, which is not documented in YARD.
2
- class RTreeC ; end
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
@@ -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,6 +126,7 @@ 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)
@@ -121,21 +134,25 @@ class RTree < RTreeC
121
134
  end
122
135
 
123
136
  # @return [Array<Integer>] version of librtree
137
+ #
124
138
  def version
125
139
  @version ||= super.split('.').map(&:to_i)
126
140
  end
127
141
 
128
142
  # @return [String] email address for librtree bug reports
143
+ #
129
144
  def bugreport
130
145
  super
131
146
  end
132
147
 
133
148
  # @return [String] librtree homepage
149
+ #
134
150
  def url
135
151
  super
136
152
  end
137
153
 
138
154
  # @!visibility private
155
+ #
139
156
  def split_flag(split)
140
157
  case split
141
158
  when :quadratic
@@ -150,6 +167,7 @@ class RTree < RTreeC
150
167
  end
151
168
 
152
169
  # @!visibility private
170
+ #
153
171
  def node_page_flag(node_page)
154
172
  node_page << 2
155
173
  end
@@ -184,7 +202,7 @@ class RTree < RTreeC
184
202
  # @param dim [Integer] the dimension of the tree
185
203
  # @param split [:linear, :quadratic, :greene] determines the splitting
186
204
  # strategy, the linear strategy is faster to build, the quadratic
187
- # and greene strategies produces a better-quality R-trees which is
205
+ # and greene strategies produce better-quality R-trees which are
188
206
  # faster to query.
189
207
  # @param node_page [Integer] the nodes-per-page value. This value can
190
208
  # affect performance quite dramatically, particularly build time. A
@@ -195,6 +213,7 @@ class RTree < RTreeC
195
213
  # You may get better performance for your use-case by manual
196
214
  # experimentation, but zero is a good place to start.
197
215
  # @return [RTree] the newly instantiated RTree
216
+ #
198
217
  def initialize(dim, split: :quadratic, node_page: 0)
199
218
  @split = split
200
219
  @node_page = node_page
@@ -203,6 +222,7 @@ class RTree < RTreeC
203
222
 
204
223
  # Create a deep copy
205
224
  # @return [RTree] a deep copy of the RTree
225
+ #
206
226
  def clone
207
227
  super
208
228
  end
@@ -219,6 +239,7 @@ class RTree < RTreeC
219
239
  # @example Add a rectangle to a dimension two RTree
220
240
  # rtree = RTree.new(2)
221
241
  # rtree.add_rect(7, [0, 0, 1, 1])
242
+ #
222
243
  def add_rect(id, coords)
223
244
  super
224
245
  end
@@ -228,6 +249,7 @@ class RTree < RTreeC
228
249
  # @return [Array<Integer>] the ids of all rectangles which intersect
229
250
  # the search rectangle. If a block is given then these values will
230
251
  # be yielded to the block (one at a time).
252
+ #
231
253
  def search(coords)
232
254
  if block_given? then
233
255
  super
@@ -253,18 +275,21 @@ class RTree < RTreeC
253
275
  # block and then convert the returned Ruby Floats to C; so we would
254
276
  # expect that it loses much of its competitive advantage when
255
277
  # compared to an R-tree rebuild.
278
+ #
256
279
  def update!
257
280
  super
258
281
  end
259
282
 
260
283
  # The height to the tree in the usual mathematical sense
261
284
  # @return [Integer] the tree height
285
+ #
262
286
  def height
263
287
  super
264
288
  end
265
289
 
266
290
  # Whether the RTree has any rectangles or not
267
291
  # @return [Boolean] true if the RTree is empty
292
+ #
268
293
  def empty?
269
294
  height == 0
270
295
  end
@@ -275,6 +300,7 @@ class RTree < RTreeC
275
300
  # @see .json_read
276
301
  # @example Write to file
277
302
  # File.open('rtree.json', 'w') { |io| rtree.json_write(io) }
303
+ #
278
304
  def json_write(io)
279
305
  super
280
306
  end
@@ -285,6 +311,7 @@ class RTree < RTreeC
285
311
  # @see .bsrt_read
286
312
  # @example Write to file
287
313
  # File.open('rtree.bsrt', 'w') { |io| rtree.bsrt_write(io) }
314
+ #
288
315
  def bsrt_write(io)
289
316
  super
290
317
  end
@@ -292,6 +319,7 @@ class RTree < RTreeC
292
319
  # Serialise to JSON string
293
320
  # @return [String] the UTF-8 encoded JSON
294
321
  # @see .from_json
322
+ #
295
323
  def to_json
296
324
  serialise(Encoding::UTF_8) { |io| json_write(io) }
297
325
  end
@@ -299,12 +327,14 @@ class RTree < RTreeC
299
327
  # Serialise to BSRT string
300
328
  # @return [String] the binary encoded BSRT
301
329
  # @see .from_bsrt
330
+ #
302
331
  def to_bsrt
303
332
  serialise(Encoding::BINARY) { |io| bsrt_write(io) }
304
333
  end
305
334
 
306
335
  # The RTree structure in hash form
307
336
  # @return [Hash]
337
+ #
308
338
  def to_h
309
339
  JSON.parse(to_json, symbolize_names: true)
310
340
  end
@@ -314,6 +344,7 @@ class RTree < RTreeC
314
344
  # must be in the same order. Certainly {#clone} will produce
315
345
  # an instance which is equal in this sense.
316
346
  # @return [Boolean] true if the instances are identical
347
+ #
317
348
  def eq?(other)
318
349
  super
319
350
  end
@@ -321,6 +352,7 @@ class RTree < RTreeC
321
352
  alias_method(:==, :eq?)
322
353
 
323
354
  # @return [Integer] the dimension of the R-tree
355
+ #
324
356
  def dim
325
357
  super
326
358
  end
@@ -331,41 +363,74 @@ class RTree < RTreeC
331
363
  # running count). Performance-minded users may wish to
332
364
  # cache this value (invalidating the cache when calling
333
365
  # {#add_rect} of course).
366
+ #
334
367
  def size
335
368
  super
336
369
  end
337
370
 
338
371
  # @return [Integer] the bytes in a page of memory
372
+ #
339
373
  def page_size
340
374
  super
341
375
  end
342
376
 
343
377
  # @return [Integer] the size in bytes of a node
378
+ #
344
379
  def node_size
345
380
  super
346
381
  end
347
382
 
348
383
  # @return [Integer] the size in bytes of a rectangle
384
+ #
349
385
  def rect_size
350
386
  super
351
387
  end
352
388
 
353
389
  # @return [Integer] the size in bytes of a branch
390
+ #
354
391
  def branch_size
355
392
  super
356
393
  end
357
394
 
358
395
  # @return [Integer] the number of branches from each node
396
+ #
359
397
  def branching_factor
360
398
  super
361
399
  end
362
400
 
363
401
  # @return [Float] the volume of the unit sphere in the R-tree's
364
402
  # dimension
403
+ #
365
404
  def unit_sphere_volume
366
405
  super
367
406
  end
368
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
+
369
434
  private
370
435
 
371
436
  attr_reader :split, :node_page
@@ -397,8 +462,89 @@ class RTree < RTreeC
397
462
  end
398
463
  result
399
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
400
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
401
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
402
548
  end
403
549
 
404
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.6
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-06-17 00:00:00.000000000 Z
11
+ date: 2021-06-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler