forked from organicmaps/organicmaps
MeasurementUtils::OSMDistanceToMeters validation.
This commit is contained in:
parent
226b50494a
commit
ba208ffb6c
3 changed files with 163 additions and 1 deletions
|
@ -3,9 +3,12 @@
|
|||
|
||||
#include "geometry/mercator.hpp"
|
||||
|
||||
#include "base/string_utils.hpp"
|
||||
#include "base/macros.hpp"
|
||||
#include "base/math.hpp"
|
||||
#include "base/stl_add.hpp"
|
||||
#include "base/string_utils.hpp"
|
||||
|
||||
#include "std/cstring.hpp"
|
||||
#include "std/iomanip.hpp"
|
||||
#include "std/sstream.hpp"
|
||||
|
||||
|
@ -189,4 +192,97 @@ string FormatSpeed(double metersPerSecond)
|
|||
return res;
|
||||
}
|
||||
|
||||
bool OSMDistanceToMeters(string const & osmRawValue, double & outMeters)
|
||||
{
|
||||
char * stop;
|
||||
char const * s = osmRawValue.c_str();
|
||||
outMeters = strtod(s, &stop);
|
||||
|
||||
// Not a number, was not parsed at all.
|
||||
if (s == stop)
|
||||
return false;
|
||||
|
||||
if (!isfinite(outMeters))
|
||||
return false;
|
||||
|
||||
switch (*stop)
|
||||
{
|
||||
// Default units - meters.
|
||||
case 0: return true;
|
||||
|
||||
// Feet and probably inches.
|
||||
case '\'':
|
||||
{
|
||||
outMeters = FeetToMeters(outMeters);
|
||||
s = stop + 1;
|
||||
double const inches = strtod(s, &stop);
|
||||
if (s != stop && *stop == '"' && isfinite(inches))
|
||||
outMeters += InchesToMeters(inches);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
// Inches.
|
||||
case '\"': outMeters = InchesToMeters(outMeters); return true;
|
||||
|
||||
// It's probably a range. Use maximum value (if possible) for a range.
|
||||
case '-':
|
||||
{
|
||||
s = stop + 1;
|
||||
double const newValue = strtod(s, &stop);
|
||||
if (s != stop && isfinite(newValue))
|
||||
outMeters = newValue;
|
||||
}
|
||||
break;
|
||||
|
||||
// It's probably a list. Use maximum value (if possible) for a list.
|
||||
case ';':
|
||||
do
|
||||
{
|
||||
s = stop + 1;
|
||||
double const newValue = strtod(s, &stop);
|
||||
if (s == stop)
|
||||
break;
|
||||
if (isfinite(newValue))
|
||||
outMeters = newValue;
|
||||
} while (*stop && *stop == ';');
|
||||
break;
|
||||
}
|
||||
|
||||
while (*stop && isspace(*stop))
|
||||
++stop;
|
||||
|
||||
// Default units - meters.
|
||||
if (*stop == 0)
|
||||
return true;
|
||||
|
||||
if (strstr(stop, "nmi") == stop)
|
||||
outMeters = NauticalMilesToMeters(outMeters);
|
||||
else if (strstr(stop, "mi") == stop)
|
||||
outMeters = MilesToMeters(outMeters);
|
||||
else if (strstr(stop, "ft") == stop)
|
||||
outMeters = FeetToMeters(outMeters);
|
||||
else if (strstr(stop, "feet") == stop)
|
||||
outMeters = FeetToMeters(outMeters);
|
||||
else if (strstr(stop, "km") == stop)
|
||||
outMeters = outMeters * 1000;
|
||||
|
||||
// Count all other cases as meters.
|
||||
return true;
|
||||
}
|
||||
|
||||
string OSMDistanceToMetersString(string const & osmRawValue,
|
||||
bool supportZeroAndNegativeValues,
|
||||
int digitsAfterComma)
|
||||
{
|
||||
double meters;
|
||||
if (OSMDistanceToMeters(osmRawValue, meters))
|
||||
{
|
||||
if (!supportZeroAndNegativeValues && meters <= 0)
|
||||
return {};
|
||||
return strings::to_string_dac(meters, digitsAfterComma);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
} // namespace MeasurementUtils
|
||||
|
|
|
@ -12,6 +12,8 @@ inline double MilesToMeters(double mi) { return mi * 1609.344; }
|
|||
inline double MetersToFeet(double m) { return m * 3.2808399; }
|
||||
inline double FeetToMeters(double ft) { return ft * 0.3048; }
|
||||
inline double FeetToMiles(double ft) { return ft * 5280; }
|
||||
inline double InchesToMeters(double in) { return in / 39.370; }
|
||||
inline double NauticalMilesToMeters(double nmi) { return nmi * 1852; }
|
||||
|
||||
/// Takes into an account user settings [metric, imperial]
|
||||
/// @param[in] m meters
|
||||
|
@ -37,4 +39,13 @@ void FormatLatLon(double lat, double lon, string & latText, string & lonText, in
|
|||
string FormatMercator(m2::PointD const & mercator, int dac = 6);
|
||||
void FormatMercator(m2::PointD const & mercator, string & lat, string & lon, int dac = 6);
|
||||
|
||||
/// Converts OSM distance (height, ele etc.) to meters.
|
||||
/// @returns false if fails.
|
||||
bool OSMDistanceToMeters(string const & osmRawValue, double & outMeters);
|
||||
/// Converts OSM distance (height, ele etc.) to meters string.
|
||||
/// @returns empty string on failure.
|
||||
string OSMDistanceToMetersString(string const & osmRawValue,
|
||||
bool supportZeroAndNegativeValues = true,
|
||||
int digitsAfterComma = 2);
|
||||
|
||||
}
|
||||
|
|
|
@ -101,3 +101,58 @@ UNIT_TEST(FormatSpeed)
|
|||
TEST_EQUAL(FormatSpeed(10), "36km/h", ());
|
||||
TEST_EQUAL(FormatSpeed(1), "3.6km/h", ());
|
||||
}
|
||||
|
||||
UNIT_TEST(OSMDistanceToMetersString)
|
||||
{
|
||||
TEST_EQUAL(OSMDistanceToMetersString(""), "", ());
|
||||
TEST_EQUAL(OSMDistanceToMetersString("INF"), "", ());
|
||||
TEST_EQUAL(OSMDistanceToMetersString("NAN"), "", ());
|
||||
TEST_EQUAL(OSMDistanceToMetersString("not a number"), "", ());
|
||||
TEST_EQUAL(OSMDistanceToMetersString("10й"), "10", ());
|
||||
TEST_EQUAL(OSMDistanceToMetersString("0"), "0", ());
|
||||
TEST_EQUAL(OSMDistanceToMetersString("0.0"), "0", ());
|
||||
TEST_EQUAL(OSMDistanceToMetersString("0.0000000"), "0", ());
|
||||
TEST_EQUAL(OSMDistanceToMetersString("22.5"), "22.5", ());
|
||||
TEST_EQUAL(OSMDistanceToMetersString("+21.5"), "21.5", ());
|
||||
TEST_EQUAL(OSMDistanceToMetersString("1e+2"), "100", ());
|
||||
TEST_EQUAL(OSMDistanceToMetersString("5 метров"), "5", ());
|
||||
TEST_EQUAL(OSMDistanceToMetersString(" 4.4 "), "4.4", ());
|
||||
TEST_EQUAL(OSMDistanceToMetersString("8-15"), "15", ());
|
||||
TEST_EQUAL(OSMDistanceToMetersString("8-15 ft"), "4.57", ());
|
||||
TEST_EQUAL(OSMDistanceToMetersString("8-й километр"), "8", ());
|
||||
TEST_EQUAL(OSMDistanceToMetersString("8;9;10"), "10", ());
|
||||
TEST_EQUAL(OSMDistanceToMetersString("8;9;10 meters"), "10", ());
|
||||
TEST_EQUAL(OSMDistanceToMetersString("8;9;10 km"), "10000", ());
|
||||
TEST_EQUAL(OSMDistanceToMetersString("10;20!111"), "20", ());
|
||||
TEST_EQUAL(OSMDistanceToMetersString("10;20\""), "20", ());
|
||||
TEST_EQUAL(OSMDistanceToMetersString("-100.3"), "-100.3", ());
|
||||
TEST_EQUAL(OSMDistanceToMetersString("99.0000000"), "99", ());
|
||||
TEST_EQUAL(OSMDistanceToMetersString("8900.000023"), "8900", ());
|
||||
TEST_EQUAL(OSMDistanceToMetersString("-300.9999"), "-301", ());
|
||||
TEST_EQUAL(OSMDistanceToMetersString("-300.9"), "-300.9", ());
|
||||
TEST_EQUAL(OSMDistanceToMetersString("15 m"), "15", ());
|
||||
TEST_EQUAL(OSMDistanceToMetersString("15.9 m"), "15.9", ());
|
||||
TEST_EQUAL(OSMDistanceToMetersString("15.9m"), "15.9", ());
|
||||
TEST_EQUAL(OSMDistanceToMetersString("3000 ft"), "914.4", ());
|
||||
TEST_EQUAL(OSMDistanceToMetersString("3000ft"), "914.4", ());
|
||||
TEST_EQUAL(OSMDistanceToMetersString("100 feet"), "30.48", ());
|
||||
TEST_EQUAL(OSMDistanceToMetersString("100feet"), "30.48", ());
|
||||
TEST_EQUAL(OSMDistanceToMetersString("3 nmi"), "5556", ());
|
||||
TEST_EQUAL(OSMDistanceToMetersString("3 mi"), "4828.03", ());
|
||||
TEST_EQUAL(OSMDistanceToMetersString("3.3 km"), "3300", ());
|
||||
TEST_EQUAL(OSMDistanceToMetersString("105'"), "32", ());
|
||||
TEST_EQUAL(OSMDistanceToMetersString("11'"), "3.35", ());
|
||||
TEST_EQUAL(OSMDistanceToMetersString("11 3\""), "11", ());
|
||||
TEST_EQUAL(OSMDistanceToMetersString("11 3'"), "11", ());
|
||||
TEST_EQUAL(OSMDistanceToMetersString("11\"'"), "0.28", ());
|
||||
TEST_EQUAL(OSMDistanceToMetersString("11'\""), "3.35", ());
|
||||
TEST_EQUAL(OSMDistanceToMetersString("11'4\""), "3.45", ());
|
||||
TEST_EQUAL(OSMDistanceToMetersString("11\""), "0.28", ());
|
||||
TEST_EQUAL(OSMDistanceToMetersString("100 \""), "100", ());
|
||||
|
||||
TEST_EQUAL(OSMDistanceToMetersString("0", false), "", ());
|
||||
TEST_EQUAL(OSMDistanceToMetersString("-15", false), "", ());
|
||||
TEST_EQUAL(OSMDistanceToMetersString("15.12345", false, 1), "15.1", ());
|
||||
TEST_EQUAL(OSMDistanceToMetersString("15.123", false, 4), "15.123", ());
|
||||
TEST_EQUAL(OSMDistanceToMetersString("15.654321", true, 1), "15.7", ());
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue