]> git.openstreetmap.org Git - rails.git/commitdiff
Merge remote-tracking branch 'upstream/pull/4984'
authorTom Hughes <tom@compton.nu>
Sun, 14 Jul 2024 14:40:39 +0000 (15:40 +0100)
committerTom Hughes <tom@compton.nu>
Sun, 14 Jul 2024 14:40:39 +0000 (15:40 +0100)
1  2 
app/controllers/geocoder_controller.rb
test/controllers/geocoder_controller_test.rb

index ca6bab6df88a1e79ed4947391d22864e639c6d80,02ebc8a1bccb565796a62cafb911bbd7bdd17647..43f276efa020a35cfdbb1719155c4a3f5e61c1fe
@@@ -206,13 -206,9 +206,9 @@@ class GeocoderController < ApplicationC
      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)
      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
 +    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
 +    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"))
index 5b76053214b22a8281e13f890790dfb515666606,5ea02f76d2261af73025f00ebaf1426bb630e9e7..ac9905589bd949cf7390ff9cedd140624e92c2dd
@@@ -261,6 -261,17 +261,17 @@@ class GeocoderControllerTest < ActionDi
      end
    end
  
+   #
+   # Test identification of lat/lon pairs with mixed precision
+   def test_identify_latlon_ne_mixed_precision
+     latlon_check "N1 5 E15",    1.083333, 15
+     latlon_check "N1 5 9 E15",  1.085833, 15
+     latlon_check "N1 5 9 E1 5", 1.085833, 1.083333
+     latlon_check "N15 E1 5",    15, 1.083333
+     latlon_check "N15 E1 5 9",  15, 1.085833
+     latlon_check "N1 5 E1 5 9", 1.083333, 1.085833
+   end
    #
    # Test identification of lat/lon pairs with values close to zero
    def test_identify_latlon_close_to_zero
      assert_template :layout => "map"
      assert_equal %w[latlon osm_nominatim_reverse], assigns(:sources).pluck(:name)
      assert_nil @controller.params[:query]
 -    assert_match(/^[+-]?\d+(?:\.\d*)?$/, @controller.params[:lat])
 -    assert_match(/^[+-]?\d+(?:\.\d*)?$/, @controller.params[:lon])
 +    assert_match(/^[+-]?\d+(?:\.\d+)?$/, @controller.params[:lat])
 +    assert_match(/^[+-]?\d+(?:\.\d+)?$/, @controller.params[:lon])
      assert_in_delta lat, @controller.params[:lat].to_f
      assert_in_delta lon, @controller.params[:lon].to_f
  
      assert_template :layout => "xhr"
      assert_equal %w[latlon osm_nominatim_reverse], assigns(:sources).pluck(:name)
      assert_nil @controller.params[:query]
 -    assert_match(/^[+-]?\d+(?:\.\d*)?$/, @controller.params[:lat])
 -    assert_match(/^[+-]?\d+(?:\.\d*)?$/, @controller.params[:lon])
 +    assert_match(/^[+-]?\d+(?:\.\d+)?$/, @controller.params[:lat])
 +    assert_match(/^[+-]?\d+(?:\.\d+)?$/, @controller.params[:lon])
      assert_in_delta lat, @controller.params[:lat].to_f
      assert_in_delta lon, @controller.params[:lon].to_f
    end