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:



24
25
26
27
28
29
30
# File 'lib/rgeo/geographic/spherical_math.rb', line 24

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.



36
37
38
# File 'lib/rgeo/geographic/spherical_math.rb', line 36

def x
  @x
end

#yObject (readonly)

Returns the value of attribute y.



37
38
39
# File 'lib/rgeo/geographic/spherical_math.rb', line 37

def y
  @y
end

#zObject (readonly)

Returns the value of attribute z.



38
39
40
# File 'lib/rgeo/geographic/spherical_math.rb', line 38

def z
  @z
end

Class Method Details

.from_latlon(lat_, lon_) ⇒ Object



111
112
113
114
115
116
117
118
119
120
# File 'lib/rgeo/geographic/spherical_math.rb', line 111

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



122
123
124
# File 'lib/rgeo/geographic/spherical_math.rb', line 122

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



74
75
76
77
78
79
80
81
82
83
# File 'lib/rgeo/geographic/spherical_math.rb', line 74

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

#*(rhs_) ⇒ Object



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

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



103
104
105
106
107
108
109
# File 'lib/rgeo/geographic/spherical_math.rb', line 103

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



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/rgeo/geographic/spherical_math.rb', line 85

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: ==

Returns:

  • (Boolean)


40
41
42
# File 'lib/rgeo/geographic/spherical_math.rb', line 40

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

#latlonObject



45
46
47
48
49
50
51
52
53
54
# File 'lib/rgeo/geographic/spherical_math.rb', line 45

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

#lonlatObject



56
57
58
59
60
61
62
63
64
65
# File 'lib/rgeo/geographic/spherical_math.rb', line 56

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

#to_sObject



32
33
34
# File 'lib/rgeo/geographic/spherical_math.rb', line 32

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