librtree 0.8.0 → 0.8.5

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: 35028e6e74b4682479656b89086bf47fb42a43bd09ce7c9070df53adffcf4cec
4
- data.tar.gz: d58480430dada176e90f0e42e316b82be990fc4c414a993ce627a1b4b11ba707
3
+ metadata.gz: c9abe4061328dd6a2b8b9f1c00a38f76332a0f0a188af7a5d3e6f1125eab346e
4
+ data.tar.gz: 4029ed06803576cc76ec7bd8d3d1eb9a2d628da9fd982d04e80b643177fce244
5
5
  SHA512:
6
- metadata.gz: 5bcb8f2b41ccab397f5accef4846912e9932dd07fa540c020c114a079ed9252296a8324ae647452170a445babcceb03984f258d053eb55d45566ad1b6da03d67
7
- data.tar.gz: 8de9c0cbcfde749d139590c81d41b55bc78c73aa826cb5385f65e9b4a1c36e8a08abc3e1f5b751a082f33fadb3e56001dd8a391f93c6314f4728e5ec772454ab
6
+ metadata.gz: f6b7005f8ec37a45ff8ee894de5642eb969a26af72ad9fa330aeeae1c746447d786b309301e84116de595bed40f70bef8683fbd9a969b2b9c2cabb32e5c4d374
7
+ data.tar.gz: c4c6641e2cdfd9f14f21b50047fe2f304ab1446eb643a0f6cd3acd594fbc37469cf71c78434daa82b759bdb2741a1f887add7809d72c7bbc3f39886aee3ecc9b
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
@@ -1,35 +1,48 @@
1
1
  #include <ruby.h>
2
2
  #include <ruby/io.h>
3
+ #include <ruby/version.h>
3
4
 
4
5
  #include <rtree.h>
6
+ #include <rtree/package.h>
5
7
 
6
8
  #include <errno.h>
7
9
  #include <stdint.h>
8
10
 
9
- typedef struct
10
- {
11
- void *rtree;
12
- } lrt_t;
13
11
 
14
- static void lrt_free(void *p)
12
+ static void lrt_dfree(void *p)
15
13
  {
16
- lrt_t *lrt = p;
17
-
18
- if (lrt->rtree)
19
- {
20
- rtree_destroy(lrt->rtree);
21
- lrt->rtree = NULL;
22
- }
14
+ rtree_destroy((rtree_t*)p);
23
15
  }
24
16
 
25
- static VALUE lrt_alloc(VALUE cls)
17
+ static size_t lrt_dsize(const void *p)
26
18
  {
27
- lrt_t *lrt;
28
- VALUE obj = Data_Make_Struct(cls, lrt_t, NULL, lrt_free, lrt);
19
+ return rtree_bytes((const rtree_t*)p);
20
+ }
29
21
 
30
- lrt->rtree = NULL;
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
+ };
31
39
 
32
- return obj;
40
+ static VALUE lrt_alloc(VALUE cls)
41
+ {
42
+ rtree_t *rtree;;
43
+ if ((rtree = rtree_alloc()) == NULL)
44
+ rb_raise(rb_eNoMemError, "failed to alloc rtree");
45
+ return TypedData_Wrap_Struct(cls, &type, rtree);
33
46
  }
34
47
 
35
48
  static VALUE lrt_init(VALUE self, VALUE dim_obj, VALUE flags_obj)
@@ -40,31 +53,28 @@ static VALUE lrt_init(VALUE self, VALUE dim_obj, VALUE flags_obj)
40
53
  Check_Type(dim_obj, T_FIXNUM);
41
54
  state_flags_t flags = FIX2UINT(flags_obj);
42
55
 
43
- lrt_t *lrt;
44
- Data_Get_Struct(self, lrt_t, lrt);
56
+ rtree_t *rtree;
57
+ TypedData_Get_Struct(self, rtree_t, &type, rtree);
45
58
 
46
- if ((lrt->rtree = rtree_new(dim, flags)) == NULL)
47
- rb_raise(rb_eNoMemError, "failed to create rtree");
59
+ if ((rtree_init(rtree, dim, flags)) != 0)
60
+ rb_raise(rb_eNoMemError, "failed to init rtree");
48
61
 
