librtree 0.8.6 → 0.8.7

Sign up to get free protection for your applications and to get access to all the features.
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