geo3d 0.0.6 → 0.0.7
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/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
|