Class: RGeo::Geographic::SphericalMath::PointXYZ

Inherits:
Object
  • Object
show all
Defined in:
lib/rgeo/geographic/spherical_math.rb

Overview

Represents a point on the unit sphere in (x,y,z) coordinates instead of lat-lon. This form is often faster, more convenient, and more numerically stable for certain computations.

The coordinate system is a right-handed system where the z-axis goes through the north pole, the x-axis goes through the prime meridian, and the y-axis goes through +90 degrees longitude.

This object is also used to represent a great circle, as its axis of rotation.

Constant Summary collapse

P1 =
new(1, 0, 0)
P2 =
new(0, 1, 0)

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(x_, y_, z_) ⇒ PointXYZ

:nodoc:


60
61
62
63
64
65
66
# File 'lib/rgeo/geographic/spherical_math.rb', line 60

def initialize(x_, y_, z_)
  r_ = ::Math.sqrt(x_ * x_ + y_ * y_ + z_ * z_)
  @x = (x_ / r_).to_f
  @y = (y_ / r_).to_f
  @z = (z_ / r_).to_f
  raise "Not a number" if @x.nan? || @y.nan? || @z.nan?
end

Instance Attribute Details

#xObject (readonly)

Returns the value of attribute x


74
75
76
# File 'lib/rgeo/geographic/spherical_math.rb', line 74

def x
  @x
end

#yObject (readonly)

Returns the value of attribute y


75
76
77
# File 'lib/rgeo/geographic/spherical_math.rb', line 75

def y
  @y
end

#zObject (readonly)

Returns the value of attribute z


76
77
78
# File 'lib/rgeo/geographic/spherical_math.rb', line 76

def z
  @z
end

Class Method Details

.from_latlon(lat_, lon_) ⇒ Object


145
146
147
148
149
150
151
152
153
154
# File 'lib/rgeo/geographic/spherical_math.rb', line 145

def self.from_latlon(lat_, lon_)
  rpd_ = ImplHelper::Math::RADIANS_PER_DEGREE
  lat_rad_ = rpd_ * lat_
  lon_rad_ = rpd_ * lon_
  z_ = ::Math.sin(lat_rad_)
  r_ = ::Math.cos(lat_rad_)
  x_ = ::Math.cos(lon_rad_) * r_
  y_ = ::Math.sin(lon_rad_) * r_
  new(x_, y_, z_)
end

.weighted_combination(p1_, w1_, p2_, w2_) ⇒ Object


157
158
159
# File 'lib/rgeo/geographic/spherical_math.rb', line 157

def self.weighted_combination(p1_, w1_, p2_, w2_)
  new(p1_.x * w1_ + p2_.x * w2_, p1_.y * w1_ + p2_.y * w2_, p1_.z * w1_ + p2_.z * w2_)
end

Instance Method Details

#%(rhs_) ⇒ Object


109
110
111
112
113
114
# File 'lib/rgeo/geographic/spherical_math.rb', line 109

def %(rhs_)
  rx_ = rhs_.x
  ry_ = rhs_.y
  rz_ = rhs_.z
  PointXYZ.new(@y*rz_-@z*ry_, @z*rx_-@x*rz_, @x*ry_-@y*rx_) rescue nil
end

#*(rhs_) ⇒ Object


101
102
103
104
105
106
# File 'lib/rgeo/geographic/spherical_math.rb', line 101

def *(rhs_)
  val_ = @x * rhs_.x + @y * rhs_.y + @z * rhs_.z
  val_ = 1.0 if val_ > 1.0
  val_ = -1.0 if val_ < -1.0
  val_
end

#create_perpendicularObject

Creates some point that is perpendicular to this point


136
137
138
139
140
141
142
# File 'lib/rgeo/geographic/spherical_math.rb', line 136

def create_perpendicular
  p1dot_ = self * P1
  p2dot_ = self * P2
  p1dot_ = -p1dot_ if p1dot_ < 0
  p2dot_ = -p2dot_ if p2dot_ < 0
  p1dot_ < p2dot_ ? (self % P1) : (self % P2)
end

#dist_to_point(rhs_) ⇒ Object


117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/rgeo/geographic/spherical_math.rb', line 117

def dist_to_point(rhs_)
  rx_ = rhs_.x
  ry_ = rhs_.y
  rz_ = rhs_.z
  dot_ = @x * rx_ + @y * ry_ + @z * rz_
  if dot_ > -0.8 && dot_ < 0.8
    ::Math.acos(dot_)
  else
    x_ = @y*rz_-@z*ry_
    y_ = @z*rx_-@x*rz_
    z_ = @x*ry_-@y*rx_
    as_ = ::Math.asin(::Math.sqrt(x_*x_ + y_*y_ + z_*z_))
    dot_ > 0.0 ? as_ : ::Math::PI - as_
  end
end

#eql?(rhs_) ⇒ Boolean Also known as: ==


79
80
81
# File 'lib/rgeo/geographic/spherical_math.rb', line 79

def eql?(rhs_)
  rhs_.kind_of?(PointXYZ) && @x == rhs_.x && @y == rhs_.y && @z == rhs_.z
end

#latlonObject


85
86
87
88
89
90
# File 'lib/rgeo/geographic/spherical_math.rb', line 85

def latlon
  lat_rad_ = ::Math.asin(@z)
  lon_rad_ = ::Math.atan2(@y, @x) rescue 0.0
  rpd_ = ImplHelper::Math::RADIANS_PER_DEGREE
  [lat_rad_ / rpd_, lon_rad_ / rpd_]
end

#lonlatObject


93
94
95
96
97
98
# File 'lib/rgeo/geographic/spherical_math.rb', line 93

def lonlat
  lat_rad_ = ::Math.asin(@z)
  lon_rad_ = ::Math.atan2(@y, @x) rescue 0.0
  rpd_ = ImplHelper::Math::RADIANS_PER_DEGREE
  [lon_rad_ / rpd_, lat_rad_ / rpd_]
end

#to_sObject


69
70
71
# File 'lib/rgeo/geographic/spherical_math.rb', line 69

def to_s
  "(#{@x}, #{@y}, #{@z})"
end