geometry 6.2 → 6.3
Sign up to get free protection for your applications and to get access to all the features.
- 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]
|