geomotion 0.10.0 → 0.12.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +2 -0
- data/Gemfile.lock +1 -1
- data/README.md +104 -0
- data/app/app_delegate.rb +5 -0
- data/app/next_controller.rb +19 -0
- data/app/perspective_controller.rb +76 -0
- data/app/shearing_controller.rb +77 -0
- data/lib/geomotion/ca_transform_3d.rb +223 -0
- data/lib/geomotion/cg_affine_transform.rb +181 -0
- data/lib/geomotion/cg_rect.rb +4 -4
- data/lib/geomotion/version.rb +1 -1
- data/resources/perspective.png +0 -0
- data/resources/shearing.png +0 -0
- data/spec/ca_transform_3d_spec.rb +345 -0
- data/spec/cg_affine_transform_spec.rb +247 -0
- data/spec/cg_rect_spec.rb +8 -1
- metadata +14 -3
@@ -0,0 +1,181 @@
|
|
1
|
+
class CGAffineTransform
|
2
|
+
# CGAffineTransform.make # default transform: identity matrix
|
3
|
+
# # make a transform from scratch
|
4
|
+
# CGAffineTransform.make(a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0)
|
5
|
+
#
|
6
|
+
# # make a transform using primitives
|
7
|
+
# CGAffineTransform.make(scale: 2, translate: [10, 10], rotate: Math::PI)
|
8
|
+
def self.make(options = {})
|
9
|
+
if options.key?(:a)
|
10
|
+
args = [
|
11
|
+
:a, :b,
|
12
|
+
:c, :d,
|
13
|
+
:tx, :ty,
|
14
|
+
].map do |key|
|
15
|
+
raise "#{key.inspect} is required" unless options.key? key
|
16
|
+
options[key]
|
17
|
+
end
|
18
|
+
return self.new(*args)
|
19
|
+
else
|
20
|
+
retval = self.identity
|
21
|
+
if options[:translate]
|
22
|
+
retval = retval.translate(options[:translate])
|
23
|
+
end
|
24
|
+
if options[:scale]
|
25
|
+
retval = retval.scale(options[:scale])
|
26
|
+
end
|
27
|
+
if options[:rotate]
|
28
|
+
retval = retval.rotate(options[:rotate])
|
29
|
+
end
|
30
|
+
return retval
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Returns a transform that is translated. Accepts one or two arguments. One
|
35
|
+
# argument can be a Point or Array with two items, two arguments should be the
|
36
|
+
# x and y values.
|
37
|
+
# @return CGAffineTransform
|
38
|
+
def self.translate(point, ty=nil)
|
39
|
+
if ty
|
40
|
+
tx = point
|
41
|
+
else
|
42
|
+
tx = point[0]
|
43
|
+
ty = point[1]
|
44
|
+
end
|
45
|
+
CGAffineTransformMakeTranslation(tx, ty)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Returns a transform that is scaled. Accepts one or two arguments. One
|
49
|
+
# argument can be a Point or Array with two items or a number that will be
|
50
|
+
# used to scale both directions. Two arguments should be the x and y values.
|
51
|
+
def self.scale(scale, sy=nil)
|
52
|
+
if sy
|
53
|
+
sx = scale
|
54
|
+
elsif scale.is_a?(Numeric)
|
55
|
+
sx = sy = scale
|
56
|
+
else
|
57
|
+
sx = scale[0]
|
58
|
+
sy = scale[1]
|
59
|
+
end
|
60
|
+
CGAffineTransformMakeScale(sx, sy)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Returns a transform that is rotated by `angle` (+ => counterclockwise, - => clockwise)
|
64
|
+
# @return CGAffineTransform
|
65
|
+
def self.rotate(angle)
|
66
|
+
CGAffineTransformMakeRotation(angle)
|
67
|
+
end
|
68
|
+
|
69
|
+
# A "shear" translation turns a rectangle into a parallelogram
|
70
|
+
# @param px [Numeric] how much to shear in x direction
|
71
|
+
# @param py [Numeric] how much to shear in y direction
|
72
|
+
# @return CGAffineTransform
|
73
|
+
def self.shear(px, py)
|
74
|
+
CGAffineTransformMake(1, py, px, 1, 0, 0)
|
75
|
+
end
|
76
|
+
|
77
|
+
# Returns the CGAffineTransform identity matrix
|
78
|
+
# @return CGAffineTransform
|
79
|
+
def self.identity
|
80
|
+
CGAffineTransformIdentity
|
81
|
+
end
|
82
|
+
|
83
|
+
# Return true if the receiver is the identity matrix, false otherwise
|
84
|
+
# @return CGAffineTransform
|
85
|
+
def identity?
|
86
|
+
CGAffineTransformIsIdentity(self)
|
87
|
+
end
|
88
|
+
|
89
|
+
# @return [CATransform3D]
|
90
|
+
def to_transform3d
|
91
|
+
CATransform3DMakeAffineTransform(self)
|
92
|
+
end
|
93
|
+
|
94
|
+
# @return [Boolean] true if the two matrices are equal
|
95
|
+
def ==(transform)
|
96
|
+
CGAffineTransformEqualToTransform(self, transform)
|
97
|
+
end
|
98
|
+
|
99
|
+
# Returns self
|
100
|
+
# @return CGAffineTransform
|
101
|
+
def +@
|
102
|
+
self
|
103
|
+
end
|
104
|
+
|
105
|
+
# Concatenates the two transforms
|
106
|
+
# @return CGAffineTransform
|
107
|
+
def concat(transform)
|
108
|
+
CGAffineTransformConcat(self, transform)
|
109
|
+
end
|
110
|
+
alias :+ :concat
|
111
|
+
alias :<< :concat
|
112
|
+
|
113
|
+
# Inverts the transform
|
114
|
+
# @return CGAffineTransform
|
115
|
+
def invert
|
116
|
+
CGAffineTransformInvert(self)
|
117
|
+
end
|
118
|
+
alias :-@ :invert
|
119
|
+
|
120
|
+
# Inverts the second transform and adds the result to `self`
|
121
|
+
# @return CGAffineTransform
|
122
|
+
def -(transform)
|
123
|
+
self.concat transform.invert
|
124
|
+
end
|
125
|
+
|
126
|
+
# Applies a translation transform to the receiver
|
127
|
+
# @return CGAffineTransform
|
128
|
+
def translate(point, ty=nil)
|
129
|
+
if ty
|
130
|
+
tx = point
|
131
|
+
else
|
132
|
+
tx = point[0]
|
133
|
+
ty = point[1]
|
134
|
+
end
|
135
|
+
CGAffineTransformTranslate(self, tx, ty)
|
136
|
+
end
|
137
|
+
|
138
|
+
# Applies a scale transform to the receiver
|
139
|
+
# @return CGAffineTransform
|
140
|
+
def scale(scale, sy=nil)
|
141
|
+
if sy
|
142
|
+
sx = scale
|
143
|
+
elsif scale.is_a?(Numeric)
|
144
|
+
sx = sy = scale
|
145
|
+
else
|
146
|
+
sx = scale[0]
|
147
|
+
sy = scale[1]
|
148
|
+
end
|
149
|
+
CGAffineTransformScale(self, sx, sy)
|
150
|
+
end
|
151
|
+
|
152
|
+
# Applies a rotation transform to the receiver
|
153
|
+
# @return CGAffineTransform
|
154
|
+
def rotate(angle)
|
155
|
+
CGAffineTransformRotate(self, angle)
|
156
|
+
end
|
157
|
+
|
158
|
+
# Applies a shear transform to the receiver
|
159
|
+
# @return CGAffineTransform
|
160
|
+
def shear(px, py)
|
161
|
+
self.concat CGAffineTransform.shear(px, py)
|
162
|
+
end
|
163
|
+
|
164
|
+
def apply_to(thing)
|
165
|
+
case thing
|
166
|
+
when CGPoint
|
167
|
+
CGPointApplyAffineTransform(thing, self)
|
168
|
+
when CGSize
|
169
|
+
CGSizeApplyAffineTransform(thing, self)
|
170
|
+
when CGRect
|
171
|
+
CGRectApplyAffineTransform(thing, self)
|
172
|
+
else
|
173
|
+
raise "Cannot apply transform to #{thing.inspect}"
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
def to_a
|
178
|
+
[self.a, self.b, self.c, self.d, self.tx, self.ty]
|
179
|
+
end
|
180
|
+
|
181
|
+
end
|
data/lib/geomotion/cg_rect.rb
CHANGED
@@ -9,15 +9,15 @@ class CGRect
|
|
9
9
|
# CGRect.make(origin: point, size: size)
|
10
10
|
def self.make(options = {})
|
11
11
|
if options[:origin]
|
12
|
-
x = options[:origin]
|
13
|
-
y = options[:origin]
|
12
|
+
x = options[:origin][0]
|
13
|
+
y = options[:origin][1]
|
14
14
|
else
|
15
15
|
x = options[:x] || 0
|
16
16
|
y = options[:y] || 0
|
17
17
|
end
|
18
18
|
if options[:size]
|
19
|
-
w = options[:size]
|
20
|
-
h = options[:size]
|
19
|
+
w = options[:size][0]
|
20
|
+
h = options[:size][1]
|
21
21
|
else
|
22
22
|
w = options[:width] || 0
|
23
23
|
h = options[:height] || 0
|
data/lib/geomotion/version.rb
CHANGED
Binary file
|
Binary file
|
@@ -0,0 +1,345 @@
|
|
1
|
+
describe "CATransform3D" do
|
2
|
+
|
3
|
+
describe "operations" do
|
4
|
+
|
5
|
+
it "should support ==" do
|
6
|
+
CATransform3D.make(
|
7
|
+
m11: 1, m12: 0, m13: 0, m14: 0,
|
8
|
+
m21: 0, m22: 1, m23: 0, m24: 0,
|
9
|
+
m31: 0, m32: 0, m33: 1, m34: 0,
|
10
|
+
m41: 0, m42: 0, m43: 0, m44: 1,
|
11
|
+
).should == CATransform3D.make(
|
12
|
+
m11: 1, m12: 0, m13: 0, m14: 0,
|
13
|
+
m21: 0, m22: 1, m23: 0, m24: 0,
|
14
|
+
m31: 0, m32: 0, m33: 1, m34: 0,
|
15
|
+
m41: 0, m42: 0, m43: 0, m44: 1,
|
16
|
+
)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should support +" do
|
20
|
+
t1 = CATransform3D.make(
|
21
|
+
m11: 2, m12: 0, m13: 0, m14: 0,
|
22
|
+
m21: 0, m22: 2, m23: 0, m24: 0,
|
23
|
+
m31: 0, m32: 0, m33: 2, m34: 0,
|
24
|
+
m41: 0, m42: 0, m43: 0, m44: 1,
|
25
|
+
)
|
26
|
+
t2 = CATransform3D.make(
|
27
|
+
m11: 1, m12: 0, m13: 0, m14: 0,
|
28
|
+
m21: 0, m22: 1, m23: 0, m24: 0,
|
29
|
+
m31: 0, m32: 0, m33: 1, m34: 0,
|
30
|
+
m41: 1, m42: 2, m43: 3, m44: 1,
|
31
|
+
)
|
32
|
+
(t1 + t2).should == CATransform3D.make(
|
33
|
+
m11: 2, m12: 0, m13: 0, m14: 0,
|
34
|
+
m21: 0, m22: 2, m23: 0, m24: 0,
|
35
|
+
m31: 0, m32: 0, m33: 2, m34: 0,
|
36
|
+
m41: 1, m42: 2, m43: 3, m44: 1,
|
37
|
+
)
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should support <<" do
|
41
|
+
t1 = CATransform3D.make(
|
42
|
+
m11: 2, m12: 0, m13: 0, m14: 0,
|
43
|
+
m21: 0, m22: 2, m23: 0, m24: 0,
|
44
|
+
m31: 0, m32: 0, m33: 2, m34: 0,
|
45
|
+
m41: 0, m42: 0, m43: 0, m44: 1,
|
46
|
+
)
|
47
|
+
t2 = CATransform3D.make(
|
48
|
+
m11: 1, m12: 0, m13: 0, m14: 0,
|
49
|
+
m21: 0, m22: 1, m23: 0, m24: 0,
|
50
|
+
m31: 0, m32: 0, m33: 1, m34: 0,
|
51
|
+
m41: 1, m42: 2, m43: 3, m44: 1,
|
52
|
+
)
|
53
|
+
(t1 << t2).should == CATransform3D.make(
|
54
|
+
m11: 2, m12: 0, m13: 0, m14: 0,
|
55
|
+
m21: 0, m22: 2, m23: 0, m24: 0,
|
56
|
+
m31: 0, m32: 0, m33: 2, m34: 0,
|
57
|
+
m41: 1, m42: 2, m43: 3, m44: 1,
|
58
|
+
)
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should support -" do
|
62
|
+
t1 = CATransform3D.make(
|
63
|
+
m11: 2, m12: 0, m13: 0, m14: 0,
|
64
|
+
m21: 0, m22: 2, m23: 0, m24: 0,
|
65
|
+
m31: 0, m32: 0, m33: 2, m34: 0,
|
66
|
+
m41: 0, m42: 0, m43: 0, m44: 1,
|
67
|
+
)
|
68
|
+
t2 = CATransform3D.make(
|
69
|
+
m11: 1, m12: 0, m13: 0, m14: 0,
|
70
|
+
m21: 0, m22: 1, m23: 0, m24: 0,
|
71
|
+
m31: 0, m32: 0, m33: 1, m34: 0,
|
72
|
+
m41: 1, m42: 2, m43: 3, m44: 1,
|
73
|
+
)
|
74
|
+
(t1 - t2).should == CATransform3D.make(
|
75
|
+
m11: 2, m12: 0, m13: 0, m14: 0,
|
76
|
+
m21: 0, m22: 2, m23: 0, m24: 0,
|
77
|
+
m31: 0, m32: 0, m33: 2, m34: 0,
|
78
|
+
m41: -1, m42: -2, m43: -3, m44: 1,
|
79
|
+
)
|
80
|
+
end
|
81
|
+
|
82
|
+
it "subtracting itself should return identity (scale)" do
|
83
|
+
t1 = CATransform3D.make(
|
84
|
+
m11: 2, m12: 0, m13: 0, m14: 0,
|
85
|
+
m21: 0, m22: 2, m23: 0, m24: 0,
|
86
|
+
m31: 0, m32: 0, m33: 2, m34: 0,
|
87
|
+
m41: 0, m42: 0, m43: 0, m44: 1,
|
88
|
+
)
|
89
|
+
(t1 - t1).should == CATransform3D.make(
|
90
|
+
m11: 1, m12: 0, m13: 0, m14: 0,
|
91
|
+
m21: 0, m22: 1, m23: 0, m24: 0,
|
92
|
+
m31: 0, m32: 0, m33: 1, m34: 0,
|
93
|
+
m41: 0, m42: 0, m43: 0, m44: 1,
|
94
|
+
)
|
95
|
+
end
|
96
|
+
|
97
|
+
it "subtracting itself should return identity (translate)" do
|
98
|
+
t1 = CATransform3D.make(
|
99
|
+
m11: 1, m12: 0, m13: 0, m14: 0,
|
100
|
+
m21: 0, m22: 1, m23: 0, m24: 0,
|
101
|
+
m31: 0, m32: 0, m33: 1, m34: 0,
|
102
|
+
m41: 1, m42: 2, m43: 3, m44: 1,
|
103
|
+
)
|
104
|
+
(t1 - t1).should == CATransform3D.make(
|
105
|
+
m11: 1, m12: 0, m13: 0, m14: 0,
|
106
|
+
m21: 0, m22: 1, m23: 0, m24: 0,
|
107
|
+
m31: 0, m32: 0, m33: 1, m34: 0,
|
108
|
+
m41: 0, m42: 0, m43: 0, m44: 1,
|
109
|
+
)
|
110
|
+
end
|
111
|
+
|
112
|
+
it "subtracting itself should return identity (rotate)" do
|
113
|
+
t1 = CATransform3D.make(
|
114
|
+
m11:-1, m12: 0, m13: 0, m14: 0,
|
115
|
+
m21: 0, m22:-1, m23: 0, m24: 0,
|
116
|
+
m31: 0, m32: 0, m33: 1, m34: 0,
|
117
|
+
m41: 0, m42: 0, m43: 0, m44: 1,
|
118
|
+
)
|
119
|
+
(t1 - t1).should == CATransform3D.make(
|
120
|
+
m11: 1, m12: 0, m13: 0, m14: 0,
|
121
|
+
m21: 0, m22: 1, m23: 0, m24: 0,
|
122
|
+
m31: 0, m32: 0, m33: 1, m34: 0,
|
123
|
+
m41: 0, m42: 0, m43: 0, m44: 1,
|
124
|
+
)
|
125
|
+
end
|
126
|
+
|
127
|
+
it "should support unary -" do
|
128
|
+
(- CATransform3D.make(
|
129
|
+
m11: 1, m12: 0, m13: 0, m14: 0,
|
130
|
+
m21: 0, m22: 1, m23: 0, m24: 0,
|
131
|
+
m31: 0, m32: 0, m33: 1, m34: 0,
|
132
|
+
m41: 1, m42: 2, m43: 3, m44: 1,
|
133
|
+
)).should == CATransform3D.make(
|
134
|
+
m11: 1, m12: 0, m13: 0, m14: 0,
|
135
|
+
m21: 0, m22: 1, m23: 0, m24: 0,
|
136
|
+
m31: 0, m32: 0, m33: 1, m34: 0,
|
137
|
+
m41:-1, m42:-2, m43:-3, m44: 1,
|
138
|
+
)
|
139
|
+
end
|
140
|
+
|
141
|
+
it "should support unary +" do
|
142
|
+
(+ CATransform3D.make(
|
143
|
+
m11: 1, m12: 0, m13: 0, m14: 0,
|
144
|
+
m21: 0, m22: 1, m23: 0, m24: 0,
|
145
|
+
m31: 0, m32: 0, m33: 1, m34: 0,
|
146
|
+
m41: 1, m42: 2, m43: 3, m44: 1,
|
147
|
+
)).should == CATransform3D.make(
|
148
|
+
m11: 1, m12: 0, m13: 0, m14: 0,
|
149
|
+
m21: 0, m22: 1, m23: 0, m24: 0,
|
150
|
+
m31: 0, m32: 0, m33: 1, m34: 0,
|
151
|
+
m41: 1, m42: 2, m43: 3, m44: 1,
|
152
|
+
)
|
153
|
+
end
|
154
|
+
|
155
|
+
end
|
156
|
+
|
157
|
+
describe ".make" do
|
158
|
+
|
159
|
+
it "should work with no arguments" do
|
160
|
+
transform = CATransform3D.make
|
161
|
+
transform.should == CATransform3D.identity
|
162
|
+
end
|
163
|
+
|
164
|
+
it "should work with options" do
|
165
|
+
transform = CATransform3D.make(
|
166
|
+
m11: 1, m12: 0, m13: 0, m14: 0,
|
167
|
+
m21: 0, m22: 1, m23: 0, m24: 0,
|
168
|
+
m31: 0, m32: 0, m33: 1, m34: 0,
|
169
|
+
m41: 0, m42: 0, m43: 0, m44: 1,
|
170
|
+
)
|
171
|
+
CATransform3DIsIdentity(transform).should == true
|
172
|
+
end
|
173
|
+
|
174
|
+
it "should work with transform options (scale)" do
|
175
|
+
CATransform3D.make(scale: [2, 3, 4]).should == CATransform3D.new(2,0,0,0 ,0,3,0,0 ,0,0,4,0 ,0,0,0,1)
|
176
|
+
end
|
177
|
+
|
178
|
+
it "should work with transform options (translate)" do
|
179
|
+
CATransform3D.make(translate: [10, 20, 30]).should == CATransform3D.new(1,0,0,0 ,0,1,0,0 ,0,0,1,0 ,10,20,30,1)
|
180
|
+
end
|
181
|
+
|
182
|
+
it "should work with transform options (rotate)" do
|
183
|
+
transform = CATransform3D.make(rotate: Math::PI).to_a.map { |v| v.round(3) }
|
184
|
+
CATransform3D.new(*transform).should == CATransform3D.new(-1,0,0,0 ,0,-1,0,0 ,0,0,1,0 ,0,0,0,1)
|
185
|
+
end
|
186
|
+
|
187
|
+
it "should work with transform options (scale + translate)" do
|
188
|
+
CATransform3D.make(scale: [2, 3, 4], translate: [10, 20, 30]).should == CATransform3D.new(2,0,0,0 ,0,3,0,0 ,0,0,4,0 ,10,20,30,1)
|
189
|
+
end
|
190
|
+
|
191
|
+
it "should work with transform options (scale + translate + rotation)" do
|
192
|
+
transform = CATransform3D.make(scale: [2, 3, 4], rotate: Math::PI, translate: [10, 20, 30]).to_a.map { |v| v.round(3) }
|
193
|
+
CATransform3D.new(*transform).should == CATransform3D.new(-2,0,0,0 ,0,-3,0,0 ,0,0,4,0 ,10,20,30,1)
|
194
|
+
end
|
195
|
+
|
196
|
+
end
|
197
|
+
|
198
|
+
describe "identity" do
|
199
|
+
|
200
|
+
it "should return the identity matrix" do
|
201
|
+
CATransform3DIsIdentity(CATransform3D.identity).should == true
|
202
|
+
end
|
203
|
+
|
204
|
+
it "identity? should return true for identity matrix" do
|
205
|
+
CATransform3D.identity.identity?.should == true
|
206
|
+
end
|
207
|
+
|
208
|
+
it "identity? should return false other matrices" do
|
209
|
+
CATransform3D.scale(2).identity?.should == false
|
210
|
+
end
|
211
|
+
|
212
|
+
end
|
213
|
+
|
214
|
+
describe ".rotate" do
|
215
|
+
|
216
|
+
it "should work as a factory (x-axis)" do
|
217
|
+
transform = CATransform3D.rotate(Math::PI, 1, 0, 0).to_a.map { |v| v.round(3) }
|
218
|
+
CATransform3D.new(*transform).should == CATransform3D.new(1,0,0,0, 0,-1,0,0, 0,0,-1,0, 0,0,0,1)
|
219
|
+
end
|
220
|
+
|
221
|
+
it "should work as a factory (y-axis)" do
|
222
|
+
transform = CATransform3D.rotate(Math::PI, 0, 1, 0).to_a.map { |v| v.round(3) }
|
223
|
+
CATransform3D.new(*transform).should == CATransform3D.new(-1,0,0,0, 0,1,0,0, 0,0,-1,0, 0,0,0,1)
|
224
|
+
end
|
225
|
+
|
226
|
+
it "should work as a factory (z-axis)" do
|
227
|
+
transform = CATransform3D.rotate(Math::PI, 0, 0, 1).to_a.map { |v| v.round(3) }
|
228
|
+
CATransform3D.new(*transform).should == CATransform3D.new(-1,0,0,0 ,0,-1,0,0 ,0,0,1,0 ,0,0,0,1)
|
229
|
+
end
|
230
|
+
|
231
|
+
it "should work as a factory (default)" do
|
232
|
+
transform = CATransform3D.rotate(Math::PI).to_a.map { |v| v.round(3) }
|
233
|
+
CATransform3D.new(*transform).should == CATransform3D.new(-1,0,0,0 ,0,-1,0,0 ,0,0,1,0 ,0,0,0,1)
|
234
|
+
end
|
235
|
+
|
236
|
+
it "should work as an instance method (x-axis)" do
|
237
|
+
transform = CATransform3D.identity.rotate(Math::PI, 1, 0, 0).to_a.map { |v| v.round(3) }
|
238
|
+
CATransform3D.new(*transform).should == CATransform3D.new(1,0,0,0, 0,-1,0,0, 0,0,-1,0, 0,0,0,1)
|
239
|
+
end
|
240
|
+
|
241
|
+
it "should work as an instance method (y-axis)" do
|
242
|
+
transform = CATransform3D.identity.rotate(Math::PI, 0, 1, 0).to_a.map { |v| v.round(3) }
|
243
|
+
CATransform3D.new(*transform).should == CATransform3D.new(-1,0,0,0, 0,1,0,0, 0,0,-1,0, 0,0,0,1)
|
244
|
+
end
|
245
|
+
|
246
|
+
it "should work as an instance method (z-axis)" do
|
247
|
+
transform = CATransform3D.identity.rotate(Math::PI, 0, 0, 1).to_a.map { |v| v.round(3) }
|
248
|
+
CATransform3D.new(*transform).should == CATransform3D.new(-1,0,0,0 ,0,-1,0,0 ,0,0,1,0 ,0,0,0,1)
|
249
|
+
end
|
250
|
+
|
251
|
+
it "should work as an instance method (default)" do
|
252
|
+
transform = CATransform3D.identity.rotate(Math::PI).to_a.map { |v| v.round(3) }
|
253
|
+
CATransform3D.new(*transform).should == CATransform3D.new(-1,0,0,0 ,0,-1,0,0 ,0,0,1,0 ,0,0,0,1)
|
254
|
+
end
|
255
|
+
|
256
|
+
end
|
257
|
+
|
258
|
+
describe ".scale" do
|
259
|
+
|
260
|
+
it "should work as a factory with one argument" do
|
261
|
+
CATransform3D.scale(2).should == CATransform3D.new(2,0,0,0 ,0,2,0,0 ,0,0,1,0 ,0,0,0,1)
|
262
|
+
end
|
263
|
+
|
264
|
+
it "should work as a factory with three arguments" do
|
265
|
+
CATransform3D.scale(2, 3, 4).should == CATransform3D.new(2,0,0,0 ,0,3,0,0 ,0,0,4,0 ,0,0,0,1)
|
266
|
+
end
|
267
|
+
|
268
|
+
it "should work as a factory with one array" do
|
269
|
+
CATransform3D.scale([2, 3, 4]).should == CATransform3D.new(2,0,0,0 ,0,3,0,0 ,0,0,4,0 ,0,0,0,1)
|
270
|
+
end
|
271
|
+
|
272
|
+
it "should work as an instance method with one argument" do
|
273
|
+
CATransform3D.identity.scale(2).should == CATransform3D.new(2,0,0,0 ,0,2,0,0 ,0,0,1,0 ,0,0,0,1)
|
274
|
+
end
|
275
|
+
|
276
|
+
it "should work as an instance method with three arguments" do
|
277
|
+
CATransform3D.identity.scale(2, 3, 4).should == CATransform3D.new(2,0,0,0 ,0,3,0,0 ,0,0,4,0 ,0,0,0,1)
|
278
|
+
end
|
279
|
+
|
280
|
+
it "should work as an instance method with one array" do
|
281
|
+
CATransform3D.identity.scale([2, 3, 4]).should == CATransform3D.new(2,0,0,0 ,0,3,0,0 ,0,0,4,0 ,0,0,0,1)
|
282
|
+
end
|
283
|
+
|
284
|
+
end
|
285
|
+
|
286
|
+
describe ".translate" do
|
287
|
+
|
288
|
+
it "should work as a factory with three arguments" do
|
289
|
+
CATransform3D.translate(10, 20, 30).should == CATransform3D.new(1,0,0,0 ,0,1,0,0 ,0,0,1,0 ,10,20,30,1)
|
290
|
+
end
|
291
|
+
|
292
|
+
it "should work as a factory with one array" do
|
293
|
+
CATransform3D.translate([10, 20, 30]).should == CATransform3D.new(1,0,0,0 ,0,1,0,0 ,0,0,1,0 ,10,20,30,1)
|
294
|
+
end
|
295
|
+
|
296
|
+
it "should work as an instance method with three arguments" do
|
297
|
+
CATransform3D.identity.translate(10, 20, 30).should == CATransform3D.new(1,0,0,0 ,0,1,0,0 ,0,0,1,0 ,10,20,30,1)
|
298
|
+
end
|
299
|
+
|
300
|
+
it "should work as an instance method with one array" do
|
301
|
+
CATransform3D.identity.translate([10, 20, 30]).should == CATransform3D.new(1,0,0,0 ,0,1,0,0 ,0,0,1,0 ,10,20,30,1)
|
302
|
+
end
|
303
|
+
|
304
|
+
end
|
305
|
+
|
306
|
+
describe ".perspective" do
|
307
|
+
|
308
|
+
it "should work as a factory with two arguments" do
|
309
|
+
CATransform3D.perspective(0.002, 0).should == CATransform3D.new(1,0,0,0.002, 0,1,0,0, 0,0,1,0, 0,0,0,1)
|
310
|
+
CATransform3D.perspective(0, 0.002).should == CATransform3D.new(1,0,0,0, 0,1,0,0.002, 0,0,1,0, 0,0,0,1)
|
311
|
+
end
|
312
|
+
|
313
|
+
it "should work as an instance method with two arguments" do
|
314
|
+
CATransform3D.identity.perspective(0.002, 0).should == CATransform3D.new(1,0,0,0.002, 0,1,0,0, 0,0,1,0, 0,0,0,1)
|
315
|
+
CATransform3D.identity.perspective(0, 0.002).should == CATransform3D.new(1,0,0,0, 0,1,0,0.002, 0,0,1,0, 0,0,0,1)
|
316
|
+
end
|
317
|
+
|
318
|
+
end
|
319
|
+
|
320
|
+
describe "other methods" do
|
321
|
+
|
322
|
+
it "should support concat" do
|
323
|
+
t1 = CATransform3D.translate(10, 20, 30)
|
324
|
+
t2 = CATransform3D.scale(2)
|
325
|
+
t1.concat(t2).should == CATransform3D.new(2,0,0,0 ,0,2,0,0 ,0,0,1,0 ,20,40,30,1)
|
326
|
+
end
|
327
|
+
|
328
|
+
it "should support invert" do
|
329
|
+
t1 = CATransform3D.scale(2)
|
330
|
+
t1.invert.should == CATransform3D.new(0.5,0,0,0 ,0,0.5,0,0 ,0,0,1,0 ,0,0,0,1)
|
331
|
+
end
|
332
|
+
|
333
|
+
it "should support to_affine_transform" do
|
334
|
+
t1 = CATransform3D.new(2,0,0,0 ,0,2,0,0 ,0,0,2,0 ,0,0,0,1)
|
335
|
+
t1.to_affine_transform.should == CGAffineTransformMake(2, 0, 0, 2, 0, 0)
|
336
|
+
end
|
337
|
+
|
338
|
+
it 'should support to_a' do
|
339
|
+
t1 = CATransform3D.identity
|
340
|
+
t1.to_a.should == [1,0,0,0 ,0,1,0,0 ,0,0,1,0 ,0,0,0,1]
|
341
|
+
end
|
342
|
+
|
343
|
+
end
|
344
|
+
|
345
|
+
end
|