49
62
  return self;
50
63
  }
51
64
 
52
65
  static VALUE lrt_release(VALUE self)
53
66
  {
54
- lrt_t *lrt;
55
- Data_Get_Struct(self, lrt_t, lrt);
56
-
57
- free(lrt->rtree);
58
-
67
+ rtree_t *rtree;
68
+ TypedData_Get_Struct(self, rtree_t, &type, rtree);
69
+ rtree_destroy(rtree);
59
70
  return self;
60
71
  }
61
72
 
62
73
  static VALUE lrt_height(VALUE self)
63
74
  {
64
- lrt_t *lrt;
65
- Data_Get_Struct(self, lrt_t, lrt);
66
-
67
- return INT2NUM(rtree_height(lrt->rtree));
75
+ rtree_t *rtree;
76
+ TypedData_Get_Struct(self, rtree_t, &type, rtree);
77
+ return INT2NUM(rtree_height(rtree));
68
78
  }
69
79
 
70
80
  static VALUE lrt_add_rect(VALUE self, VALUE id_obj, VALUE coord_obj)
@@ -72,11 +82,9 @@ static VALUE lrt_add_rect(VALUE self, VALUE id_obj, VALUE coord_obj)
72
82
  Check_Type(coord_obj, T_ARRAY);
73
83
  Check_Type(id_obj, T_FIXNUM);
74
84
 
75
- lrt_t *lrt;
76
- Data_Get_Struct(self, lrt_t, lrt);
85
+ rtree_t *rtree;
86
+ TypedData_Get_Struct(self, rtree_t, &type, rtree);
77
87
 
78
- rtree_t
79
- *rtree = lrt->rtree;
80
88
  rtree_id_t
81
89
  id = FIX2ULONG(id_obj);
82
90
  size_t
@@ -132,11 +140,10 @@ static VALUE lrt_update(VALUE self)
132
140
  if (!rb_block_given_p())
133
141
  rb_raise(rb_eArgError, "Expected block");
134
142
 
135
- lrt_t *lrt;
136
- Data_Get_Struct(self, lrt_t, lrt);
137
- rtree_t *rtree = lrt->rtree;
138
- size_t len = 2 * state_dims(rtree->state);
143
+ rtree_t *rtree;
144
+ TypedData_Get_Struct(self, rtree_t, &type, rtree);
139
145
 
146
+ size_t len = 2 * state_dims(rtree->state);
140
147
  int err = rtree_update(rtree, update_cb, &len);
141
148
 
142
149
  if (err != 0)
@@ -169,11 +176,9 @@ static VALUE lrt_search(VALUE self, VALUE coord_obj)
169
176
 
170
177
  Check_Type(coord_obj, T_ARRAY);
171
178
 
172
- lrt_t *lrt;
173
- Data_Get_Struct(self, lrt_t, lrt);
179
+ rtree_t *rtree;
180
+ TypedData_Get_Struct(self, rtree_t, &type, rtree);
174
181
 
175
- rtree_t
176
- *rtree = lrt->rtree;
177
182
  size_t
178
183
  len = RARRAY_LEN(coord_obj),
179
184
  dim = state_dims(rtree->state);
@@ -215,12 +220,7 @@ static VALUE deserialise(VALUE cls, VALUE io_obj, deserialise_t *f)
215
220
  rb_raise(rb_eRuntimeError, "Failed read from stream");
216
221
  }
217
222
 
218
- lrt_t *lrt;
219
- VALUE obj = Data_Make_Struct(cls, lrt_t, NULL, lrt_free, lrt);
220
-
221
- lrt->rtree = rtree;
222
-
223
- return obj;
223
+ return TypedData_Wrap_Struct(cls, &type, rtree);
224
224
  }
225
225
 
226
226
  static VALUE lrt_json_read(VALUE cls, VALUE io_obj)
@@ -259,12 +259,7 @@ static VALUE lrt_csv_read(VALUE cls,
259
259
  rb_raise(rb_eRuntimeError, "Failed read from stream");
260
260
  }
261
261
 
262
- lrt_t *lrt;
263
- VALUE obj = Data_Make_Struct(cls, lrt_t, NULL, lrt_free, lrt);
264
-
265
- lrt->rtree = rtree;
266
-
267
- return obj;
262
+ return TypedData_Wrap_Struct(cls, &type, rtree);
268
263
  }
