nsphere 0.1.0 → 0.2.0
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 +7 -0
- data/lib/nsphere.rb +93 -19
- metadata +6 -8
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 1d92024f76898a3e73d06ddcd095735d40bbc3f8
|
|
4
|
+
data.tar.gz: cfb5fa03364c9c89c3901605b3761a3368b57e16
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 9ead903c0cfe27d7d5115e4686a9eda710ac78fd73370e7665bf27b3dffb96c0a5925c051363207d52a74326483f1f1f1d9340d75c34ab3aab7d9512e002f924
|
|
7
|
+
data.tar.gz: ba084b8222f84c80dc25eb0150a2ea1abb7484f11e6d65ba972b204f08422bcef8e5c950d4228d7c7064cb6eb8b9f13e34f957880b56cd3a5b505e83a5f8c881
|
data/lib/nsphere.rb
CHANGED
|
@@ -1,7 +1,28 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
2
|
|
|
3
|
+
# The program define the NSphere in any dimensional
|
|
4
|
+
# space, and offer the +, -, *, / operator for vector
|
|
5
|
+
# operation in the space.
|
|
6
|
+
#
|
|
7
|
+
# Author:: m00nlight (mailto:dot_wangyushi@yeah.net)
|
|
8
|
+
# Copyright:: Copyright(c) 2014 m00nlight
|
|
9
|
+
# License:: Distributed under the MIT-License
|
|
10
|
+
|
|
11
|
+
|
|
3
12
|
class NSphere
|
|
4
|
-
attr_reader :radius, :thetas, :coordinates
|
|
13
|
+
attr_reader :radius, :thetas, :coordinates, :dim
|
|
14
|
+
|
|
15
|
+
# A implementation of the n-sphere in any dimensional space
|
|
16
|
+
# In two dimensional, it is a circle to origin point(0, 0), in
|
|
17
|
+
# three dimensional space, it is a sphere to origin(0, 0, 0).
|
|
18
|
+
#
|
|
19
|
+
# === Attributes
|
|
20
|
+
#
|
|
21
|
+
# * +radius+ - Radius of the object
|
|
22
|
+
# * +thetas+ - angles value in radians
|
|
23
|
+
# * +coordinates+ - coordinates of the object
|
|
24
|
+
# * +dim+ - dimension of the space
|
|
25
|
+
|
|
5
26
|
|
|
6
27
|
def initialize(args)
|
|
7
28
|
if not (args[:radius].nil? or args[:thetas].nil?)
|
|
@@ -19,6 +40,8 @@ class NSphere
|
|
|
19
40
|
end
|
|
20
41
|
end
|
|
21
42
|
|
|
43
|
+
# Check argument of radius and thetas, the last theta must in range [0, 2PI],
|
|
44
|
+
# while the rest thetas values must be in the range of [0, PI]
|
|
22
45
|
def check_argument(radius, thetas)
|
|
23
46
|
radius >= 0.0 and thetas[0..-2].all? { |x| x >= 0 and x <= Math::PI} and
|
|
24
47
|
thetas[-1] >= 0 and thetas[-1] <= 2 * Math::PI
|
|
@@ -27,9 +50,9 @@ class NSphere
|
|
|
27
50
|
def build_by_radius_thetas(radius, thetas)
|
|
28
51
|
@radius = radius
|
|
29
52
|
@thetas = thetas
|
|
30
|
-
dim = @thetas.size + 1
|
|
31
|
-
@coordinates = [0.0] * dim
|
|
32
|
-
(0..(dim - 2)).to_a.each do |idx|
|
|
53
|
+
@dim = @thetas.size + 1
|
|
54
|
+
@coordinates = [0.0] * @dim
|
|
55
|
+
(0..(@dim - 2)).to_a.each do |idx|
|
|
33
56
|
tmp = @radius
|
|
34
57
|
(0..(idx - 1)).to_a { |j| tmp = tmp * Math.sin(@thetas[j])}
|
|
35
58
|
@coordinates[idx] = tmp * Math.cos(@thetas[idx])
|
|
@@ -39,20 +62,34 @@ class NSphere
|
|
|
39
62
|
|
|
40
63
|
def build_by_coordinate(coordinates)
|
|
41
64
|
@coordinates = coordinates
|
|
42
|
-
dim = @coordinates.size
|
|
65
|
+
@dim = @coordinates.size
|
|
43
66
|
coord_square = coordinates.map { |x| x ** 2}
|
|
44
67
|
@radius = Math.sqrt(coord_square.inject(:+))
|
|
45
|
-
sum = [0] * (dim + 1)
|
|
68
|
+
sum = [0] * (@dim + 1)
|
|
46
69
|
coord_square.each_with_index do |elem, idx|
|
|
47
70
|
sum[idx + 1] = sum[idx] + elem
|
|
48
71
|
end
|
|
49
|
-
@thetas = [0.0] * (dim - 1)
|
|
50
|
-
@thetas[dim - 2] = Math.atan2(coordinates[dim - 1],
|
|
51
|
-
|
|
52
|
-
|
|
72
|
+
@thetas = [0.0] * (@dim - 1)
|
|
73
|
+
@thetas[@dim - 2] = normalize_angle(Math.atan2(coordinates[@dim - 1],
|
|
74
|
+
coordinates[@dim - 2]),
|
|
75
|
+
2 * Math::PI)
|
|
76
|
+
(0..(@dim - 3)).to_a.reverse.each do |idx|
|
|
77
|
+
@thetas[idx] = normalize_angle(atan((sum[@dim - 1] - sum[idx]) ,
|
|
78
|
+
coordinates[idx]),
|
|
79
|
+
Math::PI)
|
|
53
80
|
end
|
|
54
81
|
end
|
|
55
82
|
|
|
83
|
+
# atan wrapper for the Math.atan method to avoid produce 0 / 0 as NaN
|
|
84
|
+
#
|
|
85
|
+
# ==== Attributes
|
|
86
|
+
#
|
|
87
|
+
# * +y+ - denominator of the atan function
|
|
88
|
+
# * +x+ - numerator of the atan function
|
|
89
|
+
#
|
|
90
|
+
# ==== Example
|
|
91
|
+
# atan(0, 0) => 0.0
|
|
92
|
+
# atan(3, 4) => 0.6435011087932844
|
|
56
93
|
def atan(y, x)
|
|
57
94
|
if x.abs <= 10e-6 && y.abs <= 10e-6
|
|
58
95
|
return 0.0
|
|
@@ -61,38 +98,70 @@ class NSphere
|
|
|
61
98
|
end
|
|
62
99
|
end
|
|
63
100
|
|
|
101
|
+
|
|
102
|
+
# normalize an angle value to [0..range]
|
|
103
|
+
def normalize_angle(angle, range)
|
|
104
|
+
(angle + range) % range
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# negate the object
|
|
64
108
|
def negate
|
|
65
|
-
NSphere.new(
|
|
66
|
-
thetas: self.thetas.map { |x| -x})
|
|
109
|
+
NSphere.new(coord: @coordinates.map { |x| -x})
|
|
67
110
|
end
|
|
68
111
|
|
|
112
|
+
# help function for doing vector multiplication and division
|
|
113
|
+
def add_angles(thetas1, thetas2)
|
|
114
|
+
|
|
115
|
+
res = []
|
|
116
|
+
res = thetas1[0..-2].zip(thetas2[0..-2]) { |x|
|
|
117
|
+
(x.inject(:+) + Math::PI) % Math::PI
|
|
118
|
+
} || res
|
|
119
|
+
|
|
120
|
+
res << ((thetas1[-1] + thetas2[-1] + 2 * Math::PI) % (2 * Math::PI))
|
|
121
|
+
res
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# add operator for two vectors
|
|
69
125
|
def +(a)
|
|
126
|
+
raise "Dimension not match" if @dim != a.dim
|
|
70
127
|
tmp = self.coordinates.zip(a.coordinates).map { |x|
|
|
71
128
|
x.inject(:+)
|
|
72
129
|
}
|
|
73
130
|
NSphere.new(coord: tmp)
|
|
74
131
|
end
|
|
75
132
|
|
|
133
|
+
# minus operator for two vectors
|
|
76
134
|
def -(a)
|
|
135
|
+
raise "Dimension not match" if @dim != a.dim
|
|
77
136
|
self + a.negate
|
|
78
137
|
end
|
|
79
138
|
|
|
139
|
+
# multiply operator for two vectors
|
|
80
140
|
def *(a)
|
|
81
|
-
tmp =
|
|
82
|
-
x.inject(:+)
|
|
83
|
-
}
|
|
141
|
+
tmp = add_angles(@thetas, a.thetas)
|
|
84
142
|
NSphere.new(radius: self.radius * a.radius,
|
|
85
143
|
thetas: tmp)
|
|
86
144
|
end
|
|
87
145
|
|
|
146
|
+
# divide operator for two vectors
|
|
88
147
|
def /(a)
|
|
89
|
-
tmp =
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
148
|
+
tmp = add_angles(@thetas, a.thetas.map { |x| -x})
|
|
149
|
+
|
|
150
|
+
p @thetas
|
|
151
|
+
p a.thetas.map { |x| -x}
|
|
152
|
+
p tmp
|
|
153
|
+
NSphere.new(radius: @radius / a.radius,
|
|
93
154
|
thetas: tmp)
|
|
94
155
|
end
|
|
95
156
|
|
|
157
|
+
# Class method, generate a random vector in any dimensional space
|
|
158
|
+
#
|
|
159
|
+
# ==== Attributes
|
|
160
|
+
#
|
|
161
|
+
# * +dim+ - dimension of the generate vector
|
|
162
|
+
# * +radius+ - radius with default value set to 1.0
|
|
163
|
+
#
|
|
164
|
+
# An random NSphere object is returned as result.
|
|
96
165
|
def self.random_vector(dim, radius = 1.0)
|
|
97
166
|
thetas = [0.0] * (dim - 1)
|
|
98
167
|
thetas[-1] = Random.rand(0..(2 * Math::PI))
|
|
@@ -102,4 +171,9 @@ class NSphere
|
|
|
102
171
|
NSphere.new(radius: radius,
|
|
103
172
|
thetas: thetas)
|
|
104
173
|
end
|
|
174
|
+
|
|
175
|
+
# override to string method of NSphere object
|
|
176
|
+
def to_s
|
|
177
|
+
"radius: #{radius}, thetas: #{thetas}, coordinates: #{coordinates}"
|
|
178
|
+
end
|
|
105
179
|
end
|
metadata
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: nsphere
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
5
|
-
prerelease:
|
|
4
|
+
version: 0.2.0
|
|
6
5
|
platform: ruby
|
|
7
6
|
authors:
|
|
8
7
|
- m00nlight
|
|
@@ -21,26 +20,25 @@ files:
|
|
|
21
20
|
homepage: https://github.com/m00nlight/nsphere
|
|
22
21
|
licenses:
|
|
23
22
|
- MIT
|
|
23
|
+
metadata: {}
|
|
24
24
|
post_install_message:
|
|
25
25
|
rdoc_options: []
|
|
26
26
|
require_paths:
|
|
27
27
|
- lib
|
|
28
28
|
required_ruby_version: !ruby/object:Gem::Requirement
|
|
29
|
-
none: false
|
|
30
29
|
requirements:
|
|
31
|
-
- -
|
|
30
|
+
- - ">="
|
|
32
31
|
- !ruby/object:Gem::Version
|
|
33
32
|
version: '0'
|
|
34
33
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
35
|
-
none: false
|
|
36
34
|
requirements:
|
|
37
|
-
- -
|
|
35
|
+
- - ">="
|
|
38
36
|
- !ruby/object:Gem::Version
|
|
39
37
|
version: '0'
|
|
40
38
|
requirements: []
|
|
41
39
|
rubyforge_project:
|
|
42
|
-
rubygems_version:
|
|
40
|
+
rubygems_version: 2.2.2
|
|
43
41
|
signing_key:
|
|
44
|
-
specification_version:
|
|
42
|
+
specification_version: 4
|
|
45
43
|
summary: NSphere
|
|
46
44
|
test_files: []
|