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

Returns a new instance of PointXYZ.


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

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


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

def x
  @x
end

#yObject (readonly)

Returns the value of attribute y


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

def y
  @y
end

#zObject (readonly)

Returns the value of attribute z


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

def z
  @z
end

Class Method Details

.from_latlon(lat, lon) ⇒ Object


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

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


116
117
118
# File 'lib/rgeo/geographic/spherical_math.rb', line 116

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


68
69
70
71
72
73
74
75
76
77
# File 'lib/rgeo/geographic/spherical_math.rb', line 68

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 StandardError
    nil
  end
end

#*(rhs) ⇒ Object


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

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


97
98
99
100
101
102
103
# File 'lib/rgeo/geographic/spherical_math.rb', line 97

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


79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/rgeo/geographic/spherical_math.rb', line 79

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)

42
43
44
# File 'lib/rgeo/geographic/spherical_math.rb', line 42

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

#latlonObject


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

def latlon
  lat_rad = Math.asin(@z)
  lon_rad = Math.atan2(@y, @x)
  rpd = ImplHelper::Math::RADIANS_PER_DEGREE
  [lat_rad / rpd, lon_rad / rpd]
end

#lonlatObject


54
55
56
57
58
59
# File 'lib/rgeo/geographic/spherical_math.rb', line 54

def lonlat
  lat_rad = Math.asin(@z)
  lon_rad = Math.atan2(@y, @x)
  rpd = ImplHelper::Math::RADIANS_PER_DEGREE
  [lon_rad / rpd, lat_rad / rpd]
end

#to_sObject


34
35
36
# File 'lib/rgeo/geographic/spherical_math.rb', line 34

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