forked from organicmaps/organicmaps
[search] Fixed coordinates input parsing.
This commit is contained in:
parent
eef1d9483d
commit
4e735a3f02
4 changed files with 58 additions and 21 deletions
|
@ -1,13 +1,14 @@
|
|||
#include "latlon_match.hpp"
|
||||
|
||||
#include "../indexer/mercator.hpp"
|
||||
|
||||
#include "../base/macros.hpp"
|
||||
|
||||
#include "../std/array.hpp"
|
||||
#include "../std/cmath.hpp"
|
||||
#include "../std/cstdlib.hpp"
|
||||
#include "../std/cstring.hpp"
|
||||
#include "../std/algorithm.hpp"
|
||||
#include "../std/utility.hpp"
|
||||
|
||||
|
||||
namespace search
|
||||
{
|
||||
|
@ -161,10 +162,10 @@ bool MatchLatLonDegree(string const & query, double & lat, double & lon)
|
|||
double const x = strtod(s, &s2);
|
||||
if (s == s2)
|
||||
{
|
||||
// Invalid token
|
||||
// invalid token
|
||||
if (s == s1)
|
||||
{
|
||||
// Return error if there are no any delimiters
|
||||
// Return error if there are no any delimiters.
|
||||
return false;
|
||||
}
|
||||
else
|
||||
|
@ -177,26 +178,36 @@ bool MatchLatLonDegree(string const & query, double & lat, double & lon)
|
|||
s = s2;
|
||||
SkipSpaces(s);
|
||||
|
||||
int const i = GetDMSIndex(s);
|
||||
switch (i)
|
||||
int i = GetDMSIndex(s);
|
||||
if (i == -1)
|
||||
{
|
||||
case -1: // expect valid control symbol
|
||||
return false;
|
||||
if (v[base].second && v[base + 1].second && !v[base + 2].second)
|
||||
{
|
||||
// assume seconds if degrees and minutes are present
|
||||
i = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
// assume degrees by default
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
case 0: // degree
|
||||
if (i == 0) // degrees
|
||||
{
|
||||
if (v[base].second)
|
||||
{
|
||||
if (base == 0)
|
||||
base += 3;
|
||||
else
|
||||
{
|
||||
// repeated value
|
||||
// too many degree values
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default: // minutes or seconds
|
||||
}
|
||||
else // minutes or seconds
|
||||
{
|
||||
if (x < 0.0 || v[base + i].second || !v[base].second)
|
||||
return false;
|
||||
}
|
||||
|
@ -230,10 +241,18 @@ bool MatchLatLonDegree(string const & query, double & lat, double & lon)
|
|||
if (arrPos[1]) lat = -lat;
|
||||
if (arrPos[3]) lon = -lon;
|
||||
|
||||
if (lon > 180.0) lon -= 360.0;
|
||||
if (lon < -180.0) lon += 360.0;
|
||||
// Valid input ranges for longitude are: [0, 360] or [-180, 180].
|
||||
// We do normilize it to [-180, 180].
|
||||
if (lon > 180.0)
|
||||
{
|
||||
if (lon > 360.0)
|
||||
return false;
|
||||
lon -= 360.0;
|
||||
}
|
||||
else if (lon < -180.0)
|
||||
return false;
|
||||
|
||||
return MercatorBounds::ValidLat(lat) && MercatorBounds::ValidLon(lon);
|
||||
return (fabs(lat) <= 90.0);
|
||||
}
|
||||
|
||||
} // search
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
#pragma once
|
||||
#include "../base/base.hpp"
|
||||
#include "../std/string.hpp"
|
||||
|
||||
|
||||
namespace search
|
||||
{
|
||||
|
||||
// Check if query can be represented as '(lat, lon)'.
|
||||
/// Check if query can be represented as '(lat, lon)'.
|
||||
/// @deprecated Use MatchLatLonDegree instead.
|
||||
bool MatchLatLon(string const & query, double & lat, double & lon,
|
||||
double & precisionLat, double & precisionLon);
|
||||
|
||||
/// Parse input query for most input coordinates cases.
|
||||
bool MatchLatLonDegree(string const & query, double & lat, double & lon);
|
||||
|
||||
} // namespace search
|
||||
|
|
|
@ -321,9 +321,8 @@ void Query::SetQuery(string const & query)
|
|||
|
||||
void Query::SearchCoordinates(string const & query, Results & res) const
|
||||
{
|
||||
double lat, lon, latPrec, lonPrec;
|
||||
if (MatchLatLon(query, lat, lon, latPrec, lonPrec) ||
|
||||
MatchLatLonDegree(query, lat, lon))
|
||||
double lat, lon;
|
||||
if (MatchLatLonDegree(query, lat, lon))
|
||||
{
|
||||
//double const precision = 5.0 * max(0.0001, min(latPrec, lonPrec)); // Min 55 meters
|
||||
res.AddResult(MakeResult(impl::PreResult2(GetViewport(), m_position, lat, lon)));
|
||||
|
|
|
@ -18,6 +18,12 @@ pair<pair<double, double>, pair<double, double> > TestLatLonMatchSuccessful(stri
|
|||
double precLat = -3503;
|
||||
double precLon = -3504;
|
||||
TEST(search::MatchLatLon(s, lat, lon, precLat, precLon), (s, lat, lon, precLat, precLon));
|
||||
|
||||
double lat1, lon1;
|
||||
TEST(search::MatchLatLonDegree(s, lat1, lon1), (s));
|
||||
TEST_ALMOST_EQUAL(lat, lat1, ());
|
||||
TEST_ALMOST_EQUAL(lon, lon1, ());
|
||||
|
||||
return make_pair(make_pair(lat, lon), make_pair(precLat, precLon));
|
||||
}
|
||||
|
||||
|
@ -27,11 +33,14 @@ void TestLatLonFailed(string const & s)
|
|||
double lon = -3502;
|
||||
double latPrec = -3503;
|
||||
double lonPrec = -3504;
|
||||
|
||||
TEST(!search::MatchLatLon(s, lat, lon, latPrec, lonPrec), (s, lat, lon, latPrec, lonPrec));
|
||||
TEST_EQUAL(lat, -3501, ());
|
||||
TEST_EQUAL(lon, -3502, ());
|
||||
TEST_EQUAL(latPrec, -3503, ());
|
||||
TEST_EQUAL(lonPrec, -3504, ());
|
||||
|
||||
TEST(!search::MatchLatLonDegree(s, lat, lon), (s));
|
||||
}
|
||||
|
||||
} // unnamed namespace
|
||||
|
@ -124,4 +133,12 @@ UNIT_TEST(LatLon_Degree_Match)
|
|||
|
||||
TEST(!MatchLatLonDegree("55°45′20.9916″W 37°37′3.6228″E", lat, lon), ());
|
||||
TEST(!MatchLatLonDegree("N55°45′20.9916″ S37°37′3.6228″", lat, lon), ());
|
||||
|
||||
TEST(MatchLatLonDegree("54° 25' 0N 1° 53' 46W", lat, lon), ());
|
||||
TEST_ALMOST_EQUAL(lat, 54.41666666666667, ());
|
||||
TEST_ALMOST_EQUAL(lon, -1.89611111111111, ());
|
||||
|
||||
TEST(MatchLatLonDegree("47.33471°N 8.53112°E", lat, lon), ());
|
||||
TEST_ALMOST_EQUAL(lat, 47.33471, ());
|
||||
TEST_ALMOST_EQUAL(lon, 8.53112, ());
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue