bresenham 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +27 -0
- data/Rakefile +7 -0
- data/bresenham.gemspec +17 -0
- data/lib/ascii_plot.rb +34 -0
- data/lib/bresenham.rb +8 -0
- data/lib/bresenham/circle.rb +89 -0
- data/lib/bresenham/line.rb +26 -0
- data/lib/bresenham/version.rb +3 -0
- data/test/ascii_plot_test.rb +174 -0
- data/test/circle_test.rb +26 -0
- data/test/line_test.rb +31 -0
- metadata +63 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Sean McCarthy
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# Bresenham
|
2
|
+
|
3
|
+
A set of functions implementing Bresenham's algorithm for lines and circles.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'bresenham'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install bresenham
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
require 'bresenham'
|
22
|
+
# x_start, y_start, x_end, y_end
|
23
|
+
line_points_set = Bresenham::Line::coordinates(0, 0, 3, 10)
|
24
|
+
|
25
|
+
# x_origin, y_origin, radius
|
26
|
+
circle_points_set = Bresenham::Circle::coordinates(0, 0, 10)
|
27
|
+
|
data/Rakefile
ADDED
data/bresenham.gemspec
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/bresenham/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Sean McCarthy"]
|
6
|
+
gem.email = ["sean@clanmccarthy.net"]
|
7
|
+
gem.description = %q{Implementation of Bresenham's algorithm for lines and circles. Functions return sets of coordinates that can be used for plotting.}
|
8
|
+
gem.summary = %q{Implementation of Bresenham's algorithm for lines and circles.}
|
9
|
+
gem.homepage = "https://github.com/seandmccarthy/bresenham"
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.name = "bresenham"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = Bresenham::VERSION
|
17
|
+
end
|
data/lib/ascii_plot.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
class ASCIIPlot
|
2
|
+
|
3
|
+
DOT = '.'
|
4
|
+
EMPTY = ' '
|
5
|
+
X_AXIS = '-'
|
6
|
+
Y_AXIS = '|'
|
7
|
+
|
8
|
+
def initialize(x_start, x_end, y_start, y_end)
|
9
|
+
@x_start = x_start
|
10
|
+
@x_end = x_end
|
11
|
+
@y_start = y_start
|
12
|
+
@y_end = y_end
|
13
|
+
end
|
14
|
+
|
15
|
+
def plot(point_list)
|
16
|
+
output = ''
|
17
|
+
@y_end.downto(@y_start).each do |y|
|
18
|
+
(@x_start..@x_end).each do |x|
|
19
|
+
if point_list.include?([x,y])
|
20
|
+
output << DOT
|
21
|
+
elsif x == 0
|
22
|
+
output << Y_AXIS
|
23
|
+
elsif y == 0
|
24
|
+
output << X_AXIS
|
25
|
+
else
|
26
|
+
output << EMPTY
|
27
|
+
end
|
28
|
+
end
|
29
|
+
output << "\n"
|
30
|
+
end
|
31
|
+
output
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
data/lib/bresenham.rb
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
module Bresenham
|
2
|
+
module Circle
|
3
|
+
def self.coordinates(xm, ym, radius)
|
4
|
+
x = -radius
|
5
|
+
y = 0
|
6
|
+
err = 2-2*radius
|
7
|
+
coords = Set.new
|
8
|
+
|
9
|
+
begin
|
10
|
+
coords << [xm + x, ym - y]
|
11
|
+
coords << [xm - x, ym + y]
|
12
|
+
coords << [xm + y, ym + x]
|
13
|
+
coords << [xm - y, ym - x]
|
14
|
+
radius = err
|
15
|
+
if radius <= y
|
16
|
+
y += 1
|
17
|
+
err += y * 2 + 1
|
18
|
+
end
|
19
|
+
if radius > x or err > y
|
20
|
+
x += 1
|
21
|
+
err += x * 2 + 1
|
22
|
+
end
|
23
|
+
end while (x < 0)
|
24
|
+
coords
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.coordinates2(x0, y0, r)
|
28
|
+
p = 3 - 2 * r
|
29
|
+
x = 0
|
30
|
+
y = r
|
31
|
+
coords = Set.new
|
32
|
+
|
33
|
+
while (y >= x)
|
34
|
+
coords << [x0 + x, y0 + y]
|
35
|
+
coords << [x0 + x, y0 - y]
|
36
|
+
coords << [x0 - x, y0 + y]
|
37
|
+
coords << [x0 - x, y0 - y]
|
38
|
+
coords << [x0 + y, y0 + x]
|
39
|
+
coords << [x0 + y, y0 - x]
|
40
|
+
coords << [x0 - y, y0 + x]
|
41
|
+
coords << [x0 - y, y0 - x]
|
42
|
+
if (p < 0)
|
43
|
+
p += 4*x + 6
|
44
|
+
x += 1
|
45
|
+
else
|
46
|
+
p += 4*(x - y) + 10
|
47
|
+
x += 1
|
48
|
+
y -= 1
|
49
|
+
end
|
50
|
+
end
|
51
|
+
coords
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.midpoint_algorithm(x0, y0, radius)
|
55
|
+
f = 1 - radius
|
56
|
+
ddF_x = 1
|
57
|
+
ddF_y = -2 * radius
|
58
|
+
x = 0
|
59
|
+
y = radius
|
60
|
+
coords = Set.new
|
61
|
+
|
62
|
+
coords << [x0, y0 + radius]
|
63
|
+
coords << [x0, y0 - radius]
|
64
|
+
coords << [x0 + radius, y0]
|
65
|
+
coords << [x0 - radius, y0]
|
66
|
+
|
67
|
+
while x < y
|
68
|
+
if f >= 0
|
69
|
+
y -= 1
|
70
|
+
ddF_y += 2
|
71
|
+
f += ddF_y
|
72
|
+
end
|
73
|
+
x += 1
|
74
|
+
ddF_x += 2;
|
75
|
+
f += ddF_x;
|
76
|
+
coords << [x0 + x, y0 + y]
|
77
|
+
coords << [x0 - x, y0 + y]
|
78
|
+
coords << [x0 + x, y0 - y]
|
79
|
+
coords << [x0 - x, y0 - y]
|
80
|
+
coords << [x0 + y, y0 + x]
|
81
|
+
coords << [x0 - y, y0 + x]
|
82
|
+
coords << [x0 + y, y0 - x]
|
83
|
+
coords << [x0 - y, y0 - x]
|
84
|
+
end
|
85
|
+
coords
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Bresenham
|
2
|
+
module Line
|
3
|
+
def self.coordinates(x0, y0, x1, y1)
|
4
|
+
dx = (x1 - x0).abs
|
5
|
+
dy = -(y1 - y0).abs
|
6
|
+
step_x = x0 < x1 ? 1 : -1
|
7
|
+
step_y = y0 < y1 ? 1 : -1
|
8
|
+
err = dx + dy
|
9
|
+
|
10
|
+
coords = Set.new [[x0, y0]]
|
11
|
+
begin
|
12
|
+
e2 = 2*err;
|
13
|
+
if e2 >= dy
|
14
|
+
err += dy
|
15
|
+
x0 += step_x
|
16
|
+
end
|
17
|
+
if e2 <= dx
|
18
|
+
err += dx
|
19
|
+
y0 += step_y
|
20
|
+
end
|
21
|
+
coords << [x0, y0]
|
22
|
+
end until (x0 == x1 && y0 == y1)
|
23
|
+
coords
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,174 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'bresenham'
|
3
|
+
require 'ascii_plot'
|
4
|
+
|
5
|
+
class TestASCIIPlot < MiniTest::Unit::TestCase
|
6
|
+
|
7
|
+
def test_short_line_plot
|
8
|
+
expected = <<EOP
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
| ..
|
17
|
+
| ....
|
18
|
+
| ...
|
19
|
+
..---------
|
20
|
+
EOP
|
21
|
+
plot = ASCIIPlot.new(0, 10, 0, 10)
|
22
|
+
output = plot.plot Bresenham::Line::coordinates(0, 0, 10, 3)
|
23
|
+
assert_equal output, expected
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_long_line_plot
|
27
|
+
expected = <<EOP
|
28
|
+
| .
|
29
|
+
| .
|
30
|
+
| .
|
31
|
+
| .
|
32
|
+
| .
|
33
|
+
| .
|
34
|
+
| .
|
35
|
+
| .
|
36
|
+
| .
|
37
|
+
| .
|
38
|
+
----------|--.-------
|
39
|
+
| .
|
40
|
+
|.
|
41
|
+
.
|
42
|
+
.
|
43
|
+
.|
|
44
|
+
. |
|
45
|
+
. |
|
46
|
+
. |
|
47
|
+
. |
|
48
|
+
. |
|
49
|
+
EOP
|
50
|
+
plot = ASCIIPlot.new(-10, 10, -10, 10)
|
51
|
+
output = plot.plot Bresenham::Line::coordinates(-5, -10, 10, 10)
|
52
|
+
assert_equal output, expected
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_small_circle_plot
|
56
|
+
expected = <<EOP
|
57
|
+
...
|
58
|
+
. | .
|
59
|
+
. | .
|
60
|
+
. | .
|
61
|
+
.---|---.
|
62
|
+
. | .
|
63
|
+
. | .
|
64
|
+
. | .
|
65
|
+
...
|
66
|
+
EOP
|
67
|
+
plot = ASCIIPlot.new(-4, 4, -4, 4)
|
68
|
+
output = plot.plot Bresenham::Circle::coordinates(0, 0, 4)
|
69
|
+
assert_equal output, expected
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_mid_circle_plot
|
73
|
+
expected = <<EOP
|
74
|
+
.....
|
75
|
+
.. | ..
|
76
|
+
. | .
|
77
|
+
. | .
|
78
|
+
. | .
|
79
|
+
. | .
|
80
|
+
. | .
|
81
|
+
. | .
|
82
|
+
.-------|-------.
|
83
|
+
. | .
|
84
|
+
. | .
|
85
|
+
. | .
|
86
|
+
. | .
|
87
|
+
. | .
|
88
|
+
. | .
|
89
|
+
.. | ..
|
90
|
+
.....
|
91
|
+
EOP
|
92
|
+
plot = ASCIIPlot.new(-8, 8, -8, 8)
|
93
|
+
output = plot.plot Bresenham::Circle::coordinates(0, 0, 8)
|
94
|
+
assert_equal output, expected
|
95
|
+
end
|
96
|
+
|
97
|
+
def test_large_circle_plot
|
98
|
+
expected = <<EOP
|
99
|
+
.........
|
100
|
+
... | ...
|
101
|
+
.. | ..
|
102
|
+
.. | ..
|
103
|
+
. | .
|
104
|
+
. | .
|
105
|
+
. | .
|
106
|
+
. | .
|
107
|
+
. | .
|
108
|
+
. | .
|
109
|
+
. | .
|
110
|
+
. | .
|
111
|
+
. | .
|
112
|
+
. | .
|
113
|
+
. | .
|
114
|
+
. | .
|
115
|
+
. | .
|
116
|
+
. | .
|
117
|
+
. | .
|
118
|
+
. | .
|
119
|
+
.-------------------|-------------------.
|
120
|
+
. | .
|
121
|
+
. | .
|
122
|
+
. | .
|
123
|
+
. | .
|
124
|
+
. | .
|
125
|
+
. | .
|
126
|
+
. | .
|
127
|
+
. | .
|
128
|
+
. | .
|
129
|
+
. | .
|
130
|
+
. | .
|
131
|
+
. | .
|
132
|
+
. | .
|
133
|
+
. | .
|
134
|
+
. | .
|
135
|
+
. | .
|
136
|
+
.. | ..
|
137
|
+
.. | ..
|
138
|
+
... | ...
|
139
|
+
.........
|
140
|
+
EOP
|
141
|
+
plot = ASCIIPlot.new(-20, 20, -20, 20)
|
142
|
+
output = plot.plot Bresenham::Circle::coordinates(0, 0, 20)
|
143
|
+
assert_equal output, expected
|
144
|
+
end
|
145
|
+
|
146
|
+
def test_non_zero_origin_plot
|
147
|
+
expected = <<EOP
|
148
|
+
. |
|
149
|
+
. |
|
150
|
+
. |
|
151
|
+
. |
|
152
|
+
. |
|
153
|
+
. |
|
154
|
+
. |
|
155
|
+
. |
|
156
|
+
. |
|
157
|
+
. |
|
158
|
+
------.---|----------
|
159
|
+
. |
|
160
|
+
. |
|
161
|
+
.|
|
162
|
+
.. ..
|
163
|
+
| .......
|
164
|
+
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
EOP
|
170
|
+
plot = ASCIIPlot.new(-10, 10, -10, 10)
|
171
|
+
output = plot.plot Bresenham::Circle::coordinates(5, 5, 10)
|
172
|
+
assert_equal output, expected
|
173
|
+
end
|
174
|
+
end
|
data/test/circle_test.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'bresenham'
|
3
|
+
|
4
|
+
class TestBresenham < MiniTest::Unit::TestCase
|
5
|
+
|
6
|
+
def test_unit_circle
|
7
|
+
expected = [[-1, 0], [0, -1], [0, 1], [1, 0]]
|
8
|
+
assert_equal Bresenham::Circle::coordinates(0, 0, 1).to_a.sort, expected
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_odd_radius
|
12
|
+
expected = [[-3, -1], [-3, 0], [-3, 1], [-2, -2], [-2, 2], [-1, -3], [-1, 3], [0, -3], [0, 3], [1, -3], [1, 3], [2, -2], [2, 2], [3, -1], [3, 0], [3, 1]]
|
13
|
+
assert_equal Bresenham::Circle::coordinates(0, 0, 3).to_a.sort, expected
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_even_radius
|
17
|
+
expected = [[-4, -1], [-4, 0], [-4, 1], [-3, -2], [-3, 2], [-2, -3], [-2, 3], [-1, -4], [-1, 4], [0, -4], [0, 4], [1, -4], [1, 4], [2, -3], [2, 3], [3, -2], [3, 2], [4, -1], [4, 0], [4, 1]]
|
18
|
+
assert_equal Bresenham::Circle::coordinates(0, 0, 4).to_a.sort, expected
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_non_zero_origin
|
22
|
+
expected = [[-6, -3], [-6, -2], [-6, -1], [-5, -4], [-5, 0], [-4, -5], [-4, 1], [-3, -6], [-3, 2], [-2, -6], [-2, 2], [-1, -6], [-1, 2], [0, -5], [0, 1], [1, -4], [1, 0], [2, -3], [2, -2], [2, -1]]
|
23
|
+
assert_equal Bresenham::Circle::coordinates(-2, -2, 4).to_a.sort, expected
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
data/test/line_test.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'bresenham'
|
3
|
+
|
4
|
+
class TestBresenhamLine < MiniTest::Unit::TestCase
|
5
|
+
|
6
|
+
def test_horizontal
|
7
|
+
expected = [[0, 0], [1, 0], [2, 0]]
|
8
|
+
assert_equal Bresenham::Line::coordinates(0, 0, 2, 0).to_a, expected
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_diagonal
|
12
|
+
expected = [[0, 0], [1, 1], [2, 2], [3, 3], [4, 4], [5, 5]]
|
13
|
+
assert_equal Bresenham::Line::coordinates(0, 0, 5, 5).to_a, expected
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_30_degrees
|
17
|
+
expected = [[0, 0], [1, 0], [2, 1], [3, 1], [4, 1], [5, 2], [6, 2], [7, 2], [8, 2], [9, 3], [10, 3]]
|
18
|
+
assert_equal Bresenham::Line::coordinates(0, 0, 10, 3).to_a, expected
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_30_degress_backwards
|
22
|
+
expected = [[10, 3], [9, 3], [8, 2], [7, 2], [6, 2], [5, 1], [4, 1], [3, 1], [2, 1], [1, 0], [0, 0]]
|
23
|
+
assert_equal Bresenham::Line::coordinates(10, 3, 0, 0).to_a, expected
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_negative_axis
|
27
|
+
expected = [[1, 3], [1, 2], [0, 1], [0, 0], [0, -1], [-1, -2], [-1, -3]]
|
28
|
+
assert_equal Bresenham::Line::coordinates(1, 3, -1, -3).to_a, expected
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
metadata
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: bresenham
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Sean McCarthy
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-08-14 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: Implementation of Bresenham's algorithm for lines and circles. Functions
|
15
|
+
return sets of coordinates that can be used for plotting.
|
16
|
+
email:
|
17
|
+
- sean@clanmccarthy.net
|
18
|
+
executables: []
|
19
|
+
extensions: []
|
20
|
+
extra_rdoc_files: []
|
21
|
+
files:
|
22
|
+
- .gitignore
|
23
|
+
- Gemfile
|
24
|
+
- LICENSE
|
25
|
+
- README.md
|
26
|
+
- Rakefile
|
27
|
+
- bresenham.gemspec
|
28
|
+
- lib/ascii_plot.rb
|
29
|
+
- lib/bresenham.rb
|
30
|
+
- lib/bresenham/circle.rb
|
31
|
+
- lib/bresenham/line.rb
|
32
|
+
- lib/bresenham/version.rb
|
33
|
+
- test/ascii_plot_test.rb
|
34
|
+
- test/circle_test.rb
|
35
|
+
- test/line_test.rb
|
36
|
+
homepage: https://github.com/seandmccarthy/bresenham
|
37
|
+
licenses: []
|
38
|
+
post_install_message:
|
39
|
+
rdoc_options: []
|
40
|
+
require_paths:
|
41
|
+
- lib
|
42
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
43
|
+
none: false
|
44
|
+
requirements:
|
45
|
+
- - ! '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
requirements: []
|
55
|
+
rubyforge_project:
|
56
|
+
rubygems_version: 1.8.15
|
57
|
+
signing_key:
|
58
|
+
specification_version: 3
|
59
|
+
summary: Implementation of Bresenham's algorithm for lines and circles.
|
60
|
+
test_files:
|
61
|
+
- test/ascii_plot_test.rb
|
62
|
+
- test/circle_test.rb
|
63
|
+
- test/line_test.rb
|