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.



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

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)

:nodoc:



26
27
28
# File 'lib/rgeo/geographic/spherical_math.rb', line 26

def x
  @x
end

#yObject (readonly)

:nodoc:



26
27
28
# File 'lib/rgeo/geographic/spherical_math.rb', line 26

def y
  @y
end

#zObject (readonly)

:nodoc:



26
27
28
# File 'lib/rgeo/geographic/spherical_math.rb', line 26

def z
  @z
end

Class Method Details

.from_latlon(lat, lon) ⇒ Object



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

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(pt1, wt1, pt2, wt2) ⇒ Object



114
115
116
# File 'lib/rgeo/geographic/spherical_math.rb', line 114

def self.weighted_combination(pt1, wt1, pt2, wt2)
  new(pt1.x * wt1 + pt2.x * wt2, pt1.y * wt1 + pt2.y * wt2, pt1.z * wt1 + pt2.z * wt2)
end

Instance Method Details

#%(other) ⇒ Object



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

def %(other)
  rx = other.x
  ry = other.y
  rz = other.z
  begin
    PointXYZ.new(@y * rz - @z * ry, @z * rx - @x * rz, @x * ry - @y * rx)
  rescue StandardError
    nil
  end
end

#*(other) ⇒ Object



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

def *(other)
  val = @x * other.x + @y * other.y + @z * other.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



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

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



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

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?(other) ⇒ Boolean Also known as: ==

Returns:

  • (Boolean)


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

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

#latlonObject



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

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



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

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



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

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