sangaku 0.5.4

Sign up to get free protection for your applications and to get access to all the features.
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm use 1.9.3@sangaku --create
data/Gemfile ADDED
@@ -0,0 +1,22 @@
1
+ source :rubygems
2
+
3
+ group :development do
4
+ gem "awesome_print"
5
+ end
6
+
7
+ group :test do
8
+ gem "rake"
9
+ gem "rspec"
10
+ gem "yard"
11
+ gem "debugger"
12
+ end
13
+
14
+ group :document do
15
+ gem "rdoc"
16
+ gem "redcarpet"
17
+ end
18
+
19
+ group :gemify do
20
+ gem "jeweler"
21
+ end
22
+
@@ -0,0 +1,46 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ awesome_print (1.1.0)
5
+ columnize (0.3.6)
6
+ debugger (1.3.3)
7
+ columnize (>= 0.3.1)
8
+ debugger-linecache (~> 1.1.1)
9
+ debugger-ruby_core_source (~> 1.2.0)
10
+ debugger-linecache (1.1.2)
11
+ debugger-ruby_core_source (>= 1.1.1)
12
+ debugger-ruby_core_source (1.2.0)
13
+ diff-lcs (1.2.1)
14
+ git (1.2.5)
15
+ jeweler (1.8.4)
16
+ bundler (~> 1.0)
17
+ git (>= 1.2.5)
18
+ rake
19
+ rdoc
20
+ json (1.7.7)
21
+ rake (10.0.3)
22
+ rdoc (4.0.0)
23
+ json (~> 1.4)
24
+ redcarpet (2.2.2)
25
+ rspec (2.13.0)
26
+ rspec-core (~> 2.13.0)
27
+ rspec-expectations (~> 2.13.0)
28
+ rspec-mocks (~> 2.13.0)
29
+ rspec-core (2.13.0)
30
+ rspec-expectations (2.13.0)
31
+ diff-lcs (>= 1.1.3, < 2.0)
32
+ rspec-mocks (2.13.0)
33
+ yard (0.8.5.2)
34
+
35
+ PLATFORMS
36
+ ruby
37
+
38
+ DEPENDENCIES
39
+ awesome_print
40
+ debugger
41
+ jeweler
42
+ rake
43
+ rdoc
44
+ redcarpet
45
+ rspec
46
+ yard
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2013 Agworld Pty. Ltd.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,45 @@
1
+ Sangaku
2
+ =======
3
+
4
+ Sangaku is a geometry gem for Ruby.
5
+
6
+ [![Build Status](https://secure.travis-ci.org/agworld/sangaku.png)](http://travis-ci.org/#!/agworld/sangaku)
7
+ [![Dependency Status](https://gemnasium.com/agworld/sangaku.png)](https://gemnasium.com/agworld/sangaku)
8
+
9
+ Getting Started
10
+ ---------------
11
+
12
+ Simply `sudo gem install sangaku` and then `require 'sangaku'` in your code.
13
+
14
+ Example Usage
15
+ -------------
16
+
17
+ ```ruby
18
+ data = [[10, 10], [10, 20], [20, 10]]
19
+ polygon = Sangaku::Polygon.new(*data)
20
+ polygon.close!
21
+ aabb = polygon.aabb
22
+ puts aabb.mid
23
+ ```
24
+
25
+ This code prints the following:
26
+
27
+ ```
28
+ (15.0, 15.0)
29
+ ```
30
+
31
+ Contributing to Sangaku
32
+ -----------------------
33
+
34
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
35
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
36
+ * Fork the project.
37
+ * Start a feature/bugfix branch.
38
+ * Commit and push until you are happy with your contribution.
39
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
40
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
41
+
42
+ Copyright
43
+ ---------
44
+
45
+ Copyright (c) 2013 Agworld Pty. Ltd. See LICENSE.txt for further details.
@@ -0,0 +1,42 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "sangaku"
18
+ gem.homepage = "https://github.com/agworld/sangaku"
19
+ gem.license = "MIT"
20
+ gem.summary = "Sangaku is a geometry gem for Ruby."
21
+ gem.description = "Sangaku contains classes for Point, Line, Polygon, AABB and so on in 2D. It can find the 'pole of inaccessibility' for a polygon. And it can simply the boundary of a polygon to minimise points while retaining detail. It works well with Gosu."
22
+ gem.email = "jason.hutchens@agworld.com.au"
23
+ gem.authors = ["Jason Hutchens"]
24
+ # dependencies defined in Gemfile
25
+ end
26
+ Jeweler::RubygemsDotOrgTasks.new
27
+
28
+ require 'rspec/core'
29
+ require 'rspec/core/rake_task'
30
+ RSpec::Core::RakeTask.new(:spec) do |spec|
31
+ spec.pattern = FileList['spec/**/*_spec.rb']
32
+ end
33
+
34
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
35
+ spec.pattern = 'spec/**/*_spec.rb'
36
+ spec.rcov = false
37
+ end
38
+
39
+ task :default => :spec
40
+
41
+ require 'yard'
42
+ YARD::Rake::YardocTask.new
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.5.4
@@ -0,0 +1,7 @@
1
+ require 'sangaku/point'
2
+ require 'sangaku/line'
3
+ require 'sangaku/polygon'
4
+ require 'sangaku/aabb'
5
+ require 'sangaku/grid'
6
+ require 'sangaku/star'
7
+ require 'sangaku/errors'
@@ -0,0 +1,53 @@
1
+ module Sangaku
2
+
3
+ class AABB
4
+
5
+ def initialize(*points)
6
+ points = Point::convert(points)
7
+ xs = points.map { |p| p.x }
8
+ ys = points.map { |p| p.y }
9
+ @line = Line.new([xs.min || 0, ys.min || 0], [xs.max || 0, ys.max || 0])
10
+ end
11
+
12
+ def min; @line.p1; end
13
+ def max; @line.p2; end
14
+ def mid; @line.mid; end
15
+
16
+ def w; @line.w; end
17
+ def h; @line.h; end
18
+
19
+ def centre!(point = [0, 0])
20
+ point = Point.new(*point) if point.is_a?(Array)
21
+ @line -= (@line.mid - point)
22
+ end
23
+
24
+ def square!
25
+ mid = @line.mid
26
+ ds = 0.5 * [w, h].max
27
+ @line.p1.x = mid.x - ds
28
+ @line.p1.y = mid.y - ds
29
+ @line.p2.x = mid.x + ds
30
+ @line.p2.y = mid.y + ds
31
+ end
32
+
33
+ def *(scale)
34
+ mid = @line.mid
35
+ dx = 0.5 * w * scale
36
+ dy = 0.5 * h * scale
37
+ AABB.new([mid.x - dx, mid.y - dy], [mid.x + dx, mid.y + dy])
38
+ end
39
+
40
+ def to_grid(count = 5)
41
+ raise if count < 2
42
+ xs = (min.x..max.x).step(w/(count-1).to_f)
43
+ ys = (min.y..max.y).step(h/(count-1).to_f)
44
+ Grid.new(xs.to_a, ys.to_a)
45
+ end
46
+
47
+ def to_a; @line.to_a; end
48
+ def to_s; @line.to_s; end
49
+ alias_method :inspect, :to_s
50
+
51
+ end
52
+
53
+ end
@@ -0,0 +1,9 @@
1
+ module Sangaku
2
+ module Errors
3
+ class OpenPolygonError < StandardError
4
+ def initialize
5
+ super "Expected poly to be closed."
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,51 @@
1
+ module Sangaku
2
+
3
+ class Grid
4
+
5
+ def initialize(xs, ys)
6
+ @xs, @ys = xs, ys
7
+ end
8
+
9
+ def get_stars(poly)
10
+ raise Errors::OpenPolygonError.new unless poly.closed?
11
+ stars = []
12
+
13
+ @xs.each do |x|
14
+ ys = poly.select(x, nil).map { |line| line.get_y(x) }
15
+ next if ys.length % 2 != 0
16
+ stars += ys.sort.each_slice(2).map do |s|
17
+ height = s.reduce(:-).abs
18
+ y = 0.5 * s.reduce(:+)
19
+ xs = poly.select(nil, y).map { |line| line.get_x(y) }
20
+ xs.sort!
21
+ s = xs.zip(xs.rotate).find { |a, b| x.between?(a, b) }
22
+ # TODO: de-hack
23
+ next unless s
24
+ width = 2 * [(x-s[0]).abs, (x-s[1]).abs].min
25
+ Star.new([x, y], [width, height])
26
+ end
27
+ end
28
+
29
+ @ys.each do |y|
30
+ xs = poly.select(nil, y).map { |line| line.get_x(y) }
31
+ next if xs.length % 2 != 0
32
+ stars += xs.sort.each_slice(2).map do |s|
33
+ width = s.reduce(:-).abs
34
+ x = 0.5 * s.reduce(:+)
35
+ ys = poly.select(x, nil).map { |line| line.get_y(x) }
36
+ ys.sort!
37
+ s = ys.zip(ys.rotate).find { |a, b| y.between?(a, b) }
38
+ # TODO: de-hack
39
+ next unless s
40
+ height = 2 * [(y-s[0]).abs, (y-s[1]).abs].min
41
+ Star.new([x, y], [width, height])
42
+ end
43
+ end
44
+
45
+ #TODO: de-hack
46
+ stars.reject{|s| s.nil?}
47
+ end
48
+
49
+ end
50
+
51
+ end
@@ -0,0 +1,77 @@
1
+ module Sangaku
2
+
3
+ class Line
4
+
5
+ def initialize(p1, p2)
6
+ @coords = Point::convert([p1, p2])
7
+ end
8
+
9
+ def p1; @coords[0]; end
10
+ def p1=(val); @coords[0] = val; end
11
+ def p2; @coords[1]; end
12
+ def p2=(val); @coords[1] = val; end
13
+
14
+ def w
15
+ (p2.x - p1.x).abs
16
+ end
17
+ def h
18
+ (p2.y - p1.y).abs
19
+ end
20
+
21
+ def length
22
+ Math.sqrt(vx ** 2 + vy ** 2)
23
+ end
24
+
25
+ def vx
26
+ p2.x - p1.x
27
+ end
28
+
29
+ def vy
30
+ p2.y - p1.y
31
+ end
32
+
33
+ def get_x(y)
34
+ ratio = p1.y != p2.y ? (y-p1.y)/(p2.y-p1.y).to_f : 0.5
35
+ p1.x + ratio * (p2.x-p1.x)
36
+ end
37
+ def get_y(x)
38
+ ratio = p1.x != p2.x ? (x-p1.x)/(p2.x-p1.x).to_f : 0.5
39
+ p1.y + ratio * (p2.y-p1.y)
40
+ end
41
+
42
+ def +(point)
43
+ Line.new(p1 + point, p2 + point)
44
+ end
45
+ def -(point)
46
+ Line.new(p1 - point, p2 - point)
47
+ end
48
+
49
+ def mid
50
+ (p1 + p2) * 0.5
51
+ end
52
+
53
+ def dot(other)
54
+ (self.vx * other.vx + self.vy * other.vy)/(self.length * other.length)
55
+ end
56
+
57
+ def cross(other)
58
+ self.vx * other.vy - self.vy * other.vx
59
+ end
60
+
61
+ def contain?(x = nil, y = nil)
62
+ (x.nil? || x.between?(*[p1.x, p2.x].sort)) &&
63
+ (y.nil? || y.between?(*[p1.y, p2.y].sort))
64
+ end
65
+
66
+ def to_a
67
+ [@p1.to_a, @p2.to_a]
68
+ end
69
+
70
+ def to_s
71
+ "#{p1}->#{p2}"
72
+ end
73
+ alias_method :inspect, :to_s
74
+
75
+ end
76
+
77
+ end
@@ -0,0 +1,49 @@
1
+ module Sangaku
2
+
3
+ class Point
4
+
5
+ def initialize(x, y)
6
+ @coord = [x, y]
7
+ end
8
+
9
+ def self.convert(points)
10
+ points.map { |p| Point.new(*p) }
11
+ end
12
+
13
+ def x; @coord[0]; end
14
+ def x=(val); @coord[0]=val; end
15
+ def y; @coord[1]; end
16
+ def y=(val); @coord[1]=val; end
17
+
18
+ alias_method :w, :x
19
+ alias_method :w=, :x=
20
+ alias_method :h, :y
21
+ alias_method :h=, :y=
22
+
23
+ def +(other)
24
+ Point.new(self.x + other.x, self.y + other.y)
25
+ end
26
+
27
+ def -(other)
28
+ Point.new(self.x - other.x, self.y - other.y)
29
+ end
30
+
31
+ def *(scale)
32
+ Point.new(self.x * scale, self.y * scale)
33
+ end
34
+
35
+ def /(scale)
36
+ Point.new(self.x / scale, self.y / scale)
37
+ end
38
+
39
+ def dist(other)
40
+ Math.sqrt((self.x - other.x) ** 2 + (self.y - other.y) ** 2 )
41
+ end
42
+
43
+ def to_a; @coord; end
44
+ def to_s; "(#{@coord.join(', ')})"; end
45
+ alias_method :inspect, :to_s
46
+
47
+ end
48
+
49
+ end
@@ -0,0 +1,75 @@
1
+ module Sangaku
2
+
3
+ class Polygon
4
+
5
+ def initialize(*points)
6
+ @points = Point::convert(points)
7
+ @lines = nil
8
+ @closed = false
9
+ @aabb = nil
10
+ end
11
+
12
+ def closed?
13
+ @closed
14
+ end
15
+
16
+ def close!
17
+ return if @closed
18
+ @closed = true
19
+ @lines = nil
20
+ @aabb = nil
21
+ end
22
+
23
+ def clear!
24
+ @points.clear
25
+ @closed = false
26
+ @lines = nil
27
+ @aabb = nil
28
+ end
29
+
30
+ def length
31
+ @points.length
32
+ end
33
+
34
+ def points
35
+ @points
36
+ end
37
+
38
+ def lines
39
+ @lines ||= _points_to_lines
40
+ end
41
+
42
+ def aabb
43
+ @aabb ||= AABB.new(*@points)
44
+ end
45
+
46
+ def <<(p)
47
+ @lines = nil
48
+ @points << Point.new(*p)
49
+ end
50
+
51
+ def select(x = nil, y = nil)
52
+ lines.select { |line| line.contain?(x, y) }
53
+ end
54
+
55
+ def to_a
56
+ @points.map { |p| p.to_a }
57
+ end
58
+
59
+ def to_s
60
+ @points.join('->')
61
+ end
62
+ alias_method :inspect, :to_s
63
+
64
+ private
65
+
66
+ def _points_to_lines
67
+ return [] if @points.length < 2
68
+ retval = @points.zip(@points.rotate).map { |p1, p2| Line.new(p1, p2) }
69
+ retval = retval[0...-1] unless @closed
70
+ retval
71
+ end
72
+
73
+ end
74
+
75
+ end
@@ -0,0 +1,25 @@
1
+ module Sangaku
2
+
3
+ class Star
4
+
5
+ include Comparable
6
+
7
+ def initialize(center, size)
8
+ @center, @size = Point.new(*center), Point.new(*size)
9
+ end
10
+
11
+ def center
12
+ @center
13
+ end
14
+
15
+ def fitness
16
+ @fitness ||= (@size.w * @size.h)/(1+0.1*(@size.w-@size.h).abs)
17
+ end
18
+
19
+ def <=>(other)
20
+ other.fitness <=> fitness
21
+ end
22
+
23
+ end
24
+
25
+ end
@@ -0,0 +1,62 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "sangaku"
8
+ s.version = "0.5.4"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Jason Hutchens"]
12
+ s.date = "2013-03-15"
13
+ s.description = "Sangaku contains classes for Point, Line, Polygon, AABB and so on in 2D. It can find the 'pole of inaccessibility' for a polygon. And it can simply the boundary of a polygon to minimise points while retaining detail. It works well with Gosu."
14
+ s.email = "jason.hutchens@agworld.com.au"
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt",
17
+ "README.md"
18
+ ]
19
+ s.files = [
20
+ ".rvmrc",
21
+ "Gemfile",
22
+ "Gemfile.lock",
23
+ "LICENSE.txt",
24
+ "README.md",
25
+ "Rakefile",
26
+ "VERSION",
27
+ "lib/sangaku.rb",
28
+ "lib/sangaku/aabb.rb",
29
+ "lib/sangaku/errors.rb",
30
+ "lib/sangaku/grid.rb",
31
+ "lib/sangaku/line.rb",
32
+ "lib/sangaku/point.rb",
33
+ "lib/sangaku/polygon.rb",
34
+ "lib/sangaku/star.rb",
35
+ "sangaku.gemspec",
36
+ "spec/aabb_spec.rb",
37
+ "spec/grid_spec.rb",
38
+ "spec/line_spec.rb",
39
+ "spec/point_spec.rb",
40
+ "spec/polygon_spec.rb",
41
+ "spec/spec_helper.rb",
42
+ "spec/star_spec.rb"
43
+ ]
44
+ s.homepage = "https://github.com/agworld/sangaku"
45
+ s.licenses = ["MIT"]
46
+ s.require_paths = ["lib"]
47
+ s.rubygems_version = "1.8.24"
48
+ s.summary = "Sangaku is a geometry gem for Ruby."
49
+
50
+ if s.respond_to? :specification_version then
51
+ s.specification_version = 3
52
+
53
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
54
+ s.add_development_dependency(%q<awesome_print>, [">= 0"])
55
+ else
56
+ s.add_dependency(%q<awesome_print>, [">= 0"])
57
+ end
58
+ else
59
+ s.add_dependency(%q<awesome_print>, [">= 0"])
60
+ end
61
+ end
62
+
@@ -0,0 +1,28 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ module Sangaku
4
+
5
+ describe AABB do
6
+
7
+ it "should just work" do
8
+ aabb = AABB.new([1, 5], [3, 1], [5, -3])
9
+ aabb.min.to_s.should eq("(1, -3)")
10
+ aabb.max.to_s.should eq("(5, 5)")
11
+ aabb.mid.to_s.should eq("(3.0, 1.0)")
12
+ aabb.w.should eq(4)
13
+ aabb.h.should eq(8)
14
+ aabb.centre!
15
+ aabb.mid.to_s.should eq("(0.0, 0.0)")
16
+ aabb.w.should eq(4)
17
+ aabb.h.should eq(8)
18
+ aabb *= 0.5
19
+ aabb.to_s.should eq("(-1.0, -2.0)->(1.0, 2.0)")
20
+ aabb.square!
21
+ aabb.mid.to_s.should eq("(0.0, 0.0)")
22
+ aabb.w.should eq(4)
23
+ aabb.w.should eq(4)
24
+ end
25
+
26
+ end
27
+
28
+ end
@@ -0,0 +1,30 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ module Sangaku
4
+
5
+ describe Grid do
6
+
7
+ context "#get_stars" do
8
+
9
+ it "should fail gracefully for an open poly" do
10
+ xs = [1,4,7]
11
+ ys = [1,3,5]
12
+ grid = Grid.new(xs,ys)
13
+ poly = Polygon.new([1,1],[4,4],[7,2])
14
+ expect { grid.get_stars(poly) }.to raise_error(Errors::OpenPolygonError)
15
+ end
16
+
17
+ it "should work for a poly that folds back on itself" do
18
+ xs = [1,2,3,4,5]
19
+ ys = [1,2,3,4,5]
20
+ grid = Grid.new(xs,ys)
21
+ poly = Polygon.new([1,1],[1,4],[1,3],[2,2],[4,1])
22
+ poly.close!
23
+ grid.get_stars(poly)
24
+ end
25
+
26
+ end
27
+
28
+ end
29
+
30
+ end
@@ -0,0 +1,60 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ module Sangaku
4
+
5
+ describe Line do
6
+
7
+ it 'should have a width and height' do
8
+ line = Line.new([10, 20], [15, 10])
9
+ line.w.should eq(5)
10
+ line.h.should eq(10)
11
+ line.to_s.should eq("(10, 20)->(15, 10)")
12
+ end
13
+
14
+ it 'should be possible to test boundary' do
15
+ line = Line.new([10, 20], [15, 10])
16
+ line.contain?.should eq(true)
17
+ line.contain?(9).should eq(false)
18
+ line.contain?(12).should eq(true)
19
+ line.contain?(16).should eq(false)
20
+ line.contain?(nil, 15).should eq(true)
21
+ line.contain?(12, 15).should eq(true)
22
+ end
23
+
24
+ it 'should be possible to do dot products yo' do
25
+ line1 = Line.new([10, 10], [20, 20])
26
+ line2 = Line.new([30, 30], [50, 50])
27
+ line3 = Line.new([20, 20], [40, 0])
28
+ line4 = Line.new([30, 30], [40, 30])
29
+ line1.dot(line2).should be_within(1e-6).of(1)
30
+ line2.dot(line1).should be_within(1e-6).of(1)
31
+ line1.dot(line3).should be_within(1e-6).of(0)
32
+ line3.dot(line2).should be_within(1e-6).of(0)
33
+ line4.dot(line2).should be_within(1e-6).of(0.5*Math.sqrt(2.0))
34
+ end
35
+
36
+ context "#get_x" do
37
+ it "should return half point for lines running along the same x" do
38
+ line = Line.new([5,1], [9,1])
39
+ line.get_x(Point.new(3,1)).should eq(7)
40
+ line.get_x(1).should eq(7)
41
+ end
42
+ it "should return the point itself for lines that are a point" do
43
+ line = Line.new([5,1], [5,1])
44
+ line.get_x(Point.new(1,1)).should eq(5)
45
+ end
46
+ end
47
+
48
+ context "#get_y" do
49
+ it "should return half point for lines running along the same y" do
50
+ line = Line.new([1,5], [1,9])
51
+ line.get_y(Point.new(1,3)).should eq(7)
52
+ line.get_y(1).should eq(7)
53
+ end
54
+ it "should return the point itself for lines that are a point" do
55
+ line = Line.new([1,5], [1,5])
56
+ line.get_y(Point.new(1,1)).should eq(5)
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,37 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ def test_splat(a, b)
4
+ a + b
5
+ end
6
+
7
+ module Sangaku
8
+
9
+ describe Point do
10
+
11
+ it "should be useful" do
12
+ point = Point.new(100, 200)
13
+ point.x.should eq(100)
14
+ point.y.should eq(200)
15
+ test_splat(*point).should eq(300)
16
+ point.x = 20
17
+ point.y = 30
18
+ point.to_s.should eq("(20, 30)")
19
+ end
20
+
21
+ it "should be possible to measure separation" do
22
+ p1 = Point.new(10, 20)
23
+ p2 = Point.new(15, 10)
24
+ delta = p2-p1
25
+ delta.w.should eq(5)
26
+ delta.h.should eq(-10)
27
+ end
28
+
29
+ it "should be possible to measure distance" do
30
+ p1 = Point.new(10, 13)
31
+ p2 = Point.new(14, 10)
32
+ p1.dist(p2).should eq(5)
33
+ end
34
+
35
+ end
36
+
37
+ end
@@ -0,0 +1,39 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ module Sangaku
4
+
5
+ describe Polygon do
6
+
7
+ it "should just work" do
8
+ poly = Polygon.new([1, 2], [3, 4], [5, 6])
9
+ lines = poly.lines
10
+ lines.length.should eq(2)
11
+ poly.close!
12
+ lines = poly.lines
13
+ lines.length.should eq(3)
14
+ lines[0].to_s.should eq("(1, 2)->(3, 4)")
15
+ lines[1].to_s.should eq("(3, 4)->(5, 6)")
16
+ lines[2].to_s.should eq("(5, 6)->(1, 2)")
17
+ poly << [7, 8]
18
+ poly.to_s.should eq("(1, 2)->(3, 4)->(5, 6)->(7, 8)")
19
+ end
20
+
21
+ it "should be possible to select lines" do
22
+ poly = Polygon.new([1, 2], [3, 4], [5, 6], [7, 8])
23
+ poly.close!
24
+ lines = poly.select(2)
25
+ lines.length.should eq(2)
26
+ lines[0].to_s.should eq("(1, 2)->(3, 4)")
27
+ lines[1].to_s.should eq("(7, 8)->(1, 2)")
28
+ end
29
+
30
+ it "should be possible to get the bounding box" do
31
+ poly = Polygon.new([1, 7], [3, 4], [5, 6], [8, 2])
32
+ aabb = poly.aabb
33
+ aabb.min.to_s.should eq("(1, 2)")
34
+ aabb.max.to_s.should eq("(8, 7)")
35
+ end
36
+
37
+ end
38
+
39
+ end
@@ -0,0 +1,14 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+ require 'rspec'
4
+ require 'sangaku'
5
+ require 'debugger'
6
+
7
+
8
+ # Requires supporting files with custom matchers and macros, etc,
9
+ # in ./support/ and its subdirectories.
10
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
11
+
12
+ RSpec.configure do |config|
13
+
14
+ end
@@ -0,0 +1,9 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ module Sangaku
4
+
5
+ describe Star do
6
+
7
+ end
8
+
9
+ end
metadata ADDED
@@ -0,0 +1,92 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sangaku
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.5.4
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Jason Hutchens
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-03-15 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: awesome_print
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ description: Sangaku contains classes for Point, Line, Polygon, AABB and so on in
31
+ 2D. It can find the 'pole of inaccessibility' for a polygon. And it can simply the
32
+ boundary of a polygon to minimise points while retaining detail. It works well with
33
+ Gosu.
34
+ email: jason.hutchens@agworld.com.au
35
+ executables: []
36
+ extensions: []
37
+ extra_rdoc_files:
38
+ - LICENSE.txt
39
+ - README.md
40
+ files:
41
+ - .rvmrc
42
+ - Gemfile
43
+ - Gemfile.lock
44
+ - LICENSE.txt
45
+ - README.md
46
+ - Rakefile
47
+ - VERSION
48
+ - lib/sangaku.rb
49
+ - lib/sangaku/aabb.rb
50
+ - lib/sangaku/errors.rb
51
+ - lib/sangaku/grid.rb
52
+ - lib/sangaku/line.rb
53
+ - lib/sangaku/point.rb
54
+ - lib/sangaku/polygon.rb
55
+ - lib/sangaku/star.rb
56
+ - sangaku.gemspec
57
+ - spec/aabb_spec.rb
58
+ - spec/grid_spec.rb
59
+ - spec/line_spec.rb
60
+ - spec/point_spec.rb
61
+ - spec/polygon_spec.rb
62
+ - spec/spec_helper.rb
63
+ - spec/star_spec.rb
64
+ homepage: https://github.com/agworld/sangaku
65
+ licenses:
66
+ - MIT
67
+ post_install_message:
68
+ rdoc_options: []
69
+ require_paths:
70
+ - lib
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ segments:
78
+ - 0
79
+ hash: -2726484618989348966
80
+ required_rubygems_version: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ requirements: []
87
+ rubyforge_project:
88
+ rubygems_version: 1.8.24
89
+ signing_key:
90
+ specification_version: 3
91
+ summary: Sangaku is a geometry gem for Ruby.
92
+ test_files: []