Class: AIXM::XY

Inherits:
Object show all
Includes:
Concerns::HashEquality
Defined in:
lib/aixm/xy.rb

Overview

Geographical coordinates

Warning!

Coordinate tuples can be noted in mathematical order (XY = longitude first, latitude second) or in (more common) geographical order (YX = latitude first, longitude second). However you sort the attributes, make sure not to flip them by accident.

See en.wikipedia.org/wiki/Geographic_coordinate_system

Recognized notations:

  • DD - examples: 12.12345678 (north or east), -12.12345678 (south or west)

  • DMS - examples: 11°22'33.44“N, 1112233.44W,

Constants:

  • AIXM::MIN - characters recognized as DMS minute symbols

  • AIXM::SEC - characters recognized as DMS second symbols

  • AIXM::DMS_RE - regular expression to match DMS coordinate notations

Examples:

All of the below are equivalent

AIXM.xy(lat: 11.375955555555556, long: -111.37595555555555)
AIXM.xy(lat: %q(11°22'33.44"), long: %q(-111°22'33.44"))
AIXM.xy(lat: %q(11°22'33.44N"), long: %q(111°22'33.44W"))
AIXM.xy(lat: '112233.44N', long: '1112233.44W')

See Also:

Constant Summary collapse

EARTH_RADIUS =
6_371_008.8

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Concerns::HashEquality

#eql?, #hash

Constructor Details

#initialize(lat:, long:) ⇒ XY

See the overview for examples.


37
38
39
# File 'lib/aixm/xy.rb', line 37

def initialize(lat:, long:)
  self.lat, self.long = lat, long
end

Instance Attribute Details

#latString, Float #lat=(value) ⇒ Object

Latitude

Overloads:

  • #latString, Float

    Parameters:

    • schema (Symbol, nil)

      either :aixm or :ofmx or nil

    Returns:

    • (String, Float)
  • #lat=(value) ⇒ Object

    Parameters:

    • value (String, Numeric)

59
60
61
62
63
64
65
# File 'lib/aixm/xy.rb', line 59

def lat(schema=nil)
  case schema
    when :ofmx then ("%011.8f" % @lat.abs.round(8)) + (@lat.negative? ? 'S' : 'N')
    when :aixm then @lat.to_dms(2).gsub(/[^\d.]/, '') + (@lat.negative? ? 'S' : 'N')
    else @lat.round(8)
  end
end

#longString, Float #long=(value) ⇒ Object

Longitude

Overloads:

  • #longString, Float

    Parameters:

    • schema (Symbol, nil)

      either :aixm or :ofmx or nil

    Returns:

    • (String, Float)
  • #long=(value) ⇒ Object

    Parameters:

    • value (String, Numeric)

80
81
82
83
84
85
86
# File 'lib/aixm/xy.rb', line 80

def long(schema=nil)
  case schema
    when :ofmx then ("%012.8f" % @long.abs.round(8)) + (@long.negative? ? 'W' : 'E')
    when :aixm then @long.to_dms(3).gsub(/[^\d.]/, '') + (@long.negative? ? 'W' : 'E')
    else @long.round(8)
  end
end

Instance Method Details

#==(other) ⇒ Object

See Also:

  • Object#==

127
128
129
# File 'lib/aixm/xy.rb', line 127

def ==(other)
  self.class === other && lat == other.lat && long == other.long
end

#distance(other) ⇒ AIXM::D

Distance as calculated by the Haversine formula

Returns:


111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/aixm/xy.rb', line 111

def distance(other)
  if self == other
    AIXM.d(0, :m)
  else
    value = 2 * EARTH_RADIUS * Math.asin(
      Math.sqrt(
        Math.sin((other.lat.to_rad - lat.to_rad) / 2) ** 2 +
          Math.cos(lat.to_rad) * Math.cos(other.lat.to_rad) *
          Math.sin((other.long.to_rad - long.to_rad) / 2) ** 2
      )
    )
    AIXM.d(value.round, :m)
  end
end

#inspectString

Returns:

  • (String)

42
43
44
# File 'lib/aixm/xy.rb', line 42

def inspect
  %Q(#<#{self.class} #{to_s}>)
end

#seconds?Boolean

Whether both longitude and latitude have zero DMS seconds (which may indicate rounded or estimated coordinates).

Returns:

  • (Boolean)

97
98
99
# File 'lib/aixm/xy.rb', line 97

def seconds?
  !(long.to_dms[-6,5].to_f.zero? && lat.to_dms[-6,5].to_f.zero?)
end

#to_pointAIXM::Component::Geometry::Point

Convert to point


104
105
106
# File 'lib/aixm/xy.rb', line 104

def to_point
  AIXM.point(xy: self)
end

#to_sString

Returns human readable representation.

Returns:

  • (String)

    human readable representation


47
48
49
# File 'lib/aixm/xy.rb', line 47

def to_s
  [lat(:ofmx), long(:ofmx)].join(' '.freeze)
end