geometry 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/.gitignore +7 -0
- data/Gemfile +4 -0
- data/README +60 -0
- data/Rakefile +1 -0
- data/geometry.gemspec +23 -0
- data/lib/geometry.rb +6 -0
- data/lib/line.rb +85 -0
- data/lib/point.rb +39 -0
- data/test/test_line.rb +84 -0
- data/test/test_point.rb +75 -0
- data/test/test_unit_extensions.rb +23 -0
- metadata +59 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
Geometry for Ruby
|
2
|
+
=================
|
3
|
+
|
4
|
+
Classes and methods for the handling of all of the basic geometry that you
|
5
|
+
learned in high school (and then forgot).
|
6
|
+
|
7
|
+
The classes in this libary are based on the Vector class provided by the Ruby
|
8
|
+
standard library. Geometric primitives are generally assumed to lie in 2D space,
|
9
|
+
but aren't necessarily restricted to it. Please let me know if you find cases
|
10
|
+
that don't work in higher dimensions and I'll do my best to fix them.
|
11
|
+
|
12
|
+
License
|
13
|
+
-------
|
14
|
+
|
15
|
+
Copyright 2012 Brandon Fosdick <bfoz@bfoz.net> and released under the BSD
|
16
|
+
license.
|
17
|
+
|
18
|
+
Primitives
|
19
|
+
----------
|
20
|
+
|
21
|
+
- Point
|
22
|
+
- Line
|
23
|
+
|
24
|
+
Examples
|
25
|
+
--------
|
26
|
+
|
27
|
+
### Point
|
28
|
+
```ruby
|
29
|
+
point = Geometry::Point[3,4] # 2D Point at coordinate 3, 4
|
30
|
+
point = Geometry.Point(1,2) # Functional constructor
|
31
|
+
|
32
|
+
# Copy constructors
|
33
|
+
point2 = Geometry::Point[point]
|
34
|
+
point2 = Geometry::Point[Vector[5,6]]
|
35
|
+
|
36
|
+
# Accessors
|
37
|
+
point.x
|
38
|
+
point.y
|
39
|
+
point[2] # Same as point.z
|
40
|
+
```
|
41
|
+
|
42
|
+
### Line
|
43
|
+
```ruby
|
44
|
+
# Two-point constructors
|
45
|
+
line = Geometry::Line[[0,0], [10,10]]
|
46
|
+
line = Geometry::Line[Geometry::Point[0,0], Geometry::Point[10,10]]
|
47
|
+
line = Geometry::Line[Vector[0,0], Vector[10,10]]
|
48
|
+
|
49
|
+
# Slope-intercept constructors
|
50
|
+
Geometry::Line[Rational(3,4), 5] # Slope = 3/4, Intercept = 5
|
51
|
+
Geometry::Line[0.75, 5]
|
52
|
+
|
53
|
+
# Point-slope constructors
|
54
|
+
Geometry::Line(Geometry::Point[0,0], 0.75)
|
55
|
+
Geometry::Line(Vector[0,0], Rational(3,4))
|
56
|
+
|
57
|
+
# Special constructors (2D only)
|
58
|
+
Geometry::Line.horizontal(y=0)
|
59
|
+
Geometry::Line.vertical(x=0)
|
60
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/geometry.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = "geometry"
|
6
|
+
s.version = '0'
|
7
|
+
s.authors = ["Brandon Fosdick"]
|
8
|
+
s.email = ["bfoz@bfoz.net"]
|
9
|
+
s.homepage = "http://github.com/bfoz/geometry"
|
10
|
+
s.summary = %q{Geometric primitives and algoritms}
|
11
|
+
s.description = %q{Geometric primitives and algorithms for Ruby}
|
12
|
+
|
13
|
+
s.rubyforge_project = "geometry"
|
14
|
+
|
15
|
+
s.files = `git ls-files`.split("\n")
|
16
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
17
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
18
|
+
s.require_paths = ["lib"]
|
19
|
+
|
20
|
+
# specify any dependencies here; for example:
|
21
|
+
# s.add_development_dependency "rspec"
|
22
|
+
# s.add_runtime_dependency "rest-client"
|
23
|
+
end
|
data/lib/geometry.rb
ADDED
data/lib/line.rb
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
require_relative 'point'
|
2
|
+
|
3
|
+
module Geometry
|
4
|
+
class Line
|
5
|
+
def self.[](*args)
|
6
|
+
Geometry.Line(*args)
|
7
|
+
end
|
8
|
+
def self.horizontal(y_intercept=0)
|
9
|
+
SlopeInterceptLine.new(0, y_intercept)
|
10
|
+
end
|
11
|
+
def self.vertical(x_intercept=0)
|
12
|
+
SlopeInterceptLine.new(1/0.0, x_intercept)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class PointSlopeLine < Line
|
17
|
+
def initialize(point, slope)
|
18
|
+
@point = point.is_a?(Geometry::Point) ? point : Geometry.Point(point)
|
19
|
+
@slope = slope
|
20
|
+
end
|
21
|
+
def to_s
|
22
|
+
'Line(' + @slope.to_s + ',' + @point.to_s + ')'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class SlopeInterceptLine < Line
|
27
|
+
def initialize(slope, intercept)
|
28
|
+
@slope = slope
|
29
|
+
@intercept = intercept
|
30
|
+
end
|
31
|
+
|
32
|
+
def horizontal?
|
33
|
+
0 == @slope
|
34
|
+
end
|
35
|
+
def vertical?
|
36
|
+
(1/0.0) == @slope
|
37
|
+
end
|
38
|
+
|
39
|
+
def intercept(axis=:y)
|
40
|
+
case axis
|
41
|
+
when :x
|
42
|
+
vertical? ? @intercept : (horizontal? ? nil : (-@intercept/@slope))
|
43
|
+
when :y
|
44
|
+
vertical? ? nil : @intercept
|
45
|
+
end
|
46
|
+
end
|
47
|
+
def slope
|
48
|
+
@slope
|
49
|
+
end
|
50
|
+
|
51
|
+
def to_s
|
52
|
+
'Line(' + @slope.to_s + ',' + @intercept.to_s + ')'
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
class TwoPointLine < Line
|
57
|
+
attr_reader :first, :last
|
58
|
+
|
59
|
+
def initialize(point0, point1)
|
60
|
+
@first, @last = [point0, point1].map {|p| p.is_a?(Point) ? p : Geometry.Point(p) }
|
61
|
+
end
|
62
|
+
def inspect
|
63
|
+
'Line(' + @first.to_s + ', ' + @last.to_s + ')'
|
64
|
+
end
|
65
|
+
alias :to_s :inspect
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.Line(*args)
|
69
|
+
if( 2 == args.size )
|
70
|
+
args.map! {|x| x.is_a?(Array) ? Point[*x] : x}
|
71
|
+
|
72
|
+
# If both args are Points, create a TwoPointLine
|
73
|
+
return TwoPointLine.new(*args) if args.all? {|x| x.is_a?(Vector)}
|
74
|
+
|
75
|
+
# If only the first arg is a Point, create a PointSlopeLine
|
76
|
+
return PointSlopeLine.new(*args) if args.first.is_a?(Vector)
|
77
|
+
|
78
|
+
# Otherise, create a SlopeInterceptLine
|
79
|
+
return SlopeInterceptLine.new(*args)
|
80
|
+
else
|
81
|
+
nil
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
data/lib/point.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'matrix'
|
2
|
+
|
3
|
+
module Geometry
|
4
|
+
class Point < Vector
|
5
|
+
|
6
|
+
# Custom accessors to enable a more natural notation
|
7
|
+
def x
|
8
|
+
@elements[0]
|
9
|
+
end
|
10
|
+
def y
|
11
|
+
@elements[1]
|
12
|
+
end
|
13
|
+
def z
|
14
|
+
@elements[2]
|
15
|
+
end
|
16
|
+
|
17
|
+
# Allow vector-style initialization, but override to
|
18
|
+
# support copy-init from another Vector or Point
|
19
|
+
def self.[](*array)
|
20
|
+
array = array[0] if array[0].is_a?(Array)
|
21
|
+
return Point[*(array[0].to_a)] if array[0].is_a?(Vector)
|
22
|
+
super *array
|
23
|
+
end
|
24
|
+
|
25
|
+
def inspect
|
26
|
+
'Point' + @elements.inspect
|
27
|
+
end
|
28
|
+
def to_s
|
29
|
+
'Point' + @elements.to_s
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
def Geometry.Point(*args)
|
36
|
+
args[0] = args[0].to_a if args[0].is_a?(Vector)
|
37
|
+
args = args[0] if args[0].is_a?(Array)
|
38
|
+
Geometry::Point[*args]
|
39
|
+
end
|
data/test/test_line.rb
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require_relative 'test_unit_extensions'
|
3
|
+
require_relative '../lib/line'
|
4
|
+
|
5
|
+
class PointTest < Test::Unit::TestCase
|
6
|
+
must "create a Line object from 2 Points" do
|
7
|
+
line = Geometry::Line[Geometry::Point[0,0], Geometry::Point[10,10]]
|
8
|
+
assert_kind_of(Geometry::Line, line)
|
9
|
+
assert_kind_of(Geometry::TwoPointLine, line)
|
10
|
+
end
|
11
|
+
must "create a Line object from two arrays" do
|
12
|
+
line = Geometry::Line[[0,0], [10,10]]
|
13
|
+
assert(line.is_a?(Geometry::Line))
|
14
|
+
assert_kind_of(Geometry::TwoPointLine, line)
|
15
|
+
assert_kind_of(Geometry::Point, line.first)
|
16
|
+
assert_kind_of(Geometry::Point, line.last)
|
17
|
+
end
|
18
|
+
must "create a Line object from two Vectors" do
|
19
|
+
line = Geometry::Line[Vector[0,0], Vector[10,10]]
|
20
|
+
assert(line.is_a?(Geometry::Line))
|
21
|
+
assert_kind_of(Geometry::TwoPointLine, line)
|
22
|
+
end
|
23
|
+
|
24
|
+
must "create a Line from a slope and y-intercept" do
|
25
|
+
line = Geometry::Line[0.75, 5]
|
26
|
+
assert(line.is_a?(Geometry::Line))
|
27
|
+
assert_kind_of(Geometry::SlopeInterceptLine, line)
|
28
|
+
assert_equal(5, line.intercept)
|
29
|
+
assert_equal(0.75, line.slope)
|
30
|
+
end
|
31
|
+
|
32
|
+
must "create a Line from a Rational slope and y-intercept" do
|
33
|
+
line = Geometry::Line[Rational(3,4), 5]
|
34
|
+
assert_kind_of(Geometry::SlopeInterceptLine, line)
|
35
|
+
assert(line.is_a?(Geometry::Line))
|
36
|
+
assert_equal(Rational(3,4), line.slope)
|
37
|
+
end
|
38
|
+
|
39
|
+
must "have a special constructor for horizontal lines" do
|
40
|
+
line = Geometry::Line.horizontal
|
41
|
+
assert(line.horizontal?)
|
42
|
+
end
|
43
|
+
must "have a special constructor for vertical lines" do
|
44
|
+
line = Geometry::Line.vertical
|
45
|
+
assert(line.vertical?)
|
46
|
+
end
|
47
|
+
|
48
|
+
must "have accessor for y-intercept" do
|
49
|
+
line = Geometry::Line[0.75, 5]
|
50
|
+
assert_equal(5, line.intercept)
|
51
|
+
assert_equal(5, line.intercept(:y))
|
52
|
+
end
|
53
|
+
must "have accessor for x-intercept" do
|
54
|
+
line = Geometry::Line.vertical(7)
|
55
|
+
assert_equal(7, line.intercept(:x))
|
56
|
+
end
|
57
|
+
|
58
|
+
must "return the correct x-intercept for vertical lines" do
|
59
|
+
line = Geometry::Line.vertical(7)
|
60
|
+
assert_equal(7, line.intercept(:x))
|
61
|
+
end
|
62
|
+
must "return the correct y-intercept for horizontal lines" do
|
63
|
+
line = Geometry::Line.horizontal(4)
|
64
|
+
assert_equal(4, line.intercept(:y))
|
65
|
+
end
|
66
|
+
|
67
|
+
must "return nil x-intercept for horizontal lines" do
|
68
|
+
line = Geometry::Line.horizontal
|
69
|
+
assert_nil(line.intercept(:x))
|
70
|
+
end
|
71
|
+
must "return nil y-intercept for vertical lines" do
|
72
|
+
line = Geometry::Line.vertical
|
73
|
+
assert_nil(line.intercept(:y))
|
74
|
+
end
|
75
|
+
|
76
|
+
must "implement inspect" do
|
77
|
+
line = Geometry::Line[[0,0], [10,10]]
|
78
|
+
assert_equal('Line(Point[0, 0], Point[10, 10])', line.inspect)
|
79
|
+
end
|
80
|
+
must "implement to_s" do
|
81
|
+
line = Geometry::Line[[0,0], [10,10]]
|
82
|
+
assert_equal('Line(Point[0, 0], Point[10, 10])', line.to_s)
|
83
|
+
end
|
84
|
+
end
|
data/test/test_point.rb
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require_relative 'test_unit_extensions'
|
3
|
+
require_relative '../lib/point'
|
4
|
+
|
5
|
+
class PointTest < Test::Unit::TestCase
|
6
|
+
must "create a Point object using list syntax" do
|
7
|
+
point = Geometry::Point[2,1]
|
8
|
+
assert_equal(2, point.size)
|
9
|
+
assert_equal(2, point.x)
|
10
|
+
assert_equal(1, point.y)
|
11
|
+
end
|
12
|
+
must "create a Point object from an array" do
|
13
|
+
point = Geometry::Point([3,4])
|
14
|
+
assert_equal(2, point.size)
|
15
|
+
assert_equal(3, point.x)
|
16
|
+
assert_equal(4, point.y)
|
17
|
+
end
|
18
|
+
must "create a Point object from an array using list syntax" do
|
19
|
+
point = Geometry::Point[[3,4]]
|
20
|
+
assert_equal(2, point.size)
|
21
|
+
assert_equal(3, point.x)
|
22
|
+
assert_equal(4, point.y)
|
23
|
+
end
|
24
|
+
must "create a Point object from individual parameters" do
|
25
|
+
point = Geometry.Point(3,4)
|
26
|
+
assert_equal(2, point.size)
|
27
|
+
assert_equal(3, point.x)
|
28
|
+
assert_equal(4, point.y)
|
29
|
+
end
|
30
|
+
must "create a Point object from a Vector" do
|
31
|
+
point = Geometry.Point(Vector[3,4])
|
32
|
+
assert_equal(2, point.size)
|
33
|
+
assert_equal(3, point.x)
|
34
|
+
assert_equal(4, point.y)
|
35
|
+
end
|
36
|
+
must "create a Point object from a Point" do
|
37
|
+
point = Geometry.Point(Geometry::Point[3,4])
|
38
|
+
assert_equal(2, point.size)
|
39
|
+
assert_equal(3, point.x)
|
40
|
+
assert_equal(4, point.y)
|
41
|
+
end
|
42
|
+
must "create a Point object from a Vector using list syntax" do
|
43
|
+
point = Geometry::Point[Vector[3,4]]
|
44
|
+
assert_equal(2, point.size)
|
45
|
+
assert_equal(3, point.x)
|
46
|
+
assert_equal(4, point.y)
|
47
|
+
end
|
48
|
+
must "create a Point object from a Point using list syntax" do
|
49
|
+
point = Geometry::Point[Geometry::Point[13,14]]
|
50
|
+
assert_equal(2, point.size)
|
51
|
+
assert_equal(13, point.x)
|
52
|
+
assert_equal(14, point.y)
|
53
|
+
end
|
54
|
+
must "allow indexed element access" do
|
55
|
+
point = Geometry::Point[5,6]
|
56
|
+
assert_equal(2, point.size)
|
57
|
+
assert_equal(5, point[0])
|
58
|
+
assert_equal(6, point[1])
|
59
|
+
end
|
60
|
+
must "allow named element access" do
|
61
|
+
point = Geometry::Point[5,6,7]
|
62
|
+
assert_equal(3, point.size)
|
63
|
+
assert_equal(5, point.x)
|
64
|
+
assert_equal(6, point.y)
|
65
|
+
assert_equal(7, point.z)
|
66
|
+
end
|
67
|
+
must "implement inspect" do
|
68
|
+
point = Geometry::Point[8,9]
|
69
|
+
assert_equal('Point[8, 9]', point.inspect)
|
70
|
+
end
|
71
|
+
must "implement to_s" do
|
72
|
+
point = Geometry::Point[10,11]
|
73
|
+
assert_equal('Point[10, 11]', point.to_s)
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# https://github.com/sandal/rbp/blob/master/testing/test_unit_extensions.rb
|
2
|
+
|
3
|
+
module Test::Unit
|
4
|
+
# Used to fix a minor minitest/unit incompatibility in flexmock
|
5
|
+
AssertionFailedError = Class.new(StandardError)
|
6
|
+
|
7
|
+
class TestCase
|
8
|
+
|
9
|
+
def self.must(name, &block)
|
10
|
+
test_name = "test_#{name.gsub(/\s+/,'_')}".to_sym
|
11
|
+
defined = instance_method(test_name) rescue false
|
12
|
+
raise "#{test_name} is already defined in #{self}" if defined
|
13
|
+
if block_given?
|
14
|
+
define_method(test_name, &block)
|
15
|
+
else
|
16
|
+
define_method(test_name) do
|
17
|
+
flunk "No implementation provided for #{name}"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
metadata
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: geometry
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0'
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Brandon Fosdick
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-03-08 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: Geometric primitives and algorithms for Ruby
|
15
|
+
email:
|
16
|
+
- bfoz@bfoz.net
|
17
|
+
executables: []
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- .gitignore
|
22
|
+
- Gemfile
|
23
|
+
- README
|
24
|
+
- Rakefile
|
25
|
+
- geometry.gemspec
|
26
|
+
- lib/geometry.rb
|
27
|
+
- lib/line.rb
|
28
|
+
- lib/point.rb
|
29
|
+
- test/test_line.rb
|
30
|
+
- test/test_point.rb
|
31
|
+
- test/test_unit_extensions.rb
|
32
|
+
homepage: http://github.com/bfoz/geometry
|
33
|
+
licenses: []
|
34
|
+
post_install_message:
|
35
|
+
rdoc_options: []
|
36
|
+
require_paths:
|
37
|
+
- lib
|
38
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
45
|
+
none: false
|
46
|
+
requirements:
|
47
|
+
- - ! '>='
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '0'
|
50
|
+
requirements: []
|
51
|
+
rubyforge_project: geometry
|
52
|
+
rubygems_version: 1.8.17
|
53
|
+
signing_key:
|
54
|
+
specification_version: 3
|
55
|
+
summary: Geometric primitives and algoritms
|
56
|
+
test_files:
|
57
|
+
- test/test_line.rb
|
58
|
+
- test/test_point.rb
|
59
|
+
- test/test_unit_extensions.rb
|