269
264
 
270
265
  /* serialisation */
@@ -281,9 +276,8 @@ static VALUE serialise(VALUE self, VALUE io_obj, serialise_t *f)
281
276
  rb_io_check_writable(io);
282
277
  FILE *fp = rb_io_stdio_file(io);
283
278
 
284
- lrt_t *lrt;
285
- Data_Get_Struct(self, lrt_t, lrt);
286
- rtree_t *rtree = lrt->rtree;
279
+ rtree_t *rtree;
280
+ TypedData_Get_Struct(self, rtree_t, &type, rtree);
287
281
 
288
282
  int err = f(rtree, fp);
289
283
  if (err != 0)
@@ -304,12 +298,10 @@ static VALUE lrt_bsrt_write(VALUE self, VALUE io_obj)
304
298
 
305
299
  static VALUE lrt_identical(VALUE self, VALUE other)
306
300
  {
307
- lrt_t *lrt_self, *lrt_other;
308
- Data_Get_Struct(self, lrt_t, lrt_self);
309
- Data_Get_Struct(other, lrt_t, lrt_other);
310
- rtree_t
311
- *rtree_self = lrt_self->rtree,
312
- *rtree_other = lrt_other->rtree;
301
+ rtree_t *rtree_self, *rtree_other;
302
+
303
+ TypedData_Get_Struct(self, rtree_t, &type, rtree_self);
304
+ TypedData_Get_Struct(other, rtree_t, &type, rtree_other);
313
305
 
314
306
  if (rtree_identical(rtree_self, rtree_other))
315
307
  return Qtrue;
@@ -319,12 +311,12 @@ static VALUE lrt_identical(VALUE self, VALUE other)
319
311
 
320
312
  static VALUE lrt_clone(VALUE self)
321
313
  {
322
- lrt_t *lrt;
323
- Data_Get_Struct(self, lrt_t, lrt);
324
314
  rtree_t *rtree;
315
+ TypedData_Get_Struct(self, rtree_t, &type, rtree);
325
316
 
317
+ rtree_t *clone;
326
318
  errno = 0;
327
- if ((rtree = rtree_clone(lrt->rtree)) == NULL)
319
+ if ((clone = rtree_clone(rtree)) == NULL)
328
320
  {
329
321
  if (errno)
330
322
  rb_sys_fail(__func__);
@@ -332,13 +324,73 @@ static VALUE lrt_clone(VALUE self)
332
324
  rb_raise(rb_eRuntimeError, "Failed clone");
333
325
  }
334
326
 
335
- lrt_t *lrt_cloned;
336
- VALUE cls = CLASS_OF(self);
337
- VALUE obj = Data_Make_Struct(cls, lrt_t, NULL, lrt_free, lrt_cloned);
327
+ return TypedData_Wrap_Struct(CLASS_OF(self), &type, clone);
328
+ }
329
+
330
+ static VALUE state_size_access(VALUE self, size_t (*f)(const state_t*))
331
+ {
332
+ rtree_t *rtree;
333
+ TypedData_Get_Struct(self, rtree_t, &type, rtree);
334
+ return INT2NUM(f(rtree->state));
335
+ }
336
+
337
+ static VALUE lrt_dim(VALUE self)
338
+ {
339
+ return state_size_access(self, state_dims);
340
+ }
341
+
342
+ static VALUE lrt_page_size(VALUE self)
343
+ {
344
+ return state_size_access(self, state_page_size);
345
+ }
346
+
347
+ static VALUE lrt_node_size(VALUE self)
348
+ {
349
+ return state_size_access(self, state_node_size);
350
+ }
338
351
 
339
- lrt_cloned->rtree = rtree;
352
+ static VALUE lrt_rect_size(VALUE self)
353
+ {
354
+ return state_size_access(self, state_rect_size);
355
+ }
356
+
357
+ static VALUE lrt_branch_size(VALUE self)
358
+ {
359
+ return state_size_access(self, state_branch_size);
360
+ }
361
+
362
+ static VALUE lrt_branching_factor(VALUE self)
363
+ {
364
+ return state_size_access(self, state_branching_factor);
365
+ }
340
366
 
341
- return obj;
367
+ static VALUE lrt_unit_sphere_volume(VALUE self)
368
+ {
369
+ rtree_t *rtree;
370
+ TypedData_Get_Struct(self, rtree_t, &type, rtree);
371
+ return DBL2NUM(state_unit_sphere_volume(rtree->state));
372
+ }
373
+
374
+ static VALUE lrt_size(VALUE self)
375
+ {
376
+ rtree_t *rtree;
377
+ TypedData_Get_Struct(self, rtree_t, &type, rtree);
378
+ return INT2NUM(rtree_bytes(rtree));
379
+ }
380
+
381
+ static VALUE lrt_version(VALUE self)
382
+ {
383
+ return rb_str_new_cstr(rtree_package_version);
384
+ }
385
+
386
+ static VALUE lrt_bugreport(VALUE self)
387
+ {
388
+ return rb_str_new_cstr(rtree_package_bugreport);
389
+ }
390
+
391
+ static VALUE lrt_url(VALUE self)
392
+ {
393
+ return rb_str_new_cstr(rtree_package_url);
342
394
  }
343
395
 
344
396
  void Init_rtree(void)
@@ -356,6 +408,17 @@ void Init_rtree(void)
356
408
  rb_define_method(cls, "json_write", lrt_json_write, 1);
357
409
  rb_define_method(cls, "bsrt_write", lrt_bsrt_write, 1);
358
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);
359
422
  rb_define_singleton_method(cls, "json_read", lrt_json_read, 1);
360
423
  rb_define_singleton_method(cls, "bsrt_read", lrt_bsrt_read, 1);
361
424
  rb_define_singleton_method(cls, "csv_read", lrt_csv_read, 3);
data/lib/rtree.rb CHANGED
@@ -1,4 +1,4 @@
1
- # The C extension
1
+ # The Ruby/C interface, which is not documented in YARD.
2
2
  class RTreeC ; end
3
3
 
4
4
  # @author RTree J. J. Green
@@ -7,6 +7,12 @@ class RTreeC ; end
7
7
  # {http://soliton.vm.bytemark.co.uk/pub/jjg/en/code/librtree librtree}
8
8
  # implementing the R-tree spatial index of Guttman-Green.
9
9
  #
10
+ # Use
11
+ #
12
+ # require 'rtree'
13
+ #
14
+ # to make the {RTree} class available.
15
+ #
10
16
  # Given a set or rectangles (or higher dimensional cuboids) and their
11
17
  # associated ids, one can build an {RTree} using the {.csv_read} class
12
18
  # method or repeated calls to the {#add_rect} instance method. The
@@ -43,7 +49,7 @@ class RTreeC ; end
43
49
  # it as payload. In particular, the value may be non-unique and may be zero.
44
50
  # One should note that the id type used internally by the library is
45
51
  # determined at compile-time (with the RTREE_ID_TYPE variable) and by
46
- # default this is a 32-bit unsigned integer.
52
+ # default this is a 64-bit unsigned integer.
47
53
  #
48
54
  class RTree < RTreeC
49
55
 
@@ -93,6 +99,11 @@ class RTree < RTreeC
93
99
  # @param split [:linear, :quadratic] See {#initialize}
94
100
  # @param node_page [Integer] See {#initialize}
95
101
  # @return [RTree] the newly built RTree
102
+ # @note The CSV file (without header) should have the id in the
103
+ # first column, then twice as many floats as the dimension.
104
+ # Extra columns may be present and will be ignored (this
105
+ # useful feature is the reason that the dimension is a required
106
+ # argument).
96
107
  def csv_read(io, dim, split: :quadratic, node_page: 0)
97
108
  flags = split_flag(split) | node_page_flag(node_page)
98
109
  super(io, dim, flags)
@@ -109,6 +120,21 @@ class RTree < RTreeC
109
120
  end
110
121
  end
111
122
 
123
+ # @return [Array<Integer>] version of librtree
124
+ def version
125
+ @version ||= super.split('.').map(&:to_i)
126
+ end
127
+
128
+ # @return [String] email address for librtree bug reports
129
+ def bugreport
130
+ super
131
+ end
132
+
133
+ # @return [String] librtree homepage
134
+ def url
135
+ super
136
+ end
137
+
112
138
  # @!visibility private
113
139
  def split_flag(split)
114
140
  case split
@@ -222,7 +248,7 @@ class RTree < RTreeC
222
248
  # is much faster than rebuilding the R-tree; in this Ruby interface
223
249
  # the callback must convert C floats to Ruby, yield them to the
224
250
  # block and then convert the returned Ruby Floats to C; so we would
225
- # expect that it loses much of its competetive advantage when
251
+ # expect that it loses much of its competitive advantage when
226
252
  # compared to an R-tree rebuild.
227
253
  def update!
228
254
  super
@@ -241,7 +267,7 @@ class RTree < RTreeC
241
267
  end
242
268
 
243
269
  # Serialise to JSON stream
244
- # @param io [IO] a writeable stream
270
+ # @param io [IO] a writable stream
245
271
  # @return [self]
246
272
  # @see .json_read
247
273
  # @example Write to file
@@ -251,7 +277,7 @@ class RTree < RTreeC
251
277
  end
252
278
 
253
279
  # Serialise to BSRT (binary serialised R-tree) stream
254
- # @param io [IO] a writeable stream
280
+ # @param io [IO] a writable stream
255
281
  # @return [self]
256
282
  # @see .bsrt_read
257
283
  # @example Write to file
@@ -281,7 +307,7 @@ class RTree < RTreeC
281
307
  end
282
308
 
283
309
  # Equality of RTrees. This is a rather strict equality,
284
- # not only must the tree have the same rectangkes, they
310
+ # not only must the tree have the same rectangles, they
285
311
  # must be in the same order. Certainly {#clone} will produce
286
312
  # an instance which is equal in this sense.
287
313
  # @return [Boolean] true if the instances are identical
@@ -291,6 +317,52 @@ class RTree < RTreeC
291
317
 
292
318
  alias_method(:==, :eq?)
293
319
 
320
+ # @return [Integer] the dimension of the R-tree
321
+ def dim
322
+ super
323
+ end
324
+
325
+ # @return [Integer] the total bytes allocated for the instance
326
+ # @note This method traverses the entire tree summing the
327
+ # contributions for each node (rather than maintaining a
328
+ # running count). Performance-minded users may wish to
329
+ # cache this value (invalidating the cache when calling
330
+ # {#add_rect} of course).
331
+ def size
332
+ super
333
+ end
334
+
335
+ # @return [Integer] the bytes in a page of memory
336
+ def page_size
337
+ super
338
+ end
339
+
340
+ # @return [Integer] the size in bytes of a node
341
+ def node_size
342
+ super
343
+ end
344
+
345
+ # @return [Integer] the size in bytes of a rectangle
346
+ def rect_size
347
+ super
348
+ end
349
+
350
+ # @return [Integer] the size in bytes of a branch
351
+ def branch_size
352
+ super
353
+ end
354
+
355
+ # @return [Integer] the number of branches from each node
356
+ def branching_factor
357
+ super
358
+ end
359
+
360
+ # @return [Float] the volume of the unit sphere in the R-tree's
361
+ # dimension
362
+ def unit_sphere_volume
363
+ super
364
+ end
365
+
294
366
  private
295
367
 
296
368
  attr_reader :split, :node_page
@@ -323,6 +395,7 @@ class RTree < RTreeC
323
395
  result
324
396
  end
325
397
 
398
+
326
399
  end
327
400
 
328
401
  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.0
4
+ version: 0.8.5
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-17 00:00:00.000000000 Z
11
+ date: 2021-06-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -95,8 +95,8 @@ dependencies:
95
95
  - !ruby/object:Gem::Version
96
96
  version: '1'
97
97
  description: |
98
- A Ruby native extension for librtree implementing the R-tree
99
- spatial-index of Guttman-Green.
98
+ A Ruby extension implementing the R-tree spatial-index of
99
+ Guttman-Green.
100
100
  email: j.j.green@gmx.co.uk
101
101
  executables: []
102
102
  extensions:
@@ -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
129
+ - The librtree library (1.0.5 or later)
130
130
  rubygems_version: 3.1.2
131
131
  signing_key:
132
132
  specification_version: 4