class Terraformer::Coordinate

Constants

EARTH_MEAN_RADIUS

en.wikipedia.org/wiki/Earth_radius#Mean_radius

Attributes

ary[RW]

array holding the numeric coordinate values

crs[RW]

Public Class Methods

big_decimal(n) click to toggle source
# File lib/terraformer/coordinate.rb, line 28
def big_decimal n
  case n
  when String
    BigDecimal(n)
  when BigDecimal
    n
  when Numeric
    BigDecimal(n.to_s)
  else
    raise ArgumentError
  end
end
from_array(a) click to toggle source
# File lib/terraformer/coordinate.rb, line 16
def from_array a
  if Coordinate === a
    a.dup
  elsif Numeric === a[0]
    Coordinate.new a
  elsif Array === a
    a.map {|e| Coordinate.from_array e }
  else
    raise ArgumentError
  end
end
new(_x, _y = nil, _z = nil) click to toggle source
# File lib/terraformer/coordinate.rb, line 43
def initialize _x, _y = nil, _z = nil
  @ary = Array.new 3
  case _x
  when Array
    raise ArgumentError if _y
    self.x = _x[0]
    self.y = _x[1]
    self.z = _x[2] if _x[2]

  when Coordinate
    raise ArgumentError if _y
    self.x = _x.x
    self.y = _x.y
    self.z = _x.z if _x.z

  when Numeric, String
    raise ArgumentError unless _y
    self.x = _x
    self.y = _y
    self.z = _z if _z
  else
    raise ArgumentError.new "invalid argument: #{_x}"
  end
end

Public Instance Methods

+(obj) click to toggle source
# File lib/terraformer/coordinate.rb, line 192
def + obj
  arithmetic :+, obj
end
-(obj) click to toggle source
# File lib/terraformer/coordinate.rb, line 196
def - obj
  arithmetic :-, obj
end
<=>(other) click to toggle source
# File lib/terraformer/coordinate.rb, line 169
def <=> other
  raise ArgumentError unless Coordinate === other
  dx = x - other.x
  dy = y - other.y
  case
  when dx > dy; 1
  when dx < dy; -1
  else;         0
  end
end
==(other) click to toggle source
# File lib/terraformer/coordinate.rb, line 102
def == other
  case other
  when Array
    @ary == other
  when Coordinate
    @ary == other.ary
  else
    false
  end
end
[](index) click to toggle source
# File lib/terraformer/coordinate.rb, line 98
def [] index
  @ary[index]
end
buffer(radius, resolution = DEFAULT_BUFFER_RESOLUTION) click to toggle source
# File lib/terraformer/coordinate.rb, line 158
def buffer radius, resolution = DEFAULT_BUFFER_RESOLUTION
  center = to_mercator unless mercator?
  coordinates = (1..resolution).map {|step|
    radians = step.to_d * (360.to_d / resolution.to_d) * PI / 180.to_d
    [center.x + radius.to_d * BigMath.cos(radians, PRECISION),
     center.y + radius.to_d * BigMath.sin(radians, PRECISION)]
  }
  coordinates << coordinates[0]
  Polygon.new(coordinates).to_geographic
end
distance_and_bearing_to(obj) click to toggle source
# File lib/terraformer/coordinate.rb, line 231
def distance_and_bearing_to obj
  raise ArgumentError unless Coordinate === obj
  Geodesic.compute_distance_and_bearing y, x, obj.y, obj.x
end
distance_to(obj) click to toggle source
# File lib/terraformer/coordinate.rb, line 236
def distance_to obj
  distance_and_bearing_to(obj)[:distance]
end
dup() click to toggle source
# File lib/terraformer/coordinate.rb, line 68
def dup
  Coordinate.new @ary.dup
end
euclidean_distance_to(obj) click to toggle source
# File lib/terraformer/coordinate.rb, line 207
def euclidean_distance_to obj
  BigMath.sqrt squared_euclidean_distance_to(obj), PRECISION
end
final_bearing_to(obj) click to toggle source
# File lib/terraformer/coordinate.rb, line 244
def final_bearing_to obj
  distance_and_bearing_to(obj)[:bearing][:final]
end
geographic?() click to toggle source
# File lib/terraformer/coordinate.rb, line 150
def geographic?
  crs.nil? or crs == GEOGRAPHIC_CRS
