bribera-rubyvor 0.0.9 → 0.1.0

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.
data/History.txt CHANGED
@@ -1,3 +1,15 @@
1
+ === 0.1.0 / 2009-01-13
2
+
3
+ * Configurable handling of "no neighbors" case.
4
+ * Tests for "no neighbors" case.
5
+
6
+ === 0.0.9 / 2009-01-01
7
+
8
+ Happy New Year!
9
+ * New speed improvements.
10
+ * Additional visualization tweaks.
11
+ * More tests.
12
+
1
13
  === 0.0.8 / 2008-12-23
2
14
 
3
15
  * Several C warning fixes (more ISO C compliance unused variables, etc)
@@ -247,14 +247,23 @@ RubyVor_minimum_spanning_tree(int argc, VALUE *argv, VALUE self)
247
247
  VALUE
248
248
  RubyVor_nn_graph(VALUE self)
249
249
  {
250
- long i;
251
250
  VALUE dtRaw, graph, points, * dtPtr, * tripletPtr, * graphPtr;
251
+ long i, j, noNeighborResponse;
252
252
 
253
253
  graph = rb_iv_get(self, "@nn_graph");
254
254
 
255
255
  if (RTEST(graph))
256
256
  return graph;
257
257
 
258
+ /* Figure out our "no neighbor" response value */
259
+ if (SYM2ID(rb_iv_get(self, "@no_neighbor_response")) == rb_intern("raise")) {
260
+ noNeighborResponse = 1;
261
+ } else if (SYM2ID(rb_iv_get(self, "@no_neighbor_response")) == rb_intern("use_all")) {
262
+ noNeighborResponse = 2;
263
+ } else {
264
+ noNeighborResponse = 0;
265
+ }
266
+
258
267
  /* Create an array of same size as points for the graph */
259
268
  points = rb_iv_get(self, "@points");
260
269
 
@@ -283,16 +292,23 @@ RubyVor_nn_graph(VALUE self)
283
292
  }
