Repo created
This commit is contained in:
parent
4af19165ec
commit
68073add76
12458 changed files with 12350765 additions and 2 deletions
367
generator/feature_segments_checker/feature_segments_checker.cpp
Normal file
367
generator/feature_segments_checker/feature_segments_checker.cpp
Normal file
|
|
@ -0,0 +1,367 @@
|
|||
#include "generator/srtm_parser.hpp"
|
||||
|
||||
#include "routing_common/bicycle_model.hpp"
|
||||
|
||||
#include "indexer/classificator_loader.hpp"
|
||||
#include "indexer/feature.hpp"
|
||||
#include "indexer/feature_processor.hpp"
|
||||
|
||||
#include "geometry/mercator.hpp"
|
||||
#include "geometry/point2d.hpp"
|
||||
#include "geometry/point_with_altitude.hpp"
|
||||
|
||||
#include "base/checked_cast.hpp"
|
||||
#include "base/logging.hpp"
|
||||
#include "base/math.hpp"
|
||||
|
||||
#include <cmath>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
#include <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 feature_segments_checker
|
||||
{
|
||||
using namespace feature;
|
||||
|
||||
routing::BicycleModel const & GetBicycleModel()
|
||||
{
|
||||
static routing::BicycleModel const instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
int32_t Coord2RoughCoord(double d)
|
||||
{
|
||||
int32_t constexpr kFactor = 100000;
|
||||
return static_cast<int32_t>(d * kFactor);
|
||||
}
|
||||
|
||||
struct RoughPoint
|
||||
{
|
||||
explicit 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 <typename Cont>
|
||||
void PrintCont(Cont const & cont, std::string const & title, std::string const & msgText1, std::string const & msgText2)
|
||||
{
|
||||
std::cout << std::endl << title << std::endl;
|
||||
for (auto const & a : cont)
|
||||
std::cout << a.second << msgText1 << a.first << msgText2 << std::endl;
|
||||
}
|
||||
|
||||
template <typename Cont>
|
||||
void WriteCSV(Cont const & cont, std::string const & fileName)
|
||||
{
|
||||
std::ofstream fout(fileName);
|
||||
for (auto const & a : cont)
|
||||
fout << a.first << "," << a.second << std::endl;
|
||||
}
|
||||
|
||||
/// \returns y = k * x + b. It's the expected altitude in meters.
|
||||
double GetY(double k, double b, double x)
|
||||
{
|
||||
return k * x + b;
|
||||
}
|
||||
|
||||
/// \brief Calculates factors |k| and |b| of a line using linear least squares method.
|
||||
/// \returns false in case of error (e.g. if the line is parallel to the vertical axis)
|
||||
/// and true otherwise.
|
||||
bool LinearLeastSquaresFactors(std::vector<double> const & xs, std::vector<double> const & ys, double & k, double & b)
|
||||
{
|
||||
double constexpr kEpsilon = 1e-6;
|
||||
size_t const n = xs.size();
|
||||
double mx = 0, my = 0, mxy = 0, mx2 = 0;
|
||||
for (size_t i = 0; i < n; ++i)
|
||||
{
|
||||
mx += xs[i] / n;
|
||||
my += ys[i] / n;
|
||||
mxy += xs[i] * ys[i] / n;
|
||||
mx2 += xs[i] * xs[i] / n;
|
||||
}
|
||||
|
||||
if (AlmostEqualAbs(mx * mx, mx2, kEpsilon))
|
||||
return false;
|
||||
|
||||
k = (my * mx - mxy) / (mx * mx - mx2);
|
||||
b = my - k * mx;
|
||||
return true;
|
||||
}
|
||||
|
||||
class Processor
|
||||
{
|
||||
public:
|
||||
generator::SrtmTileManager & m_srtmManager;
|
||||
std::set<RoughPoint> m_uniqueRoadPoints;
|
||||
/// 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.
|
||||
std::map<geometry::Altitude, uint32_t> m_altitudeDiffs;
|
||||
/// Key is a length of a feature in meters. Value is a number of features.
|
||||
std::map<uint32_t, uint32_t> m_featureLength;
|
||||
/// Key is a length of a feature segment in meters. Value is a segment counter.
|
||||
std::map<uint32_t, uint32_t> 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.
|
||||
std::map<int32_t, uint32_t> m_featureWave;
|
||||
/// Key is number of meters which is necessary to go up following the feature.
|
||||
/// Value is a number of features.
|
||||
std::map<int32_t, uint32_t> m_featureUp;
|
||||
/// Key is number of meters which is necessary to go down following the feature.
|
||||
/// Value is a number of features.
|
||||
std::map<int32_t, uint32_t> m_featureDown;
|
||||
/// Key is number of meters. It shows altitude deviation of intermediate feature points
|
||||
/// from linear model.
|
||||
/// Value is a number of features.
|
||||
std::map<geometry::Altitude, uint32_t> m_diffFromLinear;
|
||||
/// Key is number of meters. It shows altitude deviation of intermediate feature points
|
||||
/// from line calculated base on least squares method for all feature points.
|
||||
/// Value is a number of features.
|
||||
std::map<geometry::Altitude, uint32_t> m_leastSquaresDiff;
|
||||
/// Number of features for GetBicycleModel().IsRoad(feature) == true.
|
||||
uint32_t m_roadCount;
|
||||
/// 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;
|
||||
/// Number of features for GetBicycleModel().IsRoad(feature) != true.
|
||||
uint32_t m_notRoadCount;
|
||||
geometry::Altitude m_minAltitude = geometry::kInvalidAltitude;
|
||||
geometry::Altitude m_maxAltitude = geometry::kInvalidAltitude;
|
||||
|
||||
explicit Processor(generator::SrtmTileManager & manager)
|
||||
: m_srtmManager(manager)
|
||||
, m_roadCount(0)
|
||||
, m_emptyRoadCount(0)
|
||||
, m_roadPointCount(0)
|
||||
, m_notRoadCount(0)
|
||||
{}
|
||||
|
||||
void operator()(FeatureType & f, uint32_t const & id)
|
||||
{
|
||||
f.ParseAllBeforeGeometry();
|
||||
|
||||
if (!GetBicycleModel().IsRoad(feature::TypesHolder(f)))
|
||||
{
|
||||
++m_notRoadCount;
|
||||
return;
|
||||
}
|
||||
|
||||
f.ParseGeometry(FeatureType::BEST_GEOMETRY);
|
||||
uint32_t const numPoints = base::asserted_cast<uint32_t>(f.GetPointsCount());
|
||||
if (numPoints == 0)
|
||||
{
|
||||
++m_emptyRoadCount;
|
||||
return;
|
||||
}
|
||||
|
||||
++m_roadCount;
|
||||
|
||||
m_roadPointCount += numPoints;
|
||||
|
||||
for (uint32_t i = 0; i < numPoints; ++i)
|
||||
m_uniqueRoadPoints.insert(RoughPoint(f.GetPoint(i)));
|
||||
|
||||
// Preparing feature altitude and length.
|
||||
geometry::Altitudes pointAltitudes(numPoints);
|
||||
std::vector<double> pointDists(numPoints);
|
||||
double distFromStartMeters = 0;
|
||||
for (uint32_t i = 0; i < numPoints; ++i)
|
||||
{
|
||||
// Feature segment altitude.
|
||||
geometry::Altitude altitude = m_srtmManager.GetAltitude(mercator::ToLatLon(f.GetPoint(i)));
|
||||
pointAltitudes[i] = altitude == geometry::kInvalidAltitude ? 0 : altitude;
|
||||
if (i == 0)
|
||||
{
|
||||
pointDists[i] = 0;
|
||||
continue;
|
||||
}
|
||||
// Feature segment length.
|
||||
double const segmentLengthMeters = mercator::DistanceOnEarth(f.GetPoint(i - 1), f.GetPoint(i));
|
||||
distFromStartMeters += segmentLengthMeters;
|
||||
pointDists[i] = distFromStartMeters;
|
||||
}
|
||||
|
||||
// Min and max altitudes.
|
||||
for (auto const a : pointAltitudes)
|
||||
{
|
||||
if (m_minAltitude == geometry::kInvalidAltitude || a < m_minAltitude)
|
||||
m_minAltitude = a;
|
||||
if (m_maxAltitude == geometry::kInvalidAltitude || a > m_maxAltitude)
|
||||
m_maxAltitude = a;
|
||||
}
|
||||
|
||||
// Feature length and feature segment length.
|
||||
double realFeatureLengthMeters = 0.0;
|
||||
for (uint32_t i = 0; i + 1 < numPoints; ++i)
|
||||
{
|
||||
// Feature segment length.
|
||||
double const realSegmentLengthMeters = pointDists[i + 1] - pointDists[i];
|
||||
m_segLength[static_cast<uint32_t>(floor(realSegmentLengthMeters))]++;
|
||||
|
||||
// Feature length.
|
||||
realFeatureLengthMeters += realSegmentLengthMeters;
|
||||
}
|
||||
m_featureLength[static_cast<uint32_t>(realFeatureLengthMeters)]++;
|
||||
|
||||
// Feature altitude difference.
|
||||
geometry::Altitude const startAltitude = pointAltitudes[0];
|
||||
geometry::Altitude const endAltitude = pointAltitudes[numPoints - 1];
|
||||
int16_t const altitudeDiff = endAltitude - startAltitude;
|
||||
m_altitudeDiffs[altitudeDiff]++;
|
||||
|
||||
// Wave feature factor. Climb minus altitude difference.
|
||||
int32_t climb = 0;
|
||||
int32_t up = 0;
|
||||
int32_t down = 0;
|
||||
for (uint32_t i = 0; i + 1 < numPoints; ++i)
|
||||
{
|
||||
auto const segAltDiff = pointAltitudes[i + 1] - pointAltitudes[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 (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 const k = (endAltitude - startAltitude) / realFeatureLengthMeters;
|
||||
for (uint32_t i = 1; i + 1 < numPoints; ++i)
|
||||
{
|
||||
int32_t const deviation =
|
||||
static_cast<geometry::Altitude>(GetY(k, startAltitude, pointDists[i])) - pointAltitudes[i];
|
||||
m_diffFromLinear[deviation]++;
|
||||
}
|
||||
|
||||
// Linear least squares for feature points.
|
||||
{
|
||||
double k;
|
||||
double b;
|
||||
std::vector<double> const pointAltitudesMeters(pointAltitudes.begin(), pointAltitudes.end());
|
||||
if (!LinearLeastSquaresFactors(pointDists, pointAltitudesMeters, k, b))
|
||||
return;
|
||||
|
||||
for (uint32_t i = 0; i < numPoints; ++i)
|
||||
{
|
||||
geometry::Altitude const deviation =
|
||||
static_cast<geometry::Altitude>(GetY(k, b, pointDists[i])) - pointAltitudes[i];
|
||||
m_leastSquaresDiff[deviation]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
double CalculateEntropy(std::map<geometry::Altitude, uint32_t> const & diffFromLinear)
|
||||
{
|
||||
uint32_t innerPointCount = 0;
|
||||
for (auto const & f : diffFromLinear)
|
||||
innerPointCount += f.second;
|
||||
|
||||
if (innerPointCount == 0)
|
||||
return 0.0;
|
||||
|
||||
double entropy = 0;
|
||||
for (auto const & f : diffFromLinear)
|
||||
{
|
||||
double const p = static_cast<double>(f.second) / innerPointCount;
|
||||
entropy += -p * log2(p);
|
||||
}
|
||||
return entropy;
|
||||
}
|
||||
} // namespace feature_segments_checker
|
||||
|
||||
int main(int argc, char ** argv)
|
||||
{
|
||||
using namespace feature_segments_checker;
|
||||
|
||||
gflags::SetUsageMessage("This tool extracts some staticstics about features and its altitudes.");
|
||||
gflags::ParseCommandLineFlags(&argc, &argv, true);
|
||||
|
||||
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_dir_path);
|
||||
|
||||
Processor processor(manager);
|
||||
ForEachFeature(FLAGS_mwm_file_path, processor);
|
||||
|
||||
PrintCont(processor.m_altitudeDiffs, "Altitude difference between start and end of features.",
|
||||
" feature(s) with altitude difference ", " meter(s)");
|
||||
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(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)");
|
||||
|
||||
PrintCont(processor.m_leastSquaresDiff, "Altitude deviation of feature points from least squares line.",
|
||||
" internal feature point(s) deviate from linear model with ", " meter(s)");
|
||||
|
||||
using std::cout, std::endl;
|
||||
cout << endl << FLAGS_mwm_file_path << endl;
|
||||
cout << "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;
|
||||
cout << "Entropy for altitude deviation of internal feature points from linear model = "
|
||||
<< CalculateEntropy(processor.m_diffFromLinear) << endl;
|
||||
cout << "Entropy for altitude deviation of feature points from least squares line = "
|
||||
<< CalculateEntropy(processor.m_leastSquaresDiff) << endl;
|
||||
cout << "Min altitude of the mwm = " << processor.m_minAltitude << endl;
|
||||
cout << "Max altitude of the mwm = " << processor.m_maxAltitude << endl;
|
||||
return 0;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue