Class: GeoUtm::UTM

Inherits:
Object
  • Object
show all
Defined in:
lib/geoutm/utm.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(zone, e, n, ellipsoid = Ellipsoid::WGS84) ⇒ UTM

Creates a new UTM coorrdinate

Parameters:

  • The (String)

    UTM zone to use, eg. `32H`

  • The (Float)

    easting component of the coordinate

  • The (Float)

    northing component of the coordinate

  • The (String, Symbol, Ellipsoid)

    ellipsoid to use


22
23
24
# File 'lib/geoutm/utm.rb', line 22

def initialize(zone, e, n, ellipsoid = Ellipsoid::WGS84)
  @n, @e, @zone, @ellipsoid = n, e, zone, Ellipsoid::clean_parameter(ellipsoid)
end

Instance Attribute Details

#eObject (readonly)

Easting


12
13
14
# File 'lib/geoutm/utm.rb', line 12

def e
  @e
end

#ellipsoidObject (readonly)

Returns the value of attribute ellipsoid


14
15
16
# File 'lib/geoutm/utm.rb', line 14

def ellipsoid
  @ellipsoid
end

#nObject (readonly)

Northing


10
11
12
# File 'lib/geoutm/utm.rb', line 10

def n
  @n
end

#zoneObject (readonly)

Returns the value of attribute zone


13
14
15
# File 'lib/geoutm/utm.rb', line 13

def zone
  @zone
end

Class Method Details

.latlon_to_utm(latlon, options = {}) ⇒ Object

:nodoc:


27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/geoutm/utm.rb', line 27

def UTM.latlon_to_utm(latlon, options = {})
      ellipsoid = (options[:ellipsoid] && Ellipsoid::clean_parameter(options[:ellipsoid])) || Ellipsoid::WGS84

  lat_rad = Math::PI / 180.0 * latlon.lat
  k0 = 0.9996 # scale
  zone = options[:zone] || UTMZones::calc_utm_zone(latlon.lat, latlon.lon)

  eccentricity = ellipsoid.eccentricity
  eccentprime = ellipsoid.eccentricity/(1.0-eccentricity)

  n = ellipsoid.radius / Math::sqrt(1 - eccentricity * Math::sin(lat_rad)*Math::sin(lat_rad))
  t = Math::tan(lat_rad) * Math::tan(lat_rad)
  c = eccentprime * Math::cos(lat_rad)*Math::cos(lat_rad)
  a = Math::cos(lat_rad) * Math::PI / 180.0 * (UTMZones::clean_longitude(latlon.lon) - UTMZones::lon_origin(zone))
  m = ellipsoid.radius * (
      (1 - eccentricity/4 - 3 * eccentricity * eccentricity/64 - 
        5 * eccentricity * eccentricity * eccentricity/256) * lat_rad - 
      (3 * eccentricity/8 + 3 * eccentricity * eccentricity/32 + 
        45 * eccentricity * eccentricity * eccentricity/1024) * Math::sin(2 * lat_rad) + 
      (15 * eccentricity * eccentricity/256 +
        45 * eccentricity * eccentricity * eccentricity/1024) * Math::sin(4 * lat_rad) - 
      (35 * eccentricity * eccentricity * eccentricity/3072) * Math::sin(6 * lat_rad)
    )
  utm_easting = k0*n*(a+(1-t+c)*a*a*a/6 + (5-18*t+t*t+72*c-58*eccentprime)*a*a*a*a*a/120) + 500000.0
  utm_northing = k0 * ( m + n*Math::tan(lat_rad) * ( a*a/2+(5-t+9*c+4*c*c)*a*a*a*a/24 + 
                               (61-58*t+t*t+600*c-330*eccentprime) * a*a*a*a*a*a/720))
  utm_northing += 10000000.0 if latlon.lat < 0
  UTM.new zone, utm_easting, utm_northing, ellipsoid
end

Instance Method Details

#distance_to(other) ⇒ Float

