]> git.openstreetmap.org Git - rails.git/blobdiff - app/controllers/geocoder_controller.rb
Merge remote-tracking branch 'upstream/pull/5398'
[rails.git] / app / controllers / geocoder_controller.rb
index 0dabc5a62de2225b7c95441f1a6e35f09456bcb4..43f276efa020a35cfdbb1719155c4a3f5e61c1fe 100644 (file)
@@ -206,13 +206,9 @@ class GeocoderController < ApplicationController
     if query = params[:query]
       query.strip!
 
-      if latlon = query.match(/^(?<ns>[NS])\s*(?<nsd>\d{1,3}(?:\.\d+)?)°?\W*(?<ew>[EW])\s*(?<ewd>\d{1,3}(?:\.\d+)?)°?$/) ||                                                                                                     # [NSEW] decimal degrees
-                  query.match(/^(?<nsd>\d{1,3}(?:\.\d+)?)°?\s*(?<ns>[NS])\W*(?<ewd>\d{1,3}(?:\.\d+)?)°?\s*(?<ew>[EW])$/) ||                                                                                                     # decimal degrees [NSEW]
-                  query.match(/^(?<ns>[NS])\s*(?<nsd>\d{1,3})°?(?:\s*(?<nsm>\d{1,3}(?:\.\d+)?)['′]?)\W*(?<ew>[EW])\s*(?<ewd>\d{1,3})°?(?:\s*(?<ewm>\d{1,3}(?:\.\d+)?)['′]?)$/) ||                                               # [NSEW] degrees, decimal minutes
-                  query.match(/^(?<nsd>\d{1,3})°?(?:\s*(?<nsm>\d{1,3}(?:\.\d+)?)['′]?)\s*(?<ns>[NS])\W*(?<ewd>\d{1,3})°?(?:\s*(?<ewm>\d{1,3}(?:\.\d+)?)['′]?)\s*(?<ew>[EW])$/) ||                                               # degrees, decimal minutes [NSEW]
-                  query.match(/^(?<ns>[NS])\s*(?<nsd>\d{1,3})°?\s*(?<nsm>\d{1,2})['′]?(?:\s*(?<nss>\d{1,3}(?:\.\d+)?)["″]?)\W*(?<ew>[EW])\s*(?<ewd>\d{1,3})°?\s*(?<ewm>\d{1,2})['′]?(?:\s*(?<ews>\d{1,3}(?:\.\d+)?)["″]?)$/) || # [NSEW] degrees, minutes, decimal seconds
-                  query.match(/^(?<nsd>\d{1,3})°?\s*(?<nsm>\d{1,2})['′]?(?:\s*(?<nss>\d{1,3}(?:\.\d+)?)["″]?)\s*(?<ns>[NS])\W*(?<ewd>\d{1,3})°?\s*(?<ewm>\d{1,2})['′]?(?:\s*(?<ews>\d{1,3}(?:\.\d+)?)["″]?)\s*(?<ew>[EW])$/)    # degrees, minutes, decimal seconds [NSEW]
-        params.merge!(to_decdeg(latlon.named_captures)).delete(:query)
+      if latlon = query.match(/^(?<ns>[NS])\s*#{dms_regexp('ns')}\W*(?<ew>[EW])\s*#{dms_regexp('ew')}$/) ||
+                  query.match(/^#{dms_regexp('ns')}\s*(?<ns>[NS])\W*#{dms_regexp('ew')}\s*(?<ew>[EW])$/)
+        params.merge!(to_decdeg(latlon.named_captures.compact)).delete(:query)
 
       elsif latlon = query.match(%r{^(?<lat>[+-]?\d+(?:\.\d+)?)(?:\s+|\s*[,/]\s*)(?<lon>[+-]?\d+(?:\.\d+)?)$})
         params.merge!(:lat => latlon["lat"], :lon => latlon["lon"]).delete(:query)
@@ -224,20 +220,28 @@ class GeocoderController < ApplicationController
     params.permit(:query, :lat, :lon, :latlon_digits, :zoom, :minlat, :minlon, :maxlat, :maxlon)
   end
 
+  def dms_regexp(name_prefix)
+    /
+      (?: (?<#{name_prefix}d>\d{1,3}(?:\.\d+)?)°? ) |
+      (?: (?<#{name_prefix}d>\d{1,3})°?\s*(?<#{name_prefix}m>\d{1,2}(?:\.\d+)?)['′]? ) |
+      (?: (?<#{name_prefix}d>\d{1,3})°?\s*(?<#{name_prefix}m>\d{1,2})['′]?\s*(?<#{name_prefix}s>\d{1,2}(?:\.\d+)?)["″]? )
+    /x
+  end
+
   def to_decdeg(captures)
-    ns = captures.fetch("ns").casecmp("s").zero? ? -1 : 1
-    nsd = captures.fetch("nsd", "0").to_f
-    nsm = captures.fetch("nsm", "0").to_f
-    nss = captures.fetch("nss", "0").to_f
+    ns = captures.fetch("ns").casecmp?("s") ? -1 : 1
+    nsd = BigDecimal(captures.fetch("nsd", "0"))
+    nsm = BigDecimal(captures.fetch("nsm", "0"))
+    nss = BigDecimal(captures.fetch("nss", "0"))
 
-    ew = captures.fetch("ew").casecmp("w").zero? ? -1 : 1
-    ewd = captures.fetch("ewd", "0").to_f
-    ewm = captures.fetch("ewm", "0").to_f
-    ews = captures.fetch("ews", "0").to_f
+    ew = captures.fetch("ew").casecmp?("w") ? -1 : 1
+    ewd = BigDecimal(captures.fetch("ewd", "0"))
+    ewm = BigDecimal(captures.fetch("ewm", "0"))
+    ews = BigDecimal(captures.fetch("ews", "0"))
 
     lat = ns * (nsd + (nsm / 60) + (nss / 3600))
     lon = ew * (ewd + (ewm / 60) + (ews / 3600))
 
-    { :lat => lat, :lon => lon }
+    { :lat => lat.round(6).to_s("F"), :lon => lon.round(6).to_s("F") }
   end
 end