librtree 0.8.4 → 0.8.8

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