From: Tom Hughes Date: Sun, 14 Jul 2024 14:40:39 +0000 (+0100) Subject: Merge remote-tracking branch 'upstream/pull/4984' X-Git-Tag: live~818 X-Git-Url: https://git.openstreetmap.org./rails.git/commitdiff_plain/185972855834ecba5eb064582a03d6cd979cde9f?hp=-c Merge remote-tracking branch 'upstream/pull/4984' --- 185972855834ecba5eb064582a03d6cd979cde9f diff --combined app/controllers/geocoder_controller.rb index ca6bab6df,02ebc8a1b..43f276efa --- a/app/controllers/geocoder_controller.rb +++ b/app/controllers/geocoder_controller.rb @@@ -206,13 -206,9 +206,9 @@@ class GeocoderController < ApplicationC if query = params[:query] query.strip! - if latlon = query.match(/^(?[NS])\s*(?\d{1,3}(?:\.\d+)?)°?\W*(?[EW])\s*(?\d{1,3}(?:\.\d+)?)°?$/) || # [NSEW] decimal degrees - query.match(/^(?\d{1,3}(?:\.\d+)?)°?\s*(?[NS])\W*(?\d{1,3}(?:\.\d+)?)°?\s*(?[EW])$/) || # decimal degrees [NSEW] - query.match(/^(?[NS])\s*(?\d{1,3})°?(?:\s*(?\d{1,3}(?:\.\d+)?)['′]?)\W*(?[EW])\s*(?\d{1,3})°?(?:\s*(?\d{1,3}(?:\.\d+)?)['′]?)$/) || # [NSEW] degrees, decimal minutes - query.match(/^(?\d{1,3})°?(?:\s*(?\d{1,3}(?:\.\d+)?)['′]?)\s*(?[NS])\W*(?\d{1,3})°?(?:\s*(?\d{1,3}(?:\.\d+)?)['′]?)\s*(?[EW])$/) || # degrees, decimal minutes [NSEW] - query.match(/^(?[NS])\s*(?\d{1,3})°?\s*(?\d{1,2})['′]?(?:\s*(?\d{1,3}(?:\.\d+)?)["″]?)\W*(?[EW])\s*(?\d{1,3})°?\s*(?\d{1,2})['′]?(?:\s*(?\d{1,3}(?:\.\d+)?)["″]?)$/) || # [NSEW] degrees, minutes, decimal seconds - query.match(/^(?\d{1,3})°?\s*(?\d{1,2})['′]?(?:\s*(?\d{1,3}(?:\.\d+)?)["″]?)\s*(?[NS])\W*(?\d{1,3})°?\s*(?\d{1,2})['′]?(?:\s*(?\d{1,3}(?:\.\d+)?)["″]?)\s*(?[EW])$/) # degrees, minutes, decimal seconds [NSEW] - params.merge!(to_decdeg(latlon.named_captures)).delete(:query) + if latlon = query.match(/^(?[NS])\s*#{dms_regexp('ns')}\W*(?[EW])\s*#{dms_regexp('ew')}$/) || + query.match(/^#{dms_regexp('ns')}\s*(?[NS])\W*#{dms_regexp('ew')}\s*(?[EW])$/) + params.merge!(to_decdeg(latlon.named_captures.compact)).delete(:query) elsif latlon = query.match(%r{^(?[+-]?\d+(?:\.\d+)?)(?:\s+|\s*[,/]\s*)(?[+-]?\d+(?:\.\d+)?)$}) params.merge!(:lat => latlon["lat"], :lon => latlon["lon"]).delete(:query) @@@ -224,13 -220,21 +220,21 @@@ 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")) diff --combined test/controllers/geocoder_controller_test.rb index 5b7605321,5ea02f76d..ac9905589 --- a/test/controllers/geocoder_controller_test.rb +++ b/test/controllers/geocoder_controller_test.rb @@@ -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 @@@ -418,8 -429,8 +429,8 @@@ 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 @@@ -429,8 -440,8 +440,8 @@@ 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