The euclidian distance between two points (ie. `sqrt(dx * dx + dy * dy)`)

Parameters:

  • The (LatLon, UTM)

    other coordinate. Should be in close proximity to avoid large errors

Returns:

  • (Float)

114
115
116
117
118
119
120
121
122
# File 'lib/geoutm/utm.rb', line 114

def distance_to(other)
  if other.class == LatLon
    other = UTM::latlon_to_utm other, :ellipsoid => @ellipsoid, :zone => @zone
  end
  unless other.zone == @zone
    raise GeoUtmException, 'Cannot calc distance for points in different zones - convert first'
  end
  Math::sqrt((@n - other.n) ** 2.0 + (@e - other.e) ** 2.0) 
end

#to_lat_lonLatLon

Converts this position into the latitude/longitude coordinate system

Returns:


76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/geoutm/utm.rb', line 76

def to_lat_lon
  k0 = 0.9996
  x  = @e - 500000 # Remove Longitude offset
  y  = @n

  # Set hemisphere (1=Northern, 0=Southern)
  y    -= 10000000.0 unless UTMZones::northern_hemisphere? @zone

  ecc = @ellipsoid.eccentricity
  eccPrimeSquared = (ecc)/(1-ecc)
  m  = y / k0
  mu = m / (@ellipsoid.radius * (1 - ecc / 4 - 3 * ecc ** 2 / 64 - 5 * ecc ** 3 / 256))
  e1 = (1 - Math::sqrt(1 - ecc)) / (1 + Math::sqrt(1 - ecc))
  phi1rad = mu +
    (3 * e1 / 2 - 27 * e1 ** 3 / 32) * Math::sin(2 * mu) +
    (21 * e1 ** 2 / 16 - 55 * e1 ** 4 / 32) * Math::sin(4 * mu) +
    (151 * e1 ** 3 / 96) * Math::sin(6 * mu)
  n1 = @ellipsoid.radius / Math::sqrt(1 - ecc * Math::sin(phi1rad) ** 2)
  t1 = Math::tan(phi1rad) ** 2
  c1 = ecc * Math::cos(phi1rad)**2
  r1 = @ellipsoid.radius * (1 - ecc) / ((1 - ecc * Math::sin(phi1rad) ** 2) ** 1.5)
  d = x / (n1 * k0)
  latitude_rad = phi1rad-
    (n1 * Math::tan(phi1rad) / r1) * (d * d / 2 - 
                                (5 + 3 * t1 + 10 * c1 - 4 * c1 * c1 - 9 * eccPrimeSquared) * d ** 4 / 24 +
                                (61 + 90 * t1 + 298 * c1 + 45 * t1 * t1 - 
                                 252 * eccPrimeSquared - 3 * c1 * c1) * d ** 6 / 720)
  latitude_deg = latitude_rad * 180.0 / Math::PI
  lon_tmp = (d - (1 + 2 * t1 + c1) * d ** 3 / 6 +
               (5 - 2 * c1 + 28 * t1 - 3 * c1 * c1 + 8 * eccPrimeSquared +
                24 * t1 * t1) * d ** 5 / 120) / Math::cos(phi1rad)
  longitude_deg = UTMZones::lon_origin(@zone) + lon_tmp * 180.0 / Math::PI
  LatLon.new latitude_deg, longitude_deg
end

#to_sObject


70
71
72
# File 'lib/geoutm/utm.rb', line 70

def to_s
  '%s %.2f %.2f' % [zone, e, n]
end

#zone_letterObject Also known as: zone_band

Returns the band letter portion of the zone, eg `H` for `32H`


58
59
60
# File 'lib/geoutm/utm.rb', line 58

def zone_letter
    UTMZones::split_zone(@zone).last
end

#zone_numberObject

Returns the number portion of the zone, eg `32` for `32H`


65
66
67
# File 'lib/geoutm/utm.rb', line 65

def zone_number
    UTMZones::split_zone(@zone).first.to_i
end