rubyvor 0.1.3
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.rdoc +60 -0
- data/Manifest.txt +30 -0
- data/README.rdoc +76 -0
- data/Rakefile +41 -0
- data/ext/Doc +30 -0
- data/ext/edgelist.c +204 -0
- data/ext/extconf.rb +3 -0
- data/ext/geometry.c +219 -0
- data/ext/heap.c +118 -0
- data/ext/memory.c +118 -0
- data/ext/output.c +251 -0
- data/ext/rb_cComputation.c +369 -0
- data/ext/rb_cPoint.c +35 -0
- data/ext/rb_cPriorityQueue.c +120 -0
- data/ext/ruby_vor_c.c +115 -0
- data/ext/ruby_vor_c.h +40 -0
- data/ext/vdefs.h +150 -0
- data/ext/voronoi.c +271 -0
- data/lib/ruby_vor.rb +16 -0
- data/lib/ruby_vor/computation.rb +136 -0
- data/lib/ruby_vor/geo_ruby_extensions.rb +15 -0
- data/lib/ruby_vor/point.rb +32 -0
- data/lib/ruby_vor/priority_queue.rb +87 -0
- data/lib/ruby_vor/version.rb +3 -0
- data/lib/ruby_vor/visualizer.rb +218 -0
- data/rubyvor.gemspec +35 -0
- data/test/test_computation.rb +354 -0
- data/test/test_point.rb +100 -0
- data/test/test_priority_queue.rb +129 -0
- data/test/test_voronoi_interface.rb +161 -0
- metadata +99 -0
data/test/test_point.rb
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'minitest/unit'
|
3
|
+
require File.dirname(__FILE__) + '/../lib/ruby_vor'
|
4
|
+
|
5
|
+
class TestPoint < MiniTest::Unit::TestCase
|
6
|
+
|
7
|
+
def test_instantiation
|
8
|
+
a = b = nil
|
9
|
+
|
10
|
+
assert_raises TypeError do
|
11
|
+
a = RubyVor::Point.new(:"10", 10)
|
12
|
+
end
|
13
|
+
|
14
|
+
assert_raises TypeError do
|
15
|
+
a = RubyVor::Point.new(10, :"10")
|
16
|
+
end
|
17
|
+
|
18
|
+
assert_nothing_raised do
|
19
|
+
a = RubyVor::Point.new(123.456, 789.10)
|
20
|
+
b = RubyVor::Point.new("123.456", "789.10")
|
21
|
+
end
|
22
|
+
|
23
|
+
assert_equal a, b
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_comparison
|
27
|
+
a = RubyVor::Point.new(10, 10)
|
28
|
+
b = RubyVor::Point.new(1, 1)
|
29
|
+
|
30
|
+
assert a > b
|
31
|
+
assert b < a
|
32
|
+
assert_equal(-1, (b <=> a))
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_equality
|
36
|
+
a = RubyVor::Point.new(10, 10)
|
37
|
+
b = RubyVor::Point.new(10.0, 10)
|
38
|
+
c = RubyVor::Point.new(10.0, 10.0)
|
39
|
+
d = RubyVor::Point.new(10, 10.0)
|
40
|
+
|
41
|
+
z = RubyVor::Point.new(Math::PI, Math::PI)
|
42
|
+
o = a
|
43
|
+
|
44
|
+
|
45
|
+
# Test equality of values; both == and eql? perform this function.
|
46
|
+
assert a == a
|
47
|
+
assert a == b
|
48
|
+
assert a == c
|
49
|
+
assert a == d
|
50
|
+
assert a == o
|
51
|
+
assert a.eql?(a)
|
52
|
+
assert a.eql?(b)
|
53
|
+
assert a.eql?(c)
|
54
|
+
assert a.eql?(d)
|
55
|
+
assert a.eql?(o)
|
56
|
+
|
57
|
+
refute a == z
|
58
|
+
refute a.eql?(z)
|
59
|
+
|
60
|
+
|
61
|
+
# Test object equality.
|
62
|
+
refute a.equal?(b)
|
63
|
+
refute a.equal?(c)
|
64
|
+
refute a.equal?(d)
|
65
|
+
refute a.equal?(z)
|
66
|
+
|
67
|
+
assert a.equal?(a)
|
68
|
+
assert a.equal?(o)
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_hash
|
72
|
+
a = RubyVor::Point.new(10, 10)
|
73
|
+
b = RubyVor::Point.new(10.0, 10)
|
74
|
+
c = RubyVor::Point.new(10.0, 10.0)
|
75
|
+
d = RubyVor::Point.new(10, 10.0)
|
76
|
+
|
77
|
+
z = RubyVor::Point.new(Math::PI, Math::PI)
|
78
|
+
o = a
|
79
|
+
|
80
|
+
assert_equal a.hash, b.hash
|
81
|
+
assert_equal a.hash, c.hash
|
82
|
+
assert_equal a.hash, d.hash
|
83
|
+
assert_equal a.hash, o.hash
|
84
|
+
|
85
|
+
refute_equal a.hash, z.hash
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
|
90
|
+
def assert_nothing_raised(&b)
|
91
|
+
begin
|
92
|
+
yield
|
93
|
+
rescue Exception => e
|
94
|
+
flunk "#{mu_pp(e)} exception encountered, expected no exceptions"
|
95
|
+
return
|
96
|
+
end
|
97
|
+
pass()
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'minitest/unit'
|
3
|
+
require File.dirname(__FILE__) + '/../lib/ruby_vor'
|
4
|
+
|
5
|
+
class TestPriorityQueue < MiniTest::Unit::TestCase
|
6
|
+
|
7
|
+
def test_heap_order_property
|
8
|
+
# min heap by default
|
9
|
+
q = RubyVor::PriorityQueue.new
|
10
|
+
|
11
|
+
items = [1,2,3,4,5,6,99,4,-20,101,5412,2,-1,-1,-1,33.0,0,55,7,12321,123.123,-123.123,0,0,0]
|
12
|
+
items.each{|i| q.push(i)}
|
13
|
+
|
14
|
+
items.sort!
|
15
|
+
idx = 0
|
16
|
+
|
17
|
+
# Test peek
|
18
|
+
assert_equal q.peek.data, items[0]
|
19
|
+
|
20
|
+
while min = q.pop
|
21
|
+
# Test pop
|
22
|
+
assert_equal min.data, items[idx]
|
23
|
+
|
24
|
+
# Test peek
|
25
|
+
assert_equal q.peek.data, items[idx + 1] if idx + 1 < items.length
|
26
|
+
|
27
|
+
idx += 1
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_heapify
|
32
|
+
q = RubyVor::PriorityQueue.new
|
33
|
+
|
34
|
+
# Create a randomized data set.
|
35
|
+
#
|
36
|
+
# Not ideal for unit tests, since they *should* be done
|
37
|
+
# on static data so that failure/success is deterministic...
|
38
|
+
# but works for me.
|
39
|
+
|
40
|
+
100.times{ q.push(rand * 10000.0 - 5000.0)}
|
41
|
+
|
42
|
+
# Set things right.
|
43
|
+
q.heapify()
|
44
|
+
|
45
|
+
old_n = -1.0 * Float::MAX
|
46
|
+
while n = q.pop
|
47
|
+
assert n.priority >= old_n, 'Heap-order property violated'
|
48
|
+
old_n = n.priority
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_bad_data
|
53
|
+
q = RubyVor::PriorityQueue.new
|
54
|
+
10.times { q.push(rand * 100.0 - 50.0) }
|
55
|
+
|
56
|
+
#
|
57
|
+
# Heapify
|
58
|
+
#
|
59
|
+
old_data = q.data[1]
|
60
|
+
q.data[1] = 45
|
61
|
+
assert_raises TypeError do
|
62
|
+
q.heapify()
|
63
|
+
end
|
64
|
+
q.data[1] = old_data
|
65
|
+
assert_nothing_raised do
|
66
|
+
q.heapify()
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
#
|
71
|
+
# Percolation
|
72
|
+
#
|
73
|
+
[100, -100].each do |i|
|
74
|
+
assert_raises IndexError do
|
75
|
+
q.percolate_up(i)
|
76
|
+
end
|
77
|
+
assert_raises IndexError do
|
78
|
+
q.percolate_down(i)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
[:x, Class, nil, false].each do |i|
|
82
|
+
assert_raises TypeError do
|
83
|
+
q.percolate_up(i)
|
84
|
+
end
|
85
|
+
assert_raises TypeError do
|
86
|
+
q.percolate_down(i)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
[0,1,2,3].each do |i|
|
90
|
+
assert_nothing_raised do
|
91
|
+
q.percolate_up(i)
|
92
|
+
end
|
93
|
+
assert_nothing_raised do
|
94
|
+
q.percolate_down(i)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def test_build_queue
|
100
|
+
n = 100
|
101
|
+
|
102
|
+
q = RubyVor::PriorityQueue.build_queue(n) do |queue_item|
|
103
|
+
queue_item.priority = rand * 10000.0 - 5000.0
|
104
|
+
end
|
105
|
+
|
106
|
+
assert_equal n, q.data.length
|
107
|
+
assert_equal n, q.size
|
108
|
+
|
109
|
+
old_n = -1.0 * Float::MAX
|
110
|
+
while n = q.pop
|
111
|
+
assert n.priority >= old_n, 'Heap-order property violated'
|
112
|
+
old_n = n.priority
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
private
|
117
|
+
|
118
|
+
def assert_nothing_raised(&b)
|
119
|
+
begin
|
120
|
+
yield
|
121
|
+
rescue Exception => e
|
122
|
+
flunk "#{mu_pp(e)} exception encountered, expected no exceptions"
|
123
|
+
return
|
124
|
+
end
|
125
|
+
pass()
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
MiniTest::Unit.autorun
|
@@ -0,0 +1,161 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'minitest/unit'
|
3
|
+
require File.dirname(__FILE__) + '/../lib/ruby_vor'
|
4
|
+
|
5
|
+
|
6
|
+
class TestVoronoiInterface < MiniTest::Unit::TestCase
|
7
|
+
|
8
|
+
def initialize(*args)
|
9
|
+
@points = @trianglulation_raw = @diagram_raw = nil
|
10
|
+
super(*args)
|
11
|
+
end
|
12
|
+
|
13
|
+
|
14
|
+
MAX_DELTA = 0.000001
|
15
|
+
|
16
|
+
def test_diagram_correct
|
17
|
+
# Perform the computation.
|
18
|
+
comp = RubyVor::VDDT::Computation.from_points(sample_points)
|
19
|
+
|
20
|
+
# Test each raw entry against three basic assertions:
|
21
|
+
# * entry lengths must match
|
22
|
+
# * entry types must match
|
23
|
+
# * entry values must match, with allowance for rounding errors (i.e. within a very small delta)
|
24
|
+
comp.voronoi_diagram_raw.each_with_index do |computed_entry, i|
|
25
|
+
sample_entry = example_diagram_raw[i]
|
26
|
+
|
27
|
+
|
28
|
+
assert_equal computed_entry.length, sample_entry.length
|
29
|
+
assert_equal computed_entry.first, sample_entry.first
|
30
|
+
|
31
|
+
computed_entry.each_with_index do |computed_value,j|
|
32
|
+
# We already tested the type...
|
33
|
+
next if j == 0
|
34
|
+
assert_in_delta computed_value, sample_entry[j], MAX_DELTA
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
def test_triangulation_correct
|
41
|
+
# Perform the computation.
|
42
|
+
comp = RubyVor::VDDT::Computation.from_points(sample_points)
|
43
|
+
|
44
|
+
# One assertion:
|
45
|
+
# * raw triangulation must match exactly.
|
46
|
+
|
47
|
+
assert_equal example_triangulation_raw, comp.delaunay_triangulation_raw
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
|
52
|
+
#
|
53
|
+
# A few helper methods
|
54
|
+
#
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def sample_points
|
59
|
+
# Build a sample case
|
60
|
+
if @points.nil? || @points.empty?
|
61
|
+
@points = []
|
62
|
+
data = %w{ 0.0 0.0
|
63
|
+
0.0 0.5
|
64
|
+
0.5 0.0
|
65
|
+
3 3
|
66
|
+
0.5 0.5
|
67
|
+
5.0 5.0
|
68
|
+
5.0 5.5
|
69
|
+
5.5 5.0
|
70
|
+
5.5 5.5 }
|
71
|
+
for x in 0..(data.length/2 - 1)
|
72
|
+
@points << RubyVor::Point.new(data[x * 2].to_f, data[x * 2 + 1].to_f)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
@points
|
76
|
+
end
|
77
|
+
|
78
|
+
def example_diagram_raw
|
79
|
+
if @diagram_raw.nil? || @diagram_raw.empty?
|
80
|
+
@diagram_raw = [
|
81
|
+
[:s, 0.000000, 0.000000],
|
82
|
+
[:s, 0.500000, 0.000000],
|
83
|
+
[:l, 1.000000, 0.000000, 0.250000],
|
84
|
+
[:s, 0.000000, 0.500000],
|
85
|
+
[:l, 0.000000, 1.000000, 0.250000],
|
86
|
+
[:s, 0.500000, 0.500000],
|
87
|
+
[:l, 0.000000, 1.000000, 0.250000],
|
88
|
+
[:v, 0.250000, 0.250000],
|
89
|
+
[:l, 1.000000, 1.000000, 0.500000],
|
90
|
+
[:v, 0.250000, 0.250000],
|
91
|
+
[:e, 3, 1, 0],
|
92
|
+
[:l, 1.000000, 0.000000, 0.250000],
|
93
|
+
[:s, 3.000000, 3.000000],
|
94
|
+
[:l, 1.000000, 1.000000, 3.500000],
|
95
|
+
[:v, 3.250000, 0.250000],
|
96
|
+
[:e, 2, 0, 2],
|
97
|
+
[:l, 0.833333, 1.000000, 2.958333],
|
98
|
+
[:s, 5.000000, 5.000000],
|
99
|
+
[:l, 1.000000, 1.000000, 8.000000],
|
100
|
+
[:s, 5.500000, 5.000000],
|
101
|
+
[:l, 1.000000, 0.800000, 7.450000],
|
102
|
+
[:v, 5.249999, 2.750001],
|
103
|
+
[:l, 1.000000, 0.000000, 5.250000],
|
104
|
+
[:s, 5.000000, 5.500000],
|
105
|
+
[:l, 0.000000, 1.000000, 5.250000],
|
106
|
+
[:s, 5.500000, 5.500000],
|
107
|
+
[:l, 0.000000, 1.000000, 5.250000],
|
108
|
+
[:v, 5.250000, 5.250000],
|
109
|
+
[:e, 9, 4, 3],
|
110
|
+
[:l, 1.000000, 1.000000, 10.500000],
|
111
|
+
[:v, 5.250000, 5.250000],
|
112
|
+
[:e, 12, 5, 4],
|
113
|
+
[:l, 1.000000, 0.000000, 5.250000],
|
114
|
+
[:v, 0.250000, 3.250000],
|
115
|
+
[:e, 4, 6, 1],
|
116
|
+
[:e, 5, 6, 2],
|
117
|
+
[:l, 1.000000, 0.833333, 2.958333],
|
118
|
+
[:v, 2.750000, 5.250000],
|
119
|
+
[:e, 7, 7, 3],
|
120
|
+
[:e, 10, 7, 5],
|
121
|
+
[:l, 0.800000, 1.000000, 7.450000],
|
122
|
+
[:v, 15.249999, -9.749999],
|
123
|
+
[:e, 8, 3, 8],
|
124
|
+
[:e, 6, 2, 8],
|
125
|
+
[:l, 1.000000, 1.000000, 5.500000],
|
126
|
+
[:v, -9.749999, 15.249999],
|
127
|
+
[:e, 14, 9, 6],
|
128
|
+
[:e, 15, 9, 7],
|
129
|
+
[:l, 1.000000, 1.000000, 5.500000],
|
130
|
+
[:e, 1, -1, 1],
|
131
|
+
[:e, 17, -1, 9],
|
132
|
+
[:e, 13, -1, 5],
|
133
|
+
[:e, 11, 4, -1],
|
134
|
+
[:e, 16, 8, -1],
|
135
|
+
[:e, 0, 0, -1]
|
136
|
+
]
|
137
|
+
end
|
138
|
+
@diagram_raw
|
139
|
+
end
|
140
|
+
|
141
|
+
def example_triangulation_raw
|
142
|
+
if @trianglulation_raw.nil? || @trianglulation_raw.empty?
|
143
|
+
@trianglulation_raw = [
|
144
|
+
[0, 4, 2],
|
145
|
+
[1, 4, 0],
|
146
|
+
[3, 2, 4],
|
147
|
+
[5, 7, 3],
|
148
|
+
[5, 8, 7],
|
149
|
+
[6, 8, 5],
|
150
|
+
[1, 3, 4],
|
151
|
+
[3, 6, 5],
|
152
|
+
[7, 2, 3],
|
153
|
+
[1, 6, 3]
|
154
|
+
]
|
155
|
+
end
|
156
|
+
@trianglulation_raw
|
157
|
+
end
|
158
|
+
|
159
|
+
end
|
160
|
+
|
161
|
+
MiniTest::Unit.autorun
|
metadata
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rubyvor
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.3
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Brendan Ribera
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2010-01-26 00:00:00 -08:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: hoe
|
17
|
+
type: :development
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 2.4.0
|
24
|
+
version:
|
25
|
+
description: 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.
|
26
|
+
email:
|
27
|
+
- brendan.ribera+rubyvor@gmail.com
|
28
|
+
executables: []
|
29
|
+
|
30
|
+
extensions:
|
31
|
+
- ext/extconf.rb
|
32
|
+
extra_rdoc_files:
|
33
|
+
- Manifest.txt
|
34
|
+
files:
|
35
|
+
- History.rdoc
|
36
|
+
- Manifest.txt
|
37
|
+
- README.rdoc
|
38
|
+
- Rakefile
|
39
|
+
- ext/Doc
|
40
|
+
- ext/edgelist.c
|
41
|
+
- ext/extconf.rb
|
42
|
+
- ext/geometry.c
|
43
|
+
- ext/heap.c
|
44
|
+
- ext/memory.c
|
45
|
+
- ext/output.c
|
46
|
+
- ext/rb_cComputation.c
|
47
|
+
- ext/rb_cPoint.c
|
48
|
+
- ext/rb_cPriorityQueue.c
|
49
|
+
- ext/ruby_vor_c.c
|
50
|
+
- ext/ruby_vor_c.h
|
51
|
+
- ext/vdefs.h
|
52
|
+
- ext/voronoi.c
|
53
|
+
- lib/ruby_vor.rb
|
54
|
+
- lib/ruby_vor/computation.rb
|
55
|
+
- lib/ruby_vor/geo_ruby_extensions.rb
|
56
|
+
- lib/ruby_vor/point.rb
|
57
|
+
- lib/ruby_vor/priority_queue.rb
|
58
|
+
- lib/ruby_vor/version.rb
|
59
|
+
- lib/ruby_vor/visualizer.rb
|
60
|
+
- rubyvor.gemspec
|
61
|
+
- test/test_computation.rb
|
62
|
+
- test/test_point.rb
|
63
|
+
- test/test_priority_queue.rb
|
64
|
+
- test/test_voronoi_interface.rb
|
65
|
+
has_rdoc: true
|
66
|
+
homepage: http://github.com/bribera/rubyvor
|
67
|
+
licenses: []
|
68
|
+
|
69
|
+
post_install_message:
|
70
|
+
rdoc_options:
|
71
|
+
- --main
|
72
|
+
- README.rdoc
|
73
|
+
require_paths:
|
74
|
+
- lib
|
75
|
+
- ext
|
76
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - ">="
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: "0"
|
81
|
+
version:
|
82
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
83
|
+
requirements:
|
84
|
+
- - ">="
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: "0"
|
87
|
+
version:
|
88
|
+
requirements: []
|
89
|
+
|
90
|
+
rubyforge_project: rubyvor
|
91
|
+
rubygems_version: 1.3.5
|
92
|
+
signing_key:
|
93
|
+
specification_version: 3
|
94
|
+
summary: Efficient Voronoi diagrams and Delaunay trianglation for Ruby
|
95
|
+
test_files:
|
96
|
+
- test/test_computation.rb
|
97
|
+
- test/test_point.rb
|
98
|
+
- test/test_priority_queue.rb
|
99
|
+
- test/test_voronoi_interface.rb
|