Class: Geospatial::Location

Inherits:
Object
  • Object
show all
Defined in:
lib/geospatial/location.rb

Overview

This location is specifically relating to a WGS84 coordinate on Earth.

Constant Summary collapse

WGS84_A =

WGS 84 semi-major axis constant in meters

6378137.0
WGS84_B =

WGS 84 semi-minor axis constant in meters

6356752.3
EARTH_RADIUS =
(WGS84_A + WGS84_B) / 2.0
WGS84_E =

WGS 84 eccentricity

8.1819190842622e-2
R2D =

Radians to degrees multiplier

(180.0 / Math::PI)
D2R =
(Math::PI / 180.0)
MIN_LONGITUDE =
-180 * D2R
MAX_LONGITUDE =
180 * D2R
VALID_LONGITUDE =
MIN_LONGITUDE...MAX_LONGITUDE
MIN_LATITUDE =
-90.0 * D2R
MAX_LATITUDE =
90 * D2R
VALID_LATITUDE =
MIN_LATITUDE...MAX_LATITUDE

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(longitude, latitude) ⇒ Location

Returns a new instance of Location.



46
47
48
49
# File 'lib/geospatial/location.rb', line 46

def initialize(longitude, latitude)
	@latitude = latitude
	@longitude = longitude
end

Instance Attribute Details

#latitudeObject (readonly)

-90 -> 90 (equivalent to y)



66
67
68
# File 'lib/geospatial/location.rb', line 66

def latitude
  @latitude
end

#longitudeObject (readonly)

-180 -> 180 (equivalent to x)



65
66
67
# File 'lib/geospatial/location.rb', line 65

def longitude
  @longitude
end

Class Method Details

.from_ecef(x, y, z) ⇒ Object



117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/geospatial/location.rb', line 117

def self.from_ecef(x, y, z)
	# Constants (WGS ellipsoid)
	a = WGS84_A
	e = WGS84_E
	
	b = Math::sqrt((a*a) * (1.0-(e*e)))
	ep = Math::sqrt(((a*a)-(b*b))/(b*b))
	
	p = Math::sqrt((x*x)+(y*y))
	th = Math::atan2(a*z, b*p)
	
	lon = Math::atan2(y, x)
	lat = Math::atan2((z+ep*ep*b*(Math::sin(th) ** 3)), (p-e*e*a*(Math::cos(th)**3)))
	
	n = a / Math::sqrt(1.0-e*e*(Math::sin(lat) ** 2))
	# alt = p / Math::cos(lat)-n
	
	return self.new(lat*R2D, lon*R2D)
end

Instance Method Details

#bounding_box(distance, radius = EARTH_RADIUS) ⇒ Object

Raises:

  • (ArgumentError)


69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/geospatial/location.rb', line 69

def bounding_box(distance, radius = EARTH_RADIUS)
	raise ArgumentError.new("Invalid distance or radius") if distance < 0 or radius < 0

	# angular distance in radians on a great circle
	angular_distance = distance / radius

	min_latitude = (self.latitude * D2R) - angular_distance
	max_latitude = (self.latitude * D2R) + angular_distance

	if min_latitude > MIN_LATITUDE and max_latitude < MAX_LATITUDE
		longitude_delta = Math::asin(Math::sin(angular_distance) / Math::cos(self.latitude * D2R))
		
		min_longitude = (self.longitude * D2R) - longitude_delta
		min_longitude += 2.0 * Math::PI if (min_longitude < MIN_LONGITUDE)
		
		max_longitude = (self.longitude * D2R) + longitude_delta;
		max_longitude -= 2.0 * Math::PI if (max_longitude > MAX_LONGITUDE)
	else
		# a pole is within the distance
		min_latitude = [min_latitude, MIN_LATITUDE].max
		max_latitude = [max_latitude, MAX_LATITUDE].min
		
		min_longitude = MIN_LONGITUDE
		max_longitude = MAX_LONGITUDE
	end
	
	return {
		:latitude => Range.new(min_latitude * R2D, max_latitude * R2D),
		:longitude => Range.new(min_longitude * R2D, max_longitude * R2D),
	}
end

#distance_from(other_position) ⇒ Object

calculate distance in metres between us and something else ref: codingandweb.blogspot.co.nz/2012/04/calculating-distance-between-two-points.html



139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/geospatial/location.rb', line 139

def distance_from(other_position)
	rlong1 = self.longitude * D2R 
	rlat1 = self.latitude * D2R 
	rlong2 = other_position.longitude * D2R 
	rlat2 = other_position.latitude * D2R 
	
	dlon = rlong1 - rlong2
	dlat = rlat1 - rlat2
	
	a = Math::sin(dlat/2) ** 2 + Math::cos(rlat1) * Math::cos(rlat2) * Math::sin(dlon/2) ** 2
	c = 2 * Math::atan2(Math::sqrt(a), Math::sqrt(1-a))
	d = EARTH_RADIUS * c
	
	return d
end

#to_aObject



55
56
57
# File 'lib/geospatial/location.rb', line 55

def to_a
	[@longitude, @latitude]
end

#to_ecefObject

Converts latitude, longitude to ECEF coordinate system



102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/geospatial/location.rb', line 102

def to_ecef
	clon = Math::cos(lon * D2R)
	slon = Math::sin(lon * D2R)
	clat = Math::cos(lat * D2R)
	slat = Math::sin(lat * D2R)

	n = WGS84_A / Math::sqrt(1.0 - WGS84_E * WGS84_E * slat * slat)

	x = n * clat * clon
	y = n * clat * slon
	z = n * (1.0 - WGS84_E * WGS84_E) * slat
	
	return x, y, z
end

#to_sObject Also known as: inspect



59
60
61
# File 'lib/geospatial/location.rb', line 59

def to_s
	"#<Location longitude=#{@longitude.to_f} latitude=#{@latitude}>"
end

#valid?Boolean

Returns:

  • (Boolean)


51
52
53
# File 'lib/geospatial/location.rb', line 51

def valid?
	VALID_LONGITUDE.include?(longitude) and VALID_LATITUDE.include?(latitude)
end