geo3d 0.0.6 → 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +33 -1
- data/lib/geo3d/version.rb +1 -1
- data/lib/matrix.rb +12 -0
- data/lib/quaternion.rb +16 -16
- data/lib/utils.rb +13 -0
- data/spec/lib/matrix_spec.rb +17 -3
- data/spec/lib/quaternion_spec.rb +47 -9
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 96291332d1c108ec9adeee6a9ce2deb8244dac5e
|
4
|
+
data.tar.gz: 95de37c194cda4d9462e9cd13accad6e4da44acf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f7fa1397c73eb27f538fac995e5c5ce422059342968c51cf12ddc3653994fe0615ba893fc50fdb51a3ba76ca26815c2de1a1c2e40ccda50efb24fcecfa916062
|
7
|
+
data.tar.gz: 0670ed712274a93812c7d304c194342edb08560ae6152afb0842fc3b617239576268e0329b92ddb3594a267bd5279c3acd6ad7fb4d6f3474a2e655db5887a71c
|
data/README.md
CHANGED
@@ -119,10 +119,11 @@ Inverse
|
|
119
119
|
```
|
120
120
|
mat.inverse #returns inverse of matrix
|
121
121
|
mat.inverse true #returns inverse of matrix along with its determinant
|
122
|
+
mat.determinant #returns the determinant
|
122
123
|
```
|
123
124
|
Transpose
|
124
125
|
```
|
125
|
-
mat.
|
126
|
+
mat.transpose
|
126
127
|
```
|
127
128
|
|
128
129
|
Common matrix constructors
|
@@ -174,6 +175,37 @@ Matrix Decomposition
|
|
174
175
|
matrix.rotation_component
|
175
176
|
```
|
176
177
|
|
178
|
+
## Plane
|
179
|
+
|
180
|
+
Represents a 2d surface in three dimensional space. Has the attributes a,b,c,d that mirror the standard plane equations.
|
181
|
+
|
182
|
+
There are a couple constructors to build planes from points and normals.
|
183
|
+
````
|
184
|
+
Geo3d::Plane.from_points pv1, pv2, pv3 #builds a plane from known points on the plane
|
185
|
+
Geo3d::Plane.from_point_and_normal point, normal #builds a plane from it's normal and a known point
|
186
|
+
````
|
187
|
+
|
188
|
+
Additional plane operations
|
189
|
+
|
190
|
+
Dot product
|
191
|
+
```
|
192
|
+
plane.dot v #v can be a vector or another plane
|
193
|
+
```
|
194
|
+
Normalize
|
195
|
+
```
|
196
|
+
plane.normalize #returns a normalized version of the plane
|
197
|
+
plane.normalize! #normalizes the plane in place
|
198
|
+
```
|
199
|
+
Line intersection
|
200
|
+
```
|
201
|
+
plane.line_intersection line_start, line_end #returns the intersection of the line onto the plane
|
202
|
+
````
|
203
|
+
Plane Transformation
|
204
|
+
````
|
205
|
+
#transforms plane by the matrix, if use_inverse_transpose is set to true, the plane will be transformed by the inverse transpose of matrix
|
206
|
+
plane.transform matrix, use_inverse_transpose = true
|
207
|
+
````
|
208
|
+
|
177
209
|
|
178
210
|
## Quaternion
|
179
211
|
|
data/lib/geo3d/version.rb
CHANGED
data/lib/matrix.rb
CHANGED
@@ -287,6 +287,18 @@ module Geo3d
|
|
287
287
|
inverse(true).last
|
288
288
|
end
|
289
289
|
|
290
|
+
def trace
|
291
|
+
_11 + _22 + _33 + _44
|
292
|
+
end
|
293
|
+
|
294
|
+
def orthogonal?
|
295
|
+
inverse == transpose
|
296
|
+
end
|
297
|
+
|
298
|
+
def is_rotation_transform?
|
299
|
+
orthogonal? && Geo3d::Utils.float_cmp(determinant, 1.0)
|
300
|
+
end
|
301
|
+
|
290
302
|
def inverse with_determinant = false
|
291
303
|
mat = to_a
|
292
304
|
dst = Array.new 16
|
data/lib/quaternion.rb
CHANGED
@@ -13,6 +13,10 @@ module Geo3d
|
|
13
13
|
@w = args[3].to_f if args.size > 3
|
14
14
|
end
|
15
15
|
|
16
|
+
def to_a
|
17
|
+
[x,y,z,w]
|
18
|
+
end
|
19
|
+
|
16
20
|
def x= v
|
17
21
|
@x = v.to_f
|
18
22
|
end
|
@@ -46,6 +50,7 @@ module Geo3d
|
|
46
50
|
end
|
47
51
|
|
48
52
|
def self.from_axis rotation_axis, radians = 0
|
53
|
+
radians = Geo3d::Utils.normalize_angle radians #todo: is this cheating?....
|
49
54
|
normalized_rotation_axis = rotation_axis.zero_w.normalize
|
50
55
|
q = self.new
|
51
56
|
q.x = Math.sin(radians / 2.0) * normalized_rotation_axis.x
|
@@ -62,13 +67,14 @@ module Geo3d
|
|
62
67
|
def self.from_matrix pm
|
63
68
|
pout = self.new
|
64
69
|
|
65
|
-
trace
|
66
|
-
if trace > 0
|
67
|
-
|
68
|
-
pout.
|
69
|
-
pout.
|
70
|
-
pout.
|
71
|
-
|
70
|
+
#puts "trace is #{pm.trace}"
|
71
|
+
if false && pm.trace > 1.0
|
72
|
+
sq_root_of_trace = Math.sqrt pm.trace
|
73
|
+
pout.x = (pm._23 - pm._32) / (2.0 * sq_root_of_trace)
|
74
|
+
pout.y = (pm._31 - pm._13) / (2.0 * sq_root_of_trace)
|
75
|
+
pout.z = (pm._12- pm._21) / (2.0 * sq_root_of_trace)
|
76
|
+
pout.w = sq_root_of_trace / 2.0
|
77
|
+
#puts "a and pout is #{pout.inspect}"
|
72
78
|
|
73
79
|
return pout
|
74
80
|
end
|
@@ -104,7 +110,7 @@ module Geo3d
|
|
104
110
|
pout.z = 0.25 * s
|
105
111
|
pout.w = (pm._12 - pm._21) / s
|
106
112
|
end
|
107
|
-
puts "b"
|
113
|
+
#puts "b"
|
108
114
|
pout
|
109
115
|
end
|
110
116
|
|
@@ -150,17 +156,11 @@ module Geo3d
|
|
150
156
|
end
|
151
157
|
|
152
158
|
def axis
|
153
|
-
|
154
|
-
v = Vector.new
|
155
|
-
v.x = q.x / Math.sqrt(1-q.w*q.w)
|
156
|
-
v.y = q.y / Math.sqrt(1-q.w*q.w)
|
157
|
-
v.z = q.z / Math.sqrt(1-q.w*q.w)
|
158
|
-
v
|
159
|
+
Vector.new( *(normalize / Math.sin( angle / 2.0 )).to_a ).zero_w
|
159
160
|
end
|
160
161
|
|
161
162
|
def angle
|
162
|
-
|
163
|
-
Math.acos(q.w) * 2.0
|
163
|
+
Math.acos(normalize.w) * 2.0
|
164
164
|
end
|
165
165
|
|
166
166
|
def angle_degrees
|
data/lib/utils.rb
CHANGED
@@ -11,5 +11,18 @@ module Geo3d
|
|
11
11
|
def self.to_radians degrees
|
12
12
|
degrees * Math::PI / 180.0
|
13
13
|
end
|
14
|
+
|
15
|
+
def self.normalize_angle radians
|
16
|
+
if radians.abs > Math::PI * 2.0
|
17
|
+
absolute = radians.abs % (Math::PI * 2.0 )
|
18
|
+
if radians < 0
|
19
|
+
-absolute
|
20
|
+
else
|
21
|
+
absolute
|
22
|
+
end
|
23
|
+
else
|
24
|
+
radians
|
25
|
+
end
|
26
|
+
end
|
14
27
|
end
|
15
28
|
end
|
data/spec/lib/matrix_spec.rb
CHANGED
@@ -26,15 +26,21 @@ describe Geo3d::Matrix do
|
|
26
26
|
end
|
27
27
|
|
28
28
|
it "should be able to extract translation component" do
|
29
|
-
|
29
|
+
translation = Geo3d::Vector.new 3,-4,6
|
30
|
+
matrix = Geo3d::Matrix.translation translation.x, translation.y, translation.z
|
31
|
+
matrix.translation_component.should == translation
|
30
32
|
end
|
31
33
|
|
32
34
|
it "should be able to extract scaling component" do
|
33
|
-
|
35
|
+
scaling = Geo3d::Vector.new 3,4,6
|
36
|
+
matrix = Geo3d::Matrix.scaling scaling.x, scaling.y, scaling.z
|
37
|
+
matrix.scaling_component.should == scaling
|
34
38
|
end
|
35
39
|
|
36
40
|
it "should be able to extract rotation component" do
|
37
|
-
|
41
|
+
angle = 2.234
|
42
|
+
matrix = Geo3d::Matrix.rotation_z angle
|
43
|
+
matrix.rotation_component.should == Geo3d::Quaternion.from_axis(Geo3d::Vector.new(0,0,1), angle)
|
38
44
|
end
|
39
45
|
|
40
46
|
it "should be invertible" do
|
@@ -157,6 +163,8 @@ describe Geo3d::Matrix do
|
|
157
163
|
data[:expected].size.should == 16
|
158
164
|
expected = Geo3d::Matrix.new *data[:expected]
|
159
165
|
matrix.should == expected
|
166
|
+
matrix.is_rotation_transform?.should == true
|
167
|
+
expected.is_rotation_transform?.should == true
|
160
168
|
end
|
161
169
|
end
|
162
170
|
|
@@ -167,6 +175,8 @@ describe Geo3d::Matrix do
|
|
167
175
|
data[:expected].size.should == 16
|
168
176
|
expected = Geo3d::Matrix.new *data[:expected]
|
169
177
|
matrix.should == expected
|
178
|
+
matrix.is_rotation_transform?.should == true
|
179
|
+
expected.is_rotation_transform?.should == true
|
170
180
|
end
|
171
181
|
end
|
172
182
|
|
@@ -177,6 +187,8 @@ describe Geo3d::Matrix do
|
|
177
187
|
data[:expected].size.should == 16
|
178
188
|
expected = Geo3d::Matrix.new *data[:expected]
|
179
189
|
matrix.should == expected
|
190
|
+
matrix.is_rotation_transform?.should == true
|
191
|
+
expected.is_rotation_transform?.should == true
|
180
192
|
end
|
181
193
|
end
|
182
194
|
|
@@ -186,6 +198,8 @@ describe Geo3d::Matrix do
|
|
186
198
|
data[:expected].size.should == 16
|
187
199
|
expected = Geo3d::Matrix.new *data[:expected]
|
188
200
|
matrix.should == expected
|
201
|
+
matrix.is_rotation_transform?.should == true
|
202
|
+
expected.is_rotation_transform?.should == true
|
189
203
|
end
|
190
204
|
end
|
191
205
|
|
data/spec/lib/quaternion_spec.rb
CHANGED
@@ -33,21 +33,32 @@ describe Geo3d::Quaternion do
|
|
33
33
|
end
|
34
34
|
|
35
35
|
it "should be able to convert to a rotation matrix" do
|
36
|
-
|
36
|
+
[{:quaternion => [0.0, 0.7071067811865475, 0.0, 0.7071067811865475], :expected => [0.000000, 0.000000, -1.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 1.000000]}].each do |data|
|
37
|
+
quaternion = Geo3d::Quaternion.new *data[:quaternion]
|
38
|
+
data[:expected].size.should == 16
|
39
|
+
expected = Geo3d::Matrix.new *data[:expected]
|
40
|
+
quaternion.to_matrix.should == expected
|
41
|
+
end
|
37
42
|
end
|
38
43
|
|
39
|
-
it "should return axis of rotation" do
|
44
|
+
it "should return axis and angle of rotation" do
|
40
45
|
for i in 0..10000
|
41
46
|
angle = 0.1 * i + 0.1
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
end
|
47
|
+
normalized_angle = Geo3d::Utils.normalize_angle angle
|
48
|
+
|
49
|
+
Geo3d::Quaternion.from_axis(Geo3d::Vector.new(1, 0, 0), angle).axis.should == Geo3d::Vector.new(1, 0, 0)
|
50
|
+
Geo3d::Quaternion.from_axis(Geo3d::Vector.new(0, 1, 0), angle).axis.should == Geo3d::Vector.new(0, 1, 0)
|
51
|
+
Geo3d::Quaternion.from_axis(Geo3d::Vector.new(0, 0, 1), angle).axis.should == Geo3d::Vector.new(0, 0, 1)
|
48
52
|
|
49
|
-
it "should return rotation amount as angle" do
|
50
53
|
|
54
|
+
Geo3d::Quaternion.from_matrix(Geo3d::Matrix.rotation_x angle).axis.should == Geo3d::Vector.new(1, 0, 0)
|
55
|
+
Geo3d::Quaternion.from_matrix(Geo3d::Matrix.rotation_y angle).axis.should == Geo3d::Vector.new(0, 1, 0)
|
56
|
+
Geo3d::Quaternion.from_matrix(Geo3d::Matrix.rotation_z angle).axis.should == Geo3d::Vector.new(0, 0, 1)
|
57
|
+
|
58
|
+
Geo3d::Utils.float_cmp(Geo3d::Quaternion.from_matrix(Geo3d::Matrix.rotation_x angle).angle, normalized_angle).should == true
|
59
|
+
Geo3d::Utils.float_cmp(Geo3d::Quaternion.from_matrix(Geo3d::Matrix.rotation_y angle).angle, normalized_angle).should == true
|
60
|
+
Geo3d::Utils.float_cmp(Geo3d::Quaternion.from_matrix(Geo3d::Matrix.rotation_z angle).angle, normalized_angle).should == true
|
61
|
+
end
|
51
62
|
end
|
52
63
|
|
53
64
|
it "should return conjugate" do
|
@@ -108,6 +119,33 @@ describe Geo3d::Quaternion do
|
|
108
119
|
end
|
109
120
|
end
|
110
121
|
|
122
|
+
|
123
|
+
it "multiplying two quaternions with same axis should result in a quaternion with the same axis and the sum of their angles" do
|
124
|
+
[[1, 0, 0], [0, 1, 0], [0, 0, 1], [2, 2, 8]].each do |axis|
|
125
|
+
axis = Geo3d::Vector.new *axis
|
126
|
+
|
127
|
+
[[2.3, 0.4],
|
128
|
+
[2.3, 0.4, -0.1],
|
129
|
+
[-1, -0.25, -0.5, 2.3]].each do |angles|
|
130
|
+
product = nil
|
131
|
+
angles.each do |angle|
|
132
|
+
q = Geo3d::Quaternion.from_axis axis, angle
|
133
|
+
if product.nil?
|
134
|
+
product = q
|
135
|
+
else
|
136
|
+
product *= q
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
Geo3d::Utils.float_cmp(product.angle, angles.inject(:+)).should == true
|
141
|
+
product.axis.should == axis.normalize
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
|
147
|
+
|
148
|
+
|
111
149
|
#todo: add tests for quaternion interpolation
|
112
150
|
|
113
151
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: geo3d
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Misha Conway
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-01-
|
11
|
+
date: 2014-01-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|