end
haversine_distance_to(other) click to toggle source
# File lib/terraformer/coordinate.rb, line 211
def haversine_distance_to other
  raise ArgumentError unless Coordinate === other

  d_lat = (self.y - other.y).to_rad
  d_lon = (self.x - other.x).to_rad

  lat_r = self.y.to_rad
  other_lat_r = other.y.to_rad

  a = BigMath.sin(d_lat / 2, PRECISION)**2 +
      BigMath.sin(d_lon / 2, PRECISION)**2 *
      BigMath.cos(lat_r, PRECISION) * BigMath.cos(other_lat_r, PRECISION)

  y = BigMath.sqrt a, PRECISION
  x = BigMath.sqrt (1 - a), PRECISION
  c = 2 * BigMath.atan2(y, x, PRECISION)

  c * EARTH_MEAN_RADIUS
end
initial_bearing_to(obj) click to toggle source
# File lib/terraformer/coordinate.rb, line 240
def initial_bearing_to obj
  distance_and_bearing_to(obj)[:bearing][:initial]
end
inspect() click to toggle source
# File lib/terraformer/coordinate.rb, line 113
def inspect
  "#<Terraformer::Coordinate lon=#{lon.to_s 'F'} lat=#{lat.to_s 'F'} #{z if z }>"
end
lat()
Alias for: y
lon()
Alias for: x
mercator?() click to toggle source
# File lib/terraformer/coordinate.rb, line 154
def mercator?
  crs == MERCATOR_CRS
end
squared_euclidean_distance_to(obj) click to toggle source
# File lib/terraformer/coordinate.rb, line 200
def squared_euclidean_distance_to obj
  raise ArgumentError unless Coordinate === obj
  dx = obj.x - x
  dy = obj.y - y
  dx * dx + dy * dy
end
to_geographic() click to toggle source
# File lib/terraformer/coordinate.rb, line 117
def to_geographic
  xerd = (x / EARTH_RADIUS).to_deg
  _x = xerd - (((xerd + 180.0) / 360.0).floor * 360.0)
  _y = (
    (Math::PI / 2).to_d -
    (2 * BigMath.atan(BigMath.exp(-1.0 * y / EARTH_RADIUS, PRECISION), PRECISION))
  ).to_deg
  geog = self.class.new _x.round(PRECISION), _y.round(PRECISION)
  geog.crs = GEOGRAPHIC_CRS
  geog
end
to_json(*args) click to toggle source
# File lib/terraformer/coordinate.rb, line 142
def to_json *args
  @ary.compact.to_json(*args)
end
to_mercator() click to toggle source
# File lib/terraformer/coordinate.rb, line 129
def to_mercator
  _x = x.to_rad * EARTH_RADIUS
  syr = BigMath.sin y.to_rad, PRECISION
  _y = (EARTH_RADIUS / 2.0) * BigMath.log((1.0 + syr) / (1.0 - syr), PRECISION)
  merc = self.class.new _x.round(PRECISION), _y.round(PRECISION)
  merc.crs = MERCATOR_CRS
  merc
end
to_point() click to toggle source
# File lib/terraformer/coordinate.rb, line 146
def to_point
  Point.new self
end
to_s() click to toggle source
# File lib/terraformer/coordinate.rb, line 138
def to_s
  @ary.compact.join ','
end
x() click to toggle source
# File lib/terraformer/coordinate.rb, line 72
def x
  @ary[0]
end
Also aliased as: lon
x=(_x) click to toggle source
# File lib/terraformer/coordinate.rb, line 77
def x= _x
  @ary[0] = Coordinate.big_decimal _x
end
y() click to toggle source
# File lib/terraformer/coordinate.rb, line 81
def y
  @ary[1]
end
Also aliased as: lat
y=(_y) click to toggle source
# File lib/terraformer/coordinate.rb, line 86
def y= _y
  @ary[1] = Coordinate.big_decimal _y
end
z() click to toggle source
# File lib/terraformer/coordinate.rb, line 90
def z
  @ary[2]
end
z=(_z) click to toggle source
# File lib/terraformer/coordinate.rb, line 94
def z= _z
  @ary[2] = Coordinate.big_decimal _z
end

Private Instance Methods

arithmetic(operator, obj) click to toggle source
# File lib/terraformer/coordinate.rb, line 180
def arithmetic operator, obj
  case obj
  when Array
    _x = self.x.__send__ operator, obj[0] if obj[0]
    _y = self.y.__send__ operator, obj[1] if obj[1]
    Coordinate.new((_x || x), (_y || y))
  else
    raise NotImplementedError
  end
end