geometry 6.2 → 6.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.
- checksums.yaml +4 -4
- data/.travis.yml +4 -0
- data/README.markdown +58 -44
- data/geometry.gemspec +1 -1
- data/lib/geometry.rb +1 -0
- data/lib/geometry/annulus.rb +74 -0
- data/lib/geometry/circle.rb +6 -0
- data/lib/geometry/edge.rb +6 -3
- data/lib/geometry/obround.rb +6 -0
- data/lib/geometry/point.rb +40 -3
- data/lib/geometry/point_iso.rb +133 -0
- data/lib/geometry/point_one.rb +131 -0
- data/lib/geometry/point_zero.rb +19 -1
- data/lib/geometry/polygon.rb +6 -6
- data/lib/geometry/polyline.rb +4 -0
- data/lib/geometry/rectangle.rb +6 -0
- data/lib/geometry/regular_polygon.rb +59 -52
- data/lib/geometry/rotation.rb +1 -0
- data/lib/geometry/size.rb +41 -11
- data/lib/geometry/size_one.rb +85 -0
- data/lib/geometry/size_zero.rb +8 -0
- data/lib/geometry/square.rb +6 -0
- data/lib/geometry/triangle.rb +21 -0
- data/test/geometry/annulus.rb +69 -0
- data/test/geometry/circle.rb +36 -0
- data/test/geometry/obround.rb +5 -0
- data/test/geometry/point.rb +40 -5
- data/test/geometry/point_iso.rb +189 -0
- data/test/geometry/point_one.rb +199 -0
- data/test/geometry/point_zero.rb +23 -2
- data/test/geometry/polyline.rb +4 -0
- data/test/geometry/rectangle.rb +4 -0
- data/test/geometry/regular_polygon.rb +57 -11
- data/test/geometry/rotation.rb +6 -0
- data/test/geometry/size.rb +31 -10
- data/test/geometry/size_one.rb +155 -0
- data/test/geometry/size_zero.rb +8 -0
- data/test/geometry/square.rb +4 -0
- data/test/geometry/triangle.rb +16 -0
- metadata +15 -2
@@ -0,0 +1,131 @@
|
|
1
|
+
require_relative 'point'
|
2
|
+
|
3
|
+
module Geometry
|
4
|
+
=begin rdoc
|
5
|
+
An object repesenting a {Point} that is one unit away from the origin, along each
|
6
|
+
axis, in N-dimensional space
|
7
|
+
|
8
|
+
A {PointOne} object is a {Point} that will always compare equal to one and unequal to
|
9
|
+
everything else, regardless of size. It's similar to the
|
10
|
+
{http://en.wikipedia.org/wiki/Null_Object_pattern Null Object Pattern}, but for ones.
|
11
|
+
=end
|
12
|
+
class PointOne
|
13
|
+
def eql?(other)
|
14
|
+
if other.respond_to? :all?
|
15
|
+
other.all? {|e| e.eql? 1}
|
16
|
+
else
|
17
|
+
other == 1
|
18
|
+
end
|
19
|
+
end
|
20
|
+
alias == eql?
|
21
|
+
|
22
|
+
def coerce(other)
|
23
|
+
if other.is_a? Numeric
|
24
|
+
[other, 1]
|
25
|
+
elsif other.is_a? Array
|
26
|
+
[other, Array.new(other.size, 1)]
|
27
|
+
elsif other.is_a? Vector
|
28
|
+
[other, Vector[*Array.new(other.size, 1)]]
|
29
|
+
else
|
30
|
+
[Point[other], Point[Array.new(other.size, 1)]]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def is_a?(klass)
|
35
|
+
(klass == Point) || super
|
36
|
+
end
|
37
|
+
alias :kind_of? :is_a?
|
38
|
+
|
39
|
+
# This is a hack to get Array#== to work properly. It works on ruby 2.0 and 1.9.3.
|
40
|
+
def to_ary
|
41
|
+
[]
|
42
|
+
end
|
43
|
+
|
44
|
+
# @group Accessors
|
45
|
+
# @param [Integer] i Index into the {Point}'s elements
|
46
|
+
# @return [Numeric] Element i (starting at 0)
|
47
|
+
def [](i)
|
48
|
+
1
|
49
|
+
end
|
50
|
+
|
51
|
+
# @attribute [r] x
|
52
|
+
# @return [Numeric] X-component
|
53
|
+
def x
|
54
|
+
1
|
55
|
+
end
|
56
|
+
|
57
|
+
# @attribute [r] y
|
58
|
+
# @return [Numeric] Y-component
|
59
|
+
def y
|
60
|
+
1
|
61
|
+
end
|
62
|
+
|
63
|
+
# @attribute [r] z
|
64
|
+
# @return [Numeric] Z-component
|
65
|
+
def z
|
66
|
+
1
|
67
|
+
end
|
68
|
+
# @endgroup
|
69
|
+
|
70
|
+
# @group Arithmetic
|
71
|
+
|
72
|
+
# @group Unary operators
|
73
|
+
def +@
|
74
|
+
self
|
75
|
+
end
|
76
|
+
|
77
|
+
def -@
|
78
|
+
-1
|
79
|
+
end
|
80
|
+
# @endgroup
|
81
|
+
|
82
|
+
def +(other)
|
83
|
+
case other
|
84
|
+
when Numeric
|
85
|
+
Point.iso(other + 1)
|
86
|
+
when Size
|
87
|
+
Point[other.map {|a| a + 1 }]
|
88
|
+
else
|
89
|
+
if other.respond_to?(:map)
|
90
|
+
other.map {|a| a + 1 }
|
91
|
+
else
|
92
|
+
Point[other + 1]
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def -(other)
|
98
|
+
if other.is_a? Size
|
99
|
+
Point[other.map {|a| 1 - a }]
|
100
|
+
elsif other.respond_to? :map
|
101
|
+
other.map {|a| 1 - a }
|
102
|
+
elsif other == 1
|
103
|
+
Point.zero
|
104
|
+
else
|
105
|
+
Point.iso(1 - other)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def *(other)
|
110
|
+
raise OperationNotDefined unless other.is_a? Numeric
|
111
|
+
other
|
112
|
+
end
|
113
|
+
|
114
|
+
def /(other)
|
115
|
+
raise OperationNotDefined unless other.is_a? Numeric
|
116
|
+
raise ZeroDivisionError if 0 == other
|
117
|
+
1 / other
|
118
|
+
end
|
119
|
+
# @endgroup
|
120
|
+
|
121
|
+
# @group Enumerable
|
122
|
+
|
123
|
+
# Return the first, or first n, elements (always 0)
|
124
|
+
# @param n [Number] the number of elements to return
|
125
|
+
def first(n=nil)
|
126
|
+
Array.new(n, 1) rescue 1
|
127
|
+
end
|
128
|
+
# @endgroup
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
data/lib/geometry/point_zero.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require_relative 'point'
|
2
|
+
require_relative 'point_iso'
|
2
3
|
|
3
4
|
module Geometry
|
4
5
|
=begin rdoc
|
@@ -30,6 +31,11 @@ everything else, regardless of size. You can think of it as an application of th
|
|
30
31
|
end
|
31
32
|
end
|
32
33
|
|
34
|
+
def is_a?(klass)
|
35
|
+
(klass == Point) || super
|
36
|
+
end
|
37
|
+
alias :kind_of? :is_a?
|
38
|
+
|
33
39
|
# This is a hack to get Array#== to work properly. It works on ruby 2.0 and 1.9.3.
|
34
40
|
def to_ary
|
35
41
|
[]
|
@@ -75,7 +81,9 @@ everything else, regardless of size. You can think of it as an application of th
|
|
75
81
|
|
76
82
|
def +(other)
|
77
83
|
case other
|
78
|
-
when Array
|
84
|
+
when Array then other
|
85
|
+
when Numeric
|
86
|
+
Point.iso(other)
|
79
87
|
else
|
80
88
|
Point[other]
|
81
89
|
end
|
@@ -84,6 +92,8 @@ everything else, regardless of size. You can think of it as an application of th
|
|
84
92
|
def -(other)
|
85
93
|
if other.is_a? Size
|
86
94
|
-Point[other]
|
95
|
+
elsif other.is_a? Numeric
|
96
|
+
Point.iso(-other)
|
87
97
|
elsif other.respond_to? :-@
|
88
98
|
-other
|
89
99
|
elsif other.respond_to? :map
|
@@ -102,6 +112,14 @@ everything else, regardless of size. You can think of it as an application of th
|
|
102
112
|
end
|
103
113
|
# @endgroup
|
104
114
|
|
115
|
+
# @group Enumerable
|
116
|
+
|
117
|
+
# Return the first, or first n, elements (always 0)
|
118
|
+
# @param n [Number] the number of elements to return
|
119
|
+
def first(n=nil)
|
120
|
+
Array.new(n, 0) rescue 0
|
121
|
+
end
|
122
|
+
# @endgroup
|
105
123
|
end
|
106
124
|
end
|
107
125
|
|
data/lib/geometry/polygon.rb
CHANGED
@@ -18,11 +18,11 @@ but there's currently nothing that enforces simplicity.
|
|
18
18
|
class Polygon < Polyline
|
19
19
|
|
20
20
|
# Construct a new Polygon from Points and/or Edges
|
21
|
-
# The constructor will try to convert all of its arguments into Points and
|
22
|
-
# Edges. Then successive Points will be collpased into Edges. Successive
|
23
|
-
# Edges that share a common vertex will be added to the new Polygon. If
|
24
|
-
# there's a gap between Edges it will be automatically filled with a new
|
25
|
-
# Edge. The resulting Polygon will then be closed if it isn't already.
|
21
|
+
# The constructor will try to convert all of its arguments into {Points} and
|
22
|
+
# {Edges}. Then successive {Points} will be collpased into {Edges}. Successive
|
23
|
+
# {Edges} that share a common vertex will be added to the new {Polygon}. If
|
24
|
+
# there's a gap between {Edges} it will be automatically filled with a new
|
25
|
+
# {Edge}. The resulting Polygon will then be closed, if it isn't already.
|
26
26
|
# @overload initialize(Edge, Edge, ...)
|
27
27
|
# @return [Polygon]
|
28
28
|
# @overload initialize(Point, Point, ...)
|
@@ -116,7 +116,7 @@ but there's currently nothing that enforces simplicity.
|
|
116
116
|
if (a.first == b.first) and (a.last == b.last) # Equal edges
|
117
117
|
elsif (a.first == b.last) and (a.last == b.first) # Ignore equal but opposite edges
|
118
118
|
else
|
119
|
-
if a.
|
119
|
+
if a.direction == b.direction # Same direction?
|
120
120
|
offsetA += 1 if ringA.insert_boundary(indexA + 1 + offsetA, b.first)
|
121
121
|
offsetB += 1 if ringB.insert_boundary(indexB + 1 + offsetB, a.last)
|
122
122
|
else # Opposite direction
|
data/lib/geometry/polyline.rb
CHANGED
@@ -15,6 +15,10 @@ also like a {Path} in that it isn't necessarily closed.
|
|
15
15
|
class Polyline
|
16
16
|
attr_reader :edges, :vertices
|
17
17
|
|
18
|
+
# @!attribute points
|
19
|
+
# @return [Array<Point>] all of the vertices of the {Polyline} (alias of #vertices)
|
20
|
+
alias :points :vertices
|
21
|
+
|
18
22
|
# Construct a new Polyline from Points and/or Edges
|
19
23
|
# @note The constructor will try to convert all of its arguments into {Point}s and
|
20
24
|
# {Edge}s. Then successive {Point}s will be collpased into {Edge}s. Successive
|
data/lib/geometry/rectangle.rb
CHANGED
@@ -123,6 +123,12 @@ The {Rectangle} class cluster represents your typical arrangement of 4 corners a
|
|
123
123
|
Point[(max.x+min.x)/2, (max.y+min.y)/2]
|
124
124
|
end
|
125
125
|
|
126
|
+
# @!attribute closed?
|
127
|
+
# @return [Bool] always true
|
128
|
+
def closed?
|
129
|
+
true
|
130
|
+
end
|
131
|
+
|
126
132
|
# @return [Array<Edge>] The {Rectangle}'s four edges (counterclockwise)
|
127
133
|
def edges
|
128
134
|
point0, point2 = *@points
|
@@ -1,4 +1,3 @@
|
|
1
|
-
require_relative 'cluster_factory'
|
2
1
|
require_relative 'polygon'
|
3
2
|
|
4
3
|
module Geometry
|
@@ -10,53 +9,49 @@ A {RegularPolygon} is a lot like a {Polygon}, but more regular.
|
|
10
9
|
== Usage
|
11
10
|
polygon = Geometry::RegularPolygon.new sides:4, center:[1,2], radius:3
|
12
11
|
polygon = Geometry::RegularPolygon.new sides:6, center:[1,2], diameter:6
|
12
|
+
|
13
|
+
polygon = Geometry::RegularPolygon.new sides:4, center:[1,2], inradius:3
|
14
|
+
polygon = Geometry::RegularPolygon.new sides:6, center:[1,2], indiameter:6
|
13
15
|
=end
|
14
16
|
|
15
17
|
class RegularPolygon < Polygon
|
16
|
-
include ClusterFactory
|
17
|
-
|
18
18
|
# @return [Point] The {RegularPolygon}'s center point
|
19
19
|
attr_reader :center
|
20
20
|
|
21
21
|
# @return [Number] The {RegularPolygon}'s number of sides
|
22
22
|
attr_reader :edge_count
|
23
23
|
|
24
|
-
# @return [Number] The {RegularPolygon}'s radius
|
25
|
-
attr_reader :radius
|
26
|
-
|
27
24
|
# @overload new(sides, center, radius)
|
28
25
|
# Construct a {RegularPolygon} using a center point and radius
|
29
26
|
# @option options [Number] :sides The number of edges
|
30
27
|
# @option options [Point] :center (PointZero) The center point of the {RegularPolygon}
|
31
|
-
# @option options [Number] :radius The
|
28
|
+
# @option options [Number] :radius The circumradius of the {RegularPolygon}
|
29
|
+
# @overload new(sides, center, inradius)
|
30
|
+
# Construct a {RegularPolygon} using a center point and radius
|
31
|
+
# @option options [Number] :sides The number of edges
|
32
|
+
# @option options [Point] :center (PointZero) The center point of the {RegularPolygon}
|
33
|
+
# @option options [Number] :inradius The inradius of the {RegularPolygon}
|
32
34
|
# @overload new(sides, center, diameter)
|
33
35
|
# Construct a {RegularPolygon} using a center point and diameter
|
34
36
|
# @option options [Number] :sides The number of edges
|
35
37
|
# @option options [Point] :center (PointZero) The center point of the {RegularPolygon}
|
36
|
-
# @option options [Number] :diameter The
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
if options.has_key?(:radius)
|
44
|
-
self.allocate.tap {|polygon| polygon.send :initialize, options[:sides], center, options[:radius], &block }
|
45
|
-
elsif options.has_key?(:diameter)
|
46
|
-
DiameterRegularPolygon.new options[:sides], center, options[:diameter], &block
|
47
|
-
else
|
48
|
-
raise ArgumentError, "RegularPolygon.new requires a radius or a diameter"
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
# Construct a new {RegularPolygon} from a centerpoint and radius
|
53
|
-
# @param [Number] edge_count The number of edges
|
54
|
-
# @param [Point] center The center point of the {Circle}
|
55
|
-
# @param [Number] radius The radius of the {Circle}
|
38
|
+
# @option options [Number] :diameter The circumdiameter of the {RegularPolygon}
|
39
|
+
# @overload new(sides, center, indiameter)
|
40
|
+
# Construct a {RegularPolygon} using a center point and diameter
|
41
|
+
# @option options [Number] :sides The number of edges
|
42
|
+
# @option options [Point] :center (PointZero) The center point of the {RegularPolygon}
|
43
|
+
# @option options [Number] :indiameter The circumdiameter of the {RegularPolygon}
|
56
44
|
# @return [RegularPolygon] A new {RegularPolygon} object
|
57
|
-
def initialize(edge_count, center, radius)
|
58
|
-
@
|
59
|
-
|
45
|
+
def initialize(edge_count:nil, sides:nil, center:nil, radius:nil, diameter:nil, indiameter:nil, inradius:nil)
|
46
|
+
@edge_count = edge_count || sides
|
47
|
+
raise ArgumentError, "RegularPolygon requires an edge count" unless @edge_count
|
48
|
+
|
49
|
+
raise ArgumentError, "RegularPolygon.new requires a radius or a diameter" unless diameter || indiameter || inradius || radius
|
50
|
+
|
51
|
+
@center = center ? Point[center] : Point.zero
|
52
|
+
@diameter = diameter
|
53
|
+
@indiameter = indiameter
|
54
|
+
@inradius = inradius
|
60
55
|
@radius = radius
|
61
56
|
end
|
62
57
|
|
@@ -65,6 +60,12 @@ A {RegularPolygon} is a lot like a {Polygon}, but more regular.
|
|
65
60
|
end
|
66
61
|
alias :== :eql?
|
67
62
|
|
63
|
+
# Check to see if the {Polygon} is closed (always true)
|
64
|
+
# @return [True] Always true because a {Polygon} is always closed
|
65
|
+
def closed?
|
66
|
+
true
|
67
|
+
end
|
68
|
+
|
68
69
|
# @!group Accessors
|
69
70
|
# @return [Rectangle] The smallest axis-aligned {Rectangle} that bounds the receiver
|
70
71
|
def bounds
|
@@ -74,8 +75,9 @@ A {RegularPolygon} is a lot like a {Polygon}, but more regular.
|
|
74
75
|
# @!attribute [r] diameter
|
75
76
|
# @return [Numeric] The diameter of the {RegularPolygon}
|
76
77
|
def diameter
|
77
|
-
@radius
|
78
|
+
@diameter || (@radius && 2*@radius) || (@indiameter && @indiameter/cosine_half_angle)
|
78
79
|
end
|
80
|
+
alias :circumdiameter :diameter
|
79
81
|
|
80
82
|
# !@attribute [r] edges
|
81
83
|
def edges
|
@@ -88,6 +90,7 @@ A {RegularPolygon} is a lot like a {Polygon}, but more regular.
|
|
88
90
|
def vertices
|
89
91
|
(0...2*Math::PI).step(2*Math::PI/edge_count).map {|angle| center + Point[Math::cos(angle), Math::sin(angle)]*radius }
|
90
92
|
end
|
93
|
+
alias :points :vertices
|
91
94
|
|
92
95
|
# @return [Point] The upper right corner of the bounding {Rectangle}
|
93
96
|
def max
|
@@ -103,34 +106,38 @@ A {RegularPolygon} is a lot like a {Polygon}, but more regular.
|
|
103
106
|
def minmax
|
104
107
|
[self.min, self.max]
|
105
108
|
end
|
106
|
-
# @!endgroup
|
107
|
-
end
|
108
|
-
|
109
|
-
class DiameterRegularPolygon < RegularPolygon
|
110
|
-
# @return [Number] The {RegularPolygon}'s diameter
|
111
|
-
attr_reader :diameter
|
112
109
|
|
113
|
-
#
|
114
|
-
#
|
115
|
-
|
116
|
-
|
117
|
-
# @return [RegularPolygon] A new {RegularPolygon} object
|
118
|
-
def initialize(edge_count, center, diameter)
|
119
|
-
@center = center ? Point[center] : nil
|
120
|
-
@edge_count = edge_count
|
121
|
-
@diameter = diameter
|
110
|
+
# @!attribute indiameter
|
111
|
+
# @return [Number] the indiameter
|
112
|
+
def indiameter
|
113
|
+
@indiameter || (@inradius && 2*@inradius) || (@diameter && (@diameter * cosine_half_angle)) || (@radius && (2 * @radius * cosine_half_angle))
|
122
114
|
end
|
123
115
|
|
124
|
-
|
125
|
-
|
116
|
+
# @!attribute inradius
|
117
|
+
# @return [Number] The inradius
|
118
|
+
def inradius
|
119
|
+
@inradius || (@indiameter && @indiameter/2) || (@radius && (@radius * cosine_half_angle))
|
126
120
|
end
|
127
|
-
alias
|
121
|
+
alias :apothem :inradius
|
128
122
|
|
129
|
-
# @!
|
130
|
-
# @return [Number]
|
123
|
+
# @!attribute [r] radius
|
124
|
+
# @return [Number] The {RegularPolygon}'s radius
|
131
125
|
def radius
|
132
|
-
@diameter/2
|
126
|
+
@radius || (@diameter && @diameter/2) || (@inradius && (@inradius / cosine_half_angle)) || (@indiameter && @indiameter/cosine_half_angle/2)
|
127
|
+
end
|
128
|
+
alias :circumradius :radius
|
129
|
+
|
130
|
+
# @!attribute [r] side_length
|
131
|
+
# @return [Number] The length of each side
|
132
|
+
def side_length
|
133
|
+
2 * circumradius * Math.sin(Math::PI/edge_count)
|
133
134
|
end
|
135
|
+
|
136
|
+
private
|
137
|
+
def cosine_half_angle
|
138
|
+
Math.cos(Math::PI/edge_count)
|
139
|
+
end
|
140
|
+
|
134
141
|
# @!endgroup
|
135
142
|
end
|
136
143
|
end
|
data/lib/geometry/rotation.rb
CHANGED
@@ -105,6 +105,7 @@ A generalized representation of a rotation transformation.
|
|
105
105
|
# @param [Point] point the {Point} to rotate into the parent coordinate frame
|
106
106
|
# @return [Point] the rotated {Point}
|
107
107
|
def transform(point)
|
108
|
+
return point if point.is_a?(PointZero)
|
108
109
|
m = matrix
|
109
110
|
m ? Point[m * Point[point]] : point
|
110
111
|
end
|
data/lib/geometry/size.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
require 'matrix'
|
2
2
|
|
3
|
+
require_relative 'size_one'
|
4
|
+
require_relative 'size_zero'
|
5
|
+
|
3
6
|
module Geometry
|
4
7
|
=begin
|
5
8
|
An object representing the size of something.
|
@@ -29,13 +32,42 @@ methods (width, height and depth).
|
|
29
32
|
array.flatten!
|
30
33
|
super *array
|
31
34
|
end
|
32
|
-
|
35
|
+
|
36
|
+
# Creates and returns a new {SizeOne} instance. Or, a {Size} full of ones if the size argument is given.
|
37
|
+
# @param size [Number] the size of the new {Size} full of ones
|
38
|
+
# @return [SizeOne] A new {SizeOne} instance
|
39
|
+
def self.one(size=nil)
|
40
|
+
size ? Size[Array.new(size, 1)] : SizeOne.new
|
41
|
+
end
|
42
|
+
|
43
|
+
# Creates and returns a new {SizeOne} instance. Or, a {Size} full of zeros if the size argument is given.
|
44
|
+
# @param size [Number] the size of the new {Size} full of zeros
|
45
|
+
# @return [SizeOne] A new {SizeOne} instance
|
46
|
+
def self.zero(size=nil)
|
47
|
+
size ? Size[Array.new(size, 0)] : SizeOne.new
|
48
|
+
end
|
49
|
+
|
33
50
|
# Allow comparison with an Array, otherwise do the normal thing
|
34
51
|
def ==(other)
|
35
52
|
return @elements == other if other.is_a?(Array)
|
36
53
|
super other
|
37
54
|
end
|
38
55
|
|
56
|
+
# Override Vector#[] to allow for regular array slicing
|
57
|
+
def [](*args)
|
58
|
+
@elements[*args]
|
59
|
+
end
|
60
|
+
|
61
|
+
def coerce(other)
|
62
|
+
case other
|
63
|
+
when Array then [Size[*other], self]
|
64
|
+
when Numeric then [Size[Array.new(self.size, other)], self]
|
65
|
+
when Vector then [Size[*other], self]
|
66
|
+
else
|
67
|
+
raise TypeError, "#{self.class} can't be coerced into #{other.class}"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
39
71
|
def inspect
|
40
72
|
'Size' + @elements.inspect
|
41
73
|
end
|
@@ -91,13 +123,12 @@ methods (width, height and depth).
|
|
91
123
|
left = top = -args.shift
|
92
124
|
right = bottom = 0
|
93
125
|
elsif 2 == args.size
|
94
|
-
left = -args.shift
|
95
|
-
top = -args.shift
|
96
|
-
right = bottom = 0
|
126
|
+
left = right = -args.shift
|
127
|
+
top = bottom = -args.shift
|
97
128
|
end
|
98
129
|
|
99
|
-
left = -options[:x] if options[:x]
|
100
|
-
top = -options[:y] if options[:y]
|
130
|
+
left = right = -options[:x] if options[:x]
|
131
|
+
top = bottom = -options[:y] if options[:y]
|
101
132
|
|
102
133
|
top = -options[:top] if options[:top]
|
103
134
|
left = -options[:left] if options[:left]
|
@@ -125,13 +156,12 @@ methods (width, height and depth).
|
|
125
156
|
left = top = args.shift
|
126
157
|
right = bottom = 0
|
127
158
|
elsif 2 == args.size
|
128
|
-
left = args.shift
|
129
|
-
top = args.shift
|
130
|
-
right = bottom = 0
|
159
|
+
left = right = args.shift
|
160
|
+
top = bottom = args.shift
|
131
161
|
end
|
132
162
|
|
133
|
-
left = options[:x] if options[:x]
|
134
|
-
top = options[:y] if options[:y]
|
163
|
+
left = right = options[:x] if options[:x]
|
164
|
+
top = bottom = options[:y] if options[:y]
|
135
165
|
|
136
166
|
top = options[:top] if options[:top]
|
137
167
|
left = options[:left] if options[:left]
|