Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Zolotarev <alex@maps.me>2016-03-15 20:39:41 +0300
committerSergey Yershov <yershov@corp.mail.ru>2016-03-23 16:57:05 +0300
commitba208ffb6cc5e9ab60310e22b4487c58635b39e8 (patch)
tree3cca4a06ae72af58748670b16152e5e084b89840 /platform
parent226b50494a06297c205fb979a83a9fcfbfab8f61 (diff)
MeasurementUtils::OSMDistanceToMeters validation.
Diffstat (limited to 'platform')
-rw-r--r--platform/measurement_utils.cpp98
-rw-r--r--platform/measurement_utils.hpp11
-rw-r--r--platform/platform_tests/measurement_tests.cpp55
3 files changed, 163 insertions, 1 deletions
diff --git a/platform/measurement_utils.cpp b/platform/measurement_utils.cpp
index b29d17f03d..5ba0a7cf5d 100644
--- a/platform/measurement_utils.cpp
+++ b/platform/measurement_utils.cpp
@@ -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
diff --git a/platform/measurement_utils.hpp b/platform/measurement_utils.hpp
index 0fe8c4c257..1da8145ec7 100644
--- a/platform/measurement_utils.hpp
+++ b/platform/measurement_utils.hpp
@@ -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);
+
}
diff --git a/platform/platform_tests/measurement_tests.cpp b/platform/platform_tests/measurement_tests.cpp
index ebca1c103a..6129601300 100644
--- a/platform/platform_tests/measurement_tests.cpp
+++ b/platform/platform_tests/measurement_tests.cpp
@@ -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", ());
+}