From 0b4f6903e5470769fb395fbaa86471e9faaff230 Mon Sep 17 00:00:00 2001 From: Vladimir Byko-Ianko Date: Mon, 16 May 2016 18:26:08 +0300 Subject: [PATCH 1/4] A tool to get some statistics about map features for its altitude. --- .../feature_segments_checker.cpp | 212 ++++++++++++++++++ .../feature_segments_checker.pro | 23 ++ omim.pro | 8 +- 3 files changed, 242 insertions(+), 1 deletion(-) create mode 100644 generator/feature_segments_checker/feature_segments_checker.cpp create mode 100644 generator/feature_segments_checker/feature_segments_checker.pro diff --git a/generator/feature_segments_checker/feature_segments_checker.cpp b/generator/feature_segments_checker/feature_segments_checker.cpp new file mode 100644 index 0000000000..d0dd1f40a0 --- /dev/null +++ b/generator/feature_segments_checker/feature_segments_checker.cpp @@ -0,0 +1,212 @@ +#include "generator/srtm_parser.hpp" + +#include "routing/bicycle_model.hpp" + +#include "coding/file_name_utils.hpp" + +#include "geometry/mercator.hpp" +#include "geometry/point2d.hpp" + +#include "indexer/classificator_loader.hpp" +#include "indexer/feature.hpp" +#include "indexer/feature_processor.hpp" +#include "indexer/map_style_reader.hpp" + +#include "platform/platform.hpp" + +#include "base/logging.hpp" + +#include "3party/gflags/src/gflags/gflags.h" + +#include "std/iostream.hpp" +#include "std/map.hpp" +#include "std/string.hpp" + +DEFINE_string(srtm_path, "", "Path to directory with SRTM files"); +DEFINE_string(mwm_path, "", "Path to an mwm file."); + +namespace +{ +routing::BicycleModel const & GetBicycleModel() +{ + static routing::BicycleModel const instance; + return instance; +} + +template +void IncrementStats(K const & k, map & m) +{ + if (m.find(k) == m.cend()) + m[k] = 0; + m[k] += 1; +} + +template +void PrintCont(Cont const & cont, string const & title, string const & msgText1, string const & msgText2) +{ + cout << endl << title << endl; + for (auto const a : cont) + cout << a.second << msgText1 << a.first << msgText2 << endl; +} + +/// \brief Adds |point| to |uniqueRoadPoints| if there's no a point in |uniqueRoadPoints| +/// in |kErrorMeters| environment of |point|. +/// \note This method does get an exact result. The problem is points are sorted in |uniqueRoadPoints| +/// according to operator<(m2::PointD const &, m2::PointD const &). It's not the same criteria with +/// MercatorBounds::DistanceOnEarth(lowerPnt, point). But according to tests the error is less then 1%, +/// and function implemented below works much faster. +bool IsNewFeatureEnd(m2::PointD const & point, set & uniqueRoadPoints) +{ + double constexpr kErrorMeters = 3.; + auto const lower = uniqueRoadPoints.lower_bound(point); + auto const upper = uniqueRoadPoints.upper_bound(point); + + if (lower == uniqueRoadPoints.cend() || upper == uniqueRoadPoints.cend()) + uniqueRoadPoints.insert(point); + + m2::PointD const lowerPnt = *lower; + m2::PointD const upperPnt = *upper; + + if (MercatorBounds::DistanceOnEarth(lowerPnt, point) <= kErrorMeters + || MercatorBounds::DistanceOnEarth(upperPnt, point) <= kErrorMeters) + { + return false; + } + + uniqueRoadPoints.insert(point); + return true; +} + +class Processor +{ +public: + generator::SrtmTileManager & m_srtmManager; + set m_uniqueRoadPoints; + /// Key is altitude difference for feature in meters. If a feature goes up the key is more then 0. + /// Value is a feature counter. + map m_altitudeDiffs; + /// Key is length of feature in meters. Value is a feature counter. + map m_featureLength; + /// Key is length of feature segment in meters. Value is a segment counter. + map m_segLength; + /// Key is difference between two values: + /// 1. how many meters it's necessary to go up following the feature. If feature wavy + /// calculates only raise meters. + /// 2. the difference in altitude between end and start of features. + /// Value is a segment counter. + map m_featureWave; + /// Feature counter for GetBicycleModel().IsRoad(feature) == true. + uint32_t m_roadCount; + /// Point counter for feature where GetBicycleModel().IsRoad(feature) == true. + uint32_t m_roadPointCount; + /// Feature counter for GetBicycleModel().IsRoad(feature) != true. + uint32_t m_notRoadCount; + + Processor(generator::SrtmTileManager & manager) + : m_srtmManager(manager), m_roadCount(0), m_roadPointCount(0), m_notRoadCount(0) {} + + void operator() (FeatureType const & f, uint32_t const & id) + { + f.ParseBeforeStatistic(); + if (!GetBicycleModel().IsRoad(f)) + { + ++m_notRoadCount; + return; + } + + f.ParseGeometry(FeatureType::BEST_GEOMETRY); + ++m_roadCount; + + size_t const pointCount = f.GetPointsCount(); + m_roadPointCount += pointCount; + + for (int i = 0; i < pointCount; ++i) + { + IsNewFeatureEnd(f.GetPoint(i), m_uniqueRoadPoints); + } + + // Feature length. + size_t featureLengthMeters = 0; + if (pointCount != 0) + featureLengthMeters = MercatorBounds::DistanceOnEarth(f.GetPoint(0), f.GetPoint(pointCount - 1)); + IncrementStats(featureLengthMeters, m_featureLength); + + // Feature segment length. + if (pointCount != 0) + { + for (int i = 0; i < pointCount - 1; ++i) + { + size_t const segmentLengthMeters = MercatorBounds::DistanceOnEarth(f.GetPoint(i), f.GetPoint(i + 1)); + IncrementStats(segmentLengthMeters, m_segLength); + } + } + + // Feature altitude difference. + generator::SrtmTile::THeight startAltitude = 0, endAltitude = 0; + if (pointCount != 0) + { + startAltitude = m_srtmManager.GetHeight(MercatorBounds::ToLatLon(f.GetPoint(0))); + endAltitude = m_srtmManager.GetHeight(MercatorBounds::ToLatLon(f.GetPoint(pointCount - 1))); + } + + int16_t const altitudeDiff = endAltitude - startAltitude; + IncrementStats(altitudeDiff, m_altitudeDiffs); + + // Wave feature factor. Climb minus altitude difference. + int32_t climb = 0; + if (pointCount != 0) + { + for (int i = 0; i < pointCount - 1; ++i) + { + auto const segAltDiff = (m_srtmManager.GetHeight(MercatorBounds::ToLatLon(f.GetPoint(i + 1))) - + m_srtmManager.GetHeight(MercatorBounds::ToLatLon(f.GetPoint(i)))); + if (altitudeDiff >= 0) + { + // If the feature goes up generaly calculates how many meters it's necessary + // to go up following the feature. + if (segAltDiff > 0) + climb += segAltDiff; + } + else + { + // If the feature goes down generaly calculates how many meters it's necessary + // to go down following the feature. + if (segAltDiff < 0) + climb += segAltDiff; + } + } + // Estimates monotony of the feature. If climb == altitudeDiff it's monotonous. + // If not it's wavy. The more abs(climb - altitudeDiff) the more wavy the feature. + int32_t const waveFactor = climb - altitudeDiff; + IncrementStats(waveFactor, m_featureWave); + } + } +}; +} // namespace + +int main(int argc, char ** argv) +{ + google::SetUsageMessage("This tool extracts some staticstics about features and its altetude."); + google::ParseCommandLineFlags(&argc, &argv, true); + + LOG(LINFO, ("srtm_path =", FLAGS_srtm_path)); + LOG(LINFO, ("mwm_path =", FLAGS_mwm_path)); + + classificator::Load(); + generator::SrtmTileManager manager(FLAGS_srtm_path); + + Processor doProcess(manager); + feature::ForEachFromDat(FLAGS_mwm_path, doProcess); + + cout << endl << "doProcess.m_roadCount = " << doProcess.m_roadCount << endl; + cout << "doProcess.m_uniqueRoadPoints.size = " << doProcess.m_uniqueRoadPoints.size() << endl; + cout << "doProcess.m_roadPointCount = " << doProcess.m_roadPointCount << endl; + cout << "doProcess.m_notRoadCount = " << doProcess.m_notRoadCount << endl; + + PrintCont(doProcess.m_altitudeDiffs, "Altitude difference between start and end of features.", + " feature(s) with altitude difference ", " meter(s)"); + PrintCont(doProcess.m_featureLength, "Feature length.", " feature(s) with length ", " meter(s)"); + PrintCont(doProcess.m_segLength, "Feature segment length.", " segment(s) with length ", " meter(s)"); + PrintCont(doProcess.m_featureWave, "Wave factor", " features(s) with wave factor ", ""); + return 0; +} diff --git a/generator/feature_segments_checker/feature_segments_checker.pro b/generator/feature_segments_checker/feature_segments_checker.pro new file mode 100644 index 0000000000..be269b569b --- /dev/null +++ b/generator/feature_segments_checker/feature_segments_checker.pro @@ -0,0 +1,23 @@ +# Feature segments checker tool. +# Checks for different properties of feature in mwm. + +TARGET = feature_segments_checker +CONFIG += console warn_on +CONFIG -= app_bundle +TEMPLATE = app + +ROOT_DIR = ../.. +DEPENDENCIES = generator map routing storage indexer platform geometry coding base minizip succinct protobuf gflags + +include($$ROOT_DIR/common.pri) + +INCLUDEPATH *= $$ROOT_DIR/3party/gflags/src + +QT *= core + +macx-* { + LIBS *= "-framework IOKit" "-framework SystemConfiguration" +} + +SOURCES += \ + feature_segments_checker.cpp \ diff --git a/omim.pro b/omim.pro index a6d6a159db..b6188b83f6 100644 --- a/omim.pro +++ b/omim.pro @@ -39,7 +39,9 @@ SUBDIRS = 3party base coding geometry editor indexer routing search routing_consistency_tests.depends = $$SUBDIRS srtm_coverage_checker.subdir = generator/srtm_coverage_checker srtm_coverage_checker.depends = $$SUBDIRS routing - SUBDIRS *= routing_integration_tests routing_consistency_tests srtm_coverage_checker + feature_segments_checker.subdir = generator/feature_segments_checker + feature_segments_checker.depends = $$SUBDIRS routing + SUBDIRS *= routing_integration_tests routing_consistency_tests srtm_coverage_checker feature_segments_checker } CONFIG(desktop) { @@ -174,6 +176,10 @@ SUBDIRS = 3party base coding geometry editor indexer routing search srtm_coverage_checker.depends = $$MapDepLibs routing SUBDIRS *= srtm_coverage_checker + feature_segments_checker.subdir = generator/feature_segments_checker + feature_segments_checker.depends = $$MapDepLibs routing + SUBDIRS *= feature_segments_checker + # TODO(AlexZ): Move pedestrian tests into routing dir. pedestrian_routing_tests.depends = $$MapDepLibs routing SUBDIRS *= pedestrian_routing_tests From 2dd718695d4fa4f3879dccaca89dbb988a63e787 Mon Sep 17 00:00:00 2001 From: Vladimir Byko-Ianko Date: Thu, 19 May 2016 15:09:21 +0300 Subject: [PATCH 2/4] git-clang-format --- .../feature_segments_checker.cpp | 34 ++++++++++++------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/generator/feature_segments_checker/feature_segments_checker.cpp b/generator/feature_segments_checker/feature_segments_checker.cpp index d0dd1f40a0..49b4fc70be 100644 --- a/generator/feature_segments_checker/feature_segments_checker.cpp +++ b/generator/feature_segments_checker/feature_segments_checker.cpp @@ -42,7 +42,8 @@ void IncrementStats(K const & k, map & m) } template -void PrintCont(Cont const & cont, string const & title, string const & msgText1, string const & msgText2) +void PrintCont(Cont const & cont, string const & title, string const & msgText1, + string const & msgText2) { cout << endl << title << endl; for (auto const a : cont) @@ -51,7 +52,8 @@ void PrintCont(Cont const & cont, string const & title, string const & msgText1, /// \brief Adds |point| to |uniqueRoadPoints| if there's no a point in |uniqueRoadPoints| /// in |kErrorMeters| environment of |point|. -/// \note This method does get an exact result. The problem is points are sorted in |uniqueRoadPoints| +/// \note This method does get an exact result. The problem is points are sorted in +/// |uniqueRoadPoints| /// according to operator<(m2::PointD const &, m2::PointD const &). It's not the same criteria with /// MercatorBounds::DistanceOnEarth(lowerPnt, point). But according to tests the error is less then 1%, /// and function implemented below works much faster. @@ -67,8 +69,8 @@ bool IsNewFeatureEnd(m2::PointD const & point, set & uniqueRoadPoint m2::PointD const lowerPnt = *lower; m2::PointD const upperPnt = *upper; - if (MercatorBounds::DistanceOnEarth(lowerPnt, point) <= kErrorMeters - || MercatorBounds::DistanceOnEarth(upperPnt, point) <= kErrorMeters) + if (MercatorBounds::DistanceOnEarth(lowerPnt, point) <= kErrorMeters || + MercatorBounds::DistanceOnEarth(upperPnt, point) <= kErrorMeters) { return false; } @@ -103,9 +105,11 @@ public: uint32_t m_notRoadCount; Processor(generator::SrtmTileManager & manager) - : m_srtmManager(manager), m_roadCount(0), m_roadPointCount(0), m_notRoadCount(0) {} + : m_srtmManager(manager), m_roadCount(0), m_roadPointCount(0), m_notRoadCount(0) + { + } - void operator() (FeatureType const & f, uint32_t const & id) + void operator()(FeatureType const & f, uint32_t const & id) { f.ParseBeforeStatistic(); if (!GetBicycleModel().IsRoad(f)) @@ -128,15 +132,17 @@ public: // Feature length. size_t featureLengthMeters = 0; if (pointCount != 0) - featureLengthMeters = MercatorBounds::DistanceOnEarth(f.GetPoint(0), f.GetPoint(pointCount - 1)); - IncrementStats(featureLengthMeters, m_featureLength); + featureLengthMeters = + MercatorBounds::DistanceOnEarth(f.GetPoint(0), f.GetPoint(pointCount - 1)); + IncrementStats(featureLengthMeters, m_featureLength); // Feature segment length. if (pointCount != 0) { for (int i = 0; i < pointCount - 1; ++i) { - size_t const segmentLengthMeters = MercatorBounds::DistanceOnEarth(f.GetPoint(i), f.GetPoint(i + 1)); + size_t const segmentLengthMeters = + MercatorBounds::DistanceOnEarth(f.GetPoint(i), f.GetPoint(i + 1)); IncrementStats(segmentLengthMeters, m_segLength); } } @@ -158,8 +164,9 @@ public: { for (int i = 0; i < pointCount - 1; ++i) { - auto const segAltDiff = (m_srtmManager.GetHeight(MercatorBounds::ToLatLon(f.GetPoint(i + 1))) - - m_srtmManager.GetHeight(MercatorBounds::ToLatLon(f.GetPoint(i)))); + auto const segAltDiff = + (m_srtmManager.GetHeight(MercatorBounds::ToLatLon(f.GetPoint(i + 1))) - + m_srtmManager.GetHeight(MercatorBounds::ToLatLon(f.GetPoint(i)))); if (altitudeDiff >= 0) { // If the feature goes up generaly calculates how many meters it's necessary @@ -182,7 +189,7 @@ public: } } }; -} // namespace +} // namespace int main(int argc, char ** argv) { @@ -206,7 +213,8 @@ int main(int argc, char ** argv) PrintCont(doProcess.m_altitudeDiffs, "Altitude difference between start and end of features.", " feature(s) with altitude difference ", " meter(s)"); PrintCont(doProcess.m_featureLength, "Feature length.", " feature(s) with length ", " meter(s)"); - PrintCont(doProcess.m_segLength, "Feature segment length.", " segment(s) with length ", " meter(s)"); + PrintCont(doProcess.m_segLength, "Feature segment length.", " segment(s) with length ", + " meter(s)"); PrintCont(doProcess.m_featureWave, "Wave factor", " features(s) with wave factor ", ""); return 0; } From b5e70def5dad98d09f2346eb3978a329c72e8c6e Mon Sep 17 00:00:00 2001 From: Vladimir Byko-Ianko Date: Fri, 20 May 2016 13:15:34 +0300 Subject: [PATCH 3/4] Extracting altitude deviation of internal feature points from linear model and review fixes. --- .../feature_segments_checker.cpp | 250 +++++++++++------- 1 file changed, 152 insertions(+), 98 deletions(-) diff --git a/generator/feature_segments_checker/feature_segments_checker.cpp b/generator/feature_segments_checker/feature_segments_checker.cpp index 49b4fc70be..ad66dcfc7c 100644 --- a/generator/feature_segments_checker/feature_segments_checker.cpp +++ b/generator/feature_segments_checker/feature_segments_checker.cpp @@ -17,8 +17,10 @@ #include "base/logging.hpp" #include "3party/gflags/src/gflags/gflags.h" +#include "3party/kdtree++/kdtree.hpp" #include "std/iostream.hpp" +#include "std/fstream.hpp" #include "std/map.hpp" #include "std/string.hpp" @@ -33,12 +35,26 @@ routing::BicycleModel const & GetBicycleModel() return instance; } -template -void IncrementStats(K const & k, map & m) +int32_t Coord2RoughCoord(double d) { - if (m.find(k) == m.cend()) - m[k] = 0; - m[k] += 1; + int32_t constexpr kFactor = 100000; + return static_cast(round(d * kFactor)); +} + +struct RoughPoint +{ + RoughPoint(m2::PointD const & point) + : x(Coord2RoughCoord(point.x)), y(Coord2RoughCoord(point.y)) {} + + int32_t x; + int32_t y; +}; + +bool operator< (RoughPoint const & l, RoughPoint const & r) +{ + if (l.x != r.x) + return l.x < r.x; + return l.y < r.y; } template @@ -46,66 +62,67 @@ void PrintCont(Cont const & cont, string const & title, string const & msgText1, string const & msgText2) { cout << endl << title << endl; - for (auto const a : cont) + for (auto const & a : cont) cout << a.second << msgText1 << a.first << msgText2 << endl; } -/// \brief Adds |point| to |uniqueRoadPoints| if there's no a point in |uniqueRoadPoints| -/// in |kErrorMeters| environment of |point|. -/// \note This method does get an exact result. The problem is points are sorted in -/// |uniqueRoadPoints| -/// according to operator<(m2::PointD const &, m2::PointD const &). It's not the same criteria with -/// MercatorBounds::DistanceOnEarth(lowerPnt, point). But according to tests the error is less then 1%, -/// and function implemented below works much faster. -bool IsNewFeatureEnd(m2::PointD const & point, set & uniqueRoadPoints) +template +void WriteCSV(Cont const & cont, string const & fileName) { - double constexpr kErrorMeters = 3.; - auto const lower = uniqueRoadPoints.lower_bound(point); - auto const upper = uniqueRoadPoints.upper_bound(point); + ofstream fout(fileName); + for (auto const & a : cont) + fout << a.first << ";" << a.second << endl; +} - if (lower == uniqueRoadPoints.cend() || upper == uniqueRoadPoints.cend()) - uniqueRoadPoints.insert(point); - - m2::PointD const lowerPnt = *lower; - m2::PointD const upperPnt = *upper; - - if (MercatorBounds::DistanceOnEarth(lowerPnt, point) <= kErrorMeters || - MercatorBounds::DistanceOnEarth(upperPnt, point) <= kErrorMeters) - { - return false; - } - - uniqueRoadPoints.insert(point); - return true; +/// \returns expected point altitude in meters according to linear model. +double ExpectedPointAltitude(int16_t startAltitudeMeters, int16_t endAltitudeMeters, + double distFromStartMeters, double featureLengthMeters) +{ + if (featureLengthMeters == 0.0) + return 0; + double const k = (endAltitudeMeters - startAltitudeMeters) / featureLengthMeters; + return startAltitudeMeters + k * distFromStartMeters; } class Processor { public: generator::SrtmTileManager & m_srtmManager; - set m_uniqueRoadPoints; + set m_uniqueRoadPoints; /// Key is altitude difference for feature in meters. If a feature goes up the key is more then 0. /// Value is a feature counter. - map m_altitudeDiffs; + map m_altitudeDiffs; /// Key is length of feature in meters. Value is a feature counter. - map m_featureLength; + map m_featureLength; /// Key is length of feature segment in meters. Value is a segment counter. - map m_segLength; + map m_segLength; /// Key is difference between two values: /// 1. how many meters it's necessary to go up following the feature. If feature wavy /// calculates only raise meters. /// 2. the difference in altitude between end and start of features. /// Value is a segment counter. - map m_featureWave; + map m_featureWave; + /// Key is number of meters which is necessary to go up following the feature. + /// Value is a feature counter. + map m_featureUp; + /// Key is number of meters which is necessary to go down following the feature. + /// Value is a feature counter. + map m_featureDown; + /// Key is number of meters. It shows altitude deviation of intermediate feature points + /// from linear model. + /// Value is a feature counter. + map m_diffFromLinear; /// Feature counter for GetBicycleModel().IsRoad(feature) == true. uint32_t m_roadCount; + /// Feature counter for empty features with GetBicycleModel().IsRoad(feature). + uint32_t m_emptyRoadCount; /// Point counter for feature where GetBicycleModel().IsRoad(feature) == true. uint32_t m_roadPointCount; /// Feature counter for GetBicycleModel().IsRoad(feature) != true. uint32_t m_notRoadCount; Processor(generator::SrtmTileManager & manager) - : m_srtmManager(manager), m_roadCount(0), m_roadPointCount(0), m_notRoadCount(0) + : m_srtmManager(manager), m_roadCount(0), m_emptyRoadCount(0), m_roadPointCount(0), m_notRoadCount(0) { } @@ -119,73 +136,94 @@ public: } f.ParseGeometry(FeatureType::BEST_GEOMETRY); + uint32_t const pointCount = f.GetPointsCount(); + if (pointCount == 0) + { + ++m_emptyRoadCount; + return; + } + ++m_roadCount; - size_t const pointCount = f.GetPointsCount(); m_roadPointCount += pointCount; for (int i = 0; i < pointCount; ++i) - { - IsNewFeatureEnd(f.GetPoint(i), m_uniqueRoadPoints); - } + m_uniqueRoadPoints.insert(RoughPoint(f.GetPoint(i))); - // Feature length. - size_t featureLengthMeters = 0; - if (pointCount != 0) - featureLengthMeters = - MercatorBounds::DistanceOnEarth(f.GetPoint(0), f.GetPoint(pointCount - 1)); - IncrementStats(featureLengthMeters, m_featureLength); - - // Feature segment length. - if (pointCount != 0) + // Feature length and feature segment length. + double realFeatureLengthMeters = 0.0; + for (int i = 0; i < pointCount - 1; ++i) { - for (int i = 0; i < pointCount - 1; ++i) - { - size_t const segmentLengthMeters = - MercatorBounds::DistanceOnEarth(f.GetPoint(i), f.GetPoint(i + 1)); - IncrementStats(segmentLengthMeters, m_segLength); - } + // Feature segment length. + double const realSegmentLengthMeters = MercatorBounds::DistanceOnEarth(f.GetPoint(i), f.GetPoint(i + 1)); + m_segLength[static_cast(floor(realSegmentLengthMeters))]++; + + // Feature length. + realFeatureLengthMeters += realSegmentLengthMeters; } + m_featureLength[static_cast(floor(realFeatureLengthMeters))]++; // Feature altitude difference. - generator::SrtmTile::THeight startAltitude = 0, endAltitude = 0; - if (pointCount != 0) - { - startAltitude = m_srtmManager.GetHeight(MercatorBounds::ToLatLon(f.GetPoint(0))); - endAltitude = m_srtmManager.GetHeight(MercatorBounds::ToLatLon(f.GetPoint(pointCount - 1))); - } - + generator::SrtmTile::THeight const startAltitude = + m_srtmManager.GetHeight(MercatorBounds::ToLatLon(f.GetPoint(0))); + generator::SrtmTile::THeight const endAltitude = + m_srtmManager.GetHeight(MercatorBounds::ToLatLon(f.GetPoint(pointCount - 1))); int16_t const altitudeDiff = endAltitude - startAltitude; - IncrementStats(altitudeDiff, m_altitudeDiffs); + m_altitudeDiffs[altitudeDiff]++; // Wave feature factor. Climb minus altitude difference. int32_t climb = 0; - if (pointCount != 0) + int32_t up = 0; + int32_t down = 0; + for (int i = 0; i < pointCount - 1; ++i) { - for (int i = 0; i < pointCount - 1; ++i) + auto const segAltDiff = + (m_srtmManager.GetHeight(MercatorBounds::ToLatLon(f.GetPoint(i + 1))) - + m_srtmManager.GetHeight(MercatorBounds::ToLatLon(f.GetPoint(i)))); + if (altitudeDiff >= 0) { - auto const segAltDiff = - (m_srtmManager.GetHeight(MercatorBounds::ToLatLon(f.GetPoint(i + 1))) - - m_srtmManager.GetHeight(MercatorBounds::ToLatLon(f.GetPoint(i)))); - if (altitudeDiff >= 0) - { - // If the feature goes up generaly calculates how many meters it's necessary - // to go up following the feature. - if (segAltDiff > 0) - climb += segAltDiff; - } - else - { - // If the feature goes down generaly calculates how many meters it's necessary - // to go down following the feature. - if (segAltDiff < 0) - climb += segAltDiff; - } + // If the feature goes up generaly calculates how many meters it's necessary + // to go up following the feature. + if (segAltDiff > 0) + climb += segAltDiff; } - // Estimates monotony of the feature. If climb == altitudeDiff it's monotonous. - // If not it's wavy. The more abs(climb - altitudeDiff) the more wavy the feature. - int32_t const waveFactor = climb - altitudeDiff; - IncrementStats(waveFactor, m_featureWave); + else + { + // If the feature goes down generaly calculates how many meters it's necessary + // to go down following the feature. + if (segAltDiff < 0) + climb += segAltDiff; + } + + if (segAltDiff >= 0) + up += segAltDiff; + else + down += segAltDiff; + } + // Estimates monotony of the feature. If climb == altitudeDiff it's monotonous. + // If not it's wavy. The more abs(climb - altitudeDiff) the more wavy the feature. + int32_t const waveFactor = climb - altitudeDiff; + m_featureWave[waveFactor]++; + m_featureUp[up]++; + m_featureDown[down]++; + + // Altitude deviation of internal feature points from linear model. + if (realFeatureLengthMeters == 0.0) + return; + + double distFromStartMeters = 0; + for (int i = 1; i < pointCount - 1; ++i) + { + // Feature segment length. + double const segmentLengthMeters = + MercatorBounds::DistanceOnEarth(f.GetPoint(i - 1), f.GetPoint(i)); + distFromStartMeters += segmentLengthMeters; + + generator::SrtmTile::THeight const pointAltitude = + m_srtmManager.GetHeight(MercatorBounds::ToLatLon(f.GetPoint(i))); + int32_t const deviation = static_cast(ExpectedPointAltitude(startAltitude, endAltitude, distFromStartMeters, + realFeatureLengthMeters)) - pointAltitude; + m_diffFromLinear[deviation]++; } } }; @@ -193,7 +231,7 @@ public: int main(int argc, char ** argv) { - google::SetUsageMessage("This tool extracts some staticstics about features and its altetude."); + google::SetUsageMessage("This tool extracts some staticstics about features and its altitudes."); google::ParseCommandLineFlags(&argc, &argv, true); LOG(LINFO, ("srtm_path =", FLAGS_srtm_path)); @@ -202,19 +240,35 @@ int main(int argc, char ** argv) classificator::Load(); generator::SrtmTileManager manager(FLAGS_srtm_path); - Processor doProcess(manager); - feature::ForEachFromDat(FLAGS_mwm_path, doProcess); + Processor processor(manager); + feature::ForEachFromDat(FLAGS_mwm_path, processor); - cout << endl << "doProcess.m_roadCount = " << doProcess.m_roadCount << endl; - cout << "doProcess.m_uniqueRoadPoints.size = " << doProcess.m_uniqueRoadPoints.size() << endl; - cout << "doProcess.m_roadPointCount = " << doProcess.m_roadPointCount << endl; - cout << "doProcess.m_notRoadCount = " << doProcess.m_notRoadCount << endl; + cout << endl << "Road feature count = " << processor.m_roadCount << endl; + cout << "Empty road feature count = " << processor.m_emptyRoadCount << endl; + cout << "Unique road points count = " << processor.m_uniqueRoadPoints.size() << endl; + cout << "All road point count = " << processor.m_roadPointCount << endl; + cout << "Not road feature count = " << processor.m_notRoadCount << endl; - PrintCont(doProcess.m_altitudeDiffs, "Altitude difference between start and end of features.", + PrintCont(processor.m_altitudeDiffs, "Altitude difference between start and end of features.", " feature(s) with altitude difference ", " meter(s)"); - PrintCont(doProcess.m_featureLength, "Feature length.", " feature(s) with length ", " meter(s)"); - PrintCont(doProcess.m_segLength, "Feature segment length.", " segment(s) with length ", + WriteCSV(processor.m_altitudeDiffs, "altitude_difference.csv"); + + PrintCont(processor.m_featureLength, "Feature length.", " feature(s) with length ", " meter(s)"); + WriteCSV(processor.m_featureLength, "feature_length.csv"); + + PrintCont(processor.m_segLength, "Feature segment length.", " segment(s) with length ", " meter(s)"); - PrintCont(doProcess.m_featureWave, "Wave factor", " features(s) with wave factor ", ""); + + PrintCont(processor.m_featureWave, "Wave factor", " feature(s) with wave factor ", ""); + WriteCSV(processor.m_featureWave, "feature_wave.csv"); + + PrintCont(processor.m_featureUp, "Feature go up in meters", " feature(s) go up ", " meter(s)"); + WriteCSV(processor.m_featureUp, "feature_up.csv"); + + PrintCont(processor.m_featureDown, "Feature go down in meters", " feature(s) go down ", " meter(s)"); + WriteCSV(processor.m_featureDown, "feature_down.csv"); + + PrintCont(processor.m_diffFromLinear, "Altitude deviation of internal feature points from linear model.", + " internal feature point(s) deviate from linear model with ", " meter(s)"); return 0; } From b885007e00c6eb8d2eb34c6993c6399310c2ee91 Mon Sep 17 00:00:00 2001 From: Vladimir Byko-Ianko Date: Mon, 30 May 2016 11:20:44 +0300 Subject: [PATCH 4/4] Review fixes. --- .../feature_segments_checker.cpp | 66 +++++++++---------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/generator/feature_segments_checker/feature_segments_checker.cpp b/generator/feature_segments_checker/feature_segments_checker.cpp index ad66dcfc7c..80a2e8541d 100644 --- a/generator/feature_segments_checker/feature_segments_checker.cpp +++ b/generator/feature_segments_checker/feature_segments_checker.cpp @@ -4,28 +4,28 @@ #include "coding/file_name_utils.hpp" -#include "geometry/mercator.hpp" -#include "geometry/point2d.hpp" - #include "indexer/classificator_loader.hpp" #include "indexer/feature.hpp" #include "indexer/feature_processor.hpp" #include "indexer/map_style_reader.hpp" +#include "geometry/mercator.hpp" +#include "geometry/point2d.hpp" + #include "platform/platform.hpp" #include "base/logging.hpp" -#include "3party/gflags/src/gflags/gflags.h" -#include "3party/kdtree++/kdtree.hpp" - #include "std/iostream.hpp" #include "std/fstream.hpp" #include "std/map.hpp" +#include "std/set.hpp" #include "std/string.hpp" -DEFINE_string(srtm_path, "", "Path to directory with SRTM files"); -DEFINE_string(mwm_path, "", "Path to an mwm file."); +#include "3party/gflags/src/gflags/gflags.h" + +DEFINE_string(srtm_dir_path, "", "Path to directory with SRTM files"); +DEFINE_string(mwm_file_path, "", "Path to an mwm file."); namespace { @@ -38,7 +38,7 @@ routing::BicycleModel const & GetBicycleModel() int32_t Coord2RoughCoord(double d) { int32_t constexpr kFactor = 100000; - return static_cast(round(d * kFactor)); + return static_cast(d * kFactor); } struct RoughPoint @@ -71,7 +71,7 @@ void WriteCSV(Cont const & cont, string const & fileName) { ofstream fout(fileName); for (auto const & a : cont) - fout << a.first << ";" << a.second << endl; + fout << a.first << "," << a.second << endl; } /// \returns expected point altitude in meters according to linear model. @@ -89,12 +89,12 @@ class Processor public: generator::SrtmTileManager & m_srtmManager; set m_uniqueRoadPoints; - /// Key is altitude difference for feature in meters. If a feature goes up the key is more then 0. - /// Value is a feature counter. + /// Key is an altitude difference for a feature in meters. If a feature goes up the key is greater then 0. + /// Value is a number of features. map m_altitudeDiffs; - /// Key is length of feature in meters. Value is a feature counter. + /// Key is a length of a feature in meters. Value is a number of features. map m_featureLength; - /// Key is length of feature segment in meters. Value is a segment counter. + /// Key is a length of a feature segment in meters. Value is a segment counter. map m_segLength; /// Key is difference between two values: /// 1. how many meters it's necessary to go up following the feature. If feature wavy @@ -103,22 +103,22 @@ public: /// Value is a segment counter. map m_featureWave; /// Key is number of meters which is necessary to go up following the feature. - /// Value is a feature counter. + /// Value is a number of features. map m_featureUp; /// Key is number of meters which is necessary to go down following the feature. - /// Value is a feature counter. + /// Value is a number of features. map m_featureDown; /// Key is number of meters. It shows altitude deviation of intermediate feature points /// from linear model. - /// Value is a feature counter. + /// Value is a number of features. map m_diffFromLinear; - /// Feature counter for GetBicycleModel().IsRoad(feature) == true. + /// Number of features for GetBicycleModel().IsRoad(feature) == true. uint32_t m_roadCount; - /// Feature counter for empty features with GetBicycleModel().IsRoad(feature). + /// Number of features for empty features with GetBicycleModel().IsRoad(feature). uint32_t m_emptyRoadCount; /// Point counter for feature where GetBicycleModel().IsRoad(feature) == true. uint32_t m_roadPointCount; - /// Feature counter for GetBicycleModel().IsRoad(feature) != true. + /// Number of features for GetBicycleModel().IsRoad(feature) != true. uint32_t m_notRoadCount; Processor(generator::SrtmTileManager & manager) @@ -136,8 +136,8 @@ public: } f.ParseGeometry(FeatureType::BEST_GEOMETRY); - uint32_t const pointCount = f.GetPointsCount(); - if (pointCount == 0) + uint32_t const numPoints = f.GetPointsCount(); + if (numPoints == 0) { ++m_emptyRoadCount; return; @@ -145,14 +145,14 @@ public: ++m_roadCount; - m_roadPointCount += pointCount; + m_roadPointCount += numPoints; - for (int i = 0; i < pointCount; ++i) + for (uint32_t i = 0; i < numPoints; ++i) m_uniqueRoadPoints.insert(RoughPoint(f.GetPoint(i))); // Feature length and feature segment length. double realFeatureLengthMeters = 0.0; - for (int i = 0; i < pointCount - 1; ++i) + for (uint32_t i = 0; i + 1 < numPoints; ++i) { // Feature segment length. double const realSegmentLengthMeters = MercatorBounds::DistanceOnEarth(f.GetPoint(i), f.GetPoint(i + 1)); @@ -161,13 +161,13 @@ public: // Feature length. realFeatureLengthMeters += realSegmentLengthMeters; } - m_featureLength[static_cast(floor(realFeatureLengthMeters))]++; + m_featureLength[static_cast(realFeatureLengthMeters)]++; // Feature altitude difference. generator::SrtmTile::THeight const startAltitude = m_srtmManager.GetHeight(MercatorBounds::ToLatLon(f.GetPoint(0))); generator::SrtmTile::THeight const endAltitude = - m_srtmManager.GetHeight(MercatorBounds::ToLatLon(f.GetPoint(pointCount - 1))); + m_srtmManager.GetHeight(MercatorBounds::ToLatLon(f.GetPoint(numPoints - 1))); int16_t const altitudeDiff = endAltitude - startAltitude; m_altitudeDiffs[altitudeDiff]++; @@ -175,7 +175,7 @@ public: int32_t climb = 0; int32_t up = 0; int32_t down = 0; - for (int i = 0; i < pointCount - 1; ++i) + for (uint32_t i = 0; i + 1 < numPoints; ++i) { auto const segAltDiff = (m_srtmManager.GetHeight(MercatorBounds::ToLatLon(f.GetPoint(i + 1))) - @@ -212,7 +212,7 @@ public: return; double distFromStartMeters = 0; - for (int i = 1; i < pointCount - 1; ++i) + for (uint32_t i = 1; i + 1 < numPoints; ++i) { // Feature segment length. double const segmentLengthMeters = @@ -234,14 +234,14 @@ int main(int argc, char ** argv) google::SetUsageMessage("This tool extracts some staticstics about features and its altitudes."); google::ParseCommandLineFlags(&argc, &argv, true); - LOG(LINFO, ("srtm_path =", FLAGS_srtm_path)); - LOG(LINFO, ("mwm_path =", FLAGS_mwm_path)); + LOG(LINFO, ("srtm_dir_path =", FLAGS_srtm_dir_path)); + LOG(LINFO, ("mwm_file_path =", FLAGS_mwm_file_path)); classificator::Load(); - generator::SrtmTileManager manager(FLAGS_srtm_path); + generator::SrtmTileManager manager(FLAGS_srtm_dir_path); Processor processor(manager); - feature::ForEachFromDat(FLAGS_mwm_path, processor); + feature::ForEachFromDat(FLAGS_mwm_file_path, processor); cout << endl << "Road feature count = " << processor.m_roadCount << endl; cout << "Empty road feature count = " << processor.m_emptyRoadCount << endl;