284
293
  for (i = 0; i < RARRAY(graph)->len; i++) {
285
294
  if (RARRAY(graphPtr[i])->len < 1) {
286
- rb_raise(rb_eIndexError, "index of 0 (no neighbors) at %i", i);
287
- /* No valid triangles touched this node -- include *all* possible neighbors
288
- for(j = 0; j < RARRAY(points)->len; j++) {
289
- if (j != i) {
290
- rb_ary_push(graphPtr[i], INT2FIX(j));
291
- if (RARRAY(graphPtr[j])->len > 0 && !rb_ary_includes(graphPtr[j], INT2FIX(i)))
292
- rb_ary_push(graphPtr[j], INT2FIX(i));
295
+ /* Evaluate noNeighborResponse and respond accordingly */
296
+ if (noNeighborResponse == 1) {
297
+ rb_raise(rb_eIndexError, "index of 0 (no neighbors) at %i", i);
298
+ } else if (noNeighborResponse == 2) {
299
+ /* No valid triangles touched this node -- include *all* possible neighbors
300
+ *
301
+ * Note that this can make for exceptionally slow (ie O(n^2) time) clustering,
302
+ * but should only happen in rare cases.
303
+ */
304
+ for(j = 0; j < RARRAY(points)->len; j++) {
305
+ if (j != i) {
306
+ rb_ary_push(graphPtr[i], INT2FIX(j));
307
+ if (RARRAY(graphPtr[j])->len > 0 && !rb_ary_includes(graphPtr[j], INT2FIX(i)))
308
+ rb_ary_push(graphPtr[j], INT2FIX(i));
309
+ }
293
310
  }
294
311
  }
295
- */
296
312
  } else {
297
313
  rb_funcall(graphPtr[i], rb_intern("uniq!"), 0);
298
314
  }
@@ -1,19 +1,33 @@
1
1
  module RubyVor
2
2
  module VDDT
3
3
  class Computation
4
- attr_reader :points, :voronoi_diagram_raw, :delaunay_triangulation_raw
4
+ attr_reader :points, :voronoi_diagram_raw, :delaunay_triangulation_raw, :no_neighbor_response
5
5
 
6
6
  DIST_PROC = lambda{|a,b| a.distance_from(b)}
7
+ NO_NEIGHBOR_RESPONSES = [:raise, :use_all, :ignore]
7
8
 
8
9
  # Create a computation from an existing set of raw data.
9
10
  def initialize
10
11
  @points = []
11
- @unique_points = []
12
- @point_map = {}
12
+
13
13
  @voronoi_diagram_raw = []
14
14
  @delaunay_triangulation_raw = []
15
+
15
16
  @nn_graph = nil
16
17
  @mst = nil
18
+
19
+ @no_neighbor_response = :use_all
20
+ end
21
+
22
+ # Decided what action to take if we find a point with no neighbors
23
+ # while computing the nn_graph.
24
+ #
25
+ # Choices are:
26
+ # * :use_all - include all other nodes as potential neighbors. This choice is the default, and can lead to higher big-O lower bounds when clustering.
27
+ # * :raise - raise an error
28
+ # * :ignore - leave this node disconnected from the rest of the graph.
29
+ def no_neighbor_response=(v)
30
+ @no_neighbor_response = v if NO_NEIGHBOR_RESPONSES.include?(v)
17
31
  end
18
32
 
19
33
  # Uses the nearest-neighbors information encapsulated by the Delaunay triangulation as a seed for clustering:
@@ -1,3 +1,3 @@
1
1
  module RubyVor
2
- VERSION = '0.0.9'
2
+ VERSION = '0.1.0'
3
3
  end
@@ -3,8 +3,9 @@ module RubyVor
3
3
  class Visualizer
4
4
 
5
5
  COLORS = %w{black red blue lime gray yellow purple orange pink}
6
-
7
- include LibXML
6
+
7
+ # Support various versions of LibXML
8
+ include LibXML if defined?(LibXML)
8
9
 
9
10
  def self.make_svg(computation, opts={})
10
11
  @opts = opts = {
data/rubyvor.gemspec CHANGED
@@ -2,11 +2,11 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{rubyvor}
5
- s.version = "0.0.9"
5
+ s.version = "0.1.0"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Brendan Ribera"]
9
- s.date = %q{2009-01-01}
9
+ s.date = %q{2009-01-13}
10
10
  s.description = %q{RubyVor provides efficient computation of Voronoi diagrams and Delaunay triangulation for a set of Ruby points. It is intended to function as a complemenet to GeoRuby. These structures can be used to compute a nearest-neighbor graph for a set of points. This graph can in turn be used for proximity-based clustering of the input points.}
11
11
  s.email = ["brendan.ribera+rubyvor@gmail.com"]
12
12
  s.extensions = ["ext/extconf.rb"]
@@ -233,6 +233,44 @@ class TestComputation < MiniTest::Unit::TestCase
233
233
  end
234
234
  end
235
235
 
236
+
237
+ def test_no_neighbors
238
+ nn_graph = nil
239
+
240
+ # Test :raise
241
+ comp = RubyVor::VDDT::Computation.from_points([1,2,3,4,5].map{|xy| RubyVor::Point.new(xy,xy)})
242
+ comp.no_neighbor_response = :raise
243
+
244
+ assert_equal comp.no_neighbor_response, :raise
245
+ assert_raises(IndexError) { nn_graph = comp.nn_graph }
246
+ assert_raises(IndexError) { comp.cluster_by_distance(5) }
247
+ assert_equal nn_graph, nil
248
+
249
+
250
+ # Test :use_all (default)
251
+ comp = RubyVor::VDDT::Computation.from_points([1,2,3,4,5].map{|xy| RubyVor::Point.new(xy,xy)})
252
+ comp.no_neighbor_response = :use_all
253
+
254
+ assert_equal comp.no_neighbor_response, :use_all
255
+ assert_nothing_raised { nn_graph = comp.nn_graph }
256
+ assert_nothing_raised do
257
+ assert_equal comp.cluster_by_distance(5).map{|a| a.sort}.sort, [[0,1,2,3,4]]
258
+ end
259
+ refute_equal nn_graph, nil
260
+
261
+
262
+ # Test :ignore
263
+ comp = RubyVor::VDDT::Computation.from_points([1,2,3,4,5].map{|xy| RubyVor::Point.new(xy,xy)})
264
+ comp.no_neighbor_response = :ignore
265
+
266
+ assert_equal comp.no_neighbor_response, :ignore
267
+ assert_nothing_raised { nn_graph = comp.nn_graph }
268
+ assert_nothing_raised do
269
+ assert_equal comp.cluster_by_distance(5).map{|a| a.sort}.sort, [[0],[1],[2],[3],[4]]
270
+ end
271
+ refute_equal nn_graph, nil
272
+ end
273
+
236
274
 
237
275
  def test_cluster_by_size
238
276
  comp = RubyVor::VDDT::Computation.from_points([
@@ -291,6 +329,16 @@ class TestComputation < MiniTest::Unit::TestCase
291
329
  end
292
330
  @points
293
331
  end
332
+
333
+ def assert_nothing_raised(&b)
334
+ begin
335
+ yield
336
+ rescue Exception => e
337
+ flunk "#{mu_pp(e)} exception encountered, expected no exceptions"
338
+ return
339
+ end
340
+ pass()
341
+ end
294
342
  end
295
343
 
296
344
  MiniTest::Unit.autorun
data/test/test_point.rb CHANGED
@@ -29,7 +29,7 @@ class TestPoint < MiniTest::Unit::TestCase
29
29
 
30
30
  assert a > b
31
31
  assert b < a
32
- assert_equal -1, b <=> a
32
+ assert_equal(-1, (b <=> a))
33
33
  end
34
34
 
35
35
  def test_equality
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bribera-rubyvor
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.9
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brendan Ribera
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-01-01 00:00:00 -08:00
12
+ date: 2009-01-13 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency