mirror of
https://codeberg.org/comaps/comaps
synced 2025-12-24 06:53:46 +00:00
Format all C++ and Java code via clang-format
Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
This commit is contained in:
@@ -67,9 +67,8 @@ m2::PointD FindCenter(FeatureType & f)
|
||||
ClosestPoint closest(f.GetLimitRect(FeatureType::BEST_GEOMETRY).Center());
|
||||
if (f.GetGeomType() == feature::GeomType::Area)
|
||||
{
|
||||
f.ForEachTriangle([&closest](m2::PointD const & p1, m2::PointD const & p2,
|
||||
m2::PointD const & p3) { closest((p1 + p2 + p3) / 3); },
|
||||
FeatureType::BEST_GEOMETRY);
|
||||
f.ForEachTriangle([&closest](m2::PointD const & p1, m2::PointD const & p2, m2::PointD const & p3)
|
||||
{ closest((p1 + p2 + p3) / 3); }, FeatureType::BEST_GEOMETRY);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -93,7 +92,7 @@ string GetReadableType(FeatureType & f)
|
||||
|
||||
string GetWheelchairType(FeatureType & f)
|
||||
{
|
||||
static const uint32_t wheelchair = classif().GetTypeByPath({"wheelchair"});
|
||||
static uint32_t const wheelchair = classif().GetTypeByPath({"wheelchair"});
|
||||
string result;
|
||||
f.ForEachType([&result](uint32_t type)
|
||||
{
|
||||
@@ -110,9 +109,10 @@ string GetWheelchairType(FeatureType & f)
|
||||
|
||||
bool HasAtm(FeatureType & f)
|
||||
{
|
||||
static const uint32_t atm = classif().GetTypeByPath({"amenity", "atm"});
|
||||
static uint32_t const atm = classif().GetTypeByPath({"amenity", "atm"});
|
||||
bool result = false;
|
||||
f.ForEachType([&result](uint32_t type) {
|
||||
f.ForEachType([&result](uint32_t type)
|
||||
{
|
||||
if (type == atm)
|
||||
result = true;
|
||||
});
|
||||
@@ -122,8 +122,7 @@ bool HasAtm(FeatureType & f)
|
||||
string BuildUniqueId(ms::LatLon const & coords, string const & name)
|
||||
{
|
||||
ostringstream ss;
|
||||
ss << strings::to_string_dac(coords.m_lat, 6) << ','
|
||||
<< strings::to_string_dac(coords.m_lon, 6) << ',' << name;
|
||||
ss << strings::to_string_dac(coords.m_lat, 6) << ',' << strings::to_string_dac(coords.m_lon, 6) << ',' << name;
|
||||
uint32_t hash = 0;
|
||||
for (char const c : ss.str())
|
||||
hash = hash * 101 + c;
|
||||
@@ -191,10 +190,7 @@ public:
|
||||
|
||||
void ClearCache() { m_villagesCache.Clear(); }
|
||||
|
||||
void operator()(FeatureType & f, map<uint32_t, base::GeoObjectId> const & ft2osm)
|
||||
{
|
||||
Process(f, ft2osm);
|
||||
}
|
||||
void operator()(FeatureType & f, map<uint32_t, base::GeoObjectId> const & ft2osm) { Process(f, ft2osm); }
|
||||
|
||||
void Process(FeatureType & f, map<uint32_t, base::GeoObjectId> const & ft2osm)
|
||||
{
|
||||
@@ -205,8 +201,7 @@ public:
|
||||
auto const metaOperator = meta.Get(feature::Metadata::FMD_OPERATOR);
|
||||
auto const & osmIt = ft2osm.find(f.GetID().m_index);
|
||||
if ((!f.HasName() && metaOperator.empty()) ||
|
||||
(f.GetGeomType() == feature::GeomType::Line && category != "highway-pedestrian") ||
|
||||
category.empty())
|
||||
(f.GetGeomType() == feature::GeomType::Line && category != "highway-pedestrian") || category.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -217,9 +212,7 @@ public:
|
||||
|
||||
string_view city;
|
||||
m_finder.GetLocality(center, [&city](search::LocalityItem const & item)
|
||||
{
|
||||
item.GetSpecifiedOrDefaultName(StringUtf8Multilang::kDefaultCode, city);
|
||||
});
|
||||
{ item.GetSpecifiedOrDefaultName(StringUtf8Multilang::kDefaultCode, city); });
|
||||
|
||||
string const & mwmName = f.GetID().GetMwmName();
|
||||
|
||||
@@ -276,11 +269,39 @@ public:
|
||||
string const fee = category.ends_with("-fee") ? "yes" : "";
|
||||
string const atm = HasAtm(f) ? "yes" : "";
|
||||
|
||||
vector<string> columns = {
|
||||
osmId, uid, lat, lon, mwmName, category, name, std::string(city),
|
||||
addrStreet, addrHouse, phone, website, stars, std::string(metaOperator), internet,
|
||||
denomination, wheelchair, opening_hours, check_date, check_date_opening_hours, wikipedia, floor, fee, atm, contact_facebook,
|
||||
contact_instagram, contact_twitter, contact_vk, contact_line, contact_fediverse, contact_bluesky, wikimedia_commons, panoramax};
|
||||
vector<string> columns = {osmId,
|
||||
uid,
|
||||
lat,
|
||||
lon,
|
||||
mwmName,
|
||||
category,
|
||||
name,
|
||||
std::string(city),
|
||||
addrStreet,
|
||||
addrHouse,
|
||||
phone,
|
||||
website,
|
||||
stars,
|
||||
std::string(metaOperator),
|
||||
internet,
|
||||
denomination,
|
||||
wheelchair,
|
||||
opening_hours,
|
||||
check_date,
|
||||
check_date_opening_hours,
|
||||
wikipedia,
|
||||
floor,
|
||||
fee,
|
||||
atm,
|
||||
contact_facebook,
|
||||
contact_instagram,
|
||||
contact_twitter,
|
||||
contact_vk,
|
||||
contact_line,
|
||||
contact_fediverse,
|
||||
contact_bluesky,
|
||||
wikimedia_commons,
|
||||
panoramax};
|
||||
|
||||
AppendNames(f, columns);
|
||||
PrintAsCSV(columns, ';', cout);
|
||||
@@ -289,12 +310,40 @@ public:
|
||||
|
||||
void PrintHeader()
|
||||
{
|
||||
vector<string> columns = {"id", "old_id", "lat", "lon", "mwm",
|
||||
"category", "name", "city", "street", "house",
|
||||
"phone", "website", "cuisines", "stars", "operator",
|
||||
"internet", "denomination", "wheelchair", "opening_hours", "check_date", "check_date_opening_hours", "wikipedia",
|
||||
"floor", "fee", "atm", "contact_facebook", "contact_instagram",
|
||||
"contact_twitter", "contact_vk", "contact_line", "contact_fediverse", "contact_bluesky", "wikimedia_commons", "panoramax"};
|
||||
vector<string> columns = {"id",
|
||||
"old_id",
|
||||
"lat",
|
||||
"lon",
|
||||
"mwm",
|
||||
"category",
|
||||
"name",
|
||||
"city",
|
||||
"street",
|
||||
"house",
|
||||
"phone",
|
||||
"website",
|
||||
"cuisines",
|
||||
"stars",
|
||||
"operator",
|
||||
"internet",
|
||||
"denomination",
|
||||
"wheelchair",
|
||||
"opening_hours",
|
||||
"check_date",
|
||||
"check_date_opening_hours",
|
||||
"wikipedia",
|
||||
"floor",
|
||||
"fee",
|
||||
"atm",
|
||||
"contact_facebook",
|
||||
"contact_instagram",
|
||||
"contact_twitter",
|
||||
"contact_vk",
|
||||
"contact_line",
|
||||
"contact_fediverse",
|
||||
"contact_bluesky",
|
||||
"wikimedia_commons",
|
||||
"panoramax"};
|
||||
// Append all supported name languages in order.
|
||||
for (uint8_t idx = 1; idx < kLangCount; idx++)
|
||||
columns.push_back("name_" + string(StringUtf8Multilang::GetLangByCode(idx)));
|
||||
@@ -304,15 +353,12 @@ void PrintHeader()
|
||||
bool ParseFeatureIdToOsmIdMapping(string const & path, map<uint32_t, base::GeoObjectId> & mapping)
|
||||
{
|
||||
return generator::ForEachOsmId2FeatureId(
|
||||
path, [&](auto const & compositeId, uint32_t const featureId) {
|
||||
mapping[featureId] = compositeId.m_mainId;
|
||||
});
|
||||
path, [&](auto const & compositeId, uint32_t const featureId) { mapping[featureId] = compositeId.m_mainId; });
|
||||
}
|
||||
|
||||
void DidDownload(storage::CountryId const & /* countryId */,
|
||||
shared_ptr<platform::LocalCountryFile> const & /* localFile */)
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
bool WillDelete(storage::CountryId const & /* countryId */,
|
||||
shared_ptr<platform::LocalCountryFile> const & /* localFile */)
|
||||
@@ -325,8 +371,7 @@ int main(int argc, char ** argv)
|
||||
platform::tests_support::ChangeMaxNumberOfOpenFiles(search::search_quality::kMaxOpenFiles);
|
||||
if (argc <= 1)
|
||||
{
|
||||
LOG(LERROR, ("Usage:", argc == 1 ? argv[0] : "feature_list",
|
||||
"<mwm_path> [<data_path>] [<mwm_prefix>]"));
|
||||
LOG(LERROR, ("Usage:", argc == 1 ? argv[0] : "feature_list", "<mwm_path> [<data_path>] [<mwm_prefix>]"));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -350,8 +395,7 @@ int main(int argc, char ** argv)
|
||||
|
||||
FrozenDataSource dataSource;
|
||||
vector<platform::LocalCountryFile> mwms;
|
||||
platform::FindAllLocalMapsAndCleanup(numeric_limits<int64_t>::max() /* the latest version */,
|
||||
mwms);
|
||||
platform::FindAllLocalMapsAndCleanup(numeric_limits<int64_t>::max() /* the latest version */, mwms);
|
||||
for (auto & mwm : mwms)
|
||||
{
|
||||
mwm.SyncWithDisk();
|
||||
@@ -372,17 +416,15 @@ int main(int argc, char ** argv)
|
||||
if (argc > 3 && !(mwmInfo->GetCountryName() + DATA_FILE_EXTENSION).starts_with(argv[3]))
|
||||
continue;
|
||||
LOG(LINFO, ("Processing", mwmInfo->GetCountryName()));
|
||||
string osmToFeatureFile = base::JoinPath(
|
||||
argv[1], mwmInfo->GetCountryName() + DATA_FILE_EXTENSION + OSM2FEATURE_FILE_EXTENSION);
|
||||
string osmToFeatureFile =
|
||||
base::JoinPath(argv[1], mwmInfo->GetCountryName() + DATA_FILE_EXTENSION + OSM2FEATURE_FILE_EXTENSION);
|
||||
map<uint32_t, base::GeoObjectId> featureIdToOsmId;
|
||||
ParseFeatureIdToOsmIdMapping(osmToFeatureFile, featureIdToOsmId);
|
||||
MwmSet::MwmId mwmId(mwmInfo);
|
||||
FeaturesLoaderGuard loader(dataSource, mwmId);
|
||||
for (uint32_t ftIndex = 0; ftIndex < loader.GetNumFeatures(); ftIndex++)
|
||||
{
|
||||
if (auto ft = loader.GetFeatureByIndex(static_cast<uint32_t>(ftIndex)))
|
||||
doProcess.Process(*ft, featureIdToOsmId);
|
||||
}
|
||||
doProcess.ClearCache();
|
||||
}
|
||||
|
||||
|
||||
@@ -5,4 +5,4 @@
|
||||
namespace openlr
|
||||
{
|
||||
size_t constexpr kCacheLineSize = 64;
|
||||
} // namespace
|
||||
} // namespace openlr
|
||||
|
||||
@@ -62,9 +62,8 @@ bool CandidatePathsGetter::Link::IsPointOnPath(geometry::PointWithAltitude const
|
||||
}
|
||||
|
||||
// CandidatePathsGetter ----------------------------------------------------------------------------
|
||||
bool CandidatePathsGetter::GetLineCandidatesForPoints(
|
||||
vector<LocationReferencePoint> const & points,
|
||||
vector<vector<Graph::EdgeVector>> & lineCandidates)
|
||||
bool CandidatePathsGetter::GetLineCandidatesForPoints(vector<LocationReferencePoint> const & points,
|
||||
vector<vector<Graph::EdgeVector>> & lineCandidates)
|
||||
{
|
||||
for (size_t i = 0; i < points.size(); ++i)
|
||||
{
|
||||
@@ -77,14 +76,11 @@ bool CandidatePathsGetter::GetLineCandidatesForPoints(
|
||||
|
||||
lineCandidates.emplace_back();
|
||||
auto const isLastPoint = i == points.size() - 1;
|
||||
double const distanceToNextPointM =
|
||||
(isLastPoint ? points[i - 1] : points[i]).m_distanceToNextPoint;
|
||||
double const distanceToNextPointM = (isLastPoint ? points[i - 1] : points[i]).m_distanceToNextPoint;
|
||||
|
||||
vector<m2::PointD> pointCandidates;
|
||||
m_pointsGetter.GetCandidatePoints(mercator::FromLatLon(points[i].m_latLon),
|
||||
pointCandidates);
|
||||
GetLineCandidates(points[i], isLastPoint, distanceToNextPointM, pointCandidates,
|
||||
lineCandidates.back());
|
||||
m_pointsGetter.GetCandidatePoints(mercator::FromLatLon(points[i].m_latLon), pointCandidates);
|
||||
GetLineCandidates(points[i], isLastPoint, distanceToNextPointM, pointCandidates, lineCandidates.back());
|
||||
|
||||
if (lineCandidates.back().empty())
|
||||
{
|
||||
@@ -117,11 +113,9 @@ void CandidatePathsGetter::GetStartLines(vector<m2::PointD> const & points, bool
|
||||
base::SortUnique(edges, less<Graph::Edge>(), EdgesAreAlmostEqual);
|
||||
}
|
||||
|
||||
void CandidatePathsGetter::GetAllSuitablePaths(Graph::EdgeVector const & startLines,
|
||||
bool isLastPoint, double bearDistM,
|
||||
FunctionalRoadClass functionalRoadClass,
|
||||
FormOfWay formOfWay, double distanceToNextPointM,
|
||||
vector<LinkPtr> & allPaths)
|
||||
void CandidatePathsGetter::GetAllSuitablePaths(Graph::EdgeVector const & startLines, bool isLastPoint, double bearDistM,
|
||||
FunctionalRoadClass functionalRoadClass, FormOfWay formOfWay,
|
||||
double distanceToNextPointM, vector<LinkPtr> & allPaths)
|
||||
{
|
||||
queue<LinkPtr> q;
|
||||
|
||||
@@ -179,9 +173,9 @@ void CandidatePathsGetter::GetAllSuitablePaths(Graph::EdgeVector const & startLi
|
||||
}
|
||||
}
|
||||
|
||||
void CandidatePathsGetter::GetBestCandidatePaths(
|
||||
vector<LinkPtr> const & allPaths, bool const isLastPoint, uint32_t const requiredBearing,
|
||||
double const bearDistM, m2::PointD const & startPoint, vector<Graph::EdgeVector> & candidates)
|
||||
void CandidatePathsGetter::GetBestCandidatePaths(vector<LinkPtr> const & allPaths, bool const isLastPoint,
|
||||
uint32_t const requiredBearing, double const bearDistM,
|
||||
m2::PointD const & startPoint, vector<Graph::EdgeVector> & candidates)
|
||||
{
|
||||
set<CandidatePath> candidatePaths;
|
||||
set<CandidatePath> fakeEndingsCandidatePaths;
|
||||
@@ -212,8 +206,7 @@ void CandidatePathsGetter::GetBestCandidatePaths(
|
||||
|
||||
--traceBackIterationsLeft;
|
||||
|
||||
auto const bearEndPoint =
|
||||
pointsSelector.GetEndPoint(part->m_edge, part->m_distanceM);
|
||||
auto const bearEndPoint = pointsSelector.GetEndPoint(part->m_edge, part->m_distanceM);
|
||||
|
||||
auto const bearing = cpg::Bearing(bearStartPoint, bearEndPoint);
|
||||
auto const bearingDiff = AbsDifference(bearing, requiredBearing);
|
||||
@@ -228,21 +221,16 @@ void CandidatePathsGetter::GetBestCandidatePaths(
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT(
|
||||
none_of(begin(candidatePaths), end(candidatePaths), mem_fn(&CandidatePath::HasFakeEndings)),
|
||||
());
|
||||
ASSERT(fakeEndingsCandidatePaths.empty() ||
|
||||
any_of(begin(fakeEndingsCandidatePaths), end(fakeEndingsCandidatePaths),
|
||||
mem_fn(&CandidatePath::HasFakeEndings)),
|
||||
ASSERT(none_of(begin(candidatePaths), end(candidatePaths), mem_fn(&CandidatePath::HasFakeEndings)), ());
|
||||
ASSERT(fakeEndingsCandidatePaths.empty() || any_of(begin(fakeEndingsCandidatePaths), end(fakeEndingsCandidatePaths),
|
||||
mem_fn(&CandidatePath::HasFakeEndings)),
|
||||
());
|
||||
|
||||
vector<CandidatePath> paths;
|
||||
copy_n(begin(candidatePaths), min(static_cast<size_t>(kMaxCandidates), candidatePaths.size()),
|
||||
back_inserter(paths));
|
||||
copy_n(begin(candidatePaths), min(static_cast<size_t>(kMaxCandidates), candidatePaths.size()), back_inserter(paths));
|
||||
|
||||
copy_n(begin(fakeEndingsCandidatePaths),
|
||||
min(static_cast<size_t>(kMaxFakeCandidates), fakeEndingsCandidatePaths.size()),
|
||||
back_inserter(paths));
|
||||
min(static_cast<size_t>(kMaxFakeCandidates), fakeEndingsCandidatePaths.size()), back_inserter(paths));
|
||||
|
||||
LOG(LDEBUG, ("List candidate paths..."));
|
||||
for (auto const & path : paths)
|
||||
@@ -258,8 +246,7 @@ void CandidatePathsGetter::GetBestCandidatePaths(
|
||||
}
|
||||
}
|
||||
|
||||
void CandidatePathsGetter::GetLineCandidates(openlr::LocationReferencePoint const & p,
|
||||
bool const isLastPoint,
|
||||
void CandidatePathsGetter::GetLineCandidates(openlr::LocationReferencePoint const & p, bool const isLastPoint,
|
||||
double const distanceToNextPointM,
|
||||
vector<m2::PointD> const & pointCandidates,
|
||||
vector<Graph::EdgeVector> & candidates)
|
||||
@@ -280,8 +267,8 @@ void CandidatePathsGetter::GetLineCandidates(openlr::LocationReferencePoint cons
|
||||
auto const startPoint = mercator::FromLatLon(p.m_latLon);
|
||||
|
||||
vector<LinkPtr> allPaths;
|
||||
GetAllSuitablePaths(startLines, isLastPoint, bearDistM, p.m_functionalRoadClass, p.m_formOfWay,
|
||||
distanceToNextPointM, allPaths);
|
||||
GetAllSuitablePaths(startLines, isLastPoint, bearDistM, p.m_functionalRoadClass, p.m_formOfWay, distanceToNextPointM,
|
||||
allPaths);
|
||||
GetBestCandidatePaths(allPaths, isLastPoint, p.m_bearing, bearDistM, startPoint, candidates);
|
||||
LOG(LDEBUG, (candidates.size(), "candidate paths found for point (LatLon)", p.m_latLon));
|
||||
}
|
||||
|
||||
@@ -20,11 +20,13 @@ class CandidatePointsGetter;
|
||||
class CandidatePathsGetter
|
||||
{
|
||||
public:
|
||||
CandidatePathsGetter(CandidatePointsGetter & pointsGetter, Graph & graph,
|
||||
RoadInfoGetter & infoGetter, v2::Stats & stat)
|
||||
: m_pointsGetter(pointsGetter), m_graph(graph), m_infoGetter(infoGetter), m_stats(stat)
|
||||
{
|
||||
}
|
||||
CandidatePathsGetter(CandidatePointsGetter & pointsGetter, Graph & graph, RoadInfoGetter & infoGetter,
|
||||
v2::Stats & stat)
|
||||
: m_pointsGetter(pointsGetter)
|
||||
, m_graph(graph)
|
||||
, m_infoGetter(infoGetter)
|
||||
, m_stats(stat)
|
||||
{}
|
||||
|
||||
bool GetLineCandidatesForPoints(std::vector<LocationReferencePoint> const & points,
|
||||
std::vector<std::vector<Graph::EdgeVector>> & lineCandidates);
|
||||
@@ -44,8 +46,7 @@ private:
|
||||
, m_edge(edge)
|
||||
, m_distanceM(distanceM)
|
||||
, m_hasFake((parent && parent->m_hasFake) || edge.IsFake())
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
bool IsPointOnPath(geometry::PointWithAltitude const & point) const;
|
||||
|
||||
@@ -71,8 +72,7 @@ private:
|
||||
, m_bearingDiff(bearingDiff)
|
||||
, m_pathDistanceDiff(pathDistanceDiff)
|
||||
, m_startPointDistance(startPointDistance)
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
bool operator<(CandidatePath const & o) const { return GetPenalty() < o.GetPenalty(); }
|
||||
|
||||
@@ -102,21 +102,18 @@ private:
|
||||
// distance-to-next point is taken from point 3. You can learn more in
|
||||
// TomTom OpenLR spec.
|
||||
|
||||
void GetStartLines(std::vector<m2::PointD> const & points, bool const isLastPoint,
|
||||
Graph::EdgeVector & edges);
|
||||
void GetStartLines(std::vector<m2::PointD> const & points, bool const isLastPoint, Graph::EdgeVector & edges);
|
||||
|
||||
void GetAllSuitablePaths(Graph::EdgeVector const & startLines, bool isLastPoint, double bearDistM,
|
||||
FunctionalRoadClass functionalRoadClass, FormOfWay formOfWay,
|
||||
double distanceToNextPointM, std::vector<LinkPtr> & allPaths);
|
||||
FunctionalRoadClass functionalRoadClass, FormOfWay formOfWay, double distanceToNextPointM,
|
||||
std::vector<LinkPtr> & allPaths);
|
||||
|
||||
void GetBestCandidatePaths(std::vector<LinkPtr> const & allPaths, bool const isLastPoint,
|
||||
uint32_t const requiredBearing, double const bearDistM,
|
||||
m2::PointD const & startPoint,
|
||||
uint32_t const requiredBearing, double const bearDistM, m2::PointD const & startPoint,
|
||||
std::vector<Graph::EdgeVector> & candidates);
|
||||
|
||||
void GetLineCandidates(openlr::LocationReferencePoint const & p, bool const isLastPoint,
|
||||
double const distanceToNextPointM,
|
||||
std::vector<m2::PointD> const & pointCandidates,
|
||||
double const distanceToNextPointM, std::vector<m2::PointD> const & pointCandidates,
|
||||
std::vector<Graph::EdgeVector> & candidates);
|
||||
|
||||
CandidatePointsGetter & m_pointsGetter;
|
||||
|
||||
@@ -18,22 +18,21 @@ using namespace routing;
|
||||
|
||||
namespace openlr
|
||||
{
|
||||
void CandidatePointsGetter::FillJunctionPointCandidates(m2::PointD const & p,
|
||||
std::vector<m2::PointD> & candidates)
|
||||
void CandidatePointsGetter::FillJunctionPointCandidates(m2::PointD const & p, std::vector<m2::PointD> & candidates)
|
||||
{
|
||||
// TODO(mgsergio): Get optimal value using experiments on a sample.
|
||||
// Or start with small radius and scale it up when there are too few points.
|
||||
size_t const kRectSideMeters = 110;
|
||||
|
||||
auto const rect = mercator::RectByCenterXYAndSizeInMeters(p, kRectSideMeters);
|
||||
auto const selectCandidates = [&rect, &candidates](FeatureType & ft) {
|
||||
auto const selectCandidates = [&rect, &candidates](FeatureType & ft)
|
||||
{
|
||||
ft.ParseGeometry(FeatureType::BEST_GEOMETRY);
|
||||
ft.ForEachPoint(
|
||||
[&rect, &candidates](m2::PointD const & candidate) {
|
||||
if (rect.IsPointInside(candidate))
|
||||
candidates.emplace_back(candidate);
|
||||
},
|
||||
scales::GetUpperScale());
|
||||
ft.ForEachPoint([&rect, &candidates](m2::PointD const & candidate)
|
||||
{
|
||||
if (rect.IsPointInside(candidate))
|
||||
candidates.emplace_back(candidate);
|
||||
}, scales::GetUpperScale());
|
||||
};
|
||||
|
||||
m_dataSource.ForEachInRect(selectCandidates, rect, scales::GetUpperScale());
|
||||
@@ -44,17 +43,14 @@ void CandidatePointsGetter::FillJunctionPointCandidates(m2::PointD const & p,
|
||||
// later. The idea to fix this was to move SortUnique to the stage
|
||||
// after enriching with projections.
|
||||
|
||||
base::SortUnique(candidates,
|
||||
[&p](m2::PointD const & a, m2::PointD const & b) {
|
||||
return mercator::DistanceOnEarth(a, p) < mercator::DistanceOnEarth(b, p);
|
||||
},
|
||||
base::SortUnique(candidates, [&p](m2::PointD const & a, m2::PointD const & b)
|
||||
{ return mercator::DistanceOnEarth(a, p) < mercator::DistanceOnEarth(b, p); },
|
||||
[](m2::PointD const & a, m2::PointD const & b) { return a == b; });
|
||||
|
||||
candidates.resize(std::min(m_maxJunctionCandidates, candidates.size()));
|
||||
}
|
||||
|
||||
void CandidatePointsGetter::EnrichWithProjectionPoints(m2::PointD const & p,
|
||||
std::vector<m2::PointD> & candidates)
|
||||
void CandidatePointsGetter::EnrichWithProjectionPoints(m2::PointD const & p, std::vector<m2::PointD> & candidates)
|
||||
{
|
||||
m_graph.ResetFakes();
|
||||
|
||||
|
||||
@@ -22,8 +22,7 @@ public:
|
||||
, m_maxProjectionCandidates(maxProjectionCandidates)
|
||||
, m_dataSource(dataSource)
|
||||
, m_graph(graph)
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
void GetCandidatePoints(m2::PointD const & p, std::vector<m2::PointD> & candidates)
|
||||
{
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
#define THROW_IF_NODE_IS_EMPTY(node, exc, msg) \
|
||||
if (!node) \
|
||||
MYTHROW(exc, msg)
|
||||
MYTHROW(exc, msg)
|
||||
|
||||
namespace
|
||||
{
|
||||
@@ -81,10 +81,7 @@ void WriteAsMappingForSpark(std::string const & fileName, std::vector<DecodedPat
|
||||
WriteAsMappingForSpark(ofs, paths);
|
||||
|
||||
if (ofs.fail())
|
||||
{
|
||||
MYTHROW(DecodedPathSaveError,
|
||||
("An error occured while writing file", fileName, strerror(errno)));
|
||||
}
|
||||
MYTHROW(DecodedPathSaveError, ("An error occured while writing file", fileName, strerror(errno)));
|
||||
}
|
||||
|
||||
void WriteAsMappingForSpark(std::ostream & ost, std::vector<DecodedPath> const & paths)
|
||||
@@ -105,11 +102,9 @@ void WriteAsMappingForSpark(std::ostream & ost, std::vector<DecodedPath> const &
|
||||
for (auto it = std::begin(p.m_path); it != std::end(p.m_path); ++it)
|
||||
{
|
||||
auto const & fid = it->GetFeatureId();
|
||||
ost << fid.m_mwmId.GetInfo()->GetCountryName()
|
||||
<< kFieldSep << fid.m_index
|
||||
<< kFieldSep << it->GetSegId()
|
||||
<< kFieldSep << (it->IsForward() ? "fwd" : "bwd")
|
||||
<< kFieldSep << mercator::DistanceOnEarth(GetStart(*it), GetEnd(*it));
|
||||
ost << fid.m_mwmId.GetInfo()->GetCountryName() << kFieldSep << fid.m_index << kFieldSep << it->GetSegId()
|
||||
<< kFieldSep << (it->IsForward() ? "fwd" : "bwd") << kFieldSep
|
||||
<< mercator::DistanceOnEarth(GetStart(*it), GetEnd(*it));
|
||||
|
||||
if (std::next(it) != std::end(p.m_path))
|
||||
ost << kSegmentSep;
|
||||
@@ -135,10 +130,10 @@ void PathFromXML(pugi::xml_node const & node, DataSource const & dataSource, Pat
|
||||
LatLonFromXML(e.child("StartJunction"), start);
|
||||
LatLonFromXML(e.child("EndJunction"), end);
|
||||
|
||||
p.push_back(Edge::MakeReal(
|
||||
fid, isForward, segmentId,
|
||||
geometry::PointWithAltitude(mercator::FromLatLon(start), geometry::kDefaultAltitudeMeters),
|
||||
geometry::PointWithAltitude(mercator::FromLatLon(end), geometry::kDefaultAltitudeMeters)));
|
||||
p.push_back(
|
||||
Edge::MakeReal(fid, isForward, segmentId,
|
||||
geometry::PointWithAltitude(mercator::FromLatLon(start), geometry::kDefaultAltitudeMeters),
|
||||
geometry::PointWithAltitude(mercator::FromLatLon(end), geometry::kDefaultAltitudeMeters)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -42,8 +42,14 @@ void PathToXML(Path const & path, pugi::xml_node & node);
|
||||
|
||||
namespace routing
|
||||
{
|
||||
inline m2::PointD GetStart(Edge const & e) { return e.GetStartJunction().GetPoint(); }
|
||||
inline m2::PointD GetEnd(Edge const & e) { return e.GetEndJunction().GetPoint(); }
|
||||
inline m2::PointD GetStart(Edge const & e)
|
||||
{
|
||||
return e.GetStartJunction().GetPoint();
|
||||
}
|
||||
inline m2::PointD GetEnd(Edge const & e)
|
||||
{
|
||||
return e.GetEndJunction().GetPoint();
|
||||
}
|
||||
|
||||
std::vector<m2::PointD> GetPoints(routing::RoadGraphBase::EdgeVector const & p);
|
||||
} // namespace routing
|
||||
|
||||
@@ -15,13 +15,10 @@ namespace openlr
|
||||
{
|
||||
namespace
|
||||
{
|
||||
using EdgeGetter = void (IRoadGraph::*)(geometry::PointWithAltitude const &,
|
||||
RoadGraphBase::EdgeListT &) const;
|
||||
using EdgeGetter = void (IRoadGraph::*)(geometry::PointWithAltitude const &, RoadGraphBase::EdgeListT &) const;
|
||||
|
||||
void GetRegularEdges(geometry::PointWithAltitude const & junction, IRoadGraph const & graph,
|
||||
EdgeGetter const edgeGetter,
|
||||
Graph::EdgeCacheT & cache,
|
||||
Graph::EdgeListT & edges)
|
||||
EdgeGetter const edgeGetter, Graph::EdgeCacheT & cache, Graph::EdgeListT & edges)
|
||||
{
|
||||
auto const it = cache.find(junction);
|
||||
if (it == end(cache))
|
||||
@@ -39,9 +36,9 @@ void GetRegularEdges(geometry::PointWithAltitude const & junction, IRoadGraph co
|
||||
} // namespace
|
||||
|
||||
Graph::Graph(DataSource & dataSource, shared_ptr<CarModelFactory> carModelFactory)
|
||||
: m_dataSource(dataSource, nullptr /* numMwmIDs */), m_graph(m_dataSource, IRoadGraph::Mode::ObeyOnewayTag, carModelFactory)
|
||||
{
|
||||
}
|
||||
: m_dataSource(dataSource, nullptr /* numMwmIDs */)
|
||||
, m_graph(m_dataSource, IRoadGraph::Mode::ObeyOnewayTag, carModelFactory)
|
||||
{}
|
||||
|
||||
void Graph::GetOutgoingEdges(Junction const & junction, EdgeListT & edges)
|
||||
{
|
||||
@@ -68,9 +65,8 @@ void Graph::GetRegularIngoingEdges(Junction const & junction, EdgeListT & edges)
|
||||
void Graph::FindClosestEdges(m2::PointD const & point, uint32_t const count,
|
||||
vector<pair<Edge, Junction>> & vicinities) const
|
||||
{
|
||||
m_graph.FindClosestEdges(
|
||||
mercator::RectByCenterXYAndSizeInMeters(point, FeaturesRoadGraph::kClosestEdgesRadiusM),
|
||||
count, vicinities);
|
||||
m_graph.FindClosestEdges(mercator::RectByCenterXYAndSizeInMeters(point, FeaturesRoadGraph::kClosestEdgesRadiusM),
|
||||
count, vicinities);
|
||||
}
|
||||
|
||||
void Graph::AddIngoingFakeEdge(Edge const & e)
|
||||
|
||||
@@ -53,6 +53,7 @@ public:
|
||||
void GetFeatureTypes(FeatureID const & featureId, feature::TypesHolder & types) const;
|
||||
|
||||
using EdgeCacheT = std::map<Junction, EdgeListT>;
|
||||
|
||||
private:
|
||||
routing::MwmDataSource m_dataSource;
|
||||
routing::FeaturesRoadGraph m_graph;
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
#include <optional>
|
||||
#include <sstream>
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
using namespace openlr;
|
||||
@@ -34,8 +33,7 @@ openlr::FunctionalRoadClass HighwayClassToFunctionalRoadClass(ftypes::HighwayCla
|
||||
}
|
||||
|
||||
/// \returns nullopt if |e| doesn't conform to |functionalRoadClass| and score otherwise.
|
||||
optional<Score> GetFrcScore(Graph::Edge const & e, FunctionalRoadClass functionalRoadClass,
|
||||
RoadInfoGetter & infoGetter)
|
||||
optional<Score> GetFrcScore(Graph::Edge const & e, FunctionalRoadClass functionalRoadClass, RoadInfoGetter & infoGetter)
|
||||
{
|
||||
CHECK(!e.IsFake(), ());
|
||||
Score constexpr kMaxScoreForFrc = 25;
|
||||
@@ -54,38 +52,31 @@ optional<Score> GetFrcScore(Graph::Edge const & e, FunctionalRoadClass functiona
|
||||
return hwClass == HighwayClass::Trunk ? optional<Score>(kMaxScoreForFrc) : nullopt;
|
||||
|
||||
case FunctionalRoadClass::FRC1:
|
||||
return (hwClass == HighwayClass::Trunk || hwClass == HighwayClass::Primary)
|
||||
? optional<Score>(kMaxScoreForFrc)
|
||||
: nullopt;
|
||||
return (hwClass == HighwayClass::Trunk || hwClass == HighwayClass::Primary) ? optional<Score>(kMaxScoreForFrc)
|
||||
: nullopt;
|
||||
|
||||
case FunctionalRoadClass::FRC2:
|
||||
case FunctionalRoadClass::FRC3:
|
||||
if (hwClass == HighwayClass::Secondary || hwClass == HighwayClass::Tertiary)
|
||||
return optional<Score>(kMaxScoreForFrc);
|
||||
|
||||
return hwClass == HighwayClass::Primary || hwClass == HighwayClass::LivingStreet
|
||||
? optional<Score>(0)
|
||||
: nullopt;
|
||||
return hwClass == HighwayClass::Primary || hwClass == HighwayClass::LivingStreet ? optional<Score>(0) : nullopt;
|
||||
|
||||
case FunctionalRoadClass::FRC4:
|
||||
if (hwClass == HighwayClass::LivingStreet || hwClass == HighwayClass::Service)
|
||||
return optional<Score>(kMaxScoreForFrc);
|
||||
|
||||
return (hwClass == HighwayClass::Tertiary || hwClass == HighwayClass::Secondary)
|
||||
? optional<Score>(0)
|
||||
: nullopt;
|
||||
return (hwClass == HighwayClass::Tertiary || hwClass == HighwayClass::Secondary) ? optional<Score>(0) : nullopt;
|
||||
|
||||
case FunctionalRoadClass::FRC5:
|
||||
case FunctionalRoadClass::FRC6:
|
||||
case FunctionalRoadClass::FRC7:
|
||||
return (hwClass == HighwayClass::LivingStreet ||
|
||||
hwClass == HighwayClass::Service ||
|
||||
return (hwClass == HighwayClass::LivingStreet || hwClass == HighwayClass::Service ||
|
||||
hwClass == HighwayClass::ServiceMinor)
|
||||
? optional<Score>(kMaxScoreForFrc)
|
||||
: nullopt;
|
||||
? optional<Score>(kMaxScoreForFrc)
|
||||
: nullopt;
|
||||
|
||||
case FunctionalRoadClass::NotAValue:
|
||||
UNREACHABLE();
|
||||
case FunctionalRoadClass::NotAValue: UNREACHABLE();
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
@@ -95,9 +86,9 @@ namespace openlr
|
||||
{
|
||||
// BearingPointsSelector ---------------------------------------------------------------------------
|
||||
BearingPointsSelector::BearingPointsSelector(uint32_t bearDistM, bool isLastPoint)
|
||||
: m_bearDistM(bearDistM), m_isLastPoint(isLastPoint)
|
||||
{
|
||||
}
|
||||
: m_bearDistM(bearDistM)
|
||||
, m_isLastPoint(isLastPoint)
|
||||
{}
|
||||
|
||||
m2::PointD BearingPointsSelector::GetStartPoint(Graph::Edge const & e) const
|
||||
{
|
||||
@@ -131,8 +122,7 @@ double EdgeLength(Graph::Edge const & e)
|
||||
bool EdgesAreAlmostEqual(Graph::Edge const & e1, Graph::Edge const & e2)
|
||||
{
|
||||
// TODO(mgsergio): Do I need to check fields other than points?
|
||||
return PointsAreClose(e1.GetStartPoint(), e2.GetStartPoint()) &&
|
||||
PointsAreClose(e1.GetEndPoint(), e2.GetEndPoint());
|
||||
return PointsAreClose(e1.GetStartPoint(), e2.GetStartPoint()) && PointsAreClose(e1.GetEndPoint(), e2.GetEndPoint());
|
||||
}
|
||||
|
||||
string LogAs2GisPath(Graph::EdgeVector const & path)
|
||||
@@ -157,10 +147,13 @@ string LogAs2GisPath(Graph::EdgeVector const & path)
|
||||
return ost.str();
|
||||
}
|
||||
|
||||
string LogAs2GisPath(Graph::Edge const & e) { return LogAs2GisPath(Graph::EdgeVector({e})); }
|
||||
string LogAs2GisPath(Graph::Edge const & e)
|
||||
{
|
||||
return LogAs2GisPath(Graph::EdgeVector({e}));
|
||||
}
|
||||
|
||||
bool PassesRestriction(Graph::Edge const & e, FunctionalRoadClass restriction, FormOfWay formOfWay,
|
||||
int frcThreshold, RoadInfoGetter & infoGetter)
|
||||
bool PassesRestriction(Graph::Edge const & e, FunctionalRoadClass restriction, FormOfWay formOfWay, int frcThreshold,
|
||||
RoadInfoGetter & infoGetter)
|
||||
{
|
||||
if (e.IsFake() || restriction == FunctionalRoadClass::NotAValue)
|
||||
return true;
|
||||
@@ -169,8 +162,8 @@ bool PassesRestriction(Graph::Edge const & e, FunctionalRoadClass restriction, F
|
||||
return static_cast<int>(frc) <= static_cast<int>(restriction) + frcThreshold;
|
||||
}
|
||||
|
||||
bool PassesRestrictionV3(Graph::Edge const & e, FunctionalRoadClass functionalRoadClass,
|
||||
FormOfWay formOfWay, RoadInfoGetter & infoGetter, Score & score)
|
||||
bool PassesRestrictionV3(Graph::Edge const & e, FunctionalRoadClass functionalRoadClass, FormOfWay formOfWay,
|
||||
RoadInfoGetter & infoGetter, Score & score)
|
||||
{
|
||||
CHECK(!e.IsFake(), ("Edges should not be fake:", e));
|
||||
auto const frcScore = GetFrcScore(e, functionalRoadClass, infoGetter);
|
||||
@@ -185,8 +178,8 @@ bool PassesRestrictionV3(Graph::Edge const & e, FunctionalRoadClass functionalRo
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ConformLfrcnp(Graph::Edge const & e, FunctionalRoadClass lowestFrcToNextPoint,
|
||||
int frcThreshold, RoadInfoGetter & infoGetter)
|
||||
bool ConformLfrcnp(Graph::Edge const & e, FunctionalRoadClass lowestFrcToNextPoint, int frcThreshold,
|
||||
RoadInfoGetter & infoGetter)
|
||||
{
|
||||
if (e.IsFake() || lowestFrcToNextPoint == FunctionalRoadClass::NotAValue)
|
||||
return true;
|
||||
@@ -195,8 +188,7 @@ bool ConformLfrcnp(Graph::Edge const & e, FunctionalRoadClass lowestFrcToNextPoi
|
||||
return static_cast<int>(frc) <= static_cast<int>(lowestFrcToNextPoint) + frcThreshold;
|
||||
}
|
||||
|
||||
bool ConformLfrcnpV3(Graph::Edge const & e, FunctionalRoadClass lowestFrcToNextPoint,
|
||||
RoadInfoGetter & infoGetter)
|
||||
bool ConformLfrcnpV3(Graph::Edge const & e, FunctionalRoadClass lowestFrcToNextPoint, RoadInfoGetter & infoGetter)
|
||||
{
|
||||
return GetFrcScore(e, lowestFrcToNextPoint, infoGetter).has_value();
|
||||
}
|
||||
|
||||
@@ -38,27 +38,25 @@ bool EdgesAreAlmostEqual(Graph::Edge const & e1, Graph::Edge const & e2);
|
||||
std::string LogAs2GisPath(Graph::EdgeVector const & path);
|
||||
std::string LogAs2GisPath(Graph::Edge const & e);
|
||||
|
||||
template <typename T, typename U,
|
||||
std::enable_if_t<!(std::is_signed<T>::value ^ std::is_signed<U>::value), int> = 0>
|
||||
template <typename T, typename U, std::enable_if_t<!(std::is_signed<T>::value ^ std::is_signed<U>::value), int> = 0>
|
||||
std::common_type_t<T, U> AbsDifference(T const a, U const b)
|
||||
{
|
||||
return a >= b ? a - b : b - a;
|
||||
}
|
||||
|
||||
bool PassesRestriction(Graph::Edge const & e, FunctionalRoadClass restriction, FormOfWay formOfWay,
|
||||
int frcThreshold, RoadInfoGetter & infoGetter);
|
||||
bool PassesRestriction(Graph::Edge const & e, FunctionalRoadClass restriction, FormOfWay formOfWay, int frcThreshold,
|
||||
RoadInfoGetter & infoGetter);
|
||||
/// \returns true if |e| conforms |functionalRoadClass| and |formOfWay| and false otherwise.
|
||||
/// \note If the method returns true |score| should be considered next.
|
||||
bool PassesRestrictionV3(Graph::Edge const & e, FunctionalRoadClass functionalRoadClass,
|
||||
FormOfWay formOfWay, RoadInfoGetter & infoGetter, Score & score);
|
||||
bool PassesRestrictionV3(Graph::Edge const & e, FunctionalRoadClass functionalRoadClass, FormOfWay formOfWay,
|
||||
RoadInfoGetter & infoGetter, Score & score);
|
||||
|
||||
/// \returns true if edge |e| conforms Lowest Functional Road Class to Next Point.
|
||||
/// \note frc means Functional Road Class. Please see openlr documentation for details:
|
||||
/// http://www.openlr.org/data/docs/whitepaper/1_0/OpenLR-Whitepaper_v1.0.pdf
|
||||
bool ConformLfrcnp(Graph::Edge const & e, FunctionalRoadClass lowestFrcToNextPoint,
|
||||
int frcThreshold, RoadInfoGetter & infoGetter);
|
||||
bool ConformLfrcnpV3(Graph::Edge const & e, FunctionalRoadClass lowestFrcToNextPoint,
|
||||
RoadInfoGetter & infoGetter);
|
||||
bool ConformLfrcnp(Graph::Edge const & e, FunctionalRoadClass lowestFrcToNextPoint, int frcThreshold,
|
||||
RoadInfoGetter & infoGetter);
|
||||
bool ConformLfrcnpV3(Graph::Edge const & e, FunctionalRoadClass lowestFrcToNextPoint, RoadInfoGetter & infoGetter);
|
||||
|
||||
size_t IntersectionLen(Graph::EdgeVector a, Graph::EdgeVector b);
|
||||
|
||||
|
||||
@@ -90,17 +90,15 @@ bool IsRealVertex(m2::PointD const & p, FeatureID const & fid, DataSource const
|
||||
FeaturesLoaderGuard g(dataSource, fid.m_mwmId);
|
||||
auto const ft = g.GetOriginalFeatureByIndex(fid.m_index);
|
||||
bool matched = false;
|
||||
ft->ForEachPoint(
|
||||
[&p, &matched](m2::PointD const & fp) {
|
||||
if (p == fp)
|
||||
matched = true;
|
||||
},
|
||||
FeatureType::BEST_GEOMETRY);
|
||||
ft->ForEachPoint([&p, &matched](m2::PointD const & fp)
|
||||
{
|
||||
if (p == fp)
|
||||
matched = true;
|
||||
}, FeatureType::BEST_GEOMETRY);
|
||||
return matched;
|
||||
}
|
||||
|
||||
void ExpandFake(Graph::EdgeVector & path, Graph::EdgeVector::iterator edgeIt, DataSource const & dataSource,
|
||||
Graph & g)
|
||||
void ExpandFake(Graph::EdgeVector & path, Graph::EdgeVector::iterator edgeIt, DataSource const & dataSource, Graph & g)
|
||||
{
|
||||
if (!edgeIt->IsFake())
|
||||
return;
|
||||
@@ -120,16 +118,18 @@ void ExpandFake(Graph::EdgeVector & path, Graph::EdgeVector::iterator edgeIt, Da
|
||||
|
||||
CHECK(!edges.empty(), ());
|
||||
|
||||
auto it = find_if(begin(edges), end(edges), [&edgeIt](Graph::Edge const & real) {
|
||||
if (real.GetFeatureId() == edgeIt->GetFeatureId() && real.GetSegId() == edgeIt->GetSegId())
|
||||
return true;
|
||||
return false;
|
||||
});
|
||||
auto it = find_if(begin(edges), end(edges), [&edgeIt](Graph::Edge const & real)
|
||||
{
|
||||
if (real.GetFeatureId() == edgeIt->GetFeatureId() && real.GetSegId() == edgeIt->GetSegId())
|
||||
return true;
|
||||
return false;
|
||||
});
|
||||
|
||||
// For features which cross mwm border FeatureIds may not match. Check geometry.
|
||||
if (it == end(edges))
|
||||
{
|
||||
it = find_if(begin(edges), end(edges), [&edgeIt, &startIsFake](Graph::Edge const & real) {
|
||||
it = find_if(begin(edges), end(edges), [&edgeIt, &startIsFake](Graph::Edge const & real)
|
||||
{
|
||||
// Features from the same mwm should be already matched.
|
||||
if (real.GetFeatureId().m_mwmId == edgeIt->GetFeatureId().m_mwmId)
|
||||
return false;
|
||||
@@ -170,8 +170,7 @@ void ExpandFakes(DataSource const & dataSource, Graph & g, Graph::EdgeVector & p
|
||||
// to some point along that path and drop everything form the start to that point or from
|
||||
// that point to the end.
|
||||
template <typename InputIterator>
|
||||
InputIterator CutOffset(InputIterator start, InputIterator stop, double offset,
|
||||
bool keepEnd)
|
||||
InputIterator CutOffset(InputIterator start, InputIterator stop, double offset, bool keepEnd)
|
||||
{
|
||||
if (offset == 0.0)
|
||||
return start;
|
||||
@@ -193,8 +192,8 @@ InputIterator CutOffset(InputIterator start, InputIterator stop, double offset,
|
||||
}
|
||||
|
||||
template <typename InputIterator, typename OutputIterator>
|
||||
void CopyWithoutOffsets(InputIterator start, InputIterator stop, OutputIterator out,
|
||||
uint32_t positiveOffset, uint32_t negativeOffset, bool keepEnds)
|
||||
void CopyWithoutOffsets(InputIterator start, InputIterator stop, OutputIterator out, uint32_t positiveOffset,
|
||||
uint32_t negativeOffset, bool keepEnds)
|
||||
{
|
||||
auto from = start;
|
||||
auto to = stop;
|
||||
@@ -203,8 +202,9 @@ void CopyWithoutOffsets(InputIterator start, InputIterator stop, OutputIterator
|
||||
{
|
||||
from = CutOffset(start, stop, positiveOffset, keepEnds);
|
||||
// |to| points past the last edge we need to take.
|
||||
to = CutOffset(reverse_iterator<InputIterator>(stop), reverse_iterator<InputIterator>(start),
|
||||
negativeOffset, keepEnds).base();
|
||||
to = CutOffset(reverse_iterator<InputIterator>(stop), reverse_iterator<InputIterator>(start), negativeOffset,
|
||||
keepEnds)
|
||||
.base();
|
||||
}
|
||||
|
||||
if (!keepEnds)
|
||||
@@ -216,14 +216,14 @@ void CopyWithoutOffsets(InputIterator start, InputIterator stop, OutputIterator
|
||||
copy(from, to, out);
|
||||
}
|
||||
|
||||
|
||||
class SegmentsDecoderV2
|
||||
{
|
||||
public:
|
||||
SegmentsDecoderV2(DataSource & dataSource, unique_ptr<CarModelFactory> cmf)
|
||||
: m_dataSource(dataSource), m_graph(dataSource, std::move(cmf)), m_infoGetter(dataSource)
|
||||
{
|
||||
}
|
||||
: m_dataSource(dataSource)
|
||||
, m_graph(dataSource, std::move(cmf))
|
||||
, m_infoGetter(dataSource)
|
||||
{}
|
||||
|
||||
bool DecodeSegment(LinearSegment const & segment, DecodedPath & path, v2::Stats & stat)
|
||||
{
|
||||
@@ -241,8 +241,7 @@ public:
|
||||
lineCandidates.reserve(points.size());
|
||||
LOG(LDEBUG, ("Decoding segment:", segment.m_segmentId, "with", points.size(), "points"));
|
||||
|
||||
CandidatePointsGetter pointsGetter(kMaxJunctionCandidates, kMaxProjectionCandidates,
|
||||
m_dataSource, m_graph);
|
||||
CandidatePointsGetter pointsGetter(kMaxJunctionCandidates, kMaxProjectionCandidates, m_dataSource, m_graph);
|
||||
CandidatePathsGetter pathsGetter(pointsGetter, m_graph, m_infoGetter, stat);
|
||||
|
||||
if (!pathsGetter.GetLineCandidatesForPoints(points, lineCandidates))
|
||||
@@ -261,7 +260,7 @@ public:
|
||||
// Sum app all distances between points. Last point's m_distanceToNextPoint
|
||||
// should be equal to zero, but let's skip it just in case.
|
||||
CHECK(!points.empty(), ());
|
||||
for (auto it = begin(points); it != prev(end(points)); ++it)
|
||||
for (auto it = begin(points); it != prev(end(points)); ++it)
|
||||
requiredRouteDistanceM += it->m_distanceToNextPoint;
|
||||
|
||||
double actualRouteDistanceM = 0.0;
|
||||
@@ -269,8 +268,8 @@ public:
|
||||
actualRouteDistanceM += EdgeLength(e);
|
||||
|
||||
auto const scale = actualRouteDistanceM / requiredRouteDistanceM;
|
||||
LOG(LDEBUG, ("actualRouteDistance:", actualRouteDistanceM,
|
||||
"requiredRouteDistance:", requiredRouteDistanceM, "scale:", scale));
|
||||
LOG(LDEBUG, ("actualRouteDistance:", actualRouteDistanceM, "requiredRouteDistance:", requiredRouteDistanceM,
|
||||
"scale:", scale));
|
||||
|
||||
auto const positiveOffsetM = segment.m_locationReference.m_positiveOffsetMeters * scale;
|
||||
auto const negativeOffsetM = segment.m_locationReference.m_negativeOffsetMeters * scale;
|
||||
@@ -284,8 +283,8 @@ public:
|
||||
|
||||
ExpandFakes(m_dataSource, m_graph, route);
|
||||
ASSERT(none_of(begin(route), end(route), mem_fn(&Graph::Edge::IsFake)), (segment.m_segmentId));
|
||||
CopyWithoutOffsets(begin(route), end(route), back_inserter(path.m_path), positiveOffsetM,
|
||||
negativeOffsetM, false /* keep ends */);
|
||||
CopyWithoutOffsets(begin(route), end(route), back_inserter(path.m_path), positiveOffsetM, negativeOffsetM,
|
||||
false /* keep ends */);
|
||||
|
||||
if (path.m_path.empty())
|
||||
{
|
||||
@@ -310,9 +309,10 @@ class SegmentsDecoderV3
|
||||
{
|
||||
public:
|
||||
SegmentsDecoderV3(DataSource & dataSource, unique_ptr<CarModelFactory> carModelFactory)
|
||||
: m_dataSource(dataSource), m_graph(dataSource, std::move(carModelFactory)), m_infoGetter(dataSource)
|
||||
{
|
||||
}
|
||||
: m_dataSource(dataSource)
|
||||
, m_graph(dataSource, std::move(carModelFactory))
|
||||
, m_infoGetter(dataSource)
|
||||
{}
|
||||
|
||||
bool DecodeSegment(LinearSegment const & segment, DecodedPath & path, v2::Stats & stat)
|
||||
{
|
||||
@@ -329,8 +329,7 @@ public:
|
||||
lineCandidates.reserve(points.size());
|
||||
LOG(LINFO, ("Decoding segment:", segment.m_segmentId, "with", points.size(), "points"));
|
||||
|
||||
ScoreCandidatePointsGetter pointsGetter(kMaxJunctionCandidates, kMaxProjectionCandidates,
|
||||
m_dataSource, m_graph);
|
||||
ScoreCandidatePointsGetter pointsGetter(kMaxJunctionCandidates, kMaxProjectionCandidates, m_dataSource, m_graph);
|
||||
ScoreCandidatePathsGetter pathsGetter(pointsGetter, m_graph, m_infoGetter, stat);
|
||||
|
||||
if (!pathsGetter.GetLineCandidatesForPoints(points, segment.m_source, lineCandidates))
|
||||
@@ -355,7 +354,7 @@ public:
|
||||
// Sum up all distances between points. Last point's m_distanceToNextPoint
|
||||
// should be equal to zero, but let's skip it just in case.
|
||||
CHECK(!points.empty(), ());
|
||||
for (auto it = points.begin(); it != prev(points.end()); ++it)
|
||||
for (auto it = points.begin(); it != prev(points.end()); ++it)
|
||||
requiredRouteDistanceM += it->m_distanceToNextPoint;
|
||||
|
||||
double actualRouteDistanceM = 0.0;
|
||||
@@ -363,11 +362,10 @@ public:
|
||||
actualRouteDistanceM += EdgeLength(e);
|
||||
|
||||
auto const scale = actualRouteDistanceM / requiredRouteDistanceM;
|
||||
LOG(LINFO, ("actualRouteDistance:", actualRouteDistanceM,
|
||||
"requiredRouteDistance:", requiredRouteDistanceM, "scale:", scale));
|
||||
LOG(LINFO, ("actualRouteDistance:", actualRouteDistanceM, "requiredRouteDistance:", requiredRouteDistanceM,
|
||||
"scale:", scale));
|
||||
|
||||
if (segment.m_locationReference.m_positiveOffsetMeters +
|
||||
segment.m_locationReference.m_negativeOffsetMeters >=
|
||||
if (segment.m_locationReference.m_positiveOffsetMeters + segment.m_locationReference.m_negativeOffsetMeters >=
|
||||
requiredRouteDistanceM)
|
||||
{
|
||||
++stat.m_wrongOffsets;
|
||||
@@ -379,8 +377,8 @@ public:
|
||||
auto const negativeOffsetM = segment.m_locationReference.m_negativeOffsetMeters * scale;
|
||||
|
||||
CHECK(none_of(route.begin(), route.end(), mem_fn(&Graph::Edge::IsFake)), (segment.m_segmentId));
|
||||
CopyWithoutOffsets(route.begin(), route.end(), back_inserter(path.m_path), positiveOffsetM,
|
||||
negativeOffsetM, true /* keep ends */);
|
||||
CopyWithoutOffsets(route.begin(), route.end(), back_inserter(path.m_path), positiveOffsetM, negativeOffsetM,
|
||||
true /* keep ends */);
|
||||
|
||||
if (path.m_path.empty())
|
||||
{
|
||||
@@ -403,16 +401,15 @@ size_t constexpr GetOptimalBatchSize()
|
||||
// This code computes the most optimal (in the sense of cache lines
|
||||
// occupancy) batch size.
|
||||
size_t constexpr a = math::LCM(sizeof(LinearSegment), kCacheLineSize) / sizeof(LinearSegment);
|
||||
size_t constexpr b =
|
||||
math::LCM(sizeof(IRoadGraph::EdgeVector), kCacheLineSize) / sizeof(IRoadGraph::EdgeVector);
|
||||
size_t constexpr b = math::LCM(sizeof(IRoadGraph::EdgeVector), kCacheLineSize) / sizeof(IRoadGraph::EdgeVector);
|
||||
return math::LCM(a, b);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// OpenLRDecoder::SegmentsFilter -------------------------------------------------------------
|
||||
OpenLRDecoder::SegmentsFilter::SegmentsFilter(string const & idsPath,
|
||||
bool const multipointsOnly)
|
||||
: m_idsSet(false), m_multipointsOnly(multipointsOnly)
|
||||
OpenLRDecoder::SegmentsFilter::SegmentsFilter(string const & idsPath, bool const multipointsOnly)
|
||||
: m_idsSet(false)
|
||||
, m_multipointsOnly(multipointsOnly)
|
||||
{
|
||||
if (idsPath.empty())
|
||||
return;
|
||||
@@ -437,9 +434,9 @@ bool OpenLRDecoder::SegmentsFilter::Matches(LinearSegment const & segment) const
|
||||
// OpenLRDecoder -----------------------------------------------------------------------------
|
||||
OpenLRDecoder::OpenLRDecoder(vector<FrozenDataSource> & dataSources,
|
||||
CountryParentNameGetter const & countryParentNameGetter)
|
||||
: m_dataSources(dataSources), m_countryParentNameGetter(countryParentNameGetter)
|
||||
{
|
||||
}
|
||||
: m_dataSources(dataSources)
|
||||
, m_countryParentNameGetter(countryParentNameGetter)
|
||||
{}
|
||||
|
||||
void OpenLRDecoder::DecodeV2(vector<LinearSegment> const & segments, uint32_t const numThreads,
|
||||
vector<DecodedPath> & paths)
|
||||
@@ -447,15 +444,14 @@ void OpenLRDecoder::DecodeV2(vector<LinearSegment> const & segments, uint32_t co
|
||||
Decode<SegmentsDecoderV2, v2::Stats>(segments, numThreads, paths);
|
||||
}
|
||||
|
||||
void OpenLRDecoder::DecodeV3(vector<LinearSegment> const & segments, uint32_t numThreads,
|
||||
vector<DecodedPath> & paths)
|
||||
void OpenLRDecoder::DecodeV3(vector<LinearSegment> const & segments, uint32_t numThreads, vector<DecodedPath> & paths)
|
||||
{
|
||||
Decode<SegmentsDecoderV3, v2::Stats>(segments, numThreads, paths);
|
||||
}
|
||||
|
||||
template <typename Decoder, typename Stats>
|
||||
void OpenLRDecoder::Decode(vector<LinearSegment> const & segments,
|
||||
uint32_t const numThreads, vector<DecodedPath> & paths)
|
||||
void OpenLRDecoder::Decode(vector<LinearSegment> const & segments, uint32_t const numThreads,
|
||||
vector<DecodedPath> & paths)
|
||||
{
|
||||
auto const worker = [&](size_t threadNum, DataSource & dataSource, Stats & stat)
|
||||
{
|
||||
@@ -476,8 +472,7 @@ void OpenLRDecoder::Decode(vector<LinearSegment> const & segments,
|
||||
|
||||
if (stat.m_routesHandled % kProgressFrequency == 0 || i == segments.size() - 1)
|
||||
{
|
||||
LOG(LINFO, ("Thread", threadNum, "processed", stat.m_routesHandled,
|
||||
"failed:", stat.m_routesFailed));
|
||||
LOG(LINFO, ("Thread", threadNum, "processed", stat.m_routesHandled, "failed:", stat.m_routesFailed));
|
||||
timer.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,20 +40,17 @@ public:
|
||||
bool const m_multipointsOnly;
|
||||
};
|
||||
|
||||
OpenLRDecoder(std::vector<FrozenDataSource> & dataSources,
|
||||
CountryParentNameGetter const & countryParentNameGetter);
|
||||
OpenLRDecoder(std::vector<FrozenDataSource> & dataSources, CountryParentNameGetter const & countryParentNameGetter);
|
||||
|
||||
// Maps partner segments to mwm paths. |segments| should be sorted by partner id.
|
||||
void DecodeV2(std::vector<LinearSegment> const & segments, uint32_t const numThreads,
|
||||
std::vector<DecodedPath> & paths);
|
||||
|
||||
void DecodeV3(std::vector<LinearSegment> const & segments, uint32_t numThreads,
|
||||
std::vector<DecodedPath> & paths);
|
||||
void DecodeV3(std::vector<LinearSegment> const & segments, uint32_t numThreads, std::vector<DecodedPath> & paths);
|
||||
|
||||
private:
|
||||
template <typename Decoder, typename Stats>
|
||||
void Decode(std::vector<LinearSegment> const & segments, uint32_t const numThreads,
|
||||
std::vector<DecodedPath> & paths);
|
||||
void Decode(std::vector<LinearSegment> const & segments, uint32_t const numThreads, std::vector<DecodedPath> & paths);
|
||||
|
||||
std::vector<FrozenDataSource> & m_dataSources;
|
||||
CountryParentNameGetter m_countryParentNameGetter;
|
||||
|
||||
@@ -53,48 +53,38 @@ public:
|
||||
: m_framework(framework)
|
||||
, m_drapeApi(m_framework.GetDrapeApi())
|
||||
, m_bm(framework.GetBookmarkManager())
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
void SetViewportCenter(m2::PointD const & center) override
|
||||
{
|
||||
m_framework.SetViewportCenter(center);
|
||||
}
|
||||
void SetViewportCenter(m2::PointD const & center) override { m_framework.SetViewportCenter(center); }
|
||||
|
||||
void DrawDecodedSegments(std::vector<m2::PointD> const & points) override
|
||||
{
|
||||
CHECK(!points.empty(), ("Points must not be empty."));
|
||||
|
||||
LOG(LINFO, ("Decoded segment", points));
|
||||
m_drapeApi.AddLine(kDecodedLineId,
|
||||
df::DrapeApiLineData(points, dp::Color(0, 0, 255, 255))
|
||||
.Width(3.0f).ShowPoints(true /* markPoints */));
|
||||
m_drapeApi.AddLine(
|
||||
kDecodedLineId,
|
||||
df::DrapeApiLineData(points, dp::Color(0, 0, 255, 255)).Width(3.0f).ShowPoints(true /* markPoints */));
|
||||
}
|
||||
|
||||
void DrawEncodedSegment(std::vector<m2::PointD> const & points) override
|
||||
{
|
||||
LOG(LINFO, ("Encoded segment", points));
|
||||
m_drapeApi.AddLine(kEncodedLineId,
|
||||
df::DrapeApiLineData(points, dp::Color(255, 0, 0, 255))
|
||||
.Width(3.0f).ShowPoints(true /* markPoints */));
|
||||
m_drapeApi.AddLine(
|
||||
kEncodedLineId,
|
||||
df::DrapeApiLineData(points, dp::Color(255, 0, 0, 255)).Width(3.0f).ShowPoints(true /* markPoints */));
|
||||
}
|
||||
|
||||
void DrawGoldenPath(std::vector<m2::PointD> const & points) override
|
||||
{
|
||||
m_drapeApi.AddLine(kGoldenLineId,
|
||||
df::DrapeApiLineData(points, dp::Color(255, 127, 36, 255))
|
||||
.Width(4.0f).ShowPoints(true /* markPoints */));
|
||||
m_drapeApi.AddLine(
|
||||
kGoldenLineId,
|
||||
df::DrapeApiLineData(points, dp::Color(255, 127, 36, 255)).Width(4.0f).ShowPoints(true /* markPoints */));
|
||||
}
|
||||
|
||||
void ClearGoldenPath() override
|
||||
{
|
||||
m_drapeApi.RemoveLine(kGoldenLineId);
|
||||
}
|
||||
void ClearGoldenPath() override { m_drapeApi.RemoveLine(kGoldenLineId); }
|
||||
|
||||
void ClearAllPaths() override
|
||||
{
|
||||
m_drapeApi.Clear();
|
||||
}
|
||||
void ClearAllPaths() override { m_drapeApi.Clear(); }
|
||||
|
||||
void VisualizePoints(std::vector<m2::PointD> const & points) override
|
||||
{
|
||||
@@ -104,10 +94,7 @@ public:
|
||||
editSession.CreateUserMark<DebugMarkPoint>(p);
|
||||
}
|
||||
|
||||
void ClearAllVisualizedPoints() override
|
||||
{
|
||||
m_bm.GetEditSession().ClearGroup(UserMark::Type::DEBUG_MARK);
|
||||
}
|
||||
void ClearAllVisualizedPoints() override { m_bm.GetEditSession().ClearGroup(UserMark::Type::DEBUG_MARK); }
|
||||
|
||||
private:
|
||||
Framework & m_framework;
|
||||
@@ -129,8 +116,7 @@ public:
|
||||
, m_dataSource(const_cast<DataSource &>(GetDataSource()), nullptr /* numMwmIDs */)
|
||||
, m_roadGraph(m_dataSource, routing::IRoadGraph::Mode::ObeyOnewayTag,
|
||||
std::make_unique<routing::CarModelFactory>(storage::CountryParentGetter{}))
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
std::vector<m2::PointD> GetAllJunctionPointsInViewport() const override
|
||||
{
|
||||
@@ -141,10 +127,8 @@ public:
|
||||
if (!rect.IsPointInside(point))
|
||||
return;
|
||||
for (auto const & p : points)
|
||||
{
|
||||
if (PointsMatch(point, p))
|
||||
return;
|
||||
}
|
||||
points.push_back(point);
|
||||
};
|
||||
|
||||
@@ -155,11 +139,8 @@ public:
|
||||
|
||||
/// @todo Transported (railway=rail) are also present here :)
|
||||
auto const roadClass = ftypes::GetHighwayClass(feature::TypesHolder(ft));
|
||||
if (roadClass == ftypes::HighwayClass::Undefined ||
|
||||
roadClass == ftypes::HighwayClass::Pedestrian)
|
||||
{
|
||||
if (roadClass == ftypes::HighwayClass::Undefined || roadClass == ftypes::HighwayClass::Pedestrian)
|
||||
return;
|
||||
}
|
||||
ft.ForEachPoint(pushPoint, scales::GetUpperScale());
|
||||
};
|
||||
|
||||
@@ -167,8 +148,7 @@ public:
|
||||
return points;
|
||||
}
|
||||
|
||||
std::pair<std::vector<FeaturePoint>, m2::PointD> GetCandidatePoints(
|
||||
m2::PointD const & p) const override
|
||||
std::pair<std::vector<FeaturePoint>, m2::PointD> GetCandidatePoints(m2::PointD const & p) const override
|
||||
{
|
||||
auto constexpr kInvalidIndex = std::numeric_limits<size_t>::max();
|
||||
|
||||
@@ -207,8 +187,7 @@ public:
|
||||
std::vector<m2::PointD> GetReachablePoints(m2::PointD const & p) const override
|
||||
{
|
||||
routing::FeaturesRoadGraph::EdgeListT edges;
|
||||
m_roadGraph.GetOutgoingEdges(geometry::PointWithAltitude(p, geometry::kDefaultAltitudeMeters),
|
||||
edges);
|
||||
m_roadGraph.GetOutgoingEdges(geometry::PointWithAltitude(p, geometry::kDefaultAltitudeMeters), edges);
|
||||
|
||||
std::vector<m2::PointD> points;
|
||||
for (auto const & e : edges)
|
||||
@@ -216,8 +195,7 @@ public:
|
||||
return points;
|
||||
}
|
||||
|
||||
ClickType CheckClick(m2::PointD const & clickPoint,
|
||||
m2::PointD const & lastClickedPoint,
|
||||
ClickType CheckClick(m2::PointD const & clickPoint, m2::PointD const & lastClickedPoint,
|
||||
std::vector<m2::PointD> const & reachablePoints) const override
|
||||
{
|
||||
// == Comparison is safe here since |clickPoint| is adjusted by GetFeaturesPointsByPoint
|
||||
@@ -225,10 +203,8 @@ public:
|
||||
if (clickPoint == lastClickedPoint)
|
||||
return ClickType::Remove;
|
||||
for (auto const & p : reachablePoints)
|
||||
{
|
||||
if (PointsMatch(clickPoint, p))
|
||||
return ClickType::Add;
|
||||
}
|
||||
return ClickType::Miss;
|
||||
}
|
||||
|
||||
@@ -241,9 +217,7 @@ private:
|
||||
};
|
||||
} // namespace
|
||||
|
||||
|
||||
MainWindow::MainWindow(Framework & framework)
|
||||
: m_framework(framework)
|
||||
MainWindow::MainWindow(Framework & framework) : m_framework(framework)
|
||||
{
|
||||
m_mapWidget = new MapWidget(m_framework, this /* parent */);
|
||||
|
||||
@@ -264,37 +238,37 @@ MainWindow::MainWindow(Framework & framework)
|
||||
|
||||
fileMenu->addAction("Open sample", QKeySequence("Ctrl+O"), this, &MainWindow::OnOpenTrafficSample);
|
||||
|
||||
m_closeTrafficSampleAction = fileMenu->addAction("Close sample", QKeySequence("Ctrl+W"), this, &MainWindow::OnCloseTrafficSample);
|
||||
m_saveTrafficSampleAction = fileMenu->addAction("Save sample", QKeySequence("Ctrl+S"), this, &MainWindow::OnSaveTrafficSample);
|
||||
m_closeTrafficSampleAction =
|
||||
fileMenu->addAction("Close sample", QKeySequence("Ctrl+W"), this, &MainWindow::OnCloseTrafficSample);
|
||||
m_saveTrafficSampleAction =
|
||||
fileMenu->addAction("Save sample", QKeySequence("Ctrl+S"), this, &MainWindow::OnSaveTrafficSample);
|
||||
|
||||
fileMenu->addSeparator();
|
||||
|
||||
m_goldifyMatchedPathAction = fileMenu->addAction("Goldify", QKeySequence("Ctrl+G"), [this] { m_trafficMode->GoldifyMatchedPath(); });
|
||||
m_startEditingAction = fileMenu->addAction("Edit", QKeySequence("Ctrl+E"),
|
||||
[this] {
|
||||
m_trafficMode->StartBuildingPath();
|
||||
m_mapWidget->SetMode(MapWidget::Mode::TrafficMarkup);
|
||||
m_commitPathAction->setEnabled(true /* enabled */);
|
||||
m_cancelPathAction->setEnabled(true /* enabled */);
|
||||
});
|
||||
m_commitPathAction = fileMenu->addAction("Accept path",
|
||||
QKeySequence("Ctrl+A"),
|
||||
[this] {
|
||||
m_trafficMode->CommitPath();
|
||||
m_mapWidget->SetMode(MapWidget::Mode::Normal);
|
||||
});
|
||||
m_cancelPathAction = fileMenu->addAction("Revert path",
|
||||
QKeySequence("Ctrl+R"),
|
||||
[this] {
|
||||
m_trafficMode->RollBackPath();
|
||||
m_mapWidget->SetMode(MapWidget::Mode::Normal);
|
||||
});
|
||||
m_ignorePathAction = fileMenu->addAction("Ignore path",
|
||||
QKeySequence("Ctrl+I"),
|
||||
[this] {
|
||||
m_trafficMode->IgnorePath();
|
||||
m_mapWidget->SetMode(MapWidget::Mode::Normal);
|
||||
});
|
||||
m_goldifyMatchedPathAction =
|
||||
fileMenu->addAction("Goldify", QKeySequence("Ctrl+G"), [this] { m_trafficMode->GoldifyMatchedPath(); });
|
||||
m_startEditingAction = fileMenu->addAction("Edit", QKeySequence("Ctrl+E"), [this]
|
||||
{
|
||||
m_trafficMode->StartBuildingPath();
|
||||
m_mapWidget->SetMode(MapWidget::Mode::TrafficMarkup);
|
||||
m_commitPathAction->setEnabled(true /* enabled */);
|
||||
m_cancelPathAction->setEnabled(true /* enabled */);
|
||||
});
|
||||
m_commitPathAction = fileMenu->addAction("Accept path", QKeySequence("Ctrl+A"), [this]
|
||||
{
|
||||
m_trafficMode->CommitPath();
|
||||
m_mapWidget->SetMode(MapWidget::Mode::Normal);
|
||||
});
|
||||
m_cancelPathAction = fileMenu->addAction("Revert path", QKeySequence("Ctrl+R"), [this]
|
||||
{
|
||||
m_trafficMode->RollBackPath();
|
||||
m_mapWidget->SetMode(MapWidget::Mode::Normal);
|
||||
});
|
||||
m_ignorePathAction = fileMenu->addAction("Ignore path", QKeySequence("Ctrl+I"), [this]
|
||||
{
|
||||
m_trafficMode->IgnorePath();
|
||||
m_mapWidget->SetMode(MapWidget::Mode::Normal);
|
||||
});
|
||||
|
||||
m_goldifyMatchedPathAction->setEnabled(false /* enabled */);
|
||||
m_closeTrafficSampleAction->setEnabled(false /* enabled */);
|
||||
@@ -307,15 +281,12 @@ MainWindow::MainWindow(Framework & framework)
|
||||
|
||||
void MainWindow::CreateTrafficPanel(std::string const & dataFilePath)
|
||||
{
|
||||
m_trafficMode = new TrafficMode(dataFilePath,
|
||||
m_framework.GetDataSource(),
|
||||
std::make_unique<TrafficDrawerDelegate>(m_framework),
|
||||
std::make_unique<PointsControllerDelegate>(m_framework));
|
||||
m_trafficMode =
|
||||
new TrafficMode(dataFilePath, m_framework.GetDataSource(), std::make_unique<TrafficDrawerDelegate>(m_framework),
|
||||
std::make_unique<PointsControllerDelegate>(m_framework));
|
||||
|
||||
connect(m_mapWidget, &MapWidget::TrafficMarkupClick,
|
||||
m_trafficMode, &TrafficMode::OnClick);
|
||||
connect(m_trafficMode, &TrafficMode::EditingStopped,
|
||||
this, &MainWindow::OnPathEditingStop);
|
||||
connect(m_mapWidget, &MapWidget::TrafficMarkupClick, m_trafficMode, &TrafficMode::OnClick);
|
||||
connect(m_trafficMode, &TrafficMode::EditingStopped, this, &MainWindow::OnPathEditingStop);
|
||||
connect(m_trafficMode, &TrafficMode::SegmentSelected,
|
||||
[](int segmentId) { QApplication::clipboard()->setText(QString::number(segmentId)); });
|
||||
|
||||
@@ -391,11 +362,7 @@ void MainWindow::OnSaveTrafficSample()
|
||||
return;
|
||||
|
||||
if (!m_trafficMode->SaveSampleAs(fileName.toStdString()))
|
||||
{
|
||||
QMessageBox::critical(
|
||||
this, "Saving error",
|
||||
QString("Can't save file: ") + strerror(errno));
|
||||
}
|
||||
QMessageBox::critical(this, "Saving error", QString("Can't save file: ") + strerror(errno));
|
||||
}
|
||||
|
||||
void MainWindow::OnPathEditingStop()
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace openlr
|
||||
class MapWidget;
|
||||
class TrafficMode;
|
||||
class WebView;
|
||||
}
|
||||
} // namespace openlr
|
||||
|
||||
namespace df
|
||||
{
|
||||
@@ -52,7 +52,7 @@ private:
|
||||
QAction * m_saveTrafficSampleAction = nullptr;
|
||||
QAction * m_closeTrafficSampleAction = nullptr;
|
||||
QAction * m_startEditingAction = nullptr;
|
||||
QAction * m_commitPathAction = nullptr;
|
||||
QAction * m_commitPathAction = nullptr;
|
||||
QAction * m_cancelPathAction = nullptr;
|
||||
QAction * m_ignorePathAction = nullptr;
|
||||
|
||||
|
||||
@@ -8,10 +8,7 @@
|
||||
|
||||
namespace openlr
|
||||
{
|
||||
MapWidget::MapWidget(Framework & framework, QWidget * parent)
|
||||
: Base(framework, false /* screenshotMode */, parent)
|
||||
{
|
||||
}
|
||||
MapWidget::MapWidget(Framework & framework, QWidget * parent) : Base(framework, false /* screenshotMode */, parent) {}
|
||||
|
||||
void MapWidget::mousePressEvent(QMouseEvent * e)
|
||||
{
|
||||
|
||||
@@ -29,10 +29,7 @@ public:
|
||||
|
||||
void SetMode(Mode const mode) { m_mode = mode; }
|
||||
|
||||
QSize sizeHint() const override
|
||||
{
|
||||
return QSize(800, 600);
|
||||
}
|
||||
QSize sizeHint() const override { return QSize(800, 600); }
|
||||
|
||||
signals:
|
||||
void TrafficMarkupClick(m2::PointD const & p, Qt::MouseButton const b);
|
||||
|
||||
@@ -28,13 +28,11 @@ public:
|
||||
virtual std::vector<m2::PointD> GetAllJunctionPointsInViewport() const = 0;
|
||||
/// Returns all junction points at a given location in the form of feature id and
|
||||
/// point index in the feature.
|
||||
virtual std::pair<std::vector<FeaturePoint>, m2::PointD> GetCandidatePoints(
|
||||
m2::PointD const & p) const = 0;
|
||||
virtual std::pair<std::vector<FeaturePoint>, m2::PointD> GetCandidatePoints(m2::PointD const & p) const = 0;
|
||||
// Returns all points that are one step reachable from |p|.
|
||||
virtual std::vector<m2::PointD> GetReachablePoints(m2::PointD const & p) const = 0;
|
||||
|
||||
virtual ClickType CheckClick(m2::PointD const & clickPoint,
|
||||
m2::PointD const & lastClickedPoint,
|
||||
virtual ClickType CheckClick(m2::PointD const & clickPoint, m2::PointD const & lastClickedPoint,
|
||||
std::vector<m2::PointD> const & reachablePoints) const = 0;
|
||||
};
|
||||
} // namespace openlr
|
||||
|
||||
@@ -19,11 +19,9 @@ SegmentCorrespondence::SegmentCorrespondence(SegmentCorrespondence const & sc)
|
||||
m_status = sc.m_status;
|
||||
}
|
||||
|
||||
SegmentCorrespondence::SegmentCorrespondence(openlr::LinearSegment const & segment,
|
||||
uint32_t positiveOffset, uint32_t negativeOffset,
|
||||
openlr::Path const & matchedPath,
|
||||
openlr::Path const & fakePath,
|
||||
openlr::Path const & goldenPath,
|
||||
SegmentCorrespondence::SegmentCorrespondence(openlr::LinearSegment const & segment, uint32_t positiveOffset,
|
||||
uint32_t negativeOffset, openlr::Path const & matchedPath,
|
||||
openlr::Path const & fakePath, openlr::Path const & goldenPath,
|
||||
pugi::xml_node const & partnerSegmentXML)
|
||||
: m_partnerSegment(segment)
|
||||
, m_positiveOffset(positiveOffset)
|
||||
|
||||
@@ -18,12 +18,9 @@ public:
|
||||
};
|
||||
|
||||
SegmentCorrespondence(SegmentCorrespondence const & sc);
|
||||
SegmentCorrespondence(openlr::LinearSegment const & segment,
|
||||
uint32_t positiveOffset, uint32_t negativeOffset,
|
||||
openlr::Path const & matchedPath,
|
||||
openlr::Path const & fakePath,
|
||||
openlr::Path const & goldenPath,
|
||||
pugi::xml_node const & partnerSegmentXML);
|
||||
SegmentCorrespondence(openlr::LinearSegment const & segment, uint32_t positiveOffset, uint32_t negativeOffset,
|
||||
openlr::Path const & matchedPath, openlr::Path const & fakePath,
|
||||
openlr::Path const & goldenPath, pugi::xml_node const & partnerSegmentXML);
|
||||
|
||||
openlr::Path const & GetMatchedPath() const { return m_matchedPath; }
|
||||
bool HasMatchedPath() const { return !m_matchedPath.empty(); }
|
||||
|
||||
@@ -16,14 +16,12 @@ namespace
|
||||
{
|
||||
void RemovePointFromPull(m2::PointD const & toBeRemoved, std::vector<m2::PointD> & pool)
|
||||
{
|
||||
pool.erase(
|
||||
remove_if(begin(pool), end(pool),
|
||||
[&toBeRemoved](m2::PointD const & p) { return p.EqualDxDy(toBeRemoved, 1e-6); }),
|
||||
end(pool));
|
||||
pool.erase(remove_if(begin(pool), end(pool),
|
||||
[&toBeRemoved](m2::PointD const & p) { return p.EqualDxDy(toBeRemoved, 1e-6); }),
|
||||
end(pool));
|
||||
}
|
||||
|
||||
std::vector<m2::PointD> GetReachablePoints(m2::PointD const & srcPoint,
|
||||
std::vector<m2::PointD> const path,
|
||||
std::vector<m2::PointD> GetReachablePoints(m2::PointD const & srcPoint, std::vector<m2::PointD> const path,
|
||||
PointsControllerDelegateBase const & pointsDelegate,
|
||||
size_t const lookbackIndex)
|
||||
{
|
||||
@@ -46,8 +44,7 @@ size_t const RoadPointCandidate::kInvalidId = std::numeric_limits<size_t>::max()
|
||||
/// I.e. it is a set of all pairs <FeatureID, point index>
|
||||
/// located at a specified coordinate.
|
||||
/// Only one point at a time is considered active.
|
||||
RoadPointCandidate::RoadPointCandidate(std::vector<FeaturePoint> const & points,
|
||||
m2::PointD const & coord)
|
||||
RoadPointCandidate::RoadPointCandidate(std::vector<FeaturePoint> const & points, m2::PointD const & coord)
|
||||
: m_coord(coord)
|
||||
, m_points(points)
|
||||
{
|
||||
@@ -98,8 +95,7 @@ void RoadPointCandidate::SetActivePoint(FeatureID const & fid)
|
||||
// TrafficMode -------------------------------------------------------------------------------------
|
||||
TrafficMode::TrafficMode(std::string const & dataFileName, DataSource const & dataSource,
|
||||
std::unique_ptr<TrafficDrawerDelegateBase> drawerDelegate,
|
||||
std::unique_ptr<PointsControllerDelegateBase> pointsDelegate,
|
||||
QObject * parent)
|
||||
std::unique_ptr<PointsControllerDelegateBase> pointsDelegate, QObject * parent)
|
||||
: QAbstractTableModel(parent)
|
||||
, m_dataSource(dataSource)
|
||||
, m_drawerDelegate(std::move(drawerDelegate))
|
||||
@@ -153,8 +149,7 @@ TrafficMode::TrafficMode(std::string const & dataFileName, DataSource const & da
|
||||
{
|
||||
if (auto const locationReference = method.child("olr:locationReference"))
|
||||
{
|
||||
if (auto const optionLinearLocationReference = locationReference
|
||||
.child("olr:optionLinearLocationReference"))
|
||||
if (auto const optionLinearLocationReference = locationReference.child("olr:optionLinearLocationReference"))
|
||||
{
|
||||
if (auto const positiveOffset = optionLinearLocationReference.child("olr:positiveOffset"))
|
||||
positiveOffsetM = UintValueFromXML(positiveOffset);
|
||||
@@ -166,8 +161,8 @@ TrafficMode::TrafficMode(std::string const & dataFileName, DataSource const & da
|
||||
}
|
||||
}
|
||||
|
||||
m_segments.emplace_back(segment, positiveOffsetM, negativeOffsetM, matchedPath, fakePath,
|
||||
goldenPath, partnerSegmentXML);
|
||||
m_segments.emplace_back(segment, positiveOffsetM, negativeOffsetM, matchedPath, fakePath, goldenPath,
|
||||
partnerSegmentXML);
|
||||
if (auto const status = xmlSegment.child("Ignored"))
|
||||
{
|
||||
if (status.text().as_bool())
|
||||
@@ -198,9 +193,7 @@ bool TrafficMode::SaveSampleAs(std::string const & fileName) const
|
||||
segment.append_copy(sc.GetPartnerXMLSegment());
|
||||
|
||||
if (sc.GetStatus() == SegmentCorrespondence::Status::Ignored)
|
||||
{
|
||||
segment.append_child("Ignored").text() = true;
|
||||
}
|
||||
if (sc.HasMatchedPath())
|
||||
{
|
||||
auto node = segment.append_child("Route");
|
||||
@@ -222,14 +215,17 @@ bool TrafficMode::SaveSampleAs(std::string const & fileName) const
|
||||
return true;
|
||||
}
|
||||
|
||||
int TrafficMode::rowCount(const QModelIndex & parent) const
|
||||
int TrafficMode::rowCount(QModelIndex const & parent) const
|
||||
{
|
||||
return static_cast<int>(m_segments.size());
|
||||
}
|
||||
|
||||
int TrafficMode::columnCount(const QModelIndex & parent) const { return 4; }
|
||||
int TrafficMode::columnCount(QModelIndex const & parent) const
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
|
||||
QVariant TrafficMode::data(const QModelIndex & index, int role) const
|
||||
QVariant TrafficMode::data(QModelIndex const & index, int role) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QVariant();
|
||||
@@ -255,8 +251,7 @@ QVariant TrafficMode::data(const QModelIndex & index, int role) const
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QVariant TrafficMode::headerData(int section, Qt::Orientation orientation,
|
||||
int role /* = Qt::DisplayRole */) const
|
||||
QVariant TrafficMode::headerData(int section, Qt::Orientation orientation, int role /* = Qt::DisplayRole */) const
|
||||
{
|
||||
if (orientation != Qt::Horizontal && role != Qt::DisplayRole)
|
||||
return QVariant();
|
||||
@@ -309,8 +304,7 @@ void TrafficMode::GoldifyMatchedPath()
|
||||
{
|
||||
if (!m_currentSegment->HasMatchedPath())
|
||||
{
|
||||
QMessageBox::information(nullptr /* parent */, "Error",
|
||||
"The selected segment does not have a matched path");
|
||||
QMessageBox::information(nullptr /* parent */, "Error", "The selected segment does not have a matched path");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -384,10 +378,10 @@ void TrafficMode::CommitPath()
|
||||
auto const & prevFt = prevPoint.GetPoint();
|
||||
auto const & ft = point.GetPoint();
|
||||
|
||||
path.push_back(Edge::MakeReal(
|
||||
ft.first, prevFt.second < ft.second /* forward */, base::checked_cast<uint32_t>(prevFt.second),
|
||||
geometry::PointWithAltitude(prevPoint.GetCoordinate(), 0 /* altitude */),
|
||||
geometry::PointWithAltitude(point.GetCoordinate(), 0 /* altitude */)));
|
||||
path.push_back(Edge::MakeReal(ft.first, prevFt.second < ft.second /* forward */,
|
||||
base::checked_cast<uint32_t>(prevFt.second),
|
||||
geometry::PointWithAltitude(prevPoint.GetCoordinate(), 0 /* altitude */),
|
||||
geometry::PointWithAltitude(point.GetCoordinate(), 0 /* altitude */)));
|
||||
}
|
||||
|
||||
m_currentSegment->SetGoldenPath(path);
|
||||
@@ -417,9 +411,8 @@ void TrafficMode::IgnorePath()
|
||||
|
||||
if (m_currentSegment->HasGoldenPath())
|
||||
{
|
||||
auto const btn =
|
||||
QMessageBox::question(nullptr /* parent */, "Override warning",
|
||||
"The selected segment has a golden path. Do you want to discard it?");
|
||||
auto const btn = QMessageBox::question(nullptr /* parent */, "Override warning",
|
||||
"The selected segment has a golden path. Do you want to discard it?");
|
||||
if (btn == QMessageBox::No)
|
||||
return;
|
||||
}
|
||||
@@ -466,9 +459,7 @@ void TrafficMode::HandlePoint(m2::PointD clickPoint, Qt::MouseButton const butto
|
||||
return;
|
||||
|
||||
auto const currentPathLength = GetPointsCount();
|
||||
auto const lastClickedPoint = currentPathLength != 0
|
||||
? GetLastPoint()
|
||||
: m2::PointD::Zero();
|
||||
auto const lastClickedPoint = currentPathLength != 0 ? GetLastPoint() : m2::PointD::Zero();
|
||||
|
||||
auto const & p = m_pointsDelegate->GetCandidatePoints(clickPoint);
|
||||
auto const & candidatePoints = p.first;
|
||||
@@ -476,14 +467,14 @@ void TrafficMode::HandlePoint(m2::PointD clickPoint, Qt::MouseButton const butto
|
||||
if (candidatePoints.empty())
|
||||
return;
|
||||
|
||||
auto reachablePoints = GetReachablePoints(clickPoint, GetGoldenPathPoints(), *m_pointsDelegate,
|
||||
0 /* lookBackIndex */);
|
||||
auto const & clickablePoints = currentPathLength != 0
|
||||
? GetReachablePoints(lastClickedPoint, GetGoldenPathPoints(), *m_pointsDelegate,
|
||||
1 /* lookbackIndex */)
|
||||
// TODO(mgsergio): This is not quite correct since view port can change
|
||||
// since first call to visualize points. But it's ok in general.
|
||||
: m_pointsDelegate->GetAllJunctionPointsInViewport();
|
||||
auto reachablePoints =
|
||||
GetReachablePoints(clickPoint, GetGoldenPathPoints(), *m_pointsDelegate, 0 /* lookBackIndex */);
|
||||
auto const & clickablePoints =
|
||||
currentPathLength != 0
|
||||
? GetReachablePoints(lastClickedPoint, GetGoldenPathPoints(), *m_pointsDelegate, 1 /* lookbackIndex */)
|
||||
// TODO(mgsergio): This is not quite correct since view port can change
|
||||
// since first call to visualize points. But it's ok in general.
|
||||
: m_pointsDelegate->GetAllJunctionPointsInViewport();
|
||||
|
||||
using ClickType = PointsControllerDelegateBase::ClickType;
|
||||
switch (m_pointsDelegate->CheckClick(clickPoint, lastClickedPoint, clickablePoints))
|
||||
@@ -518,8 +509,8 @@ void TrafficMode::HandlePoint(m2::PointD clickPoint, Qt::MouseButton const butto
|
||||
}
|
||||
else
|
||||
{
|
||||
m_drawerDelegate->VisualizePoints(GetReachablePoints(
|
||||
GetLastPoint(), GetGoldenPathPoints(), *m_pointsDelegate, 1 /* lookBackIndex */));
|
||||
m_drawerDelegate->VisualizePoints(
|
||||
GetReachablePoints(GetLastPoint(), GetGoldenPathPoints(), *m_pointsDelegate, 1 /* lookBackIndex */));
|
||||
}
|
||||
|
||||
if (GetPointsCount() > 1)
|
||||
@@ -546,9 +537,8 @@ bool TrafficMode::StartBuildingPathChecks() const
|
||||
|
||||
if (m_currentSegment->HasGoldenPath())
|
||||
{
|
||||
auto const btn = QMessageBox::question(
|
||||
nullptr /* parent */, "Override warning",
|
||||
"The selected segment already has a golden path. Do you want to override?");
|
||||
auto const btn = QMessageBox::question(nullptr /* parent */, "Override warning",
|
||||
"The selected segment already has a golden path. Do you want to override?");
|
||||
if (btn == QMessageBox::No)
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
#include <QAbstractTableModel>
|
||||
|
||||
|
||||
class QItemSelection;
|
||||
class Selection;
|
||||
|
||||
@@ -35,8 +34,7 @@ namespace impl
|
||||
class RoadPointCandidate
|
||||
{
|
||||
public:
|
||||
RoadPointCandidate(std::vector<openlr::FeaturePoint> const & points,
|
||||
m2::PointD const & coord);
|
||||
RoadPointCandidate(std::vector<openlr::FeaturePoint> const & points, m2::PointD const & coord);
|
||||
|
||||
void ActivateCommonPoint(RoadPointCandidate const & rpc);
|
||||
openlr::FeaturePoint const & GetPoint() const;
|
||||
@@ -64,25 +62,22 @@ public:
|
||||
// TODO(mgsergio): Check we are on the right mwm. I.e. right mwm version and everything.
|
||||
TrafficMode(std::string const & dataFileName, DataSource const & dataSource,
|
||||
std::unique_ptr<TrafficDrawerDelegateBase> drawerDelegate,
|
||||
std::unique_ptr<PointsControllerDelegateBase> pointsDelegate,
|
||||
QObject * parent = Q_NULLPTR);
|
||||
std::unique_ptr<PointsControllerDelegateBase> pointsDelegate, QObject * parent = Q_NULLPTR);
|
||||
|
||||
bool SaveSampleAs(std::string const & fileName) const;
|
||||
|
||||
int rowCount(const QModelIndex & parent = QModelIndex()) const Q_DECL_OVERRIDE;
|
||||
int columnCount(const QModelIndex & parent = QModelIndex()) const Q_DECL_OVERRIDE;
|
||||
QVariant headerData(int section, Qt::Orientation orientation,
|
||||
int role = Qt::DisplayRole) const Q_DECL_OVERRIDE;
|
||||
int rowCount(QModelIndex const & parent = QModelIndex()) const Q_DECL_OVERRIDE;
|
||||
int columnCount(QModelIndex const & parent = QModelIndex()) const Q_DECL_OVERRIDE;
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE;
|
||||
|
||||
QVariant data(const QModelIndex & index, int role) const Q_DECL_OVERRIDE;
|
||||
QVariant data(QModelIndex const & index, int role) const Q_DECL_OVERRIDE;
|
||||
|
||||
Qt::ItemFlags flags(QModelIndex const & index) const Q_DECL_OVERRIDE;
|
||||
|
||||
bool IsBuildingPath() const { return m_buildingPath; }
|
||||
void GoldifyMatchedPath();
|
||||
void StartBuildingPath();
|
||||
void PushPoint(m2::PointD const & coord,
|
||||
std::vector<FeaturePoint> const & points);
|
||||
void PushPoint(m2::PointD const & coord, std::vector<FeaturePoint> const & points);
|
||||
void PopPoint();
|
||||
void CommitPath();
|
||||
void RollBackPath();
|
||||
@@ -95,10 +90,7 @@ public:
|
||||
|
||||
public slots:
|
||||
void OnItemSelected(QItemSelection const & selected, QItemSelection const &);
|
||||
void OnClick(m2::PointD const & clickPoint, Qt::MouseButton const button)
|
||||
{
|
||||
HandlePoint(clickPoint, button);
|
||||
}
|
||||
void OnClick(m2::PointD const & clickPoint, Qt::MouseButton const button) { HandlePoint(clickPoint, button); }
|
||||
|
||||
signals:
|
||||
void EditingStopped();
|
||||
|
||||
@@ -11,10 +11,7 @@
|
||||
namespace openlr
|
||||
{
|
||||
// ComboBoxDelegate --------------------------------------------------------------------------------
|
||||
ComboBoxDelegate::ComboBoxDelegate(QObject * parent)
|
||||
: QStyledItemDelegate(parent)
|
||||
{
|
||||
}
|
||||
ComboBoxDelegate::ComboBoxDelegate(QObject * parent) : QStyledItemDelegate(parent) {}
|
||||
|
||||
QWidget * ComboBoxDelegate::createEditor(QWidget * parent, QStyleOptionViewItem const & option,
|
||||
QModelIndex const & index) const
|
||||
@@ -30,13 +27,12 @@ QWidget * ComboBoxDelegate::createEditor(QWidget * parent, QStyleOptionViewItem
|
||||
void ComboBoxDelegate::setEditorData(QWidget * editor, QModelIndex const & index) const
|
||||
{
|
||||
auto const value = index.model()->data(index, Qt::EditRole).toString();
|
||||
static_cast<QComboBox*>(editor)->setCurrentText(value);
|
||||
static_cast<QComboBox *>(editor)->setCurrentText(value);
|
||||
}
|
||||
|
||||
void ComboBoxDelegate::setModelData(QWidget * editor, QAbstractItemModel * model,
|
||||
QModelIndex const & index) const
|
||||
void ComboBoxDelegate::setModelData(QWidget * editor, QAbstractItemModel * model, QModelIndex const & index) const
|
||||
{
|
||||
model->setData(index, static_cast<QComboBox*>(editor)->currentText(), Qt::EditRole);
|
||||
model->setData(index, static_cast<QComboBox *>(editor)->currentText(), Qt::EditRole);
|
||||
}
|
||||
|
||||
void ComboBoxDelegate::updateEditorGeometry(QWidget * editor, QStyleOptionViewItem const & option,
|
||||
@@ -46,8 +42,7 @@ void ComboBoxDelegate::updateEditorGeometry(QWidget * editor, QStyleOptionViewIt
|
||||
}
|
||||
|
||||
// TrafficPanel ------------------------------------------------------------------------------------
|
||||
TrafficPanel::TrafficPanel(QAbstractItemModel * trafficModel, QWidget * parent)
|
||||
: QWidget(parent)
|
||||
TrafficPanel::TrafficPanel(QAbstractItemModel * trafficModel, QWidget * parent) : QWidget(parent)
|
||||
{
|
||||
CreateTable(trafficModel);
|
||||
|
||||
@@ -75,8 +70,7 @@ void TrafficPanel::CreateTable(QAbstractItemModel * trafficModel)
|
||||
m_table->setModel(trafficModel);
|
||||
m_table->setItemDelegate(new ComboBoxDelegate());
|
||||
|
||||
connect(m_table->selectionModel(),
|
||||
SIGNAL(selectionChanged(QItemSelection const &, QItemSelection const &)),
|
||||
connect(m_table->selectionModel(), SIGNAL(selectionChanged(QItemSelection const &, QItemSelection const &)),
|
||||
trafficModel, SLOT(OnItemSelected(QItemSelection const &, QItemSelection const &)));
|
||||
}
|
||||
} // namespace openlr
|
||||
|
||||
@@ -21,8 +21,7 @@ public:
|
||||
|
||||
void setEditorData(QWidget * editor, QModelIndex const & index) const Q_DECL_OVERRIDE;
|
||||
|
||||
void setModelData(QWidget * editor, QAbstractItemModel * model,
|
||||
QModelIndex const & index) const Q_DECL_OVERRIDE;
|
||||
void setModelData(QWidget * editor, QAbstractItemModel * model, QModelIndex const & index) const Q_DECL_OVERRIDE;
|
||||
|
||||
void updateEditorGeometry(QWidget * editor, QStyleOptionViewItem const & option,
|
||||
QModelIndex const & index) const Q_DECL_OVERRIDE;
|
||||
|
||||
@@ -14,9 +14,7 @@ std::string const kDataFilePath = "LastOpenlrAssessmentDataFilePath";
|
||||
|
||||
namespace openlr
|
||||
{
|
||||
TrafficModeInitDlg::TrafficModeInitDlg(QWidget * parent) :
|
||||
QDialog(parent),
|
||||
m_ui(new Ui::TrafficModeInitDlg)
|
||||
TrafficModeInitDlg::TrafficModeInitDlg(QWidget * parent) : QDialog(parent), m_ui(new Ui::TrafficModeInitDlg)
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
|
||||
@@ -24,9 +22,8 @@ TrafficModeInitDlg::TrafficModeInitDlg(QWidget * parent) :
|
||||
if (settings::Get(kDataFilePath, lastDataFilePath))
|
||||
m_ui->dataFileName->setText(QString::fromStdString(lastDataFilePath));
|
||||
|
||||
connect(m_ui->chooseDataFileButton, &QPushButton::clicked, [this](bool) {
|
||||
SetFilePathViaDialog(*m_ui->dataFileName, tr("Choose data file"), "*.xml");
|
||||
});
|
||||
connect(m_ui->chooseDataFileButton, &QPushButton::clicked,
|
||||
[this](bool) { SetFilePathViaDialog(*m_ui->dataFileName, tr("Choose data file"), "*.xml"); });
|
||||
}
|
||||
|
||||
TrafficModeInitDlg::~TrafficModeInitDlg()
|
||||
@@ -41,8 +38,7 @@ void TrafficModeInitDlg::accept()
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
void TrafficModeInitDlg::SetFilePathViaDialog(QLineEdit & dest, QString const & title,
|
||||
QString const & filter)
|
||||
void TrafficModeInitDlg::SetFilePathViaDialog(QLineEdit & dest, QString const & title, QString const & filter)
|
||||
{
|
||||
QFileDialog openFileDlg(nullptr, title, {} /* directory */, filter);
|
||||
openFileDlg.exec();
|
||||
|
||||
@@ -20,9 +20,7 @@ bool IntegerFromXML(pugi::xml_node const & node, Value & value)
|
||||
{
|
||||
if (!node)
|
||||
return false;
|
||||
value = static_cast<Value>(is_signed<Value>::value
|
||||
? node.text().as_int()
|
||||
: node.text().as_uint());
|
||||
value = static_cast<Value>(is_signed<Value>::value ? node.text().as_int() : node.text().as_uint());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -33,11 +31,8 @@ std::optional<double> DoubleFromXML(pugi::xml_node const & node)
|
||||
|
||||
bool GetLatLon(pugi::xml_node const & node, int32_t & lat, int32_t & lon)
|
||||
{
|
||||
if (!IntegerFromXML(node.child("olr:latitude"), lat) ||
|
||||
!IntegerFromXML(node.child("olr:longitude"), lon))
|
||||
{
|
||||
if (!IntegerFromXML(node.child("olr:latitude"), lat) || !IntegerFromXML(node.child("olr:longitude"), lon))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -49,9 +44,8 @@ bool TableValueFromXML(pugi::xml_node const & node, Value & value)
|
||||
{
|
||||
if (!node)
|
||||
return false;
|
||||
value = static_cast<Value>(is_signed<Value>::value
|
||||
? node.attribute("olr:code").as_int()
|
||||
: node.attribute("olr:code").as_uint());
|
||||
value = static_cast<Value>(is_signed<Value>::value ? node.attribute("olr:code").as_int()
|
||||
: node.attribute("olr:code").as_uint());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -66,7 +60,6 @@ pugi::xml_node GetCoordinates(pugi::xml_node const & node)
|
||||
return node.select_node(".//coordinates").node();
|
||||
}
|
||||
|
||||
|
||||
bool IsLocationReferenceTag(pugi::xml_node const & node)
|
||||
{
|
||||
return node.select_node(".//olr:locationReference").node();
|
||||
@@ -119,8 +112,7 @@ std::optional<ms::LatLon> LatLonFormXML(pugi::xml_node const & node)
|
||||
return lat && lon ? ms::LatLon(*lat, *lon) : ms::LatLon::Zero();
|
||||
}
|
||||
|
||||
bool CoordinateFromXML(pugi::xml_node const & node, ms::LatLon const & prevCoord,
|
||||
ms::LatLon & latLon)
|
||||
bool CoordinateFromXML(pugi::xml_node const & node, ms::LatLon const & prevCoord, ms::LatLon & latLon)
|
||||
{
|
||||
int32_t lat, lon;
|
||||
if (!GetLatLon(node.child("olr:coordinate"), lat, lon))
|
||||
@@ -136,8 +128,7 @@ bool CoordinateFromXML(pugi::xml_node const & node, ms::LatLon const & prevCoord
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LinePropertiesFromXML(pugi::xml_node const & linePropNode,
|
||||
openlr::LocationReferencePoint & locPoint)
|
||||
bool LinePropertiesFromXML(pugi::xml_node const & linePropNode, openlr::LocationReferencePoint & locPoint)
|
||||
{
|
||||
if (!linePropNode)
|
||||
{
|
||||
@@ -166,8 +157,7 @@ bool LinePropertiesFromXML(pugi::xml_node const & linePropNode,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PathPropertiesFromXML(pugi::xml_node const & locPointNode,
|
||||
openlr::LocationReferencePoint & locPoint)
|
||||
bool PathPropertiesFromXML(pugi::xml_node const & locPointNode, openlr::LocationReferencePoint & locPoint)
|
||||
{
|
||||
// Last point does not contain path properties.
|
||||
if (strcmp(locPointNode.name(), "olr:last") == 0)
|
||||
@@ -203,8 +193,7 @@ bool PathPropertiesFromXML(pugi::xml_node const & locPointNode,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LocationReferencePointFromXML(pugi::xml_node const & locPointNode,
|
||||
openlr::LocationReferencePoint & locPoint)
|
||||
bool LocationReferencePointFromXML(pugi::xml_node const & locPointNode, openlr::LocationReferencePoint & locPoint)
|
||||
{
|
||||
if (!FirstCoordinateFromXML(locPointNode, locPoint.m_latLon))
|
||||
{
|
||||
@@ -216,8 +205,7 @@ bool LocationReferencePointFromXML(pugi::xml_node const & locPointNode,
|
||||
PathPropertiesFromXML(locPointNode, locPoint);
|
||||
}
|
||||
|
||||
bool LocationReferencePointFromXML(pugi::xml_node const & locPointNode,
|
||||
ms::LatLon const & firstPoint,
|
||||
bool LocationReferencePointFromXML(pugi::xml_node const & locPointNode, ms::LatLon const & firstPoint,
|
||||
openlr::LocationReferencePoint & locPoint)
|
||||
{
|
||||
if (!CoordinateFromXML(locPointNode, firstPoint, locPoint.m_latLon))
|
||||
@@ -230,8 +218,7 @@ bool LocationReferencePointFromXML(pugi::xml_node const & locPointNode,
|
||||
PathPropertiesFromXML(locPointNode, locPoint);
|
||||
}
|
||||
|
||||
bool LinearLocationReferenceFromXML(pugi::xml_node const & locRefNode,
|
||||
openlr::LinearLocationReference & locRef)
|
||||
bool LinearLocationReferenceFromXML(pugi::xml_node const & locRefNode, openlr::LinearLocationReference & locRef)
|
||||
{
|
||||
if (!locRefNode)
|
||||
{
|
||||
@@ -256,8 +243,7 @@ bool LinearLocationReferenceFromXML(pugi::xml_node const & locRefNode,
|
||||
|
||||
{
|
||||
openlr::LocationReferencePoint point;
|
||||
if (!LocationReferencePointFromXML(locRefNode.child("olr:last"),
|
||||
locRef.m_points.back().m_latLon, point))
|
||||
if (!LocationReferencePointFromXML(locRefNode.child("olr:last"), locRef.m_points.back().m_latLon, point))
|
||||
return false;
|
||||
locRef.m_points.push_back(point);
|
||||
}
|
||||
@@ -268,7 +254,7 @@ bool LinearLocationReferenceFromXML(pugi::xml_node const & locRefNode,
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!ParseValueIfExists(locRefNode.child("olr:negativeOffset"), locRef.m_negativeOffsetMeters))
|
||||
if (!ParseValueIfExists(locRefNode.child("olr:negativeOffset"), locRef.m_negativeOffsetMeters))
|
||||
{
|
||||
LOG(LERROR, ("Can't parse negative offset"));
|
||||
return false;
|
||||
|
||||
@@ -35,8 +35,7 @@ DEFINE_string(input, "", "Path to OpenLR file.");
|
||||
DEFINE_string(spark_output, "", "Path to output file in spark-oriented format");
|
||||
DEFINE_string(assessment_output, "", "Path to output file in assessment-tool oriented format");
|
||||
|
||||
DEFINE_string(non_matched_ids, "non-matched-ids.txt",
|
||||
"Path to a file ids of non-matched segments will be saved to");
|
||||
DEFINE_string(non_matched_ids, "non-matched-ids.txt", "Path to a file ids of non-matched segments will be saved to");
|
||||
DEFINE_string(mwms_path, "", "Path to a folder with mwms.");
|
||||
DEFINE_string(resources_path, "", "Path to a folder with resources.");
|
||||
DEFINE_int32(limit, -1, "Max number of segments to handle. -1 for all.");
|
||||
@@ -56,8 +55,7 @@ int32_t const kMinNumThreads = 1;
|
||||
int32_t const kMaxNumThreads = 128;
|
||||
int32_t const kHandleAllSegments = -1;
|
||||
|
||||
void LoadDataSources(std::string const & pathToMWMFolder,
|
||||
std::vector<FrozenDataSource> & dataSources)
|
||||
void LoadDataSources(std::string const & pathToMWMFolder, std::vector<FrozenDataSource> & dataSources)
|
||||
{
|
||||
CHECK(Platform::IsDirectory(pathToMWMFolder), (pathToMWMFolder, "must be a directory."));
|
||||
|
||||
@@ -73,8 +71,7 @@ void LoadDataSources(std::string const & pathToMWMFolder,
|
||||
{
|
||||
auto const fullFileName = base::JoinPath(pathToMWMFolder, fileName);
|
||||
ModelReaderPtr reader(GetPlatform().GetReader(fullFileName, "f"));
|
||||
platform::LocalCountryFile localFile(pathToMWMFolder,
|
||||
platform::CountryFile(base::FilenameWithoutExt(fileName)),
|
||||
platform::LocalCountryFile localFile(pathToMWMFolder, platform::CountryFile(base::FilenameWithoutExt(fileName)),
|
||||
version::ReadVersionDate(reader));
|
||||
|
||||
LOG(LINFO, ("Found mwm:", fullFileName));
|
||||
@@ -98,18 +95,15 @@ void LoadDataSources(std::string const & pathToMWMFolder,
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < numDataSources; ++i)
|
||||
{
|
||||
if (numCountries[i] == 0)
|
||||
LOG(LWARNING, ("No countries for thread", i));
|
||||
}
|
||||
}
|
||||
|
||||
bool ValidateLimit(char const * flagname, int32_t value)
|
||||
{
|
||||
if (value < -1)
|
||||
{
|
||||
LOG(LINFO, ("Valid value for --", std::string(flagname), ":", value,
|
||||
"must be greater or equal to -1."));
|
||||
LOG(LINFO, ("Valid value for --", std::string(flagname), ":", value, "must be greater or equal to -1."));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -120,8 +114,8 @@ bool ValidateNumThreads(char const * flagname, int32_t value)
|
||||
{
|
||||
if (value < kMinNumThreads || value > kMaxNumThreads)
|
||||
{
|
||||
LOG(LINFO, ("Valid value for --", std::string(flagname), ":", value, "must be between",
|
||||
kMinNumThreads, "and", kMaxNumThreads));
|
||||
LOG(LINFO, ("Valid value for --", std::string(flagname), ":", value, "must be between", kMinNumThreads, "and",
|
||||
kMaxNumThreads));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -157,8 +151,7 @@ bool ValidateVersion(char const * flagname, int32_t value)
|
||||
}
|
||||
|
||||
bool const g_limitDummy = gflags::RegisterFlagValidator(&FLAGS_limit, &ValidateLimit);
|
||||
bool const g_numThreadsDummy =
|
||||
gflags::RegisterFlagValidator(&FLAGS_num_threads, &ValidateNumThreads);
|
||||
bool const g_numThreadsDummy = gflags::RegisterFlagValidator(&FLAGS_num_threads, &ValidateNumThreads);
|
||||
bool const g_mwmsPathDummy = gflags::RegisterFlagValidator(&FLAGS_mwms_path, &ValidateMwmPath);
|
||||
bool const g_algoVersion = gflags::RegisterFlagValidator(&FLAGS_algo_version, &ValidateVersion);
|
||||
|
||||
@@ -169,10 +162,8 @@ void SaveNonMatchedIds(std::string const & filename, std::vector<DecodedPath> co
|
||||
|
||||
std::ofstream ofs(filename);
|
||||
for (auto const & p : paths)
|
||||
{
|
||||
if (p.m_path.empty())
|
||||
ofs << p.m_segmentId << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<LinearSegment> LoadSegments(pugi::xml_document & document)
|
||||
@@ -185,14 +176,10 @@ std::vector<LinearSegment> LoadSegments(pugi::xml_document & document)
|
||||
}
|
||||
|
||||
OpenLRDecoder::SegmentsFilter filter(FLAGS_ids_path, FLAGS_multipoints_only);
|
||||
if (FLAGS_limit != kHandleAllSegments && FLAGS_limit >= 0 &&
|
||||
static_cast<size_t>(FLAGS_limit) < segments.size())
|
||||
{
|
||||
if (FLAGS_limit != kHandleAllSegments && FLAGS_limit >= 0 && static_cast<size_t>(FLAGS_limit) < segments.size())
|
||||
segments.resize(FLAGS_limit);
|
||||
}
|
||||
|
||||
base::EraseIf(segments,
|
||||
[&filter](LinearSegment const & segment) { return !filter.Matches(segment); });
|
||||
base::EraseIf(segments, [&filter](LinearSegment const & segment) { return !filter.Matches(segment); });
|
||||
|
||||
std::sort(segments.begin(), segments.end(), base::LessBy(&LinearSegment::m_segmentId));
|
||||
|
||||
@@ -261,8 +248,8 @@ int main(int argc, char * argv[])
|
||||
|
||||
LoadDataSources(FLAGS_mwms_path, dataSources);
|
||||
|
||||
OpenLRDecoder decoder(dataSources, storage::CountryParentGetter(FLAGS_countries_filename,
|
||||
GetPlatform().ResourcesDir()));
|
||||
OpenLRDecoder decoder(dataSources,
|
||||
storage::CountryParentGetter(FLAGS_countries_filename, GetPlatform().ResourcesDir()));
|
||||
|
||||
pugi::xml_document document;
|
||||
auto const load_result = document.load_file(FLAGS_input.data());
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
#include "platform/platform_tests_support/scoped_dir.hpp"
|
||||
#include "platform/platform_tests_support/scoped_file.hpp"
|
||||
|
||||
#include "base/file_name_utils.hpp"
|
||||
#include "base/checked_cast.hpp"
|
||||
#include "base/file_name_utils.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iomanip>
|
||||
@@ -43,7 +43,10 @@ double RoughUpToFive(double d)
|
||||
return d;
|
||||
}
|
||||
|
||||
m2::PointD RoughPoint(m2::PointD const & p) { return {RoughUpToFive(p.x), RoughUpToFive(p.y)}; }
|
||||
m2::PointD RoughPoint(m2::PointD const & p)
|
||||
{
|
||||
return {RoughUpToFive(p.x), RoughUpToFive(p.y)};
|
||||
}
|
||||
|
||||
geometry::PointWithAltitude RoughJunction(geometry::PointWithAltitude const & j)
|
||||
{
|
||||
@@ -52,8 +55,7 @@ geometry::PointWithAltitude RoughJunction(geometry::PointWithAltitude const & j)
|
||||
|
||||
routing::Edge RoughEdgeJunctions(routing::Edge const & e)
|
||||
{
|
||||
return routing::Edge::MakeReal(e.GetFeatureId(), e.IsForward(), e.GetSegId(),
|
||||
RoughJunction(e.GetStartJunction()),
|
||||
return routing::Edge::MakeReal(e.GetFeatureId(), e.IsForward(), e.GetSegId(), RoughJunction(e.GetStartJunction()),
|
||||
RoughJunction(e.GetEndJunction()));
|
||||
}
|
||||
|
||||
@@ -103,10 +105,8 @@ openlr::Path MakePath(FeatureType const & road, bool const forward)
|
||||
auto const from = road.GetPoint(current);
|
||||
auto const to = road.GetPoint(next);
|
||||
path.push_back(routing::Edge::MakeReal(
|
||||
road.GetID(), forward,
|
||||
base::checked_cast<uint32_t>(current - static_cast<size_t>(!forward)) /* segId */,
|
||||
geometry::PointWithAltitude(from, 0 /* altitude */),
|
||||
geometry::PointWithAltitude(to, 0 /* altitude */)));
|
||||
road.GetID(), forward, base::checked_cast<uint32_t>(current - static_cast<size_t>(!forward)) /* segId */,
|
||||
geometry::PointWithAltitude(from, 0 /* altitude */), geometry::PointWithAltitude(to, 0 /* altitude */)));
|
||||
}
|
||||
|
||||
RoughJunctionsInPath(path);
|
||||
@@ -124,8 +124,7 @@ void WithRoad(vector<m2::PointD> const & points, Func && fn)
|
||||
|
||||
LocalCountryFile country(mwmPath, CountryFile(kTestMwm), 0 /* version */);
|
||||
ScopedDir testScopedDir(kTestDir);
|
||||
ScopedFile testScopedMwm(base::JoinPath(kTestDir, kTestMwm + DATA_FILE_EXTENSION),
|
||||
ScopedFile::Mode::Create);
|
||||
ScopedFile testScopedMwm(base::JoinPath(kTestDir, kTestMwm + DATA_FILE_EXTENSION), ScopedFile::Mode::Create);
|
||||
|
||||
{
|
||||
TestMwmBuilder builder(country, feature::DataHeader::MapType::Country);
|
||||
@@ -150,21 +149,20 @@ void WithRoad(vector<m2::PointD> const & points, Func && fn)
|
||||
UNIT_TEST(MakePath_Test)
|
||||
{
|
||||
std::vector<m2::PointD> const points{{0, 0}, {0, 1}, {1, 0}, {1, 1}};
|
||||
WithRoad(points, [&points](DataSource const & dataSource, FeatureType & road) {
|
||||
WithRoad(points, [&points](DataSource const & dataSource, FeatureType & road)
|
||||
{
|
||||
auto const & id = road.GetID();
|
||||
{
|
||||
openlr::Path const expected{
|
||||
routing::Edge::MakeReal(id, true /* forward */, 0 /* segId*/, points[0], points[1]),
|
||||
routing::Edge::MakeReal(id, true /* forward */, 1 /* segId*/, points[1], points[2]),
|
||||
routing::Edge::MakeReal(id, true /* forward */, 2 /* segId*/, points[2], points[3])};
|
||||
openlr::Path const expected{routing::Edge::MakeReal(id, true /* forward */, 0 /* segId*/, points[0], points[1]),
|
||||
routing::Edge::MakeReal(id, true /* forward */, 1 /* segId*/, points[1], points[2]),
|
||||
routing::Edge::MakeReal(id, true /* forward */, 2 /* segId*/, points[2], points[3])};
|
||||
auto const path = MakePath(road, true /* forward */);
|
||||
TEST_EQUAL(path, expected, ());
|
||||
}
|
||||
{
|
||||
openlr::Path const expected{
|
||||
routing::Edge::MakeReal(id, false /* forward */, 2 /* segId*/, points[3], points[2]),
|
||||
routing::Edge::MakeReal(id, false /* forward */, 1 /* segId*/, points[2], points[1]),
|
||||
routing::Edge::MakeReal(id, false /* forward */, 0 /* segId*/, points[1], points[0])};
|
||||
openlr::Path const expected{routing::Edge::MakeReal(id, false /* forward */, 2 /* segId*/, points[3], points[2]),
|
||||
routing::Edge::MakeReal(id, false /* forward */, 1 /* segId*/, points[2], points[1]),
|
||||
routing::Edge::MakeReal(id, false /* forward */, 0 /* segId*/, points[1], points[0])};
|
||||
{
|
||||
auto const path = MakePath(road, false /* forward */);
|
||||
TEST_EQUAL(path, expected, ());
|
||||
@@ -175,7 +173,8 @@ UNIT_TEST(MakePath_Test)
|
||||
|
||||
UNIT_TEST(PathSerializeDeserialize_Test)
|
||||
{
|
||||
WithRoad({{0, 0}, {0, 1}, {1, 0}, {1, 1}}, [](DataSource const & dataSource, FeatureType & road) {
|
||||
WithRoad({{0, 0}, {0, 1}, {1, 0}, {1, 1}}, [](DataSource const & dataSource, FeatureType & road)
|
||||
{
|
||||
{
|
||||
auto const path = MakePath(road, true /* forward */);
|
||||
TestSerializeDeserialize(path, dataSource);
|
||||
@@ -190,7 +189,8 @@ UNIT_TEST(PathSerializeDeserialize_Test)
|
||||
UNIT_TEST(GetPoints_Test)
|
||||
{
|
||||
vector<m2::PointD> const points{{0, 0}, {0, 1}, {1, 0}, {1, 1}};
|
||||
WithRoad(points, [&points](DataSource const &, FeatureType & road) {
|
||||
WithRoad(points, [&points](DataSource const &, FeatureType & road)
|
||||
{
|
||||
{
|
||||
auto path = MakePath(road, true /* forward */);
|
||||
// RoughJunctionsInPath(path);
|
||||
|
||||
@@ -16,24 +16,20 @@ namespace openlr
|
||||
{
|
||||
namespace
|
||||
{
|
||||
bool ValidatePath(Graph::EdgeVector const & path,
|
||||
double const distanceToNextPoint,
|
||||
double const pathLengthTolerance)
|
||||
bool ValidatePath(Graph::EdgeVector const & path, double const distanceToNextPoint, double const pathLengthTolerance)
|
||||
{
|
||||
|
||||
double pathLen = 0.0;
|
||||
for (auto const & e : path)
|
||||
pathLen += EdgeLength(e);
|
||||
|
||||
double pathDiffPercent = AbsDifference(static_cast<double>(distanceToNextPoint), pathLen) /
|
||||
static_cast<double>(distanceToNextPoint);
|
||||
double pathDiffPercent =
|
||||
AbsDifference(static_cast<double>(distanceToNextPoint), pathLen) / static_cast<double>(distanceToNextPoint);
|
||||
|
||||
LOG(LDEBUG, ("Validating path:", LogAs2GisPath(path)));
|
||||
|
||||
if (pathDiffPercent > pathLengthTolerance)
|
||||
{
|
||||
LOG(LDEBUG,
|
||||
("Shortest path doest not meet required length constraints, error:", pathDiffPercent));
|
||||
LOG(LDEBUG, ("Shortest path doest not meet required length constraints, error:", pathDiffPercent));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -41,14 +37,12 @@ bool ValidatePath(Graph::EdgeVector const & path,
|
||||
}
|
||||
} // namespace
|
||||
|
||||
PathsConnector::PathsConnector(double pathLengthTolerance, Graph & graph,
|
||||
RoadInfoGetter & infoGetter, v2::Stats & stat)
|
||||
PathsConnector::PathsConnector(double pathLengthTolerance, Graph & graph, RoadInfoGetter & infoGetter, v2::Stats & stat)
|
||||
: m_pathLengthTolerance(pathLengthTolerance)
|
||||
, m_graph(graph)
|
||||
, m_infoGetter(infoGetter)
|
||||
, m_stat(stat)
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
bool PathsConnector::ConnectCandidates(vector<LocationReferencePoint> const & points,
|
||||
vector<vector<Graph::EdgeVector>> const & lineCandidates,
|
||||
@@ -79,16 +73,14 @@ bool PathsConnector::ConnectCandidates(vector<LocationReferencePoint> const & po
|
||||
{
|
||||
resultPathPart.clear();
|
||||
|
||||
found = ConnectAdjacentCandidateLines(fromCandidates[fromInd], toCandidates[toInd],
|
||||
point.m_lfrcnp, distanceToNextPoint,
|
||||
resultPathPart);
|
||||
found = ConnectAdjacentCandidateLines(fromCandidates[fromInd], toCandidates[toInd], point.m_lfrcnp,
|
||||
distanceToNextPoint, resultPathPart);
|
||||
|
||||
if (!found)
|
||||
continue;
|
||||
|
||||
found = ValidatePath(resultPathPart, distanceToNextPoint, m_pathLengthTolerance);
|
||||
if (fakePath.empty() && found &&
|
||||
(resultPathPart.front().IsFake() || resultPathPart.back().IsFake()))
|
||||
if (fakePath.empty() && found && (resultPathPart.front().IsFake() || resultPathPart.back().IsFake()))
|
||||
{
|
||||
fakePath = resultPathPart;
|
||||
found = false;
|
||||
@@ -127,10 +119,7 @@ bool PathsConnector::FindShortestPath(Graph::Edge const & from, Graph::Edge cons
|
||||
{
|
||||
State(Graph::Edge const & e, uint32_t const s) : m_edge(e), m_score(s) {}
|
||||
|
||||
bool operator>(State const & o) const
|
||||
{
|
||||
return make_tuple(m_score, m_edge) > make_tuple(o.m_score, o.m_edge);
|
||||
}
|
||||
bool operator>(State const & o) const { return make_tuple(m_score, m_edge) > make_tuple(o.m_score, o.m_edge); }
|
||||
|
||||
Graph::Edge m_edge;
|
||||
uint32_t m_score;
|
||||
@@ -196,10 +185,8 @@ bool PathsConnector::FindShortestPath(Graph::Edge const & from, Graph::Edge cons
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PathsConnector::ConnectAdjacentCandidateLines(Graph::EdgeVector const & from,
|
||||
Graph::EdgeVector const & to,
|
||||
FunctionalRoadClass lowestFrcToNextPoint,
|
||||
double distanceToNextPoint,
|
||||
bool PathsConnector::ConnectAdjacentCandidateLines(Graph::EdgeVector const & from, Graph::EdgeVector const & to,
|
||||
FunctionalRoadClass lowestFrcToNextPoint, double distanceToNextPoint,
|
||||
Graph::EdgeVector & resultPath)
|
||||
|
||||
{
|
||||
@@ -217,8 +204,7 @@ bool PathsConnector::ConnectAdjacentCandidateLines(Graph::EdgeVector const & fro
|
||||
ASSERT(from.back() != to.front(), ());
|
||||
|
||||
Graph::EdgeVector shortestPath;
|
||||
auto const found =
|
||||
FindShortestPath(from.back(), to.front(), lowestFrcToNextPoint, distanceToNextPoint, shortestPath);
|
||||
auto const found = FindShortestPath(from.back(), to.front(), lowestFrcToNextPoint, distanceToNextPoint, shortestPath);
|
||||
if (!found)
|
||||
return false;
|
||||
|
||||
|
||||
@@ -14,21 +14,19 @@ namespace openlr
|
||||
class PathsConnector
|
||||
{
|
||||
public:
|
||||
PathsConnector(double pathLengthTolerance, Graph & graph, RoadInfoGetter & infoGetter,
|
||||
v2::Stats & stat);
|
||||
PathsConnector(double pathLengthTolerance, Graph & graph, RoadInfoGetter & infoGetter, v2::Stats & stat);
|
||||
|
||||
bool ConnectCandidates(std::vector<LocationReferencePoint> const & points,
|
||||
std::vector<std::vector<Graph::EdgeVector>> const & lineCandidates,
|
||||
std::vector<Graph::EdgeVector> & resultPath);
|
||||
|
||||
private:
|
||||
bool FindShortestPath(Graph::Edge const & from, Graph::Edge const & to,
|
||||
FunctionalRoadClass lowestFrcToNextPoint, uint32_t maxPathLength,
|
||||
Graph::EdgeVector & path);
|
||||
bool FindShortestPath(Graph::Edge const & from, Graph::Edge const & to, FunctionalRoadClass lowestFrcToNextPoint,
|
||||
uint32_t maxPathLength, Graph::EdgeVector & path);
|
||||
|
||||
bool ConnectAdjacentCandidateLines(Graph::EdgeVector const & from, Graph::EdgeVector const & to,
|
||||
FunctionalRoadClass lowestFrcToNextPoint,
|
||||
double distanceToNextPoint, Graph::EdgeVector & resultPath);
|
||||
FunctionalRoadClass lowestFrcToNextPoint, double distanceToNextPoint,
|
||||
Graph::EdgeVector & resultPath);
|
||||
|
||||
double m_pathLengthTolerance;
|
||||
Graph & m_graph;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#include "openlr/road_info_getter.hpp"
|
||||
|
||||
#include "indexer/classificator.hpp"
|
||||
#include "indexer/feature.hpp"
|
||||
#include "indexer/data_source.hpp"
|
||||
#include "indexer/feature.hpp"
|
||||
|
||||
#include "base/assert.hpp"
|
||||
|
||||
@@ -14,14 +14,10 @@ RoadInfoGetter::RoadInfo::RoadInfo(FeatureType & ft)
|
||||
, m_link(ftypes::IsLinkChecker::Instance()(ft))
|
||||
, m_oneWay(ftypes::IsOneWayChecker::Instance()(ft))
|
||||
, m_isRoundabout(ftypes::IsRoundAboutChecker::Instance()(ft))
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
// RoadInfoGetter ----------------------------------------------------------------------------------
|
||||
RoadInfoGetter::RoadInfoGetter(DataSource const & dataSource)
|
||||
: m_dataSource(dataSource)
|
||||
{
|
||||
}
|
||||
RoadInfoGetter::RoadInfoGetter(DataSource const & dataSource) : m_dataSource(dataSource) {}
|
||||
|
||||
RoadInfoGetter::RoadInfo RoadInfoGetter::Get(FeatureID const & fid)
|
||||
{
|
||||
|
||||
@@ -34,8 +34,7 @@ public:
|
||||
|
||||
RoadInfo Get(FeatureID const & fid);
|
||||
|
||||
private:
|
||||
|
||||
private:
|
||||
DataSource const & m_dataSource;
|
||||
std::map<FeatureID, RoadInfo> m_cache;
|
||||
};
|
||||
|
||||
@@ -83,16 +83,14 @@ bool Router::Vertex::Score::operator==(Score const & rhs) const
|
||||
}
|
||||
|
||||
// Router::Vertex ----------------------------------------------------------------------------------
|
||||
Router::Vertex::Vertex(geometry::PointWithAltitude const & junction,
|
||||
geometry::PointWithAltitude const & stageStart, double stageStartDistance,
|
||||
size_t stage, bool bearingChecked)
|
||||
Router::Vertex::Vertex(geometry::PointWithAltitude const & junction, geometry::PointWithAltitude const & stageStart,
|
||||
double stageStartDistance, size_t stage, bool bearingChecked)
|
||||
: m_junction(junction)
|
||||
, m_stageStart(stageStart)
|
||||
, m_stageStartDistance(stageStartDistance)
|
||||
, m_stage(stage)
|
||||
, m_bearingChecked(bearingChecked)
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
bool Router::Vertex::operator<(Vertex const & rhs) const
|
||||
{
|
||||
@@ -116,9 +114,11 @@ bool Router::Vertex::operator==(Vertex const & rhs) const
|
||||
|
||||
// Router::Edge ------------------------------------------------------------------------------------
|
||||
Router::Edge::Edge(Vertex const & u, Vertex const & v, routing::Edge const & raw, bool isSpecial)
|
||||
: m_u(u), m_v(v), m_raw(raw), m_isSpecial(isSpecial)
|
||||
{
|
||||
}
|
||||
: m_u(u)
|
||||
, m_v(v)
|
||||
, m_raw(raw)
|
||||
, m_isSpecial(isSpecial)
|
||||
{}
|
||||
|
||||
// static
|
||||
Router::Edge Router::Edge::MakeNormal(Vertex const & u, Vertex const & v, routing::Edge const & raw)
|
||||
@@ -146,20 +146,18 @@ std::pair<m2::PointD, m2::PointD> Router::Edge::ToPairRev() const
|
||||
|
||||
// Router::Router ----------------------------------------------------------------------------------
|
||||
Router::Router(routing::FeaturesRoadGraph & graph, RoadInfoGetter & roadInfoGetter)
|
||||
: m_graph(graph), m_roadInfoGetter(roadInfoGetter)
|
||||
{
|
||||
}
|
||||
: m_graph(graph)
|
||||
, m_roadInfoGetter(roadInfoGetter)
|
||||
{}
|
||||
|
||||
bool Router::Go(std::vector<WayPoint> const & points, double positiveOffsetM,
|
||||
double negativeOffsetM, Path & path)
|
||||
bool Router::Go(std::vector<WayPoint> const & points, double positiveOffsetM, double negativeOffsetM, Path & path)
|
||||
{
|
||||
if (!Init(points, positiveOffsetM, negativeOffsetM))
|
||||
return false;
|
||||
return FindPath(path);
|
||||
}
|
||||
|
||||
bool Router::Init(std::vector<WayPoint> const & points, double positiveOffsetM,
|
||||
double negativeOffsetM)
|
||||
bool Router::Init(std::vector<WayPoint> const & points, double positiveOffsetM, double negativeOffsetM)
|
||||
{
|
||||
CHECK_GREATER_OR_EQUAL(points.size(), 2, ());
|
||||
|
||||
@@ -177,8 +175,7 @@ bool Router::Init(std::vector<WayPoint> const & points, double positiveOffsetM,
|
||||
|
||||
std::vector<std::pair<routing::Edge, geometry::PointWithAltitude>> vicinity;
|
||||
m_graph.FindClosestEdges(
|
||||
mercator::RectByCenterXYAndSizeInMeters(m_points[i].m_point,
|
||||
routing::FeaturesRoadGraph::kClosestEdgesRadiusM),
|
||||
mercator::RectByCenterXYAndSizeInMeters(m_points[i].m_point, routing::FeaturesRoadGraph::kClosestEdgesRadiusM),
|
||||
kMaxRoadCandidates, vicinity);
|
||||
for (auto const & v : vicinity)
|
||||
{
|
||||
@@ -197,20 +194,18 @@ bool Router::Init(std::vector<WayPoint> const & points, double positiveOffsetM,
|
||||
{
|
||||
m_sourceJunction = geometry::PointWithAltitude(m_points.front().m_point, 0 /* altitude */);
|
||||
std::vector<std::pair<routing::Edge, geometry::PointWithAltitude>> sourceVicinity;
|
||||
m_graph.FindClosestEdges(
|
||||
mercator::RectByCenterXYAndSizeInMeters(m_sourceJunction.GetPoint(),
|
||||
routing::FeaturesRoadGraph::kClosestEdgesRadiusM),
|
||||
kMaxRoadCandidates, sourceVicinity);
|
||||
m_graph.FindClosestEdges(mercator::RectByCenterXYAndSizeInMeters(m_sourceJunction.GetPoint(),
|
||||
routing::FeaturesRoadGraph::kClosestEdgesRadiusM),
|
||||
kMaxRoadCandidates, sourceVicinity);
|
||||
m_graph.AddFakeEdges(m_sourceJunction, sourceVicinity);
|
||||
}
|
||||
|
||||
{
|
||||
m_targetJunction = geometry::PointWithAltitude(m_points.back().m_point, 0 /* altitude */);
|
||||
std::vector<std::pair<routing::Edge, geometry::PointWithAltitude>> targetVicinity;
|
||||
m_graph.FindClosestEdges(
|
||||
mercator::RectByCenterXYAndSizeInMeters(m_targetJunction.GetPoint(),
|
||||
routing::FeaturesRoadGraph::kClosestEdgesRadiusM),
|
||||
kMaxRoadCandidates, targetVicinity);
|
||||
m_graph.FindClosestEdges(mercator::RectByCenterXYAndSizeInMeters(m_targetJunction.GetPoint(),
|
||||
routing::FeaturesRoadGraph::kClosestEdgesRadiusM),
|
||||
kMaxRoadCandidates, targetVicinity);
|
||||
m_graph.AddFakeEdges(m_targetJunction, targetVicinity);
|
||||
}
|
||||
|
||||
@@ -224,9 +219,9 @@ bool Router::FindPath(Path & path)
|
||||
std::map<Vertex, Vertex::Score> scores;
|
||||
Links links;
|
||||
|
||||
auto const pushVertex = [&queue, &scores, &links](Vertex const & u, Vertex const & v,
|
||||
Vertex::Score const & vertexScore,
|
||||
Edge const & e) {
|
||||
auto const pushVertex =
|
||||
[&queue, &scores, &links](Vertex const & u, Vertex const & v, Vertex::Score const & vertexScore, Edge const & e)
|
||||
{
|
||||
if ((scores.count(v) == 0 || scores[v].GetScore() > vertexScore.GetScore() + kEps) && u != v)
|
||||
{
|
||||
scores[v] = vertexScore;
|
||||
@@ -279,11 +274,8 @@ bool Router::FindPath(Path & path)
|
||||
|
||||
// max(kDistanceAccuracyM, m_distanceToNextPointM) is added here
|
||||
// to throw out quite long paths.
|
||||
if (ud > u.m_stageStartDistance + distanceToNextPointM +
|
||||
std::max(kDistanceAccuracyM, distanceToNextPointM))
|
||||
{
|
||||
if (ud > u.m_stageStartDistance + distanceToNextPointM + std::max(kDistanceAccuracyM, distanceToNextPointM))
|
||||
continue;
|
||||
}
|
||||
|
||||
if (NearNextStage(u, piU) && !u.m_bearingChecked)
|
||||
{
|
||||
@@ -303,14 +295,12 @@ bool Router::FindPath(Path & path)
|
||||
|
||||
if (MayMoveToNextStage(u, piU))
|
||||
{
|
||||
Vertex v(u.m_junction, u.m_junction, ud /* stageStartDistance */, stage + 1,
|
||||
false /* bearingChecked */);
|
||||
Vertex v(u.m_junction, u.m_junction, ud /* stageStartDistance */, stage + 1, false /* bearingChecked */);
|
||||
double const piV = GetPotential(v);
|
||||
|
||||
Vertex::Score sv = su;
|
||||
sv.AddDistance(std::max(piV - piU, 0.0));
|
||||
sv.AddIntermediateErrorPenalty(
|
||||
mercator::DistanceOnEarth(v.m_junction.GetPoint(), m_points[v.m_stage].m_point));
|
||||
sv.AddIntermediateErrorPenalty(mercator::DistanceOnEarth(v.m_junction.GetPoint(), m_points[v.m_stage].m_point));
|
||||
|
||||
if (IsFinalVertex(v))
|
||||
{
|
||||
@@ -322,7 +312,8 @@ bool Router::FindPath(Path & path)
|
||||
pushVertex(u, v, sv, Edge::MakeSpecial(u, v));
|
||||
}
|
||||
|
||||
ForEachEdge(u, true /* outgoing */, m_points[stage].m_lfrcnp, [&](routing::Edge const & edge) {
|
||||
ForEachEdge(u, true /* outgoing */, m_points[stage].m_lfrcnp, [&](routing::Edge const & edge)
|
||||
{
|
||||
Vertex v = u;
|
||||
v.m_junction = edge.GetEndJunction();
|
||||
|
||||
@@ -338,8 +329,7 @@ bool Router::FindPath(Path & path)
|
||||
CHECK(!NeedToCheckBearing(u, ud), ());
|
||||
|
||||
double const delta = vd - v.m_stageStartDistance - kBearingDist;
|
||||
auto const p = PointAtSegment(edge.GetStartJunction().GetPoint(),
|
||||
edge.GetEndJunction().GetPoint(), delta);
|
||||
auto const p = PointAtSegment(edge.GetStartJunction().GetPoint(), edge.GetEndJunction().GetPoint(), delta);
|
||||
if (v.m_stageStart.GetPoint() != p)
|
||||
{
|
||||
int const expected = m_points[stage].m_bearing;
|
||||
@@ -423,8 +413,7 @@ uint32_t Router::GetReverseBearing(Vertex const & u, Links const & links) const
|
||||
if (passed + weight >= kBearingDist)
|
||||
{
|
||||
double const delta = kBearingDist - passed;
|
||||
b = PointAtSegment(edge.GetEndJunction().GetPoint(), edge.GetStartJunction().GetPoint(),
|
||||
delta);
|
||||
b = PointAtSegment(edge.GetEndJunction().GetPoint(), edge.GetStartJunction().GetPoint(), delta);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
@@ -453,25 +442,20 @@ void Router::ForEachEdge(Vertex const & u, bool outgoing, FunctionalRoadClass re
|
||||
}
|
||||
}
|
||||
|
||||
void Router::GetOutgoingEdges(geometry::PointWithAltitude const & u,
|
||||
routing::IRoadGraph::EdgeListT & edges)
|
||||
void Router::GetOutgoingEdges(geometry::PointWithAltitude const & u, routing::IRoadGraph::EdgeListT & edges)
|
||||
{
|
||||
GetEdges(u, &routing::IRoadGraph::GetRegularOutgoingEdges,
|
||||
&routing::IRoadGraph::GetFakeOutgoingEdges, m_outgoingCache, edges);
|
||||
GetEdges(u, &routing::IRoadGraph::GetRegularOutgoingEdges, &routing::IRoadGraph::GetFakeOutgoingEdges,
|
||||
m_outgoingCache, edges);
|
||||
}
|
||||
|
||||
void Router::GetIngoingEdges(geometry::PointWithAltitude const & u,
|
||||
routing::IRoadGraph::EdgeListT & edges)
|
||||
void Router::GetIngoingEdges(geometry::PointWithAltitude const & u, routing::IRoadGraph::EdgeListT & edges)
|
||||
{
|
||||
GetEdges(u, &routing::IRoadGraph::GetRegularIngoingEdges,
|
||||
&routing::IRoadGraph::GetFakeIngoingEdges, m_ingoingCache, edges);
|
||||
GetEdges(u, &routing::IRoadGraph::GetRegularIngoingEdges, &routing::IRoadGraph::GetFakeIngoingEdges, m_ingoingCache,
|
||||
edges);
|
||||
}
|
||||
|
||||
void Router::GetEdges(
|
||||
geometry::PointWithAltitude const & u, RoadGraphEdgesGetter getRegular,
|
||||
RoadGraphEdgesGetter getFake,
|
||||
EdgeCacheT & cache,
|
||||
routing::IRoadGraph::EdgeListT & edges)
|
||||
void Router::GetEdges(geometry::PointWithAltitude const & u, RoadGraphEdgesGetter getRegular,
|
||||
RoadGraphEdgesGetter getFake, EdgeCacheT & cache, routing::IRoadGraph::EdgeListT & edges)
|
||||
{
|
||||
auto const it = cache.find(u);
|
||||
if (it == cache.end())
|
||||
@@ -489,24 +473,22 @@ void Router::GetEdges(
|
||||
}
|
||||
|
||||
template <typename Fn>
|
||||
void Router::ForEachNonFakeEdge(Vertex const & u, bool outgoing, FunctionalRoadClass restriction,
|
||||
Fn && fn)
|
||||
void Router::ForEachNonFakeEdge(Vertex const & u, bool outgoing, FunctionalRoadClass restriction, Fn && fn)
|
||||
{
|
||||
ForEachEdge(u, outgoing, restriction, [&fn](routing::Edge const & edge) {
|
||||
ForEachEdge(u, outgoing, restriction, [&fn](routing::Edge const & edge)
|
||||
{
|
||||
if (!edge.IsFake())
|
||||
fn(edge);
|
||||
});
|
||||
}
|
||||
|
||||
template <typename Fn>
|
||||
void Router::ForEachNonFakeClosestEdge(Vertex const & u, FunctionalRoadClass const restriction,
|
||||
Fn && fn)
|
||||
void Router::ForEachNonFakeClosestEdge(Vertex const & u, FunctionalRoadClass const restriction, Fn && fn)
|
||||
{
|
||||
std::vector<std::pair<routing::Edge, geometry::PointWithAltitude>> vicinity;
|
||||
m_graph.FindClosestEdges(
|
||||
mercator::RectByCenterXYAndSizeInMeters(u.m_junction.GetPoint(),
|
||||
routing::FeaturesRoadGraph::kClosestEdgesRadiusM),
|
||||
kMaxRoadCandidates, vicinity);
|
||||
m_graph.FindClosestEdges(mercator::RectByCenterXYAndSizeInMeters(u.m_junction.GetPoint(),
|
||||
routing::FeaturesRoadGraph::kClosestEdgesRadiusM),
|
||||
kMaxRoadCandidates, vicinity);
|
||||
|
||||
for (auto const & p : vicinity)
|
||||
{
|
||||
@@ -652,64 +634,61 @@ bool Router::ReconstructPath(std::vector<Edge> & edges, Path & path)
|
||||
|
||||
{
|
||||
auto toPair = [](auto && e) { return e.ToPair(); };
|
||||
size_t const n = FindPrefixLengthToConsume(
|
||||
make_transform_iterator(edges.begin(), toPair),
|
||||
make_transform_iterator(edges.end(), toPair), m_positiveOffsetM);
|
||||
size_t const n = FindPrefixLengthToConsume(make_transform_iterator(edges.begin(), toPair),
|
||||
make_transform_iterator(edges.end(), toPair), m_positiveOffsetM);
|
||||
CHECK_LESS_OR_EQUAL(n, edges.size(), ());
|
||||
edges.erase(edges.begin(), edges.begin() + n);
|
||||
}
|
||||
|
||||
{
|
||||
auto toPairRev = [](auto && e) { return e.ToPairRev(); };
|
||||
size_t const n = FindPrefixLengthToConsume(
|
||||
make_transform_iterator(edges.rbegin(), toPairRev),
|
||||
make_transform_iterator(edges.rend(), toPairRev), m_negativeOffsetM);
|
||||
size_t const n = FindPrefixLengthToConsume(make_transform_iterator(edges.rbegin(), toPairRev),
|
||||
make_transform_iterator(edges.rend(), toPairRev), m_negativeOffsetM);
|
||||
CHECK_LESS_OR_EQUAL(n, edges.size(), ());
|
||||
edges.erase(edges.begin() + edges.size() - n, edges.end());
|
||||
}
|
||||
|
||||
double frontEdgeScore = -1.0;
|
||||
routing::Edge frontEdge;
|
||||
ForStagePrefix(edges.begin(), edges.end(), 0, [&](EdgeIt e) {
|
||||
ForEachNonFakeEdge(e->m_u, false /* outgoing */, m_points[0].m_lfrcnp,
|
||||
[&](routing::Edge const & edge) {
|
||||
auto toPairRev = [](auto && e) { return e.ToPairRev(); };
|
||||
double const score = GetMatchingScore(
|
||||
edge.GetEndJunction().GetPoint(), edge.GetStartJunction().GetPoint(),
|
||||
make_transform_iterator(EdgeItRev(e), toPairRev),
|
||||
make_transform_iterator(edges.rend(), toPairRev));
|
||||
if (score > frontEdgeScore)
|
||||
{
|
||||
frontEdgeScore = score;
|
||||
frontEdge = edge.GetReverseEdge();
|
||||
}
|
||||
});
|
||||
ForStagePrefix(edges.begin(), edges.end(), 0, [&](EdgeIt e)
|
||||
{
|
||||
ForEachNonFakeEdge(e->m_u, false /* outgoing */, m_points[0].m_lfrcnp, [&](routing::Edge const & edge)
|
||||
{
|
||||
auto toPairRev = [](auto && e) { return e.ToPairRev(); };
|
||||
double const score = GetMatchingScore(edge.GetEndJunction().GetPoint(), edge.GetStartJunction().GetPoint(),
|
||||
make_transform_iterator(EdgeItRev(e), toPairRev),
|
||||
make_transform_iterator(edges.rend(), toPairRev));
|
||||
if (score > frontEdgeScore)
|
||||
{
|
||||
frontEdgeScore = score;
|
||||
frontEdge = edge.GetReverseEdge();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
double backEdgeScore = -1.0;
|
||||
routing::Edge backEdge;
|
||||
ForStagePrefix(edges.rbegin(), edges.rend(), m_points.size() - 2 /* stage */, [&](EdgeItRev e) {
|
||||
ForStagePrefix(edges.rbegin(), edges.rend(), m_points.size() - 2 /* stage */, [&](EdgeItRev e)
|
||||
{
|
||||
ForEachNonFakeEdge(e->m_v, true /* outgoing */, m_points[m_points.size() - 2].m_lfrcnp,
|
||||
[&](routing::Edge const & edge) {
|
||||
auto toPair = [](auto && e) { return e.ToPair(); };
|
||||
double const score = GetMatchingScore(
|
||||
edge.GetStartJunction().GetPoint(), edge.GetEndJunction().GetPoint(),
|
||||
make_transform_iterator(e.base(), toPair),
|
||||
make_transform_iterator(edges.end(), toPair));
|
||||
if (score > backEdgeScore)
|
||||
{
|
||||
backEdgeScore = score;
|
||||
backEdge = edge;
|
||||
}
|
||||
});
|
||||
[&](routing::Edge const & edge)
|
||||
{
|
||||
auto toPair = [](auto && e) { return e.ToPair(); };
|
||||
double const score =
|
||||
GetMatchingScore(edge.GetStartJunction().GetPoint(), edge.GetEndJunction().GetPoint(),
|
||||
make_transform_iterator(e.base(), toPair), make_transform_iterator(edges.end(), toPair));
|
||||
if (score > backEdgeScore)
|
||||
{
|
||||
backEdgeScore = score;
|
||||
backEdge = edge;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
path.clear();
|
||||
for (auto const & e : edges)
|
||||
{
|
||||
if (!e.IsFake())
|
||||
path.push_back(e.m_raw);
|
||||
}
|
||||
|
||||
if (frontEdgeScore >= kFakeCoverageThreshold && !path.empty() && path.front() != frontEdge)
|
||||
path.insert(path.begin(), frontEdge);
|
||||
@@ -742,11 +721,11 @@ void Router::FindSingleEdgeApproximation(std::vector<Edge> const & edges, Path &
|
||||
double bestCoverage = -1.0;
|
||||
routing::Edge bestEdge;
|
||||
|
||||
auto checkEdge = [&](routing::Edge const & edge) {
|
||||
auto checkEdge = [&](routing::Edge const & edge)
|
||||
{
|
||||
double const weight = GetWeight(edge);
|
||||
double const fraction =
|
||||
GetCoverage(edge.GetStartJunction().GetPoint(), edge.GetEndJunction().GetPoint(),
|
||||
edges.begin(), edges.end());
|
||||
GetCoverage(edge.GetStartJunction().GetPoint(), edge.GetEndJunction().GetPoint(), edges.begin(), edges.end());
|
||||
double const coverage = weight * fraction;
|
||||
if (coverage >= bestCoverage)
|
||||
{
|
||||
|
||||
@@ -35,20 +35,20 @@ private:
|
||||
{
|
||||
public:
|
||||
// A weight for total length of true fake edges.
|
||||
static const int kTrueFakeCoeff = 10;
|
||||
static int const kTrueFakeCoeff = 10;
|
||||
|
||||
// A weight for total length of fake edges that are parts of some
|
||||
// real edges.
|
||||
static constexpr double kFakeCoeff = 0.001;
|
||||
|
||||
// A weight for passing too far from pivot points.
|
||||
static const int kIntermediateErrorCoeff = 3;
|
||||
static int const kIntermediateErrorCoeff = 3;
|
||||
|
||||
// A weight for excess of distance limit.
|
||||
static const int kDistanceErrorCoeff = 3;
|
||||
static int const kDistanceErrorCoeff = 3;
|
||||
|
||||
// A weight for deviation from bearing.
|
||||
static const int kBearingErrorCoeff = 5;
|
||||
static int const kBearingErrorCoeff = 5;
|
||||
|
||||
void AddDistance(double p) { m_distance += p; }
|
||||
void AddFakePenalty(double p, bool partOfReal);
|
||||
@@ -73,9 +73,8 @@ private:
|
||||
};
|
||||
|
||||
Vertex() = default;
|
||||
Vertex(geometry::PointWithAltitude const & junction,
|
||||
geometry::PointWithAltitude const & stageStart, double stageStartDistance, size_t stage,
|
||||
bool bearingChecked);
|
||||
Vertex(geometry::PointWithAltitude const & junction, geometry::PointWithAltitude const & stageStart,
|
||||
double stageStartDistance, size_t stage, bool bearingChecked);
|
||||
|
||||
bool operator<(Vertex const & rhs) const;
|
||||
bool operator==(Vertex const & rhs) const;
|
||||
@@ -137,8 +136,8 @@ private:
|
||||
|
||||
using Links = std::map<Vertex, std::pair<Vertex, Edge>>;
|
||||
|
||||
using RoadGraphEdgesGetter = void (routing::IRoadGraph::*)(
|
||||
geometry::PointWithAltitude const & junction, routing::IRoadGraph::EdgeListT & edges) const;
|
||||
using RoadGraphEdgesGetter = void (routing::IRoadGraph::*)(geometry::PointWithAltitude const & junction,
|
||||
routing::IRoadGraph::EdgeListT & edges) const;
|
||||
|
||||
bool Init(std::vector<WayPoint> const & points, double positiveOffsetM, double negativeOffsetM);
|
||||
bool FindPath(Path & path);
|
||||
@@ -162,8 +161,7 @@ private:
|
||||
|
||||
double GetWeight(routing::Edge const & e) const
|
||||
{
|
||||
return mercator::DistanceOnEarth(e.GetStartJunction().GetPoint(),
|
||||
e.GetEndJunction().GetPoint());
|
||||
return mercator::DistanceOnEarth(e.GetStartJunction().GetPoint(), e.GetEndJunction().GetPoint());
|
||||
}
|
||||
|
||||
double GetWeight(Edge const & e) const { return GetWeight(e.m_raw); }
|
||||
@@ -173,20 +171,15 @@ private:
|
||||
template <typename Fn>
|
||||
void ForEachEdge(Vertex const & u, bool outgoing, FunctionalRoadClass restriction, Fn && fn);
|
||||
|
||||
void GetOutgoingEdges(geometry::PointWithAltitude const & u,
|
||||
routing::IRoadGraph::EdgeListT & edges);
|
||||
void GetIngoingEdges(geometry::PointWithAltitude const & u,
|
||||
routing::IRoadGraph::EdgeListT & edges);
|
||||
void GetOutgoingEdges(geometry::PointWithAltitude const & u, routing::IRoadGraph::EdgeListT & edges);
|
||||
void GetIngoingEdges(geometry::PointWithAltitude const & u, routing::IRoadGraph::EdgeListT & edges);
|
||||
|
||||
using EdgeCacheT = std::map<geometry::PointWithAltitude, routing::IRoadGraph::EdgeListT>;
|
||||
void GetEdges(geometry::PointWithAltitude const & u, RoadGraphEdgesGetter getRegular,
|
||||
RoadGraphEdgesGetter getFake,
|
||||
EdgeCacheT & cache,
|
||||
routing::IRoadGraph::EdgeListT & edges);
|
||||
void GetEdges(geometry::PointWithAltitude const & u, RoadGraphEdgesGetter getRegular, RoadGraphEdgesGetter getFake,
|
||||
EdgeCacheT & cache, routing::IRoadGraph::EdgeListT & edges);
|
||||
|
||||
template <typename Fn>
|
||||
void ForEachNonFakeEdge(Vertex const & u, bool outgoing, FunctionalRoadClass restriction,
|
||||
Fn && fn);
|
||||
void ForEachNonFakeEdge(Vertex const & u, bool outgoing, FunctionalRoadClass restriction, Fn && fn);
|
||||
|
||||
template <typename Fn>
|
||||
void ForEachNonFakeClosestEdge(Vertex const & u, FunctionalRoadClass const restriction, Fn && fn);
|
||||
|
||||
@@ -55,16 +55,14 @@ double DifferenceInDeg(double a1, double a2)
|
||||
|
||||
void EdgeSortUniqueByStartAndEndPoints(Graph::EdgeListT & edges)
|
||||
{
|
||||
base::SortUnique(
|
||||
edges,
|
||||
[](Edge const & e1, Edge const & e2) {
|
||||
if (e1.GetStartPoint() != e2.GetStartPoint())
|
||||
return e1.GetStartPoint() < e2.GetStartPoint();
|
||||
return e1.GetEndPoint() < e2.GetEndPoint();
|
||||
},
|
||||
[](Edge const & e1, Edge const & e2) {
|
||||
return e1.GetStartPoint() == e2.GetStartPoint() && e1.GetEndPoint() == e2.GetEndPoint();
|
||||
});
|
||||
base::SortUnique(edges,
|
||||
[](Edge const & e1, Edge const & e2)
|
||||
{
|
||||
if (e1.GetStartPoint() != e2.GetStartPoint())
|
||||
return e1.GetStartPoint() < e2.GetStartPoint();
|
||||
return e1.GetEndPoint() < e2.GetEndPoint();
|
||||
}, [](Edge const & e1, Edge const & e2)
|
||||
{ return e1.GetStartPoint() == e2.GetStartPoint() && e1.GetEndPoint() == e2.GetEndPoint(); });
|
||||
}
|
||||
} // namespace scpg
|
||||
|
||||
@@ -93,9 +91,9 @@ bool ScoreCandidatePathsGetter::Link::IsJunctionInPath(geometry::PointWithAltitu
|
||||
}
|
||||
|
||||
// ScoreCandidatePathsGetter ----------------------------------------------------------------------------
|
||||
bool ScoreCandidatePathsGetter::GetLineCandidatesForPoints(
|
||||
vector<LocationReferencePoint> const & points, LinearSegmentSource source,
|
||||
vector<ScorePathVec> & lineCandidates)
|
||||
bool ScoreCandidatePathsGetter::GetLineCandidatesForPoints(vector<LocationReferencePoint> const & points,
|
||||
LinearSegmentSource source,
|
||||
vector<ScorePathVec> & lineCandidates)
|
||||
{
|
||||
CHECK_GREATER(points.size(), 1, ());
|
||||
|
||||
@@ -110,15 +108,12 @@ bool ScoreCandidatePathsGetter::GetLineCandidatesForPoints(
|
||||
|
||||
lineCandidates.emplace_back();
|
||||
auto const isLastPoint = i == points.size() - 1;
|
||||
double const distanceToNextPointM =
|
||||
(isLastPoint ? points[i - 1] : points[i]).m_distanceToNextPoint;
|
||||
double const distanceToNextPointM = (isLastPoint ? points[i - 1] : points[i]).m_distanceToNextPoint;
|
||||
|
||||
ScoreEdgeVec edgesCandidates;
|
||||
m_pointsGetter.GetEdgeCandidates(mercator::FromLatLon(points[i].m_latLon),
|
||||
isLastPoint, edgesCandidates);
|
||||
m_pointsGetter.GetEdgeCandidates(mercator::FromLatLon(points[i].m_latLon), isLastPoint, edgesCandidates);
|
||||
|
||||
GetLineCandidates(points[i], source, isLastPoint, distanceToNextPointM, edgesCandidates,
|
||||
lineCandidates.back());
|
||||
GetLineCandidates(points[i], source, isLastPoint, distanceToNextPointM, edgesCandidates, lineCandidates.back());
|
||||
|
||||
if (lineCandidates.back().empty())
|
||||
{
|
||||
@@ -132,13 +127,10 @@ bool ScoreCandidatePathsGetter::GetLineCandidatesForPoints(
|
||||
return true;
|
||||
}
|
||||
|
||||
void ScoreCandidatePathsGetter::GetAllSuitablePaths(ScoreEdgeVec const & startLines,
|
||||
LinearSegmentSource source, bool isLastPoint,
|
||||
double bearDistM,
|
||||
FunctionalRoadClass functionalRoadClass,
|
||||
FormOfWay formOfWay,
|
||||
double distanceToNextPointM,
|
||||
vector<shared_ptr<Link>> & allPaths)
|
||||
void ScoreCandidatePathsGetter::GetAllSuitablePaths(ScoreEdgeVec const & startLines, LinearSegmentSource source,
|
||||
bool isLastPoint, double bearDistM,
|
||||
FunctionalRoadClass functionalRoadClass, FormOfWay formOfWay,
|
||||
double distanceToNextPointM, vector<shared_ptr<Link>> & allPaths)
|
||||
{
|
||||
CHECK_NOT_EQUAL(source, LinearSegmentSource::NotValid, ());
|
||||
|
||||
@@ -146,15 +138,14 @@ void ScoreCandidatePathsGetter::GetAllSuitablePaths(ScoreEdgeVec const & startLi
|
||||
|
||||
for (auto const & e : startLines)
|
||||
{
|
||||
Score roadScore = 0; // Score based on functional road class and form of way.
|
||||
Score roadScore = 0; // Score based on functional road class and form of way.
|
||||
if (source == LinearSegmentSource::FromLocationReferenceTag &&
|
||||
!PassesRestrictionV3(e.m_edge, functionalRoadClass, formOfWay, m_infoGetter, roadScore))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
q.push(
|
||||
make_shared<Link>(nullptr /* parent */, e.m_edge, 0 /* distanceM */, e.m_score, roadScore));
|
||||
q.push(make_shared<Link>(nullptr /* parent */, e.m_edge, 0 /* distanceM */, e.m_score, roadScore));
|
||||
}
|
||||
|
||||
// Filling |allPaths| staring from |startLines| which have passed functional road class
|
||||
@@ -214,8 +205,8 @@ void ScoreCandidatePathsGetter::GetAllSuitablePaths(ScoreEdgeVec const & startLi
|
||||
|
||||
// Road score for a path is minimum value of score of segments based on functional road class
|
||||
// of the segments and form of way of the segments.
|
||||
q.emplace(make_shared<Link>(u, e, u->m_distanceM + currentEdgeLen, u->m_pointScore,
|
||||
min(roadScore, u->m_minRoadScore)));
|
||||
q.emplace(
|
||||
make_shared<Link>(u, e, u->m_distanceM + currentEdgeLen, u->m_pointScore, min(roadScore, u->m_minRoadScore)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -223,8 +214,7 @@ void ScoreCandidatePathsGetter::GetAllSuitablePaths(ScoreEdgeVec const & startLi
|
||||
void ScoreCandidatePathsGetter::GetBestCandidatePaths(vector<shared_ptr<Link>> const & allPaths,
|
||||
LinearSegmentSource source, bool isLastPoint,
|
||||
uint32_t requiredBearing, double bearDistM,
|
||||
m2::PointD const & startPoint,
|
||||
ScorePathVec & candidates)
|
||||
m2::PointD const & startPoint, ScorePathVec & candidates)
|
||||
{
|
||||
CHECK_NOT_EQUAL(source, LinearSegmentSource::NotValid, ());
|
||||
CHECK_LESS_OR_EQUAL(requiredBearing, 255, ());
|
||||
@@ -269,8 +259,7 @@ void ScoreCandidatePathsGetter::GetBestCandidatePaths(vector<shared_ptr<Link>> c
|
||||
|
||||
size_t constexpr kMaxCandidates = 7;
|
||||
vector<CandidatePath> paths;
|
||||
copy_n(candidatePaths.begin(), min(static_cast<size_t>(kMaxCandidates), candidatePaths.size()),
|
||||
back_inserter(paths));
|
||||
copy_n(candidatePaths.begin(), min(static_cast<size_t>(kMaxCandidates), candidatePaths.size()), back_inserter(paths));
|
||||
|
||||
for (auto const & path : paths)
|
||||
{
|
||||
@@ -285,12 +274,9 @@ void ScoreCandidatePathsGetter::GetBestCandidatePaths(vector<shared_ptr<Link>> c
|
||||
}
|
||||
}
|
||||
|
||||
void ScoreCandidatePathsGetter::GetLineCandidates(openlr::LocationReferencePoint const & p,
|
||||
LinearSegmentSource source,
|
||||
bool isLastPoint,
|
||||
double distanceToNextPointM,
|
||||
ScoreEdgeVec const & edgeCandidates,
|
||||
ScorePathVec & candidates)
|
||||
void ScoreCandidatePathsGetter::GetLineCandidates(openlr::LocationReferencePoint const & p, LinearSegmentSource source,
|
||||
bool isLastPoint, double distanceToNextPointM,
|
||||
ScoreEdgeVec const & edgeCandidates, ScorePathVec & candidates)
|
||||
{
|
||||
double constexpr kDefaultBearDistM = 25.0;
|
||||
double const bearDistM = min(kDefaultBearDistM, distanceToNextPointM);
|
||||
@@ -303,11 +289,10 @@ void ScoreCandidatePathsGetter::GetLineCandidates(openlr::LocationReferencePoint
|
||||
auto const startPoint = mercator::FromLatLon(p.m_latLon);
|
||||
|
||||
vector<shared_ptr<Link>> allPaths;
|
||||
GetAllSuitablePaths(startLines, source, isLastPoint, bearDistM, p.m_functionalRoadClass,
|
||||
p.m_formOfWay, distanceToNextPointM, allPaths);
|
||||
GetAllSuitablePaths(startLines, source, isLastPoint, bearDistM, p.m_functionalRoadClass, p.m_formOfWay,
|
||||
distanceToNextPointM, allPaths);
|
||||
|
||||
GetBestCandidatePaths(allPaths, source, isLastPoint, p.m_bearing, bearDistM, startPoint,
|
||||
candidates);
|
||||
GetBestCandidatePaths(allPaths, source, isLastPoint, p.m_bearing, bearDistM, startPoint, candidates);
|
||||
// Sorting by increasing order.
|
||||
sort(candidates.begin(), candidates.end(),
|
||||
[](ScorePath const & s1, ScorePath const & s2) { return s1.m_score > s2.m_score; });
|
||||
@@ -316,8 +301,8 @@ void ScoreCandidatePathsGetter::GetLineCandidates(openlr::LocationReferencePoint
|
||||
|
||||
bool ScoreCandidatePathsGetter::GetBearingScore(BearingPointsSelector const & pointsSelector,
|
||||
ScoreCandidatePathsGetter::Link const & part,
|
||||
m2::PointD const & bearStartPoint,
|
||||
uint32_t requiredBearing, Score & score)
|
||||
m2::PointD const & bearStartPoint, uint32_t requiredBearing,
|
||||
Score & score)
|
||||
{
|
||||
auto const bearEndPoint = pointsSelector.GetEndPoint(part.m_edge, part.m_distanceM);
|
||||
|
||||
@@ -333,8 +318,7 @@ bool ScoreCandidatePathsGetter::GetBearingScore(BearingPointsSelector const & po
|
||||
|
||||
double constexpr kMaxScoreForBearing = 60.0;
|
||||
double constexpr kAngleDeviationFactor = 1.0 / 4.3;
|
||||
score =
|
||||
static_cast<Score>(kMaxScoreForBearing / (1.0 + angleDeviationDeg * kAngleDeviationFactor));
|
||||
score = static_cast<Score>(kMaxScoreForBearing / (1.0 + angleDeviationDeg * kAngleDeviationFactor));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "openlr/helpers.hpp"
|
||||
#include "openlr/graph.hpp"
|
||||
#include "openlr/helpers.hpp"
|
||||
#include "openlr/openlr_model.hpp"
|
||||
#include "openlr/road_info_getter.hpp"
|
||||
#include "openlr/score_types.hpp"
|
||||
@@ -23,21 +23,22 @@ class ScoreCandidatePointsGetter;
|
||||
class ScoreCandidatePathsGetter
|
||||
{
|
||||
public:
|
||||
ScoreCandidatePathsGetter(ScoreCandidatePointsGetter & pointsGetter, Graph & graph,
|
||||
RoadInfoGetter & infoGetter, v2::Stats & stat)
|
||||
: m_pointsGetter(pointsGetter), m_graph(graph), m_infoGetter(infoGetter), m_stats(stat)
|
||||
{
|
||||
}
|
||||
ScoreCandidatePathsGetter(ScoreCandidatePointsGetter & pointsGetter, Graph & graph, RoadInfoGetter & infoGetter,
|
||||
v2::Stats & stat)
|
||||
: m_pointsGetter(pointsGetter)
|
||||
, m_graph(graph)
|
||||
, m_infoGetter(infoGetter)
|
||||
, m_stats(stat)
|
||||
{}
|
||||
|
||||
bool GetLineCandidatesForPoints(std::vector<LocationReferencePoint> const & points,
|
||||
LinearSegmentSource source,
|
||||
bool GetLineCandidatesForPoints(std::vector<LocationReferencePoint> const & points, LinearSegmentSource source,
|
||||
std::vector<ScorePathVec> & lineCandidates);
|
||||
|
||||
private:
|
||||
struct Link
|
||||
{
|
||||
Link(std::shared_ptr<Link> const & parent, Graph::Edge const & edge, double distanceM,
|
||||
Score pointScore, Score rfcScore)
|
||||
Link(std::shared_ptr<Link> const & parent, Graph::Edge const & edge, double distanceM, Score pointScore,
|
||||
Score rfcScore)
|
||||
: m_parent(parent)
|
||||
, m_edge(edge)
|
||||
, m_distanceM(distanceM)
|
||||
@@ -69,8 +70,7 @@ private:
|
||||
, m_pointScore(pointScore)
|
||||
, m_roadScore(rfcScore)
|
||||
, m_bearingScore(bearingScore)
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
bool operator>(CandidatePath const & o) const { return GetScore() > o.GetScore(); }
|
||||
|
||||
@@ -97,23 +97,18 @@ private:
|
||||
/// \brief Fills |allPaths| with paths near start or finish point starting from |startLines|.
|
||||
/// To extract a path from |allPaths| a item from |allPaths| should be taken,
|
||||
/// then should be taken the member |m_parent| of the item and so on till the beginning.
|
||||
void GetAllSuitablePaths(ScoreEdgeVec const & startLines, LinearSegmentSource source,
|
||||
bool isLastPoint, double bearDistM,
|
||||
FunctionalRoadClass functionalRoadClass, FormOfWay formOfWay,
|
||||
double distanceToNextPointM,
|
||||
std::vector<std::shared_ptr<Link>> & allPaths);
|
||||
void GetAllSuitablePaths(ScoreEdgeVec const & startLines, LinearSegmentSource source, bool isLastPoint,
|
||||
double bearDistM, FunctionalRoadClass functionalRoadClass, FormOfWay formOfWay,
|
||||
double distanceToNextPointM, std::vector<std::shared_ptr<Link>> & allPaths);
|
||||
|
||||
void GetBestCandidatePaths(std::vector<std::shared_ptr<Link>> const & allPaths,
|
||||
LinearSegmentSource source, bool isLastPoint, uint32_t requiredBearing,
|
||||
double bearDistM, m2::PointD const & startPoint,
|
||||
ScorePathVec & candidates);
|
||||
void GetBestCandidatePaths(std::vector<std::shared_ptr<Link>> const & allPaths, LinearSegmentSource source,
|
||||
bool isLastPoint, uint32_t requiredBearing, double bearDistM,
|
||||
m2::PointD const & startPoint, ScorePathVec & candidates);
|
||||
|
||||
void GetLineCandidates(openlr::LocationReferencePoint const & p, LinearSegmentSource source,
|
||||
bool isLastPoint, double distanceToNextPointM,
|
||||
ScoreEdgeVec const & edgeCandidates, ScorePathVec & candidates);
|
||||
void GetLineCandidates(openlr::LocationReferencePoint const & p, LinearSegmentSource source, bool isLastPoint,
|
||||
double distanceToNextPointM, ScoreEdgeVec const & edgeCandidates, ScorePathVec & candidates);
|
||||
|
||||
bool GetBearingScore(BearingPointsSelector const & pointsSelector,
|
||||
ScoreCandidatePathsGetter::Link const & part,
|
||||
bool GetBearingScore(BearingPointsSelector const & pointsSelector, ScoreCandidatePathsGetter::Link const & part,
|
||||
m2::PointD const & bearStartPoint, uint32_t requiredBearing, Score & score);
|
||||
|
||||
ScoreCandidatePointsGetter & m_pointsGetter;
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace
|
||||
{
|
||||
// Ends of segments and intermediate points of segments are considered only within this radius.
|
||||
double const kRadius = 30.0;
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
namespace openlr
|
||||
{
|
||||
@@ -36,17 +36,17 @@ void ScoreCandidatePointsGetter::GetJunctionPointCandidates(m2::PointD const & p
|
||||
ScoreEdgeVec & edgeCandidates)
|
||||
{
|
||||
ScorePointVec pointCandidates;
|
||||
auto const selectCandidates = [&p, &pointCandidates, this](FeatureType & ft) {
|
||||
auto const selectCandidates = [&p, &pointCandidates, this](FeatureType & ft)
|
||||
{
|
||||
ft.ParseGeometry(FeatureType::BEST_GEOMETRY);
|
||||
if (ft.GetGeomType() != feature::GeomType::Line || !routing::IsRoad(feature::TypesHolder(ft)))
|
||||
return;
|
||||
|
||||
ft.ForEachPoint(
|
||||
[&p, &pointCandidates, this](m2::PointD const & candidate) {
|
||||
if (mercator::DistanceOnEarth(p, candidate) < kRadius)
|
||||
pointCandidates.emplace_back(GetScoreByDistance(p, candidate), candidate);
|
||||
},
|
||||
scales::GetUpperScale());
|
||||
ft.ForEachPoint([&p, &pointCandidates, this](m2::PointD const & candidate)
|
||||
{
|
||||
if (mercator::DistanceOnEarth(p, candidate) < kRadius)
|
||||
pointCandidates.emplace_back(GetScoreByDistance(p, candidate), candidate);
|
||||
}, scales::GetUpperScale());
|
||||
};
|
||||
|
||||
m_dataSource.ForEachInRect(selectCandidates, mercator::RectByCenterXYAndSizeInMeters(p, kRadius),
|
||||
@@ -70,8 +70,7 @@ void ScoreCandidatePointsGetter::GetJunctionPointCandidates(m2::PointD const & p
|
||||
}
|
||||
}
|
||||
|
||||
void ScoreCandidatePointsGetter::EnrichWithProjectionPoints(m2::PointD const & p,
|
||||
ScoreEdgeVec & edgeCandidates)
|
||||
void ScoreCandidatePointsGetter::EnrichWithProjectionPoints(m2::PointD const & p, ScoreEdgeVec & edgeCandidates)
|
||||
{
|
||||
m_graph.ResetFakes();
|
||||
|
||||
@@ -115,8 +114,7 @@ bool ScoreCandidatePointsGetter::IsJunction(m2::PointD const & p)
|
||||
return ids.size() >= 3;
|
||||
}
|
||||
|
||||
Score ScoreCandidatePointsGetter::GetScoreByDistance(m2::PointD const & point,
|
||||
m2::PointD const & candidate)
|
||||
Score ScoreCandidatePointsGetter::GetScoreByDistance(m2::PointD const & point, m2::PointD const & candidate)
|
||||
{
|
||||
// Maximum possible score for the distance between an openlr segment ends and an osm segments.
|
||||
Score constexpr kMaxScoreForDist = 70;
|
||||
@@ -128,10 +126,9 @@ Score ScoreCandidatePointsGetter::GetScoreByDistance(m2::PointD const & point,
|
||||
double const junctionFactor = IsJunction(candidate) ? 1.1 : 1.0;
|
||||
|
||||
double const distM = mercator::DistanceOnEarth(point, candidate);
|
||||
double const score =
|
||||
distM <= kMaxScoreDistM
|
||||
? kMaxScoreForDist * junctionFactor
|
||||
: static_cast<double>(kMaxScoreForDist) * junctionFactor / (1.0 + distM - kMaxScoreDistM);
|
||||
double const score = distM <= kMaxScoreDistM
|
||||
? kMaxScoreForDist * junctionFactor
|
||||
: static_cast<double>(kMaxScoreForDist) * junctionFactor / (1.0 + distM - kMaxScoreDistM);
|
||||
|
||||
CHECK_GREATER_OR_EQUAL(score, 0.0, ());
|
||||
CHECK_LESS_OR_EQUAL(score, static_cast<double>(kMaxScoreForDist) * junctionFactor, ());
|
||||
|
||||
@@ -23,8 +23,7 @@ public:
|
||||
, m_maxProjectionCandidates(maxProjectionCandidates)
|
||||
, m_dataSource(dataSource)
|
||||
, m_graph(graph)
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
void GetEdgeCandidates(m2::PointD const & p, bool isLastPoint, ScoreEdgeVec & edges)
|
||||
{
|
||||
@@ -33,8 +32,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
void GetJunctionPointCandidates(m2::PointD const & p, bool isLastPoint,
|
||||
ScoreEdgeVec & edgeCandidates);
|
||||
void GetJunctionPointCandidates(m2::PointD const & p, bool isLastPoint, ScoreEdgeVec & edgeCandidates);
|
||||
void EnrichWithProjectionPoints(m2::PointD const & p, ScoreEdgeVec & edgeCandidates);
|
||||
|
||||
/// \returns true if |p| is a junction and false otherwise.
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <queue>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
|
||||
using namespace std;
|
||||
@@ -48,10 +48,8 @@ public:
|
||||
{
|
||||
CHECK(hwClass != ftypes::HighwayClass::Undefined, (edge));
|
||||
|
||||
m_minHwClass = static_cast<ftypes::HighwayClass>(
|
||||
min(base::Underlying(m_minHwClass), base::Underlying(hwClass)));
|
||||
m_maxHwClass = static_cast<ftypes::HighwayClass>(
|
||||
max(base::Underlying(m_maxHwClass), base::Underlying(hwClass)));
|
||||
m_minHwClass = static_cast<ftypes::HighwayClass>(min(base::Underlying(m_minHwClass), base::Underlying(hwClass)));
|
||||
m_maxHwClass = static_cast<ftypes::HighwayClass>(max(base::Underlying(m_maxHwClass), base::Underlying(hwClass)));
|
||||
|
||||
if (m_oneWay.m_allEqual && m_oneWay.m_field != ftypes::IsOneWayChecker::Instance()(types))
|
||||
m_oneWay.m_allEqual = false;
|
||||
@@ -96,8 +94,8 @@ private:
|
||||
/// \returns true if |path| may be used as a candidate. In that case |lenScore| is filled
|
||||
/// with score of this candidate based on length. The closer length of the |path| to
|
||||
/// |distanceToNextPoint| the more score.
|
||||
bool ValidatePathByLength(Graph::EdgeVector const & path, double distanceToNextPoint,
|
||||
LinearSegmentSource source, Score & lenScore)
|
||||
bool ValidatePathByLength(Graph::EdgeVector const & path, double distanceToNextPoint, LinearSegmentSource source,
|
||||
Score & lenScore)
|
||||
{
|
||||
CHECK(!path.empty(), ());
|
||||
CHECK_NOT_EQUAL(source, LinearSegmentSource::NotValid, ());
|
||||
@@ -109,12 +107,10 @@ bool ValidatePathByLength(Graph::EdgeVector const & path, double distanceToNextP
|
||||
pathLen += EdgeLength(e);
|
||||
|
||||
// 0 <= |pathDiffRatio| <= 1. The more pathDiffRatio the closer |distanceToNextPoint| and |pathLen|.
|
||||
double const pathDiffRatio =
|
||||
1.0 - abs(distanceToNextPoint - pathLen) / max(distanceToNextPoint, pathLen);
|
||||
double const pathDiffRatio = 1.0 - abs(distanceToNextPoint - pathLen) / max(distanceToNextPoint, pathLen);
|
||||
|
||||
bool const shortPath = path.size() <= 2;
|
||||
double const kMinValidPathDiffRation =
|
||||
source == LinearSegmentSource::FromLocationReferenceTag ? 0.6 : 0.25;
|
||||
double const kMinValidPathDiffRation = source == LinearSegmentSource::FromLocationReferenceTag ? 0.6 : 0.25;
|
||||
if (pathDiffRatio <= kMinValidPathDiffRation && !shortPath)
|
||||
return false;
|
||||
|
||||
@@ -126,21 +122,20 @@ bool ValidatePathByLength(Graph::EdgeVector const & path, double distanceToNextP
|
||||
|
||||
bool AreEdgesEqualWithoutAltitude(Graph::Edge const & e1, Graph::Edge const & e2)
|
||||
{
|
||||
return make_tuple(e1.GetType(), e1.GetFeatureId(), e1.IsForward(), e1.GetSegId(),
|
||||
e1.GetStartPoint(), e1.GetEndPoint()) ==
|
||||
make_tuple(e2.GetType(), e2.GetFeatureId(), e2.IsForward(), e2.GetSegId(),
|
||||
e2.GetStartPoint(), e2.GetEndPoint());
|
||||
return make_tuple(e1.GetType(), e1.GetFeatureId(), e1.IsForward(), e1.GetSegId(), e1.GetStartPoint(),
|
||||
e1.GetEndPoint()) == make_tuple(e2.GetType(), e2.GetFeatureId(), e2.IsForward(), e2.GetSegId(),
|
||||
e2.GetStartPoint(), e2.GetEndPoint());
|
||||
}
|
||||
} // namespace
|
||||
|
||||
ScorePathsConnector::ScorePathsConnector(Graph & graph, RoadInfoGetter & infoGetter, v2::Stats & stat)
|
||||
: m_graph(graph), m_infoGetter(infoGetter), m_stat(stat)
|
||||
{
|
||||
}
|
||||
: m_graph(graph)
|
||||
, m_infoGetter(infoGetter)
|
||||
, m_stat(stat)
|
||||
{}
|
||||
|
||||
bool ScorePathsConnector::FindBestPath(vector<LocationReferencePoint> const & points,
|
||||
vector<vector<ScorePath>> const & lineCandidates,
|
||||
LinearSegmentSource source,
|
||||
vector<vector<ScorePath>> const & lineCandidates, LinearSegmentSource source,
|
||||
vector<Graph::EdgeVector> & resultPath)
|
||||
{
|
||||
CHECK_NOT_EQUAL(source, LinearSegmentSource::NotValid, ());
|
||||
@@ -166,9 +161,8 @@ bool ScorePathsConnector::FindBestPath(vector<LocationReferencePoint> const & po
|
||||
for (size_t toInd = 0; toInd < toCandidates.size(); ++toInd)
|
||||
{
|
||||
Graph::EdgeVector path;
|
||||
if (!ConnectAdjacentCandidateLines(fromCandidates[fromInd].m_path,
|
||||
toCandidates[toInd].m_path, source, point.m_lfrcnp,
|
||||
distanceToNextPoint, path))
|
||||
if (!ConnectAdjacentCandidateLines(fromCandidates[fromInd].m_path, toCandidates[toInd].m_path, source,
|
||||
point.m_lfrcnp, distanceToNextPoint, path))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -177,8 +171,8 @@ bool ScorePathsConnector::FindBestPath(vector<LocationReferencePoint> const & po
|
||||
if (!ValidatePathByLength(path, distanceToNextPoint, source, pathLenScore))
|
||||
continue;
|
||||
|
||||
auto const score = pathLenScore + GetScoreForUniformity(path) +
|
||||
fromCandidates[fromInd].m_score + toCandidates[toInd].m_score;
|
||||
auto const score =
|
||||
pathLenScore + GetScoreForUniformity(path) + fromCandidates[fromInd].m_score + toCandidates[toInd].m_score;
|
||||
result.emplace_back(score, std::move(path));
|
||||
}
|
||||
}
|
||||
@@ -194,9 +188,8 @@ bool ScorePathsConnector::FindBestPath(vector<LocationReferencePoint> const & po
|
||||
return false;
|
||||
}
|
||||
|
||||
auto const it = max_element(
|
||||
result.cbegin(), result.cend(),
|
||||
[](ScorePath const & o1, ScorePath const & o2) { return o1.m_score < o2.m_score; });
|
||||
auto const it = max_element(result.cbegin(), result.cend(),
|
||||
[](ScorePath const & o1, ScorePath const & o2) { return o1.m_score < o2.m_score; });
|
||||
|
||||
// Note. In case of source == LinearSegmentSource::FromCoordinatesTag there is less
|
||||
// information about a openlr segment so less score is collected.
|
||||
@@ -217,10 +210,9 @@ bool ScorePathsConnector::FindBestPath(vector<LocationReferencePoint> const & po
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ScorePathsConnector::FindShortestPath(Graph::Edge const & from, Graph::Edge const & to,
|
||||
LinearSegmentSource source,
|
||||
FunctionalRoadClass lowestFrcToNextPoint,
|
||||
uint32_t maxPathLength, Graph::EdgeVector & path)
|
||||
bool ScorePathsConnector::FindShortestPath(Graph::Edge const & from, Graph::Edge const & to, LinearSegmentSource source,
|
||||
FunctionalRoadClass lowestFrcToNextPoint, uint32_t maxPathLength,
|
||||
Graph::EdgeVector & path)
|
||||
{
|
||||
double constexpr kLengthToleranceFactor = 1.1;
|
||||
uint32_t constexpr kMinLengthTolerance = 20;
|
||||
@@ -231,10 +223,7 @@ bool ScorePathsConnector::FindShortestPath(Graph::Edge const & from, Graph::Edge
|
||||
{
|
||||
State(Graph::Edge const & e, uint32_t const s) : m_edge(e), m_score(s) {}
|
||||
|
||||
bool operator>(State const & o) const
|
||||
{
|
||||
return tie(m_score, m_edge) > tie(o.m_score, o.m_edge);
|
||||
}
|
||||
bool operator>(State const & o) const { return tie(m_score, m_edge) > tie(o.m_score, o.m_edge); }
|
||||
|
||||
Graph::Edge m_edge;
|
||||
uint32_t m_score;
|
||||
@@ -300,12 +289,10 @@ bool ScorePathsConnector::FindShortestPath(Graph::Edge const & from, Graph::Edge
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ScorePathsConnector::ConnectAdjacentCandidateLines(Graph::EdgeVector const & from,
|
||||
Graph::EdgeVector const & to,
|
||||
bool ScorePathsConnector::ConnectAdjacentCandidateLines(Graph::EdgeVector const & from, Graph::EdgeVector const & to,
|
||||
LinearSegmentSource source,
|
||||
FunctionalRoadClass lowestFrcToNextPoint,
|
||||
double distanceToNextPoint,
|
||||
Graph::EdgeVector & resultPath)
|
||||
double distanceToNextPoint, Graph::EdgeVector & resultPath)
|
||||
{
|
||||
CHECK(!to.empty(), ());
|
||||
|
||||
@@ -322,9 +309,8 @@ bool ScorePathsConnector::ConnectAdjacentCandidateLines(Graph::EdgeVector const
|
||||
CHECK_NOT_EQUAL(from, to, ());
|
||||
|
||||
Graph::EdgeVector shortestPath;
|
||||
auto const found =
|
||||
FindShortestPath(from.back(), to.front(), source, lowestFrcToNextPoint,
|
||||
static_cast<uint32_t>(ceil(distanceToNextPoint)), shortestPath);
|
||||
auto const found = FindShortestPath(from.back(), to.front(), source, lowestFrcToNextPoint,
|
||||
static_cast<uint32_t>(ceil(distanceToNextPoint)), shortestPath);
|
||||
if (!found)
|
||||
return false;
|
||||
|
||||
@@ -332,8 +318,7 @@ bool ScorePathsConnector::ConnectAdjacentCandidateLines(Graph::EdgeVector const
|
||||
resultPath.insert(resultPath.end(), from.cbegin(), prev(from.cend()));
|
||||
resultPath.insert(resultPath.end(), shortestPath.cbegin(), shortestPath.cend());
|
||||
|
||||
CHECK(AreEdgesEqualWithoutAltitude(to.front(), shortestPath.back()),
|
||||
(to.front(), shortestPath.back()));
|
||||
CHECK(AreEdgesEqualWithoutAltitude(to.front(), shortestPath.back()), (to.front(), shortestPath.back()));
|
||||
resultPath.insert(resultPath.end(), next(to.begin()), to.end());
|
||||
|
||||
return !resultPath.empty();
|
||||
@@ -348,17 +333,16 @@ Score ScorePathsConnector::GetScoreForUniformity(Graph::EdgeVector const & path)
|
||||
auto const hwClassDiff = edgeContainer.GetHighwayClassDiff();
|
||||
Score constexpr kScoreForTheSameHwClass = 40;
|
||||
Score constexpr kScoreForNeighboringHwClasses = 15;
|
||||
Score const hwClassScore = hwClassDiff == 0
|
||||
? kScoreForTheSameHwClass
|
||||
: hwClassDiff == 1 ? kScoreForNeighboringHwClasses : 0;
|
||||
Score const hwClassScore = hwClassDiff == 0 ? kScoreForTheSameHwClass
|
||||
: hwClassDiff == 1 ? kScoreForNeighboringHwClasses
|
||||
: 0;
|
||||
|
||||
Score constexpr kScoreForOneWayOnly = 17;
|
||||
Score constexpr kScoreForRoundaboutOnly = 18;
|
||||
Score constexpr kScoreForLinkOnly = 10;
|
||||
Score const allEqualScore =
|
||||
(edgeContainer.AreAllOneWaysEqual() ? kScoreForOneWayOnly : 0) +
|
||||
(edgeContainer.AreAllRoundaboutEqual() ? kScoreForRoundaboutOnly : 0) +
|
||||
(edgeContainer.AreAllLinksEqual() ? kScoreForLinkOnly : 0);
|
||||
Score const allEqualScore = (edgeContainer.AreAllOneWaysEqual() ? kScoreForOneWayOnly : 0) +
|
||||
(edgeContainer.AreAllRoundaboutEqual() ? kScoreForRoundaboutOnly : 0) +
|
||||
(edgeContainer.AreAllLinksEqual() ? kScoreForLinkOnly : 0);
|
||||
|
||||
return hwClassScore + allEqualScore;
|
||||
}
|
||||
|
||||
@@ -21,18 +21,15 @@ public:
|
||||
/// if there's a good enough.
|
||||
/// \returns true if the best path is found and false otherwise.
|
||||
bool FindBestPath(std::vector<LocationReferencePoint> const & points,
|
||||
std::vector<std::vector<ScorePath>> const & lineCandidates,
|
||||
LinearSegmentSource source,
|
||||
std::vector<std::vector<ScorePath>> const & lineCandidates, LinearSegmentSource source,
|
||||
std::vector<Graph::EdgeVector> & resultPath);
|
||||
|
||||
private:
|
||||
bool FindShortestPath(Graph::Edge const & from, Graph::Edge const & to,
|
||||
LinearSegmentSource source, FunctionalRoadClass lowestFrcToNextPoint,
|
||||
uint32_t maxPathLength, Graph::EdgeVector & path);
|
||||
bool FindShortestPath(Graph::Edge const & from, Graph::Edge const & to, LinearSegmentSource source,
|
||||
FunctionalRoadClass lowestFrcToNextPoint, uint32_t maxPathLength, Graph::EdgeVector & path);
|
||||
|
||||
bool ConnectAdjacentCandidateLines(Graph::EdgeVector const & from, Graph::EdgeVector const & to,
|
||||
LinearSegmentSource source,
|
||||
FunctionalRoadClass lowestFrcToNextPoint,
|
||||
LinearSegmentSource source, FunctionalRoadClass lowestFrcToNextPoint,
|
||||
double distanceToNextPoint, Graph::EdgeVector & resultPath);
|
||||
|
||||
Score GetScoreForUniformity(Graph::EdgeVector const & path);
|
||||
|
||||
@@ -20,15 +20,9 @@ struct ScorePoint
|
||||
ScorePoint() = default;
|
||||
ScorePoint(Score score, m2::PointD const & point) : m_score(score), m_point(point) {}
|
||||
|
||||
bool operator<(ScorePoint const & o) const
|
||||
{
|
||||
return std::tie(m_score, m_point) < std::tie(o.m_score, o.m_point);
|
||||
}
|
||||
bool operator<(ScorePoint const & o) const { return std::tie(m_score, m_point) < std::tie(o.m_score, o.m_point); }
|
||||
|
||||
bool operator==(ScorePoint const & o) const
|
||||
{
|
||||
return m_score == o.m_score && m_point == o.m_point;
|
||||
}
|
||||
bool operator==(ScorePoint const & o) const { return m_score == o.m_score && m_point == o.m_point; }
|
||||
|
||||
Score m_score = 0;
|
||||
m2::PointD m_point;
|
||||
|
||||
@@ -44,5 +44,5 @@ struct alignas(kCacheLineSize) Stats
|
||||
// Number of zeroed distance-to-next point values in the input.
|
||||
uint32_t m_zeroDistToNextPointCount = 0;
|
||||
};
|
||||
} // namespace V2
|
||||
} // namespace v2
|
||||
} // namespace openlr
|
||||
|
||||
@@ -16,8 +16,7 @@ struct WayPoint final
|
||||
, m_distanceToNextPointM(lrp.m_distanceToNextPoint)
|
||||
, m_bearing(lrp.m_bearing)
|
||||
, m_lfrcnp(lrp.m_functionalRoadClass)
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
m2::PointD m_point;
|
||||
double m_distanceToNextPointM = 0.0;
|
||||
|
||||
@@ -50,8 +50,7 @@ bool IsReversedIntervals(size_t fromDst, size_t toDst, size_t fromSrc, size_t to
|
||||
return (fromDst > toDst) != (fromSrc > toSrc);
|
||||
}
|
||||
|
||||
std::vector<m2::PointD> AppendPointsWithAnyDirection(std::vector<MarkedPoint> const & copyFrom,
|
||||
size_t from, size_t to)
|
||||
std::vector<m2::PointD> AppendPointsWithAnyDirection(std::vector<MarkedPoint> const & copyFrom, size_t from, size_t to)
|
||||
{
|
||||
std::vector<m2::PointD> result;
|
||||
if (from > to)
|
||||
@@ -63,16 +62,14 @@ std::vector<m2::PointD> AppendPointsWithAnyDirection(std::vector<MarkedPoint> co
|
||||
return result;
|
||||
}
|
||||
|
||||
double AbsAreaDiff(std::vector<m2::PointD> const & firstPolygon,
|
||||
std::vector<m2::PointD> const & secondPolygon)
|
||||
double AbsAreaDiff(std::vector<m2::PointD> const & firstPolygon, std::vector<m2::PointD> const & secondPolygon)
|
||||
{
|
||||
auto const firstArea = generator::AreaOnEarth(firstPolygon);
|
||||
auto const secondArea = generator::AreaOnEarth(secondPolygon);
|
||||
return std::abs(secondArea - firstArea);
|
||||
}
|
||||
|
||||
bool NeedReplace(std::vector<m2::PointD> const & curSubpolygon,
|
||||
std::vector<m2::PointD> const & anotherSubpolygon)
|
||||
bool NeedReplace(std::vector<m2::PointD> const & curSubpolygon, std::vector<m2::PointD> const & anotherSubpolygon)
|
||||
{
|
||||
auto const areaDiff = AbsAreaDiff(curSubpolygon, anotherSubpolygon);
|
||||
double constexpr kMaxAreaDiffMetersSquared = 20000.0;
|
||||
@@ -195,7 +192,7 @@ void BordersData::Init(std::string const & bordersDir)
|
||||
void BordersData::DumpPolyFiles(std::string const & targetDir)
|
||||
{
|
||||
size_t n = m_bordersPolygons.size();
|
||||
for (size_t i = 0; i < n; )
|
||||
for (size_t i = 0; i < n;)
|
||||
{
|
||||
// Russia_Moscow.poly1 -> Russia_Moscow.poly
|
||||
auto name = RemoveIndexFromMwmName(m_indexToPolyFileName.at(i));
|
||||
@@ -270,11 +267,9 @@ void BordersData::PrintDiff()
|
||||
CHECK_NOT_EQUAL(allNumberBeforeCount, 0, ("Empty input?"));
|
||||
std::cout << "Number of removed points: " << m_removedPointsCount << std::endl
|
||||
<< "Removed duplicate point: " << m_duplicatedPointsCount << std::endl
|
||||
<< "Total removed points: " << m_removedPointsCount + m_duplicatedPointsCount
|
||||
<< std::endl;
|
||||
<< "Total removed points: " << m_removedPointsCount + m_duplicatedPointsCount << std::endl;
|
||||
std::cout << "Points number before processing: " << allNumberBeforeCount << ", remove( "
|
||||
<< static_cast<double>(m_removedPointsCount + m_duplicatedPointsCount) /
|
||||
allNumberBeforeCount * 100.0
|
||||
<< static_cast<double>(m_removedPointsCount + m_duplicatedPointsCount) / allNumberBeforeCount * 100.0
|
||||
<< "% )" << std::endl;
|
||||
}
|
||||
|
||||
@@ -298,8 +293,8 @@ void BordersData::RemoveEmptySpaceBetweenBorders()
|
||||
size_t constexpr kMaxLookAhead = 5;
|
||||
for (size_t shift = 1; shift <= kMaxLookAhead; ++shift)
|
||||
{
|
||||
if (TryToReplace(curBorderId, curPointId /* curLeftPointId */,
|
||||
curPointId + shift /* curRightPointId */) == base::ControlFlow::Break)
|
||||
if (TryToReplace(curBorderId, curPointId /* curLeftPointId */, curPointId + shift /* curRightPointId */) ==
|
||||
base::ControlFlow::Break)
|
||||
{
|
||||
break;
|
||||
}
|
||||
@@ -310,8 +305,7 @@ void BordersData::RemoveEmptySpaceBetweenBorders()
|
||||
DoReplace();
|
||||
}
|
||||
|
||||
base::ControlFlow BordersData::TryToReplace(size_t curBorderId, size_t & curLeftPointId,
|
||||
size_t curRightPointId)
|
||||
base::ControlFlow BordersData::TryToReplace(size_t curBorderId, size_t & curLeftPointId, size_t curRightPointId)
|
||||
{
|
||||
auto & curPolygon = m_bordersPolygons[curBorderId];
|
||||
if (curRightPointId >= curPolygon.m_points.size())
|
||||
@@ -348,10 +342,9 @@ base::ControlFlow BordersData::TryToReplace(size_t curBorderId, size_t & curLeft
|
||||
}
|
||||
|
||||
auto const anotherSubpolygon =
|
||||
AppendPointsWithAnyDirection(anotherPolygon.m_points, anotherLeftPointId, anotherRightPointId);
|
||||
AppendPointsWithAnyDirection(anotherPolygon.m_points, anotherLeftPointId, anotherRightPointId);
|
||||
|
||||
auto const curSubpolygon =
|
||||
AppendPointsWithAnyDirection(curPolygon.m_points, curLeftPointId, curRightPointId);
|
||||
auto const curSubpolygon = AppendPointsWithAnyDirection(curPolygon.m_points, curLeftPointId, curRightPointId);
|
||||
|
||||
if (!NeedReplace(curSubpolygon, anotherSubpolygon))
|
||||
return base::ControlFlow::Break;
|
||||
@@ -361,26 +354,25 @@ base::ControlFlow BordersData::TryToReplace(size_t curBorderId, size_t & curLeft
|
||||
bool const curLenIsLess = curSubpolygon.size() < anotherSubpolygon.size();
|
||||
|
||||
size_t dstFrom = curLenIsLess ? anotherLeftPointId : curLeftPointId;
|
||||
size_t dstTo = curLenIsLess ? anotherRightPointId : curRightPointId;
|
||||
size_t dstTo = curLenIsLess ? anotherRightPointId : curRightPointId;
|
||||
|
||||
size_t srcFrom = curLenIsLess ? curLeftPointId : anotherLeftPointId;
|
||||
size_t srcTo = curLenIsLess ? curRightPointId : anotherRightPointId;
|
||||
size_t srcFrom = curLenIsLess ? curLeftPointId : anotherLeftPointId;
|
||||
size_t srcTo = curLenIsLess ? curRightPointId : anotherRightPointId;
|
||||
|
||||
size_t const borderIdWhereAreaWillBeChanged = curLenIsLess ? anotherBorderId : curBorderId;
|
||||
size_t const srcBorderId = curLenIsLess ? curBorderId : anotherBorderId;
|
||||
|
||||
bool const reversed = IsReversedIntervals(dstFrom, dstTo, srcFrom, srcTo);
|
||||
|
||||
m_additionalAreaMetersSqr[borderIdWhereAreaWillBeChanged] +=
|
||||
AbsAreaDiff(curSubpolygon, anotherSubpolygon);
|
||||
m_additionalAreaMetersSqr[borderIdWhereAreaWillBeChanged] += AbsAreaDiff(curSubpolygon, anotherSubpolygon);
|
||||
|
||||
SwapIfNeeded(dstFrom, dstTo);
|
||||
SwapIfNeeded(srcFrom, srcTo);
|
||||
|
||||
// Save info for |borderIdWhereAreaWillBeChanged| - where from it should gets info about
|
||||
// replacement.
|
||||
m_bordersPolygons[borderIdWhereAreaWillBeChanged].AddReplaceInfo(
|
||||
dstFrom, dstTo, srcFrom, srcTo, srcBorderId, reversed);
|
||||
m_bordersPolygons[borderIdWhereAreaWillBeChanged].AddReplaceInfo(dstFrom, dstTo, srcFrom, srcTo, srcBorderId,
|
||||
reversed);
|
||||
|
||||
// And say for |srcBorderId| that points in segment: [srcFrom, srcTo] are frozen and cannot
|
||||
// be used anywhere (because we use them to replace points in segment: [dstFrom, dstTo]).
|
||||
|
||||
@@ -30,12 +30,10 @@ private:
|
||||
/// points and leaves only unique.
|
||||
size_t RemoveDuplicatePoints();
|
||||
|
||||
template <class PointsT> static size_t RemoveDuplicatingPointImpl(PointsT & points)
|
||||
template <class PointsT>
|
||||
static size_t RemoveDuplicatingPointImpl(PointsT & points)
|
||||
{
|
||||
auto const equalFn = [](auto const & p1, auto const & p2)
|
||||
{
|
||||
return p1.EqualDxDy(p2, kEqualityEpsilon);
|
||||
};
|
||||
auto const equalFn = [](auto const & p1, auto const & p2) { return p1.EqualDxDy(p2, kEqualityEpsilon); };
|
||||
|
||||
auto const last = std::unique(points.begin(), points.end(), equalFn);
|
||||
size_t count = std::distance(last, points.end());
|
||||
@@ -53,8 +51,7 @@ private:
|
||||
/// \brief Checks whether we can replace points from segment: [curLeftPointId, curRightPointId]
|
||||
/// of |curBorderId| to points from another border in order to get rid of empty space
|
||||
/// between curBorder and anotherBorder.
|
||||
base::ControlFlow TryToReplace(size_t curBorderId, size_t & curLeftPointId,
|
||||
size_t curRightPointId);
|
||||
base::ControlFlow TryToReplace(size_t curBorderId, size_t & curLeftPointId, size_t curRightPointId);
|
||||
|
||||
bool HasLinkAt(size_t curBorderId, size_t pointId);
|
||||
|
||||
|
||||
@@ -57,8 +57,7 @@ bool Polygon::IsFrozen(size_t a, size_t b) const
|
||||
return m_replaced.Intersects(a, b);
|
||||
}
|
||||
|
||||
void Polygon::AddReplaceInfo(size_t dstFrom, size_t dstTo,
|
||||
size_t srcFrom, size_t srcTo, size_t srcBorderId,
|
||||
void Polygon::AddReplaceInfo(size_t dstFrom, size_t dstTo, size_t srcFrom, size_t srcTo, size_t srcBorderId,
|
||||
bool reversed)
|
||||
{
|
||||
CHECK_LESS_OR_EQUAL(dstFrom, dstTo, ());
|
||||
@@ -73,10 +72,8 @@ void Polygon::AddReplaceInfo(size_t dstFrom, size_t dstTo,
|
||||
std::set<ReplaceData>::const_iterator Polygon::FindReplaceData(size_t index)
|
||||
{
|
||||
for (auto it = m_replaceData.cbegin(); it != m_replaceData.cend(); ++it)
|
||||
{
|
||||
if (it->m_dstFrom <= index && index <= it->m_dstTo)
|
||||
return it;
|
||||
}
|
||||
|
||||
return m_replaceData.cend();
|
||||
}
|
||||
|
||||
@@ -31,14 +31,15 @@ struct Link
|
||||
/// \note Using next semantic here: [replaceFrom, replaceTo], [replaceFromSrc, replaceToSrc].
|
||||
struct ReplaceData
|
||||
{
|
||||
ReplaceData(size_t replaceFrom, size_t replaceTo, size_t replaceFromSrc, size_t replaceToSrc,
|
||||
size_t borderIdSrc, bool reversed)
|
||||
ReplaceData(size_t replaceFrom, size_t replaceTo, size_t replaceFromSrc, size_t replaceToSrc, size_t borderIdSrc,
|
||||
bool reversed)
|
||||
: m_dstFrom(replaceFrom)
|
||||
, m_dstTo(replaceTo)
|
||||
, m_srcReplaceFrom(replaceFromSrc)
|
||||
, m_srcReplaceTo(replaceToSrc)
|
||||
, m_srcBorderId(borderIdSrc)
|
||||
, m_reversed(reversed) {}
|
||||
, m_reversed(reversed)
|
||||
{}
|
||||
|
||||
bool operator<(ReplaceData const & rhs) const;
|
||||
|
||||
@@ -62,10 +63,7 @@ struct MarkedPoint
|
||||
|
||||
std::optional<Link> GetLink(size_t curBorderId) const;
|
||||
|
||||
bool EqualDxDy(MarkedPoint const & p, double eps) const
|
||||
{
|
||||
return m_point.EqualDxDy(p.m_point, eps);
|
||||
}
|
||||
bool EqualDxDy(MarkedPoint const & p, double eps) const { return m_point.EqualDxDy(p.m_point, eps); }
|
||||
|
||||
m2::PointD m_point;
|
||||
std::set<Link> m_links;
|
||||
@@ -78,10 +76,7 @@ struct Polygon
|
||||
{
|
||||
m_points.assign(points.begin(), points.end());
|
||||
}
|
||||
Polygon(m2::RectD const & rect, std::vector<MarkedPoint> && points)
|
||||
: m_rect(rect), m_points(std::move(points))
|
||||
{
|
||||
}
|
||||
Polygon(m2::RectD const & rect, std::vector<MarkedPoint> && points) : m_rect(rect), m_points(std::move(points)) {}
|
||||
|
||||
Polygon(Polygon &&) = default;
|
||||
Polygon & operator=(Polygon &&) noexcept = default;
|
||||
@@ -93,9 +88,8 @@ struct Polygon
|
||||
// @}
|
||||
|
||||
// [replaceFrom, replaceTo], [replaceFromSrc, replaceToSrc]
|
||||
void AddReplaceInfo(size_t replaceFrom, size_t replaceTo,
|
||||
size_t replaceFromSrc, size_t replaceToSrc, size_t borderIdSrc,
|
||||
bool reversed);
|
||||
void AddReplaceInfo(size_t replaceFrom, size_t replaceTo, size_t replaceFromSrc, size_t replaceToSrc,
|
||||
size_t borderIdSrc, bool reversed);
|
||||
|
||||
std::set<ReplaceData>::const_iterator FindReplaceData(size_t index);
|
||||
|
||||
|
||||
@@ -39,12 +39,10 @@ void CheckByMask(Polygon const & polygons, vector<bool> markedMask)
|
||||
{
|
||||
CHECK_EQUAL(polygons.m_points.size(), markedMask.size(), ());
|
||||
for (size_t i = 0; i < polygons.m_points.size(); ++i)
|
||||
{
|
||||
if (markedMask[i])
|
||||
TestMarked(polygons, i);
|
||||
else
|
||||
TestNotMarked(polygons, i);
|
||||
}
|
||||
}
|
||||
|
||||
UNIT_TEST(PolyBordersPostprocessor_MarkPoints_1)
|
||||
@@ -55,21 +53,13 @@ UNIT_TEST(PolyBordersPostprocessor_MarkPoints_1)
|
||||
m2::PointD a(-1.0, -1.0);
|
||||
m2::PointD b(-1.0, 1.0);
|
||||
|
||||
vector<vector<m2::PointD>> polygons1 = {
|
||||
{a, b, {1.0, 1.0}, {1.0, -1.0}}
|
||||
};
|
||||
vector<vector<m2::PointD>> polygons1 = {{a, b, {1.0, 1.0}, {1.0, -1.0}}};
|
||||
|
||||
vector<vector<bool>> markedMask1 = {
|
||||
{true, true, false, false}
|
||||
};
|
||||
vector<vector<bool>> markedMask1 = {{true, true, false, false}};
|
||||
|
||||
vector<vector<m2::PointD>> polygons2 = {
|
||||
{a, b, {2.0, 1.0}, {5.0, -1.0}}
|
||||
};
|
||||
vector<vector<m2::PointD>> polygons2 = {{a, b, {2.0, 1.0}, {5.0, -1.0}}};
|
||||
|
||||
vector<vector<bool>> markedMask2 = {
|
||||
{true, true, false, false}
|
||||
};
|
||||
vector<vector<bool>> markedMask2 = {{true, true, false, false}};
|
||||
|
||||
vector<shared_ptr<ScopedFile>> files;
|
||||
files.emplace_back(CreatePolyBorderFileByPolygon(kTestDir, "First", polygons1));
|
||||
@@ -90,21 +80,13 @@ UNIT_TEST(PolyBordersPostprocessor_MarkPoints_2)
|
||||
ScopedDir const scopedDir(kTestDir);
|
||||
string const & bordersDir = scopedDir.GetFullPath();
|
||||
|
||||
vector<vector<m2::PointD>> polygons1 = {
|
||||
{{-1.0, -1.0}, {-1.0, 1.0}, {1.0, 1.0}, {1.0, -1.0}}
|
||||
};
|
||||
vector<vector<m2::PointD>> polygons1 = {{{-1.0, -1.0}, {-1.0, 1.0}, {1.0, 1.0}, {1.0, -1.0}}};
|
||||
|
||||
vector<vector<bool>> markedMask1 = {
|
||||
{false, false, false, false}
|
||||
};
|
||||
vector<vector<bool>> markedMask1 = {{false, false, false, false}};
|
||||
|
||||
vector<vector<m2::PointD>> polygons2 = {
|
||||
{{-12.0, -1.0}, {-10.0, 1.0}, {2.0, 1.0}, {5.0, -1.0}}
|
||||
};
|
||||
vector<vector<m2::PointD>> polygons2 = {{{-12.0, -1.0}, {-10.0, 1.0}, {2.0, 1.0}, {5.0, -1.0}}};
|
||||
|
||||
vector<vector<bool>> markedMask2 = {
|
||||
{false, false, false, false}
|
||||
};
|
||||
vector<vector<bool>> markedMask2 = {{false, false, false, false}};
|
||||
|
||||
vector<shared_ptr<ScopedFile>> files;
|
||||
files.emplace_back(CreatePolyBorderFileByPolygon(kTestDir, "First", polygons1));
|
||||
@@ -132,37 +114,21 @@ UNIT_TEST(PolyBordersPostprocessor_MarkPoints_3)
|
||||
m2::PointD e(-4.0, 2.0);
|
||||
m2::PointD f(-1.0, 4.0);
|
||||
|
||||
vector<vector<m2::PointD>> polygons1 = {
|
||||
{a, b, c, {1.0, -3.0}, d}
|
||||
};
|
||||
vector<vector<m2::PointD>> polygons1 = {{a, b, c, {1.0, -3.0}, d}};
|
||||
|
||||
vector<vector<bool>> markedMask1 = {
|
||||
{true, true, true, false, true}
|
||||
};
|
||||
vector<vector<bool>> markedMask1 = {{true, true, true, false, true}};
|
||||
|
||||
vector<vector<m2::PointD>> polygons2 = {
|
||||
{b, f, {2.0, 5.0}, {6.0, 3.0}, c}
|
||||
};
|
||||
vector<vector<m2::PointD>> polygons2 = {{b, f, {2.0, 5.0}, {6.0, 3.0}, c}};
|
||||
|
||||
vector<vector<bool>> markedMask2 = {
|
||||
{true, true, false, false, true}
|
||||
};
|
||||
vector<vector<bool>> markedMask2 = {{true, true, false, false, true}};
|
||||
|
||||
vector<vector<m2::PointD>> polygons3 = {
|
||||
{a, b, f, {-3.0, 4.0}, e}
|
||||
};
|
||||
vector<vector<m2::PointD>> polygons3 = {{a, b, f, {-3.0, 4.0}, e}};
|
||||
|
||||
vector<vector<bool>> markedMask3 = {
|
||||
{true, true, true, false, true}
|
||||
};
|
||||
vector<vector<bool>> markedMask3 = {{true, true, true, false, true}};
|
||||
|
||||
vector<vector<m2::PointD>> polygons4 = {
|
||||
{a, e, {-3.0, -1.0}, d}
|
||||
};
|
||||
vector<vector<m2::PointD>> polygons4 = {{a, e, {-3.0, -1.0}, d}};
|
||||
|
||||
vector<vector<bool>> markedMask4 = {
|
||||
{true, true, false, true}
|
||||
};
|
||||
vector<vector<bool>> markedMask4 = {{true, true, false, true}};
|
||||
|
||||
vector<shared_ptr<ScopedFile>> files;
|
||||
files.emplace_back(CreatePolyBorderFileByPolygon(kTestDir, "First", polygons1));
|
||||
@@ -194,23 +160,14 @@ UNIT_TEST(PolyBordersPostprocessor_MarkPoints_4)
|
||||
m2::PointD a(6.0, 2.0);
|
||||
m2::PointD b(6.0, 4.0);
|
||||
|
||||
vector<vector<m2::PointD>> polygons1 = {
|
||||
{{-2.0, -2.0}, {-2.0, 2.0}, {2.0, 2.0}, {2.0, -2.0}},
|
||||
{{4.0, 2.0}, {4.0, 4.0}, a, b}
|
||||
};
|
||||
vector<vector<m2::PointD>> polygons1 = {{{-2.0, -2.0}, {-2.0, 2.0}, {2.0, 2.0}, {2.0, -2.0}},
|
||||
{{4.0, 2.0}, {4.0, 4.0}, a, b}};
|
||||
|
||||
vector<vector<bool>> markedMask1 = {
|
||||
{false, false, false, false},
|
||||
{false, false, true, true}
|
||||
};
|
||||
vector<vector<bool>> markedMask1 = {{false, false, false, false}, {false, false, true, true}};
|
||||
|
||||
vector<vector<m2::PointD>> polygons2 = {
|
||||
{a, b, {8.0, 6.0}, {8.0, 0.0}}
|
||||
};
|
||||
vector<vector<m2::PointD>> polygons2 = {{a, b, {8.0, 6.0}, {8.0, 0.0}}};
|
||||
|
||||
vector<vector<bool>> markedMask2 = {
|
||||
{true, true, false, false}
|
||||
};
|
||||
vector<vector<bool>> markedMask2 = {{true, true, false, false}};
|
||||
|
||||
vector<shared_ptr<ScopedFile>> files;
|
||||
files.emplace_back(CreatePolyBorderFileByPolygon(kTestDir, "First", polygons1));
|
||||
@@ -219,10 +176,12 @@ UNIT_TEST(PolyBordersPostprocessor_MarkPoints_4)
|
||||
BordersData bordersData;
|
||||
bordersData.Init(bordersDir);
|
||||
|
||||
auto const & firstBordersPolygon1 = bordersData.GetBordersPolygonByName("First" + BordersData::kBorderExtension + "1");
|
||||
auto const & firstBordersPolygon1 =
|
||||
bordersData.GetBordersPolygonByName("First" + BordersData::kBorderExtension + "1");
|
||||
CheckByMask(firstBordersPolygon1, markedMask1[0]);
|
||||
|
||||
auto const & secondBordersPolygon1 = bordersData.GetBordersPolygonByName("First" + BordersData::kBorderExtension + "2");
|
||||
auto const & secondBordersPolygon1 =
|
||||
bordersData.GetBordersPolygonByName("First" + BordersData::kBorderExtension + "2");
|
||||
CheckByMask(secondBordersPolygon1, markedMask1[1]);
|
||||
|
||||
auto const & bordersPolygon2 = bordersData.GetBordersPolygonByName("Second" + BordersData::kBorderExtension + "1");
|
||||
|
||||
@@ -40,8 +40,7 @@ bool ConsistsOf(Polygon const & polygon, vector<m2::PointD> const & points)
|
||||
for (size_t i = 0; i < polygon.m_points.size(); ++i)
|
||||
{
|
||||
static double constexpr kEps = 1e-5;
|
||||
if (AlmostEqualAbs(point, polygon.m_points[i].m_point, kEps) &&
|
||||
used.count(i) == 0)
|
||||
if (AlmostEqualAbs(point, polygon.m_points[i].m_point, kEps) && used.count(i) == 0)
|
||||
{
|
||||
used.emplace(i);
|
||||
break;
|
||||
@@ -63,13 +62,9 @@ UNIT_TEST(PolyBordersPostprocessor_RemoveEmptySpaces_1)
|
||||
m2::PointD d(3.0, 0.0);
|
||||
m2::PointD e(4.0, 0.0);
|
||||
|
||||
vector<vector<m2::PointD>> polygons1 = {
|
||||
{a, b, c, d, e}
|
||||
};
|
||||
vector<vector<m2::PointD>> polygons1 = {{a, b, c, d, e}};
|
||||
|
||||
vector<vector<m2::PointD>> polygons2 = {
|
||||
{a, b, c, d, e}
|
||||
};
|
||||
vector<vector<m2::PointD>> polygons2 = {{a, b, c, d, e}};
|
||||
|
||||
vector<shared_ptr<ScopedFile>> files;
|
||||
files.emplace_back(CreatePolyBorderFileByPolygon(kTestDir, "First", polygons1));
|
||||
@@ -99,13 +94,9 @@ UNIT_TEST(PolyBordersPostprocessor_RemoveEmptySpaces_2)
|
||||
m2::PointD e(4.0, 0.0);
|
||||
|
||||
// Point |c| is absent from polygons2, algorithm should remove |c| from polygon1.
|
||||
vector<vector<m2::PointD>> polygons1 = {
|
||||
{a, b, c, d, e}
|
||||
};
|
||||
vector<vector<m2::PointD>> polygons1 = {{a, b, c, d, e}};
|
||||
|
||||
vector<vector<m2::PointD>> polygons2 = {
|
||||
{a, b, d, e}
|
||||
};
|
||||
vector<vector<m2::PointD>> polygons2 = {{a, b, d, e}};
|
||||
|
||||
vector<shared_ptr<ScopedFile>> files;
|
||||
files.emplace_back(CreatePolyBorderFileByPolygon(kTestDir, "First", polygons1));
|
||||
@@ -138,13 +129,9 @@ UNIT_TEST(PolyBordersPostprocessor_RemoveEmptySpaces_3)
|
||||
m2::PointD f(5.0, 0.0);
|
||||
|
||||
// Point |c| and |d| is absent from polygons2, algorithm should remove |c| from polygon1.
|
||||
vector<vector<m2::PointD>> polygons1 = {
|
||||
{a, b, c, d, e, f}
|
||||
};
|
||||
vector<vector<m2::PointD>> polygons1 = {{a, b, c, d, e, f}};
|
||||
|
||||
vector<vector<m2::PointD>> polygons2 = {
|
||||
{a, b, e, f}
|
||||
};
|
||||
vector<vector<m2::PointD>> polygons2 = {{a, b, e, f}};
|
||||
|
||||
vector<shared_ptr<ScopedFile>> files;
|
||||
files.emplace_back(CreatePolyBorderFileByPolygon(kTestDir, "First", polygons1));
|
||||
@@ -172,13 +159,9 @@ UNIT_TEST(PolyBordersPostprocessor_RemoveEmptySpaces_4)
|
||||
m2::PointD d(4.0, 0.0);
|
||||
m2::PointD e(5.0, 0.0);
|
||||
|
||||
vector<vector<m2::PointD>> polygons1 = {
|
||||
{a, b, c, d, e}
|
||||
};
|
||||
vector<vector<m2::PointD>> polygons1 = {{a, b, c, d, e}};
|
||||
|
||||
vector<vector<m2::PointD>> polygons2 = {
|
||||
{a, b, d, e}
|
||||
};
|
||||
vector<vector<m2::PointD>> polygons2 = {{a, b, d, e}};
|
||||
|
||||
vector<shared_ptr<ScopedFile>> files;
|
||||
files.emplace_back(CreatePolyBorderFileByPolygon(kTestDir, "First", polygons1));
|
||||
@@ -210,13 +193,9 @@ UNIT_TEST(PolyBordersPostprocessor_RemoveEmptySpaces_5)
|
||||
m2::PointD c2(c1 + kSmallPointShift);
|
||||
m2::PointD d2(d1 + kSmallPointShift);
|
||||
|
||||
vector<vector<m2::PointD>> polygons1 = {
|
||||
{a, c1, d1, e1, b}
|
||||
};
|
||||
vector<vector<m2::PointD>> polygons1 = {{a, c1, d1, e1, b}};
|
||||
|
||||
vector<vector<m2::PointD>> polygons2 = {
|
||||
{a, c2, d2, b}
|
||||
};
|
||||
vector<vector<m2::PointD>> polygons2 = {{a, c2, d2, b}};
|
||||
|
||||
vector<shared_ptr<ScopedFile>> files;
|
||||
files.emplace_back(CreatePolyBorderFileByPolygon(kTestDir, "First", polygons1));
|
||||
@@ -244,13 +223,9 @@ UNIT_TEST(PolyBordersPostprocessor_RemoveEmptySpaces_6)
|
||||
m2::PointD d(4.0, 0.0);
|
||||
m2::PointD e(5.0, 0.0);
|
||||
|
||||
vector<vector<m2::PointD>> polygons1 = {
|
||||
{a, b, c, d, d, d, e, e, e}
|
||||
};
|
||||
vector<vector<m2::PointD>> polygons1 = {{a, b, c, d, d, d, e, e, e}};
|
||||
|
||||
vector<vector<m2::PointD>> polygons2 = {
|
||||
{a, d, d, d, e}
|
||||
};
|
||||
vector<vector<m2::PointD>> polygons2 = {{a, d, d, d, e}};
|
||||
|
||||
vector<shared_ptr<ScopedFile>> files;
|
||||
files.emplace_back(CreatePolyBorderFileByPolygon(kTestDir, "First", polygons1));
|
||||
|
||||
@@ -15,8 +15,7 @@ using namespace platform::tests_support;
|
||||
|
||||
namespace
|
||||
{
|
||||
std::vector<m2::RegionD> ConvertFromPointsVector(
|
||||
std::vector<std::vector<m2::PointD>> const & polygons)
|
||||
std::vector<m2::RegionD> ConvertFromPointsVector(std::vector<std::vector<m2::PointD>> const & polygons)
|
||||
{
|
||||
std::vector<m2::RegionD> res;
|
||||
res.reserve(polygons.size());
|
||||
@@ -29,9 +28,8 @@ std::vector<m2::RegionD> ConvertFromPointsVector(
|
||||
|
||||
namespace poly_borders
|
||||
{
|
||||
std::shared_ptr<ScopedFile> CreatePolyBorderFileByPolygon(
|
||||
std::string const & relativeDirPath, std::string const & name,
|
||||
std::vector<std::vector<m2::PointD>> const & polygons)
|
||||
std::shared_ptr<ScopedFile> CreatePolyBorderFileByPolygon(std::string const & relativeDirPath, std::string const & name,
|
||||
std::vector<std::vector<m2::PointD>> const & polygons)
|
||||
{
|
||||
std::string path = base::JoinPath(relativeDirPath, name + BordersData::kBorderExtension);
|
||||
|
||||
|
||||
@@ -10,8 +10,7 @@
|
||||
|
||||
namespace poly_borders
|
||||
{
|
||||
std::shared_ptr<platform::tests_support::ScopedFile>
|
||||
CreatePolyBorderFileByPolygon(std::string const & relativeDirPath,
|
||||
std::string const & name,
|
||||
std::vector<std::vector<m2::PointD>> const & polygons);
|
||||
std::shared_ptr<platform::tests_support::ScopedFile> CreatePolyBorderFileByPolygon(
|
||||
std::string const & relativeDirPath, std::string const & name,
|
||||
std::vector<std::vector<m2::PointD>> const & polygons);
|
||||
} // namespace poly_borders
|
||||
|
||||
@@ -19,14 +19,15 @@ using namespace poly_borders;
|
||||
int main(int argc, char ** argv)
|
||||
{
|
||||
gflags::ParseCommandLineFlags(&argc, &argv, true);
|
||||
gflags::SetUsageMessage("\n\n\tThe tool is used to process *.poly borders files. We use such files\n"
|
||||
"\tto cut the planet into mwms in generator. The problem is that we have\n"
|
||||
"\tempty spaces between neighbouring borders. This tool creates new borders\n"
|
||||
"\tbased on input data by removing points from borders in such a way that the\n"
|
||||
"\tchanged area of each border will not be too large.\n"
|
||||
"\tArguments:\n"
|
||||
"\t\t--borders_path=/path/to/directory/with/borders\n"
|
||||
"\t\t--output_path=/path/to/directory/where/new/borders/will/be/placed\n");
|
||||
gflags::SetUsageMessage(
|
||||
"\n\n\tThe tool is used to process *.poly borders files. We use such files\n"
|
||||
"\tto cut the planet into mwms in generator. The problem is that we have\n"
|
||||
"\tempty spaces between neighbouring borders. This tool creates new borders\n"
|
||||
"\tbased on input data by removing points from borders in such a way that the\n"
|
||||
"\tchanged area of each border will not be too large.\n"
|
||||
"\tArguments:\n"
|
||||
"\t\t--borders_path=/path/to/directory/with/borders\n"
|
||||
"\t\t--output_path=/path/to/directory/where/new/borders/will/be/placed\n");
|
||||
|
||||
if (FLAGS_borders_path.empty() || FLAGS_output_path.empty())
|
||||
{
|
||||
|
||||
@@ -9,28 +9,26 @@
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
|
||||
#include <QtXml/QDomElement>
|
||||
#include <QtXml/QDomDocument>
|
||||
#include <QtCore/QDir>
|
||||
#include <QtXml/QDomDocument>
|
||||
#include <QtXml/QDomElement>
|
||||
|
||||
namespace tools
|
||||
{
|
||||
namespace
|
||||
{
|
||||
|
||||
static constexpr double kLargeIconSize = 24.0; // Size of the -l SVG icons
|
||||
static constexpr double kMediumIconSize = 18.0; // size of the -m SVG icons
|
||||
static constexpr double kLargeIconSize = 24.0; // Size of the -l SVG icons
|
||||
static constexpr double kMediumIconSize = 18.0; // size of the -m SVG icons
|
||||
|
||||
struct GreaterHeight
|
||||
{
|
||||
bool operator() (SkinGenerator::SymbolInfo const & left,
|
||||
SkinGenerator::SymbolInfo const & right) const
|
||||
bool operator()(SkinGenerator::SymbolInfo const & left, SkinGenerator::SymbolInfo const & right) const
|
||||
{
|
||||
QString symbolIDleft = left.m_fullFileName.left(left.m_fullFileName.lastIndexOf("."));
|
||||
QString symbolIDright = right.m_fullFileName.left(right.m_fullFileName.lastIndexOf("."));
|
||||
if (left.m_size.height() == right.m_size.height()) {
|
||||
if (left.m_size.height() == right.m_size.height())
|
||||
return symbolIDleft > symbolIDright;
|
||||
}
|
||||
return (left.m_size.height() > right.m_size.height());
|
||||
}
|
||||
};
|
||||
@@ -40,8 +38,7 @@ struct MaxDimensions
|
||||
uint32_t & m_width;
|
||||
uint32_t & m_height;
|
||||
|
||||
MaxDimensions(uint32_t & width, uint32_t & height)
|
||||
: m_width(width), m_height(height)
|
||||
MaxDimensions(uint32_t & width, uint32_t & height) : m_width(width), m_height(height)
|
||||
{
|
||||
m_width = 0;
|
||||
m_height = 0;
|
||||
@@ -65,12 +62,10 @@ uint32_t NextPowerOf2(uint32_t n)
|
||||
|
||||
return n + 1;
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void SkinGenerator::ProcessSymbols(std::string const & svgDataDir,
|
||||
std::string const & skinName,
|
||||
std::vector<QSize> const & symbolSizes,
|
||||
std::vector<std::string> const & suffixes)
|
||||
void SkinGenerator::ProcessSymbols(std::string const & svgDataDir, std::string const & skinName,
|
||||
std::vector<QSize> const & symbolSizes, std::vector<std::string> const & suffixes)
|
||||
{
|
||||
for (size_t j = 0; j < symbolSizes.size(); ++j)
|
||||
{
|
||||
@@ -97,7 +92,7 @@ void SkinGenerator::ProcessSymbols(std::string const & svgDataDir,
|
||||
QString fullFileName = QString(dir.absolutePath()) + "/" + fileName;
|
||||
if (m_svgRenderer.load(fullFileName))
|
||||
{
|
||||
QSize svgSize = m_svgRenderer.defaultSize(); // Size of the SVG file
|
||||
QSize svgSize = m_svgRenderer.defaultSize(); // Size of the SVG file
|
||||
|
||||
// Capping svg symbol to kLargeIconSize maximum, keeping aspect ratio
|
||||
/*if (svgSize.width() > kLargeIconSize)
|
||||
@@ -153,8 +148,8 @@ bool SkinGenerator::RenderPages(uint32_t maxSize)
|
||||
|
||||
for (auto & s : page.m_symbols)
|
||||
{
|
||||
s.m_handle = page.m_packer.pack(static_cast<uint32_t>(s.m_size.width()),
|
||||
static_cast<uint32_t>(s.m_size.height()));
|
||||
s.m_handle =
|
||||
page.m_packer.pack(static_cast<uint32_t>(s.m_size.width()), static_cast<uint32_t>(s.m_size.height()));
|
||||
if (m_overflowDetected)
|
||||
break;
|
||||
}
|
||||
@@ -221,7 +216,7 @@ void SkinGenerator::MarkOverflow()
|
||||
m_overflowDetected = true;
|
||||
}
|
||||
|
||||
bool SkinGenerator::WriteToFileNewStyle(std::string const &skinName)
|
||||
bool SkinGenerator::WriteToFileNewStyle(std::string const & skinName)
|
||||
{
|
||||
QDomDocument doc = QDomDocument("skin");
|
||||
QDomElement rootElem = doc.createElement("root");
|
||||
@@ -254,4 +249,4 @@ bool SkinGenerator::WriteToFileNewStyle(std::string const &skinName)
|
||||
ts << doc.toString();
|
||||
return true;
|
||||
}
|
||||
} // namespace tools
|
||||
} // namespace tools
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include "geometry/rect2d.hpp"
|
||||
#include "geometry/packer.hpp"
|
||||
#include "geometry/rect2d.hpp"
|
||||
|
||||
#include "coding/writer.hpp"
|
||||
|
||||
#include "base/base.hpp"
|
||||
|
||||
#include <QtGui/QPainter>
|
||||
#include <QtGui/QImage>
|
||||
#include <QtCore/QFileInfo>
|
||||
#include <QtCore/QSize>
|
||||
#include <QtGui/QImage>
|
||||
#include <QtGui/QPainter>
|
||||
#include <QtSvg/QSvgRenderer>
|
||||
|
||||
#include <cstdint>
|
||||
@@ -35,7 +35,9 @@ public:
|
||||
|
||||
SymbolInfo() {}
|
||||
SymbolInfo(QSize size, QString const & fullFileName, QString const & symbolID)
|
||||
: m_size(size), m_fullFileName(fullFileName), m_symbolID(symbolID)
|
||||
: m_size(size)
|
||||
, m_fullFileName(fullFileName)
|
||||
, m_symbolID(symbolID)
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -53,8 +55,7 @@ public:
|
||||
};
|
||||
|
||||
void ProcessSymbols(std::string const & symbolsDir, std::string const & skinName,
|
||||
std::vector<QSize> const & symbolSizes,
|
||||
std::vector<std::string> const & suffix);
|
||||
std::vector<QSize> const & symbolSizes, std::vector<std::string> const & suffix);
|
||||
bool RenderPages(uint32_t maxSize);
|
||||
bool WriteToFileNewStyle(std::string const & skinName);
|
||||
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
#include "generator.hpp"
|
||||
|
||||
#include "base/logging.hpp"
|
||||
#include <iostream>
|
||||
#include "base/logging.hpp"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QtCore/QFile>
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QHash>
|
||||
#include <QtCore/QString>
|
||||
|
||||
#include <gflags/gflags.h>
|
||||
|
||||
DEFINE_string(fontFileName, "../../data/01_dejavusans.ttf", "path to TrueType font file");
|
||||
DEFINE_string(symbolsFile, "../../data/results.unicode", "file with 2bytes symbols for which the skin should be generated");
|
||||
DEFINE_string(symbolsFile, "../../data/results.unicode",
|
||||
"file with 2bytes symbols for which the skin should be generated");
|
||||
DEFINE_string(symbolsDir, "../../data/styles/symbols", "directory with svg symbol files");
|
||||
DEFINE_int32(symbolWidth, 24, "width of the rendered symbol");
|
||||
DEFINE_int32(symbolHeight, 24, "height of the rendered symbol");
|
||||
@@ -21,9 +22,9 @@ DEFINE_int32(searchIconWidth, 24, "width of the search category icon");
|
||||
DEFINE_int32(searchIconHeight, 24, "height of the search category icon");
|
||||
DEFINE_int32(maxSize, 4096, "max width/height of output textures");
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
// Used to lock the hash seed, so the order of XML attributes is always the same.
|
||||
// Used to lock the hash seed, so the order of XML attributes is always the same.
|
||||
QHashSeed::setDeterministicGlobalSeed();
|
||||
try
|
||||
{
|
||||
|
||||
@@ -10,10 +10,8 @@
|
||||
namespace topography_generator
|
||||
{
|
||||
template <typename ValueType>
|
||||
void GetExtendedTile(ms::LatLon const & leftBottom, size_t stepsInDegree,
|
||||
size_t tileSize, size_t tileSizeExtension,
|
||||
ValuesProvider<ValueType> & valuesProvider,
|
||||
std::vector<ValueType> & extTileValues)
|
||||
void GetExtendedTile(ms::LatLon const & leftBottom, size_t stepsInDegree, size_t tileSize, size_t tileSizeExtension,
|
||||
ValuesProvider<ValueType> & valuesProvider, std::vector<ValueType> & extTileValues)
|
||||
{
|
||||
size_t const extendedTileSize = tileSize + 2 * tileSizeExtension;
|
||||
extTileValues.resize(extendedTileSize * extendedTileSize);
|
||||
@@ -22,19 +20,16 @@ void GetExtendedTile(ms::LatLon const & leftBottom, size_t stepsInDegree,
|
||||
double const offset = step * tileSizeExtension;
|
||||
|
||||
// Store values from North to South.
|
||||
ms::LatLon startPos = ms::LatLon(leftBottom.m_lat + 1.0 + offset,
|
||||
leftBottom.m_lon - offset);
|
||||
ms::LatLon startPos = ms::LatLon(leftBottom.m_lat + 1.0 + offset, leftBottom.m_lon - offset);
|
||||
for (size_t i = 0; i < extendedTileSize; ++i)
|
||||
{
|
||||
for (size_t j = 0; j < extendedTileSize; ++j)
|
||||
{
|
||||
auto pos = ms::LatLon(startPos.m_lat - i * step,
|
||||
startPos.m_lon + j * step);
|
||||
auto pos = ms::LatLon(startPos.m_lat - i * step, startPos.m_lon + j * step);
|
||||
auto val = valuesProvider.GetValue(pos);
|
||||
|
||||
if (val == valuesProvider.GetInvalidValue() &&
|
||||
((i < tileSizeExtension) || (i >= tileSizeExtension + tileSize) ||
|
||||
(j < tileSizeExtension) || (j >= tileSizeExtension + tileSize)))
|
||||
if (val == valuesProvider.GetInvalidValue() && ((i < tileSizeExtension) || (i >= tileSizeExtension + tileSize) ||
|
||||
(j < tileSizeExtension) || (j >= tileSizeExtension + tileSize)))
|
||||
{
|
||||
auto const ni = std::max(std::min(i, tileSizeExtension + tileSize - 1), tileSizeExtension);
|
||||
auto const nj = std::max(std::min(j, tileSizeExtension + tileSize - 1), tileSizeExtension);
|
||||
@@ -49,8 +44,7 @@ void GetExtendedTile(ms::LatLon const & leftBottom, size_t stepsInDegree,
|
||||
|
||||
template <typename ValueType>
|
||||
void ProcessWithLinearKernel(std::vector<double> const & kernel, size_t tileSize, size_t tileOffset,
|
||||
std::vector<ValueType> const & srcValues,
|
||||
std::vector<ValueType> & dstValues,
|
||||
std::vector<ValueType> const & srcValues, std::vector<ValueType> & dstValues,
|
||||
ValueType invalidValue)
|
||||
{
|
||||
auto const kernelSize = kernel.size();
|
||||
@@ -84,9 +78,7 @@ void ProcessWithLinearKernel(std::vector<double> const & kernel, size_t tileSize
|
||||
}
|
||||
}
|
||||
for (size_t j = tileOffset; j < tileSize - tileOffset; ++j)
|
||||
{
|
||||
dstValues[i * tileSize + j] = tempValues[j];
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t j = tileOffset; j < tileSize - tileOffset; ++j)
|
||||
@@ -112,17 +104,13 @@ void ProcessWithLinearKernel(std::vector<double> const & kernel, size_t tileSize
|
||||
}
|
||||
}
|
||||
for (size_t i = tileOffset; i < tileSize - tileOffset; ++i)
|
||||
{
|
||||
dstValues[i * tileSize + j] = tempValues[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename ValueType>
|
||||
void ProcessWithSquareKernel(std::vector<double> const & kernel, size_t kernelSize,
|
||||
size_t tileSize, size_t tileOffset,
|
||||
std::vector<ValueType> const & srcValues,
|
||||
std::vector<ValueType> & dstValues,
|
||||
void ProcessWithSquareKernel(std::vector<double> const & kernel, size_t kernelSize, size_t tileSize, size_t tileOffset,
|
||||
std::vector<ValueType> const & srcValues, std::vector<ValueType> & dstValues,
|
||||
ValueType invalidValue)
|
||||
{
|
||||
CHECK_EQUAL(kernelSize * kernelSize, kernel.size(), ());
|
||||
@@ -161,10 +149,8 @@ void ProcessWithSquareKernel(std::vector<double> const & kernel, size_t kernelSi
|
||||
}
|
||||
|
||||
template <typename ValueType>
|
||||
void ProcessMedian(size_t kernelRadius, size_t tileSize, size_t tileOffset,
|
||||
std::vector<ValueType> const & srcValues,
|
||||
std::vector<ValueType> & dstValues,
|
||||
ValueType invalidValue)
|
||||
void ProcessMedian(size_t kernelRadius, size_t tileSize, size_t tileOffset, std::vector<ValueType> const & srcValues,
|
||||
std::vector<ValueType> & dstValues, ValueType invalidValue)
|
||||
{
|
||||
CHECK_LESS_OR_EQUAL(kernelRadius, tileOffset, ());
|
||||
CHECK_GREATER(tileSize, tileOffset * 2, ());
|
||||
|
||||
@@ -25,8 +25,7 @@ size_t constexpr kArcSecondsInDegree = 60 * 60;
|
||||
int constexpr kAsterTilesLatTop = 60;
|
||||
int constexpr kAsterTilesLatBottom = -60;
|
||||
|
||||
void MercatorRectToTilesRange(m2::RectD const & rect,
|
||||
int & left, int & bottom, int & right, int & top)
|
||||
void MercatorRectToTilesRange(m2::RectD const & rect, int & left, int & bottom, int & right, int & top)
|
||||
{
|
||||
auto const leftBottom = mercator::ToLatLon(rect.LeftBottom());
|
||||
auto const rightTop = mercator::ToLatLon(rect.RightTop());
|
||||
@@ -65,19 +64,15 @@ bool LoadTileProfiles(std::string const & fileName, std::set<std::string> & prof
|
||||
return false;
|
||||
std::string line;
|
||||
while (std::getline(fin, line))
|
||||
{
|
||||
if (!line.empty())
|
||||
profileNames.insert(line);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
class SrtmProvider : public ValuesProvider<Altitude>
|
||||
{
|
||||
public:
|
||||
explicit SrtmProvider(std::string const & srtmDir):
|
||||
m_srtmManager(srtmDir)
|
||||
{}
|
||||
explicit SrtmProvider(std::string const & srtmDir) : m_srtmManager(srtmDir) {}
|
||||
|
||||
void SetPrefferedTile(ms::LatLon const & pos)
|
||||
{
|
||||
@@ -95,10 +90,7 @@ public:
|
||||
|
||||
Altitude GetInvalidValue() const override { return kInvalidAltitude; }
|
||||
|
||||
static bool IsValidAltitude(Altitude alt)
|
||||
{
|
||||
return alt != kInvalidAltitude && alt > -435 && alt < 8850;
|
||||
}
|
||||
static bool IsValidAltitude(Altitude alt) { return alt != kInvalidAltitude && alt > -435 && alt < 8850; }
|
||||
|
||||
private:
|
||||
Altitude GetValueImpl(ms::LatLon pos)
|
||||
@@ -111,8 +103,8 @@ private:
|
||||
// Try to prevent loading a new tile if the position can be found in the loaded one.
|
||||
auto const latDist = pos.m_lat - m_leftBottomOfPreferredTile.m_lat;
|
||||
auto const lonDist = pos.m_lon - m_leftBottomOfPreferredTile.m_lon;
|
||||
if (latDist > -kPointEqualityEps && latDist < 1.0 + kPointEqualityEps &&
|
||||
lonDist > -kPointEqualityEps && lonDist < 1.0 + kPointEqualityEps)
|
||||
if (latDist > -kPointEqualityEps && latDist < 1.0 + kPointEqualityEps && lonDist > -kPointEqualityEps &&
|
||||
lonDist < 1.0 + kPointEqualityEps)
|
||||
{
|
||||
if (latDist < 0.0)
|
||||
pos.m_lat += kPointEqualityEps;
|
||||
@@ -174,8 +166,7 @@ private:
|
||||
class RawAltitudesTile : public ValuesProvider<Altitude>
|
||||
{
|
||||
public:
|
||||
RawAltitudesTile(std::vector<Altitude> const & values,
|
||||
int leftLon, int bottomLat)
|
||||
RawAltitudesTile(std::vector<Altitude> const & values, int leftLon, int bottomLat)
|
||||
: m_values(values)
|
||||
, m_leftLon(leftLon)
|
||||
, m_bottomLat(bottomLat)
|
||||
@@ -209,10 +200,9 @@ private:
|
||||
class SeamlessAltitudeProvider : public ValuesProvider<Altitude>
|
||||
{
|
||||
public:
|
||||
using IsOnBorderFn = std::function<bool (ms::LatLon const & pos)>;
|
||||
using IsOnBorderFn = std::function<bool(ms::LatLon const & pos)>;
|
||||
|
||||
SeamlessAltitudeProvider(ValuesProvider<Altitude> & originalProvider,
|
||||
ValuesProvider<Altitude> & filteredProvider,
|
||||
SeamlessAltitudeProvider(ValuesProvider<Altitude> & originalProvider, ValuesProvider<Altitude> & filteredProvider,
|
||||
IsOnBorderFn && isOnBorderFn)
|
||||
: m_originalProvider(originalProvider)
|
||||
, m_filteredProvider(filteredProvider)
|
||||
@@ -267,10 +257,8 @@ public:
|
||||
void Do()
|
||||
{
|
||||
for (int lat = m_bottom; lat <= m_top; ++lat)
|
||||
{
|
||||
for (int lon = m_left; lon <= m_right; ++lon)
|
||||
ProcessTile(lat, lon);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -337,8 +325,7 @@ private:
|
||||
auto const outFile = GetIsolinesFilePath(lat, lon, params.m_outputDir);
|
||||
if (!m_forceRegenerate && GetPlatform().IsFileExistsByFullPath(outFile))
|
||||
{
|
||||
LOG(LINFO, ("Isolines for", tileName, ", profile", profileName,
|
||||
"are ready, skip processing."));
|
||||
LOG(LINFO, ("Isolines for", tileName, ", profile", profileName, "are ready, skip processing."));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -350,11 +337,8 @@ private:
|
||||
if (!params.m_filters.empty() && (lat >= kAsterTilesLatTop || lat < kAsterTilesLatBottom))
|
||||
{
|
||||
// Filter tiles converted from ASTER, cause they are noisy enough.
|
||||
std::vector<Altitude> filteredValues = FilterTile(params.m_filters,
|
||||
ms::LatLon(lat, lon),
|
||||
kArcSecondsInDegree,
|
||||
kArcSecondsInDegree + 1,
|
||||
m_srtmProvider);
|
||||
std::vector<Altitude> filteredValues = FilterTile(params.m_filters, ms::LatLon(lat, lon), kArcSecondsInDegree,
|
||||
kArcSecondsInDegree + 1, m_srtmProvider);
|
||||
RawAltitudesTile filteredProvider(filteredValues, lon, lat);
|
||||
GenerateSeamlessContours(lat, lon, params, filteredProvider, contours);
|
||||
}
|
||||
@@ -363,9 +347,8 @@ private:
|
||||
GenerateSeamlessContours(lat, lon, params, m_srtmProvider, contours);
|
||||
}
|
||||
|
||||
LOG(LINFO, ("Isolines for tile", tileName, ", profile", profileName,
|
||||
"min altitude", contours.m_minValue, "max altitude",
|
||||
contours.m_maxValue, "invalid values count", contours.m_invalidValuesCount));
|
||||
LOG(LINFO, ("Isolines for tile", tileName, ", profile", profileName, "min altitude", contours.m_minValue,
|
||||
"max altitude", contours.m_maxValue, "invalid values count", contours.m_invalidValuesCount));
|
||||
|
||||
if (params.m_simplificationZoom > 0)
|
||||
SimplifyContours(params.m_simplificationZoom, contours);
|
||||
@@ -375,23 +358,21 @@ private:
|
||||
}
|
||||
|
||||
void GenerateSeamlessContours(int lat, int lon, TileIsolinesParams const & params,
|
||||
ValuesProvider<Altitude> & altProvider,
|
||||
Contours<Altitude> & contours)
|
||||
ValuesProvider<Altitude> & altProvider, Contours<Altitude> & contours)
|
||||
{
|
||||
// Avoid seam between SRTM and ASTER.
|
||||
if ((lat == kAsterTilesLatTop) || (lat == kAsterTilesLatBottom - 1))
|
||||
{
|
||||
m_srtmProvider.SetPrefferedTile(ms::LatLon(lat == kAsterTilesLatTop ? lat - 0.5 : lat + 0.5, lon));
|
||||
SeamlessAltitudeProvider seamlessAltProvider(m_srtmProvider, altProvider,
|
||||
[](ms::LatLon const & pos)
|
||||
{
|
||||
// In case when two altitudes sources are used for altitudes extraction,
|
||||
// for the same position on the border could be returned different altitudes.
|
||||
// Force to use altitudes near the srtm/aster border from srtm source,
|
||||
// it helps to avoid contours gaps due to different altitudes for equal positions.
|
||||
return fabs(pos.m_lat - kAsterTilesLatTop) < mercator::kPointEqualityEps ||
|
||||
fabs(pos.m_lat - kAsterTilesLatBottom) < mercator::kPointEqualityEps;
|
||||
});
|
||||
SeamlessAltitudeProvider seamlessAltProvider(m_srtmProvider, altProvider, [](ms::LatLon const & pos)
|
||||
{
|
||||
// In case when two altitudes sources are used for altitudes extraction,
|
||||
// for the same position on the border could be returned different altitudes.
|
||||
// Force to use altitudes near the srtm/aster border from srtm source,
|
||||
// it helps to avoid contours gaps due to different altitudes for equal positions.
|
||||
return fabs(pos.m_lat - kAsterTilesLatTop) < mercator::kPointEqualityEps ||
|
||||
fabs(pos.m_lat - kAsterTilesLatBottom) < mercator::kPointEqualityEps;
|
||||
});
|
||||
GenerateContours(lat, lon, params, seamlessAltProvider, contours);
|
||||
}
|
||||
else
|
||||
@@ -400,16 +381,14 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
void GenerateContours(int lat, int lon, TileIsolinesParams const & params,
|
||||
ValuesProvider<Altitude> & altProvider, Contours<Altitude> & contours)
|
||||
void GenerateContours(int lat, int lon, TileIsolinesParams const & params, ValuesProvider<Altitude> & altProvider,
|
||||
Contours<Altitude> & contours)
|
||||
{
|
||||
auto const leftBottom = ms::LatLon(lat, lon);
|
||||
auto const rightTop = ms::LatLon(lat + 1.0, lon + 1.0);
|
||||
auto const squaresStep = 1.0 / kArcSecondsInDegree * params.m_latLonStepFactor;
|
||||
|
||||
MarchingSquares<Altitude> squares(leftBottom, rightTop,
|
||||
squaresStep, params.m_alitudesStep,
|
||||
altProvider, m_debugId);
|
||||
MarchingSquares<Altitude> squares(leftBottom, rightTop, squaresStep, params.m_alitudesStep, altProvider, m_debugId);
|
||||
squares.GenerateContours(contours);
|
||||
}
|
||||
|
||||
@@ -426,9 +405,8 @@ private:
|
||||
};
|
||||
|
||||
template <typename ParamsType>
|
||||
void RunGenerateIsolinesTasks(int left, int bottom, int right, int top,
|
||||
std::string const & srtmPath, ParamsType const & params,
|
||||
long threadsCount, long maxCachedTilesPerThread,
|
||||
void RunGenerateIsolinesTasks(int left, int bottom, int right, int top, std::string const & srtmPath,
|
||||
ParamsType const & params, long threadsCount, long maxCachedTilesPerThread,
|
||||
bool forceRegenerate)
|
||||
{
|
||||
std::vector<std::unique_ptr<TileIsolinesTask>> tasks;
|
||||
@@ -447,12 +425,10 @@ void RunGenerateIsolinesTasks(int left, int bottom, int right, int top,
|
||||
else
|
||||
{
|
||||
while (tilesRowPerTask * tilesColPerTask > static_cast<long>(maxCachedTilesPerThread))
|
||||
{
|
||||
if (tilesRowPerTask > tilesColPerTask)
|
||||
tilesRowPerTask = (tilesRowPerTask + 1) / 2;
|
||||
else
|
||||
tilesColPerTask = (tilesColPerTask + 1) / 2;
|
||||
}
|
||||
}
|
||||
|
||||
base::ComputationalThreadPool threadPool(threadsCount);
|
||||
@@ -463,43 +439,38 @@ void RunGenerateIsolinesTasks(int left, int bottom, int right, int top,
|
||||
for (int lon = left; lon < right; lon += tilesColPerTask)
|
||||
{
|
||||
int const rightLon = std::min(lon + tilesColPerTask - 1, right - 1);
|
||||
auto task = std::make_unique<TileIsolinesTask>(lon, lat, rightLon, topLat, srtmPath, ¶ms,
|
||||
forceRegenerate);
|
||||
threadPool.SubmitWork([task = std::move(task)](){ task->Do(); });
|
||||
auto task = std::make_unique<TileIsolinesTask>(lon, lat, rightLon, topLat, srtmPath, ¶ms, forceRegenerate);
|
||||
threadPool.SubmitWork([task = std::move(task)]() { task->Do(); });
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
Generator::Generator(std::string const & srtmPath, long threadsCount,
|
||||
long maxCachedTilesPerThread, bool forceRegenerate)
|
||||
Generator::Generator(std::string const & srtmPath, long threadsCount, long maxCachedTilesPerThread,
|
||||
bool forceRegenerate)
|
||||
: m_threadsCount(threadsCount)
|
||||
, m_maxCachedTilesPerThread(maxCachedTilesPerThread)
|
||||
, m_srtmPath(srtmPath)
|
||||
, m_forceRegenerate(forceRegenerate)
|
||||
{}
|
||||
|
||||
void Generator::GenerateIsolines(int left, int bottom, int right, int top,
|
||||
TileIsolinesParams const & params)
|
||||
void Generator::GenerateIsolines(int left, int bottom, int right, int top, TileIsolinesParams const & params)
|
||||
{
|
||||
RunGenerateIsolinesTasks(left, bottom, right, top, m_srtmPath, params,
|
||||
m_threadsCount, m_maxCachedTilesPerThread, m_forceRegenerate);
|
||||
RunGenerateIsolinesTasks(left, bottom, right, top, m_srtmPath, params, m_threadsCount, m_maxCachedTilesPerThread,
|
||||
m_forceRegenerate);
|
||||
}
|
||||
|
||||
|
||||
void Generator::GenerateIsolines(int left, int bottom, int right, int top,
|
||||
std::string const & tilesProfilesDir)
|
||||
void Generator::GenerateIsolines(int left, int bottom, int right, int top, std::string const & tilesProfilesDir)
|
||||
{
|
||||
TileIsolinesProfileParams params(m_profileToTileParams, tilesProfilesDir);
|
||||
RunGenerateIsolinesTasks(left, bottom, right, top, m_srtmPath, params,
|
||||
m_threadsCount, m_maxCachedTilesPerThread, m_forceRegenerate);
|
||||
RunGenerateIsolinesTasks(left, bottom, right, top, m_srtmPath, params, m_threadsCount, m_maxCachedTilesPerThread,
|
||||
m_forceRegenerate);
|
||||
}
|
||||
|
||||
void Generator::GenerateIsolinesForCountries()
|
||||
{
|
||||
auto const & pl = GetPlatform();
|
||||
if (!pl.IsFileExistsByFullPath(m_isolinesTilesOutDir) &&
|
||||
!pl.MkDirRecursively(m_isolinesTilesOutDir))
|
||||
if (!pl.IsFileExistsByFullPath(m_isolinesTilesOutDir) && !pl.MkDirRecursively(m_isolinesTilesOutDir))
|
||||
{
|
||||
LOG(LERROR, ("Can't create directory", m_isolinesTilesOutDir));
|
||||
return;
|
||||
@@ -513,8 +484,7 @@ void Generator::GenerateIsolinesForCountries()
|
||||
continue;
|
||||
checkedProfiles.insert(profileName);
|
||||
auto const profileTilesDir = GetTilesDir(m_isolinesTilesOutDir, profileName);
|
||||
if (!pl.IsFileExistsByFullPath(profileTilesDir) &&
|
||||
!pl.MkDirChecked(profileTilesDir))
|
||||
if (!pl.IsFileExistsByFullPath(profileTilesDir) && !pl.MkDirChecked(profileTilesDir))
|
||||
{
|
||||
LOG(LERROR, ("Can't create directory", profileTilesDir));
|
||||
return;
|
||||
@@ -576,18 +546,16 @@ void Generator::GenerateIsolinesForCountries()
|
||||
|
||||
LOG(LINFO, ("Generate isolines for tiles rect", boundingRect));
|
||||
|
||||
GenerateIsolines(boundingRect.LeftBottom().x, boundingRect.LeftBottom().y,
|
||||
boundingRect.RightTop().x + 1, boundingRect.RightTop().y + 1, tmpTileProfilesDir);
|
||||
GenerateIsolines(boundingRect.LeftBottom().x, boundingRect.LeftBottom().y, boundingRect.RightTop().x + 1,
|
||||
boundingRect.RightTop().y + 1, tmpTileProfilesDir);
|
||||
}
|
||||
|
||||
void Generator::PackIsolinesForCountry(storage::CountryId const & countryId,
|
||||
IsolinesPackingParams const & params)
|
||||
void Generator::PackIsolinesForCountry(storage::CountryId const & countryId, IsolinesPackingParams const & params)
|
||||
{
|
||||
PackIsolinesForCountry(countryId, params, nullptr /*needSkipTileFn*/);
|
||||
}
|
||||
|
||||
void Generator::PackIsolinesForCountry(storage::CountryId const & countryId,
|
||||
IsolinesPackingParams const & params,
|
||||
void Generator::PackIsolinesForCountry(storage::CountryId const & countryId, IsolinesPackingParams const & params,
|
||||
NeedSkipTileFn const & needSkipTileFn)
|
||||
{
|
||||
auto const outFile = GetIsolinesFilePath(countryId, params.m_outputDir);
|
||||
@@ -629,8 +597,7 @@ void Generator::PackIsolinesForCountry(storage::CountryId const & countryId,
|
||||
|
||||
LOG(LINFO, ("Begin packing isolines from tile", tileFilePath));
|
||||
|
||||
CropContours(countryRect, countryRegions, params.m_maxIsolineLength,
|
||||
params.m_alitudesStepFactor, isolines);
|
||||
CropContours(countryRect, countryRegions, params.m_maxIsolineLength, params.m_alitudesStepFactor, isolines);
|
||||
// Simplification is done already while processing tiles in ProcessTile().
|
||||
// But now a different country-specific simpificationZoom could be applied.
|
||||
if (params.m_simplificationZoom > 0)
|
||||
@@ -644,17 +611,15 @@ void Generator::PackIsolinesForCountry(storage::CountryId const & countryId,
|
||||
for (auto & levelIsolines : isolines.m_contours)
|
||||
{
|
||||
auto & dst = countryIsolines.m_contours[levelIsolines.first];
|
||||
std::move(levelIsolines.second.begin(), levelIsolines.second.end(),
|
||||
std::back_inserter(dst));
|
||||
std::move(levelIsolines.second.begin(), levelIsolines.second.end(), std::back_inserter(dst));
|
||||
}
|
||||
|
||||
LOG(LINFO, ("End packing isolines from tile", tileFilePath));
|
||||
}
|
||||
}
|
||||
|
||||
LOG(LINFO, ("End packing isolines for country", countryId,
|
||||
"min altitude", countryIsolines.m_minValue,
|
||||
"max altitude", countryIsolines.m_maxValue));
|
||||
LOG(LINFO, ("End packing isolines for country", countryId, "min altitude", countryIsolines.m_minValue, "max altitude",
|
||||
countryIsolines.m_maxValue));
|
||||
|
||||
SaveContrours(outFile, std::move(countryIsolines));
|
||||
|
||||
@@ -684,7 +649,7 @@ void Generator::PackIsolinesForCountries()
|
||||
|
||||
auto const & packingParams = m_profileToPackingParams.at(params.m_profileName);
|
||||
PackIsolinesForCountry(countryId, packingParams,
|
||||
[¶ms](int lat, int lon){ return params.NeedSkipTile(lat, lon); });
|
||||
[¶ms](int lat, int lon) { return params.NeedSkipTile(lat, lon); });
|
||||
|
||||
LOG(LINFO, ("End task", taskInd, "/", tasksCount, countryId));
|
||||
});
|
||||
@@ -703,8 +668,7 @@ void Generator::InitCountryInfoGetter(std::string const & dataDir)
|
||||
}
|
||||
|
||||
void Generator::InitProfiles(std::string const & isolinesProfilesFileName,
|
||||
std::string const & countriesToGenerateFileName,
|
||||
std::string const & isolinesTilesOutDir,
|
||||
std::string const & countriesToGenerateFileName, std::string const & isolinesTilesOutDir,
|
||||
std::string const & isolinesCountriesOutDir)
|
||||
{
|
||||
CHECK(Deserialize(isolinesProfilesFileName, m_profilesCollection), ());
|
||||
@@ -714,8 +678,7 @@ void Generator::InitProfiles(std::string const & isolinesProfilesFileName,
|
||||
for (auto const & countryParams : m_countriesToGenerate.m_countryParams)
|
||||
{
|
||||
auto const & params = countryParams.second;
|
||||
CHECK(profiles.find(params.m_profileName) != profiles.end(),
|
||||
("Unknown profile name", params.m_profileName));
|
||||
CHECK(profiles.find(params.m_profileName) != profiles.end(), ("Unknown profile name", params.m_profileName));
|
||||
}
|
||||
|
||||
m_isolinesTilesOutDir = isolinesTilesOutDir;
|
||||
@@ -735,9 +698,8 @@ void Generator::InitProfiles(std::string const & isolinesProfilesFileName,
|
||||
tileParams.m_filters.emplace_back(std::make_unique<MedianFilter<Altitude>>(profileParams.m_medianFilterR));
|
||||
if (profileParams.m_gaussianFilterStDev > 0.0 && profileParams.m_gaussianFilterRFactor > 0)
|
||||
{
|
||||
tileParams.m_filters.emplace_back(
|
||||
std::make_unique<GaussianFilter<Altitude>>(profileParams.m_gaussianFilterStDev,
|
||||
profileParams.m_gaussianFilterRFactor));
|
||||
tileParams.m_filters.emplace_back(std::make_unique<GaussianFilter<Altitude>>(
|
||||
profileParams.m_gaussianFilterStDev, profileParams.m_gaussianFilterRFactor));
|
||||
}
|
||||
m_profileToTileParams.emplace(profileName, std::move(tileParams));
|
||||
|
||||
@@ -758,10 +720,8 @@ void Generator::GetCountryRegions(storage::CountryId const & countryId, m2::Rect
|
||||
|
||||
size_t id;
|
||||
for (id = 0; id < m_infoReader->GetCountries().size(); ++id)
|
||||
{
|
||||
if (m_infoReader->GetCountries().at(id).m_countryId == countryId)
|
||||
break;
|
||||
}
|
||||
CHECK_LESS(id, m_infoReader->GetCountries().size(), ());
|
||||
|
||||
/// @todo Refactor using Memory[Mapped] reader for countries.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "topography_generator/isolines_utils.hpp"
|
||||
#include "topography_generator/isolines_profile.hpp"
|
||||
#include "topography_generator/isolines_utils.hpp"
|
||||
#include "topography_generator/tile_filter.hpp"
|
||||
|
||||
#include "storage/country_info_getter.hpp"
|
||||
@@ -18,7 +18,7 @@ struct TileIsolinesParams
|
||||
{
|
||||
Altitude m_alitudesStep = 10;
|
||||
size_t m_latLonStepFactor = 1;
|
||||
int m_simplificationZoom = 17; // Value == 0 disables simplification.
|
||||
int m_simplificationZoom = 17; // Value == 0 disables simplification.
|
||||
FiltersSequence<Altitude> m_filters;
|
||||
std::string m_outputDir;
|
||||
};
|
||||
@@ -27,8 +27,7 @@ using ProfileToTileIsolinesParams = std::map<std::string, TileIsolinesParams>;
|
||||
|
||||
struct TileIsolinesProfileParams
|
||||
{
|
||||
TileIsolinesProfileParams(ProfileToTileIsolinesParams const & profiles,
|
||||
std::string const & tilesProfilesDir)
|
||||
TileIsolinesProfileParams(ProfileToTileIsolinesParams const & profiles, std::string const & tilesProfilesDir)
|
||||
: m_profiles(profiles)
|
||||
, m_tilesProfilesDir(tilesProfilesDir)
|
||||
{}
|
||||
@@ -40,7 +39,7 @@ struct TileIsolinesProfileParams
|
||||
struct IsolinesPackingParams
|
||||
{
|
||||
size_t m_maxIsolineLength = 1000;
|
||||
int m_simplificationZoom = 17; // Value == 0 disables simplification.
|
||||
int m_simplificationZoom = 17; // Value == 0 disables simplification.
|
||||
size_t m_alitudesStepFactor = 1;
|
||||
std::string m_isolinesTilesPath;
|
||||
std::string m_outputDir;
|
||||
@@ -51,32 +50,25 @@ using ProfileToIsolinesPackingParams = std::map<std::string, IsolinesPackingPara
|
||||
class Generator
|
||||
{
|
||||
public:
|
||||
Generator(std::string const & srtmPath, long threadsCount, long maxCachedTilesPerThread,
|
||||
bool forceRegenerate);
|
||||
Generator(std::string const & srtmPath, long threadsCount, long maxCachedTilesPerThread, bool forceRegenerate);
|
||||
|
||||
void InitCountryInfoGetter(std::string const & dataDir);
|
||||
|
||||
void GenerateIsolines(int left, int bottom, int right, int top,
|
||||
TileIsolinesParams const & params);
|
||||
void GenerateIsolines(int left, int bottom, int right, int top, TileIsolinesParams const & params);
|
||||
|
||||
void PackIsolinesForCountry(storage::CountryId const & countryId,
|
||||
IsolinesPackingParams const & params);
|
||||
void PackIsolinesForCountry(storage::CountryId const & countryId, IsolinesPackingParams const & params);
|
||||
|
||||
void InitProfiles(std::string const & isolinesProfilesFileName,
|
||||
std::string const & countriesToGenerateFileName,
|
||||
std::string const & isolinesTilesOutDir,
|
||||
std::string const & isolinesCountriesOutDir);
|
||||
void InitProfiles(std::string const & isolinesProfilesFileName, std::string const & countriesToGenerateFileName,
|
||||
std::string const & isolinesTilesOutDir, std::string const & isolinesCountriesOutDir);
|
||||
|
||||
void GenerateIsolinesForCountries();
|
||||
void PackIsolinesForCountries();
|
||||
|
||||
private:
|
||||
void GenerateIsolines(int left, int bottom, int right, int top,
|
||||
std::string const & tilesProfilesDir);
|
||||
void GenerateIsolines(int left, int bottom, int right, int top, std::string const & tilesProfilesDir);
|
||||
|
||||
using NeedSkipTileFn = std::function<bool(int lat, int lon)>;
|
||||
void PackIsolinesForCountry(storage::CountryId const & countryId,
|
||||
IsolinesPackingParams const & params,
|
||||
void PackIsolinesForCountry(storage::CountryId const & countryId, IsolinesPackingParams const & params,
|
||||
NeedSkipTileFn const & needSkipTileFn);
|
||||
|
||||
void GetCountryRegions(storage::CountryId const & countryId, m2::RectD & countryRect,
|
||||
|
||||
@@ -21,10 +21,10 @@ struct IsolinesProfile
|
||||
uint32_t m_alitudesStep = 10;
|
||||
uint8_t m_latLonStepFactor = 1;
|
||||
uint32_t m_maxIsolinesLength = 1000;
|
||||
uint8_t m_simplificationZoom = 17; // Value == 0 disables simplification.
|
||||
uint8_t m_medianFilterR = 1; // Value == 0 disables filter.
|
||||
double m_gaussianFilterStDev = 2.0; // Value == 0.0 disables filter.
|
||||
double m_gaussianFilterRFactor = 1.0; // Value == 0.0 disables filter.
|
||||
uint8_t m_simplificationZoom = 17; // Value == 0 disables simplification.
|
||||
uint8_t m_medianFilterR = 1; // Value == 0 disables filter.
|
||||
double m_gaussianFilterStDev = 2.0; // Value == 0.0 disables filter.
|
||||
double m_gaussianFilterRFactor = 1.0; // Value == 0.0 disables filter.
|
||||
|
||||
DECLARE_VISITOR_AND_DEBUG_PRINT(IsolinesProfile, visitor(m_alitudesStep, "alitudesStep"),
|
||||
visitor(m_latLonStepFactor, "latLonStepFactor"),
|
||||
@@ -45,18 +45,14 @@ struct IsolinesProfilesCollection
|
||||
struct TileCoord
|
||||
{
|
||||
TileCoord() = default;
|
||||
TileCoord(int bottomLat, int leftLon): m_leftLon(leftLon), m_bottomLat(bottomLat) {}
|
||||
TileCoord(int bottomLat, int leftLon) : m_leftLon(leftLon), m_bottomLat(bottomLat) {}
|
||||
|
||||
int32_t m_leftLon = 0;
|
||||
int32_t m_bottomLat = 0;
|
||||
|
||||
bool operator==(TileCoord const & rhs) const
|
||||
{
|
||||
return m_leftLon == rhs.m_leftLon && m_bottomLat == rhs.m_bottomLat;
|
||||
}
|
||||
bool operator==(TileCoord const & rhs) const { return m_leftLon == rhs.m_leftLon && m_bottomLat == rhs.m_bottomLat; }
|
||||
|
||||
DECLARE_VISITOR_AND_DEBUG_PRINT(TileCoord, visitor(m_bottomLat, "bottomLat"),
|
||||
visitor(m_leftLon, "leftLon"))
|
||||
DECLARE_VISITOR_AND_DEBUG_PRINT(TileCoord, visitor(m_bottomLat, "bottomLat"), visitor(m_leftLon, "leftLon"))
|
||||
};
|
||||
|
||||
struct TileCoordHash
|
||||
@@ -94,7 +90,7 @@ struct CountriesToGenerate
|
||||
DECLARE_VISITOR_AND_DEBUG_PRINT(CountriesToGenerate, visitor(m_countryParams, "countryParams"))
|
||||
};
|
||||
|
||||
template<typename DataType>
|
||||
template <typename DataType>
|
||||
bool Serialize(std::string const & fileName, DataType const & data)
|
||||
{
|
||||
try
|
||||
@@ -115,7 +111,7 @@ bool Serialize(std::string const & fileName, DataType const & data)
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename DataType>
|
||||
template <typename DataType>
|
||||
bool Deserialize(std::string const & fileName, DataType & data)
|
||||
{
|
||||
try
|
||||
|
||||
@@ -12,14 +12,18 @@
|
||||
DEFINE_bool(force, false, "Force to regenerate isolines for tiles and countries.");
|
||||
|
||||
// Options for automatic isolines generating mode.
|
||||
DEFINE_string(profiles_path, "", "Automatic isolines generating mode. "
|
||||
"Path to a json file with isolines profiles.");
|
||||
DEFINE_string(countries_to_generate_path, "", "Automatic isolines generating mode. "
|
||||
"Path to a json file with countries to generate.");
|
||||
DEFINE_string(tiles_isolines_out_dir, "", "Automatic isolines generating mode. Path to output "
|
||||
"intermediate directory with tiles isolines.");
|
||||
DEFINE_string(countries_isolines_out_dir, "", "Automatic isolines generating mode. "
|
||||
"Path to output directory with countries isolines.");
|
||||
DEFINE_string(profiles_path, "",
|
||||
"Automatic isolines generating mode. "
|
||||
"Path to a json file with isolines profiles.");
|
||||
DEFINE_string(countries_to_generate_path, "",
|
||||
"Automatic isolines generating mode. "
|
||||
"Path to a json file with countries to generate.");
|
||||
DEFINE_string(tiles_isolines_out_dir, "",
|
||||
"Automatic isolines generating mode. Path to output "
|
||||
"intermediate directory with tiles isolines.");
|
||||
DEFINE_string(countries_isolines_out_dir, "",
|
||||
"Automatic isolines generating mode. "
|
||||
"Path to output directory with countries isolines.");
|
||||
|
||||
// Common option for automatic isolines generating mode and custom packing mode.
|
||||
DEFINE_string(data_dir, "", "Path to data directory.");
|
||||
@@ -34,10 +38,8 @@ DEFINE_string(out_dir, "", "Path to output directory.");
|
||||
DEFINE_uint64(simpl_zoom, 16, "Isolines simplification zoom.");
|
||||
|
||||
// Options for custom isolines packing mode.
|
||||
DEFINE_string(countryId, "",
|
||||
"Custom isolines packing mode. Pack isolines for countryId.");
|
||||
DEFINE_string(isolines_path, "",
|
||||
"Custom isolines packing mode. Path to the directory with isolines tiles.");
|
||||
DEFINE_string(countryId, "", "Custom isolines packing mode. Pack isolines for countryId.");
|
||||
DEFINE_string(isolines_path, "", "Custom isolines packing mode. Path to the directory with isolines tiles.");
|
||||
DEFINE_uint64(max_length, 1000, "Custom isolines packing mode. Isolines max length.");
|
||||
DEFINE_uint64(alt_step_factor, 1, "Custom isolines packing mode. Altitude step factor.");
|
||||
|
||||
@@ -57,40 +59,38 @@ using namespace topography_generator;
|
||||
MAIN_WITH_ERROR_HANDLING([](int argc, char ** argv)
|
||||
{
|
||||
gflags::SetUsageMessage(
|
||||
"\n\nThis tool generates isolines and works in the following modes:\n"
|
||||
"1. Automatic isolines generating mode. Generates a binary file with isolines for each\n"
|
||||
" country id from the countries_to_generate_path. Gets options for isolines generating\n"
|
||||
" from the corresponding to the country profile in profiles_path.\n"
|
||||
" Stores intermediate binary isolines tiles to tiles_isolines_out_dir and result countries\n"
|
||||
" isolines to countries_isolines_out_dir.\n"
|
||||
"2. Custom isolines generating mode. Generates binary tile with isolines for each SRTM tile in the\n"
|
||||
" specified tile rect.\n"
|
||||
" Mode activates by passing a valid tiles rect.\n"
|
||||
" An isoline would be generated for each isolines_step difference in height.\n"
|
||||
" Tiles for lat >= 60 && lat < -60 (converted from ASTER source) can be filtered by\n"
|
||||
" median and/or gaussian filters.\n"
|
||||
" Median filter activates by nonzero filter kernel radius median_r.\n"
|
||||
" Gaussian filter activates by gaussian_st_dev > 0.0 && gaussian_r_factor > 0.0 parameters.\n"
|
||||
" Contours generating steps through altitudes matrix of SRTM tile can be adjusted by\n"
|
||||
" latlon_step_factor parameter.\n"
|
||||
" Isolines simplification activates by nonzero simpl_zoom [1..17]\n"
|
||||
"\n"
|
||||
"3. Custom packing isolines from ready tiles into a binary file for specified country id.\n"
|
||||
" Mode activates by passing a countryId parameter.\n"
|
||||
" Tool gets isolines from the tiles, covered by the country regions, selects\n"
|
||||
" altitude levels with alt_step_factor (if a tile stores altitudes for each 10 meters\n"
|
||||
" and alt_step_factor == 5, the result binary file will store altitudes for each 50 meters).\n"
|
||||
" Isolines cropped by the country regions and cut by max_length parameter.\n"
|
||||
" Isolines simplification activates by nonzero simpl_zoom [1..17]\n\n");
|
||||
"\n\nThis tool generates isolines and works in the following modes:\n"
|
||||
"1. Automatic isolines generating mode. Generates a binary file with isolines for each\n"
|
||||
" country id from the countries_to_generate_path. Gets options for isolines generating\n"
|
||||
" from the corresponding to the country profile in profiles_path.\n"
|
||||
" Stores intermediate binary isolines tiles to tiles_isolines_out_dir and result countries\n"
|
||||
" isolines to countries_isolines_out_dir.\n"
|
||||
"2. Custom isolines generating mode. Generates binary tile with isolines for each SRTM tile in the\n"
|
||||
" specified tile rect.\n"
|
||||
" Mode activates by passing a valid tiles rect.\n"
|
||||
" An isoline would be generated for each isolines_step difference in height.\n"
|
||||
" Tiles for lat >= 60 && lat < -60 (converted from ASTER source) can be filtered by\n"
|
||||
" median and/or gaussian filters.\n"
|
||||
" Median filter activates by nonzero filter kernel radius median_r.\n"
|
||||
" Gaussian filter activates by gaussian_st_dev > 0.0 && gaussian_r_factor > 0.0 parameters.\n"
|
||||
" Contours generating steps through altitudes matrix of SRTM tile can be adjusted by\n"
|
||||
" latlon_step_factor parameter.\n"
|
||||
" Isolines simplification activates by nonzero simpl_zoom [1..17]\n"
|
||||
"\n"
|
||||
"3. Custom packing isolines from ready tiles into a binary file for specified country id.\n"
|
||||
" Mode activates by passing a countryId parameter.\n"
|
||||
" Tool gets isolines from the tiles, covered by the country regions, selects\n"
|
||||
" altitude levels with alt_step_factor (if a tile stores altitudes for each 10 meters\n"
|
||||
" and alt_step_factor == 5, the result binary file will store altitudes for each 50 meters).\n"
|
||||
" Isolines cropped by the country regions and cut by max_length parameter.\n"
|
||||
" Isolines simplification activates by nonzero simpl_zoom [1..17]\n\n");
|
||||
|
||||
gflags::ParseCommandLineFlags(&argc, &argv, true);
|
||||
|
||||
bool isCustomGeneratingMode = false;
|
||||
bool isCustomPackingMode = false;
|
||||
bool const isAutomaticMode = !FLAGS_profiles_path.empty() ||
|
||||
!FLAGS_countries_to_generate_path.empty() ||
|
||||
!FLAGS_tiles_isolines_out_dir.empty() ||
|
||||
!FLAGS_countries_isolines_out_dir.empty();
|
||||
bool const isAutomaticMode = !FLAGS_profiles_path.empty() || !FLAGS_countries_to_generate_path.empty() ||
|
||||
!FLAGS_tiles_isolines_out_dir.empty() || !FLAGS_countries_isolines_out_dir.empty();
|
||||
if (isAutomaticMode)
|
||||
{
|
||||
if (FLAGS_profiles_path.empty() || FLAGS_countries_to_generate_path.empty() ||
|
||||
@@ -110,9 +110,8 @@ MAIN_WITH_ERROR_HANDLING([](int argc, char ** argv)
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
auto const validTilesRect = FLAGS_right > FLAGS_left && FLAGS_top > FLAGS_bottom &&
|
||||
FLAGS_right <= 180 && FLAGS_left >= -180 &&
|
||||
FLAGS_top <= 90 && FLAGS_bottom >= -90;
|
||||
auto const validTilesRect = FLAGS_right > FLAGS_left && FLAGS_top > FLAGS_bottom && FLAGS_right <= 180 &&
|
||||
FLAGS_left >= -180 && FLAGS_top <= 90 && FLAGS_bottom >= -90;
|
||||
|
||||
isCustomGeneratingMode = validTilesRect;
|
||||
isCustomPackingMode = !FLAGS_countryId.empty();
|
||||
@@ -155,8 +154,8 @@ MAIN_WITH_ERROR_HANDLING([](int argc, char ** argv)
|
||||
if (isAutomaticMode)
|
||||
{
|
||||
generator.InitCountryInfoGetter(FLAGS_data_dir);
|
||||
generator.InitProfiles(FLAGS_profiles_path, FLAGS_countries_to_generate_path,
|
||||
FLAGS_tiles_isolines_out_dir, FLAGS_countries_isolines_out_dir);
|
||||
generator.InitProfiles(FLAGS_profiles_path, FLAGS_countries_to_generate_path, FLAGS_tiles_isolines_out_dir,
|
||||
FLAGS_countries_isolines_out_dir);
|
||||
generator.GenerateIsolinesForCountries();
|
||||
generator.PackIsolinesForCountries();
|
||||
|
||||
@@ -188,14 +187,12 @@ MAIN_WITH_ERROR_HANDLING([](int argc, char ** argv)
|
||||
|
||||
TileIsolinesParams params;
|
||||
if (FLAGS_median_r > 0)
|
||||
{
|
||||
params.m_filters.emplace_back(std::make_unique<MedianFilter<Altitude>>(FLAGS_median_r));
|
||||
}
|
||||
|
||||
if (FLAGS_gaussian_st_dev > 0.0 && FLAGS_gaussian_r_factor > 0)
|
||||
{
|
||||
params.m_filters.emplace_back(
|
||||
std::make_unique<GaussianFilter<Altitude>>(FLAGS_gaussian_st_dev, FLAGS_gaussian_r_factor));
|
||||
std::make_unique<GaussianFilter<Altitude>>(FLAGS_gaussian_st_dev, FLAGS_gaussian_r_factor));
|
||||
}
|
||||
|
||||
params.m_outputDir = FLAGS_out_dir;
|
||||
|
||||
@@ -49,10 +49,8 @@ void ContoursBuilder::AddSegment(size_t levelInd, ms::LatLon const & beginPos, m
|
||||
void ContoursBuilder::BeginLine()
|
||||
{
|
||||
for (auto & contoursList : m_activeContours)
|
||||
{
|
||||
for (auto & activeContour : contoursList)
|
||||
activeContour.m_active = false;
|
||||
}
|
||||
}
|
||||
|
||||
void ContoursBuilder::EndLine(bool finalLine)
|
||||
@@ -80,10 +78,8 @@ ContoursBuilder::ActiveContourIter ContoursBuilder::FindContourWithStartPoint(si
|
||||
{
|
||||
auto & contours = m_activeContours[levelInd];
|
||||
for (auto it = contours.begin(); it != contours.end(); ++it)
|
||||
{
|
||||
if (it->m_countour.front().EqualDxDy(pos, mercator::kPointEqualityEps))
|
||||
return it;
|
||||
}
|
||||
return contours.end();
|
||||
}
|
||||
|
||||
@@ -91,10 +87,8 @@ ContoursBuilder::ActiveContourIter ContoursBuilder::FindContourWithEndPoint(size
|
||||
{
|
||||
auto & contours = m_activeContours[levelInd];
|
||||
for (auto it = contours.begin(); it != contours.end(); ++it)
|
||||
{
|
||||
if (it->m_countour.back().EqualDxDy(pos, mercator::kPointEqualityEps))
|
||||
return it;
|
||||
}
|
||||
return contours.end();
|
||||
}
|
||||
} // namespace topography_generator
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
#include <algorithm>
|
||||
#include <deque>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace topography_generator
|
||||
{
|
||||
@@ -36,7 +36,7 @@ public:
|
||||
Contour contourMerc;
|
||||
contourMerc.reserve(contour.size());
|
||||
std::transform(contour.begin(), contour.end(), std::back_inserter(contourMerc),
|
||||
[](ms::LatLon const & pt){ return mercator::FromLatLon(pt); });
|
||||
[](ms::LatLon const & pt) { return mercator::FromLatLon(pt); });
|
||||
|
||||
contours[levelValue].emplace_back(std::move(contourMerc));
|
||||
}
|
||||
@@ -49,9 +49,7 @@ private:
|
||||
|
||||
struct ActiveContour
|
||||
{
|
||||
explicit ActiveContour(ContourRaw && isoline)
|
||||
: m_countour(std::move(isoline))
|
||||
{}
|
||||
explicit ActiveContour(ContourRaw && isoline) : m_countour(std::move(isoline)) {}
|
||||
|
||||
ContourRaw m_countour;
|
||||
bool m_active = true;
|
||||
|
||||
@@ -13,9 +13,8 @@ template <typename ValueType>
|
||||
class MarchingSquares
|
||||
{
|
||||
public:
|
||||
MarchingSquares(ms::LatLon const & leftBottom, ms::LatLon const & rightTop,
|
||||
double step, ValueType valueStep, ValuesProvider<ValueType> & valuesProvider,
|
||||
std::string const & debugId)
|
||||
MarchingSquares(ms::LatLon const & leftBottom, ms::LatLon const & rightTop, double step, ValueType valueStep,
|
||||
ValuesProvider<ValueType> & valuesProvider, std::string const & debugId)
|
||||
: m_leftBottom(leftBottom)
|
||||
, m_rightTop(rightTop)
|
||||
, m_step(step)
|
||||
@@ -58,18 +57,17 @@ public:
|
||||
// This point should be calculated _exact_ the same way as in ScanValuesInRect.
|
||||
// leftBottom + m_step doesn't work due to different floating results.
|
||||
|
||||
square.Init(
|
||||
m_leftBottom.m_lon + m_step * j, // Left
|
||||
m_leftBottom.m_lat + m_step * i, // Bottom
|
||||
m_leftBottom.m_lon + m_step * (j + 1), // Right
|
||||
m_leftBottom.m_lat + m_step * (i + 1), // Top
|
||||
square.Init(m_leftBottom.m_lon + m_step * j, // Left
|
||||
m_leftBottom.m_lat + m_step * i, // Bottom
|
||||
m_leftBottom.m_lon + m_step * (j + 1), // Right
|
||||
m_leftBottom.m_lat + m_step * (i + 1), // Top
|
||||
|
||||
grid[Idx(i, j)], // LB
|
||||
grid[Idx(i, j + 1)], // RB
|
||||
grid[Idx(i + 1, j)], // LT
|
||||
grid[Idx(i + 1, j + 1)], // RT
|
||||
grid[Idx(i, j)], // LB
|
||||
grid[Idx(i, j + 1)], // RB
|
||||
grid[Idx(i + 1, j)], // LT
|
||||
grid[Idx(i + 1, j + 1)], // RT
|
||||
|
||||
m_valuesProvider.GetInvalidValue());
|
||||
m_valuesProvider.GetInvalidValue());
|
||||
|
||||
square.GenerateSegments(contoursBuilder);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
#include "topography_generator/marching_squares/contours_builder.hpp"
|
||||
|
||||
|
||||
namespace topography_generator
|
||||
{
|
||||
template <typename ValueType>
|
||||
@@ -17,8 +16,8 @@ public:
|
||||
static_assert(std::is_integral<ValueType>::value && std::is_signed<ValueType>::value);
|
||||
}
|
||||
|
||||
void Init(double left, double bottom, double right, double top,
|
||||
ValueType lb, ValueType rb, ValueType lt, ValueType rt, ValueType invalid)
|
||||
void Init(double left, double bottom, double right, double top, ValueType lb, ValueType rb, ValueType lt,
|
||||
ValueType rt, ValueType invalid)
|
||||
{
|
||||
m_isValid = true;
|
||||
|
||||
@@ -79,7 +78,7 @@ private:
|
||||
// Shift the value slightly from the corner.
|
||||
if (val == invalid)
|
||||
{
|
||||
//LOG(LWARNING, ("Invalid value at the position", pos, m_debugId));
|
||||
// LOG(LWARNING, ("Invalid value at the position", pos, m_debugId));
|
||||
m_isValid = false;
|
||||
return val;
|
||||
}
|
||||
@@ -92,28 +91,27 @@ private:
|
||||
void AddSegments(ValueType val, uint16_t ind, ContoursBuilder & builder) const
|
||||
{
|
||||
// Segment is a vector directed so that higher values is on the right.
|
||||
static const std::pair<Rib, Rib> intersectedRibs[] =
|
||||
{
|
||||
{Rib::None, Rib::None}, // 0000
|
||||
{Rib::Left, Rib::Bottom}, // 0001
|
||||
{Rib::Top, Rib::Left}, // 0010
|
||||
{Rib::Top, Rib::Bottom}, // 0011
|
||||
{Rib::Right, Rib::Top}, // 0100
|
||||
{Rib::Unclear, Rib::Unclear}, // 0101
|
||||
{Rib::Right, Rib::Left}, // 0110
|
||||
{Rib::Right, Rib::Bottom}, // 0111
|
||||
{Rib::Bottom, Rib::Right}, // 1000
|
||||
{Rib::Left, Rib::Right}, // 1001
|
||||
{Rib::Unclear, Rib::Unclear}, // 1010
|
||||
{Rib::Top, Rib::Right}, // 1011
|
||||
{Rib::Bottom, Rib::Top}, // 1100
|
||||
{Rib::Left, Rib::Top}, // 1101
|
||||
{Rib::Bottom, Rib::Left}, // 1110
|
||||
{Rib::None, Rib::None}, // 1111
|
||||
};
|
||||
static std::pair<Rib, Rib> const intersectedRibs[] = {
|
||||
{Rib::None, Rib::None}, // 0000
|
||||
{Rib::Left, Rib::Bottom}, // 0001
|
||||
{Rib::Top, Rib::Left}, // 0010
|
||||
{Rib::Top, Rib::Bottom}, // 0011
|
||||
{Rib::Right, Rib::Top}, // 0100
|
||||
{Rib::Unclear, Rib::Unclear}, // 0101
|
||||
{Rib::Right, Rib::Left}, // 0110
|
||||
{Rib::Right, Rib::Bottom}, // 0111
|
||||
{Rib::Bottom, Rib::Right}, // 1000
|
||||
{Rib::Left, Rib::Right}, // 1001
|
||||
{Rib::Unclear, Rib::Unclear}, // 1010
|
||||
{Rib::Top, Rib::Right}, // 1011
|
||||
{Rib::Bottom, Rib::Top}, // 1100
|
||||
{Rib::Left, Rib::Top}, // 1101
|
||||
{Rib::Bottom, Rib::Left}, // 1110
|
||||
{Rib::None, Rib::None}, // 1111
|
||||
};
|
||||
|
||||
uint8_t const pattern = (m_valueLB > val ? 1u : 0u) | ((m_valueLT > val ? 1u : 0u) << 1u) |
|
||||
((m_valueRT > val ? 1u : 0u) << 2u) | ((m_valueRB > val ? 1u : 0u) << 3u);
|
||||
uint8_t const pattern = (m_valueLB > val ? 1u : 0u) | ((m_valueLT > val ? 1u : 0u) << 1u) |
|
||||
((m_valueRT > val ? 1u : 0u) << 2u) | ((m_valueRB > val ? 1u : 0u) << 3u);
|
||||
|
||||
auto const ribs = intersectedRibs[pattern];
|
||||
|
||||
@@ -145,18 +143,15 @@ private:
|
||||
builder.AddSegment(ind, topPos, rightPos);
|
||||
}
|
||||
}
|
||||
else if (m_valueLB > val)
|
||||
{
|
||||
builder.AddSegment(ind, leftPos, bottomPos);
|
||||
builder.AddSegment(ind, rightPos, topPos);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_valueLB > val)
|
||||
{
|
||||
builder.AddSegment(ind, leftPos, bottomPos);
|
||||
builder.AddSegment(ind, rightPos, topPos);
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.AddSegment(ind, topPos, leftPos);
|
||||
builder.AddSegment(ind, bottomPos, rightPos);
|
||||
}
|
||||
builder.AddSegment(ind, topPos, leftPos);
|
||||
builder.AddSegment(ind, bottomPos, rightPos);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -190,8 +185,7 @@ private:
|
||||
val2 = static_cast<double>(m_valueRB);
|
||||
lat = m_bottom;
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
default: UNREACHABLE();
|
||||
}
|
||||
|
||||
CHECK_NOT_EQUAL(val, val2, (m_debugId));
|
||||
@@ -200,15 +194,10 @@ private:
|
||||
switch (rib)
|
||||
{
|
||||
case Rib::Left:
|
||||
case Rib::Right:
|
||||
lat = (m_bottom + m_top * coeff) / (1 + coeff);
|
||||
break;
|
||||
case Rib::Right: lat = (m_bottom + m_top * coeff) / (1 + coeff); break;
|
||||
case Rib::Bottom:
|
||||
case Rib::Top:
|
||||
lon = (m_left + m_right * coeff) / (1 + coeff);
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
case Rib::Top: lon = (m_left + m_right * coeff) / (1 + coeff); break;
|
||||
default: UNREACHABLE();
|
||||
}
|
||||
|
||||
return {lat, lon};
|
||||
@@ -230,4 +219,4 @@ private:
|
||||
|
||||
bool m_isValid;
|
||||
};
|
||||
} // topography_generator
|
||||
} // namespace topography_generator
|
||||
|
||||
@@ -11,23 +11,19 @@ public:
|
||||
virtual ~FilterInterface() = default;
|
||||
|
||||
virtual size_t GetKernelRadius() const = 0;
|
||||
virtual void Process(size_t tileSize, size_t tileOffset,
|
||||
std::vector<ValueType> const & srcValues,
|
||||
std::vector<ValueType> & dstValues, ValueType invalidValue) const = 0;
|
||||
virtual void Process(size_t tileSize, size_t tileOffset, std::vector<ValueType> const & srcValues,
|
||||
std::vector<ValueType> & dstValues, ValueType invalidValue) const = 0;
|
||||
};
|
||||
|
||||
template <typename ValueType>
|
||||
class MedianFilter : public FilterInterface<ValueType>
|
||||
{
|
||||
public:
|
||||
explicit MedianFilter(size_t kernelRadius)
|
||||
: m_kernelRadius(kernelRadius)
|
||||
{}
|
||||
explicit MedianFilter(size_t kernelRadius) : m_kernelRadius(kernelRadius) {}
|
||||
|
||||
size_t GetKernelRadius() const override { return m_kernelRadius; }
|
||||
|
||||
void Process(size_t tileSize, size_t tileOffset,
|
||||
std::vector<ValueType> const & srcValues,
|
||||
void Process(size_t tileSize, size_t tileOffset, std::vector<ValueType> const & srcValues,
|
||||
std::vector<ValueType> & dstValues, ValueType invalidValue) const override
|
||||
{
|
||||
ProcessMedian(m_kernelRadius, tileSize, tileOffset, srcValues, dstValues, invalidValue);
|
||||
@@ -47,8 +43,7 @@ public:
|
||||
|
||||
size_t GetKernelRadius() const override { return m_kernel.size() / 2; }
|
||||
|
||||
void Process(size_t tileSize, size_t tileOffset,
|
||||
std::vector<ValueType> const & srcValues,
|
||||
void Process(size_t tileSize, size_t tileOffset, std::vector<ValueType> const & srcValues,
|
||||
std::vector<ValueType> & dstValues, ValueType invalidValue) const override
|
||||
{
|
||||
ProcessWithLinearKernel(m_kernel, tileSize, tileOffset, srcValues, dstValues, invalidValue);
|
||||
@@ -62,10 +57,8 @@ template <typename ValueType>
|
||||
using FiltersSequence = std::vector<std::unique_ptr<FilterInterface<ValueType>>>;
|
||||
|
||||
template <typename ValueType>
|
||||
std::vector<ValueType> FilterTile(FiltersSequence<ValueType> const & filters,
|
||||
ms::LatLon const & leftBottom,
|
||||
size_t stepsInDegree, size_t tileSize,
|
||||
ValuesProvider<ValueType> & valuesProvider)
|
||||
std::vector<ValueType> FilterTile(FiltersSequence<ValueType> const & filters, ms::LatLon const & leftBottom,
|
||||
size_t stepsInDegree, size_t tileSize, ValuesProvider<ValueType> & valuesProvider)
|
||||
{
|
||||
size_t combinedOffset = 0;
|
||||
for (auto const & filter : filters)
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
|
||||
#include "indexer/scales.hpp"
|
||||
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace topography_generator
|
||||
{
|
||||
@@ -27,12 +27,12 @@ struct Contours
|
||||
ValueType m_minValue = 0;
|
||||
ValueType m_maxValue = 0;
|
||||
ValueType m_valueStep = 0;
|
||||
size_t m_invalidValuesCount = 0; // for debug purpose only.
|
||||
size_t m_invalidValuesCount = 0; // for debug purpose only.
|
||||
};
|
||||
|
||||
template <typename ValueType>
|
||||
void CropContours(m2::RectD & rect, std::vector<m2::RegionD> & regions, size_t maxLength,
|
||||
size_t valueStepFactor, Contours<ValueType> & contours)
|
||||
void CropContours(m2::RectD & rect, std::vector<m2::RegionD> & regions, size_t maxLength, size_t valueStepFactor,
|
||||
Contours<ValueType> & contours)
|
||||
{
|
||||
static_assert(std::is_integral<ValueType>::value, "Only integral types are supported.");
|
||||
|
||||
@@ -90,8 +90,7 @@ void SimplifyContours(int simplificationZoom, Contours<ValueType> & contours)
|
||||
for (auto & contour : levelContours.second)
|
||||
{
|
||||
std::vector<m2::PointD> contourSimple;
|
||||
feature::SimplifyPoints(m2::SquaredDistanceFromSegmentToPoint(),
|
||||
simplificationZoom, contour, contourSimple);
|
||||
feature::SimplifyPoints(m2::SquaredDistanceFromSegmentToPoint(), simplificationZoom, contour, contourSimple);
|
||||
CHECK_GREATER(contourSimple.size(), 1, ());
|
||||
// Discard closed lines which are degenerate (<=3 points) or too small for the requested zoom level.
|
||||
/// @todo it doesn't fix all cases as the simplification algo
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
#include "topography_generator/utils/contours.hpp"
|
||||
|
||||
#include "coding/file_writer.hpp"
|
||||
#include "coding/file_reader.hpp"
|
||||
#include "coding/file_writer.hpp"
|
||||
#include "coding/geometry_coding.hpp"
|
||||
#include "coding/internal/file_data.hpp"
|
||||
|
||||
@@ -13,7 +13,7 @@ template <typename ValueType>
|
||||
class SerializerContours
|
||||
{
|
||||
public:
|
||||
explicit SerializerContours(Contours<ValueType> && contours): m_contours(std::move(contours)) {}
|
||||
explicit SerializerContours(Contours<ValueType> && contours) : m_contours(std::move(contours)) {}
|
||||
|
||||
template <typename Sink>
|
||||
void Serialize(Sink & sink)
|
||||
@@ -31,8 +31,7 @@ public:
|
||||
|
||||
private:
|
||||
template <typename Sink>
|
||||
void SerializeContours(Sink & sink, ValueType value,
|
||||
std::vector<topography_generator::Contour> const & contours)
|
||||
void SerializeContours(Sink & sink, ValueType value, std::vector<topography_generator::Contour> const & contours)
|
||||
{
|
||||
WriteToSink(sink, value);
|
||||
WriteToSink(sink, static_cast<uint32_t>(contours.size()));
|
||||
@@ -81,7 +80,7 @@ public:
|
||||
|
||||
private:
|
||||
void DeserializeContours(NonOwningReaderSource & source, ValueType & value,
|
||||
std::vector<topography_generator::Contour> & contours)
|
||||
std::vector<topography_generator::Contour> & contours)
|
||||
{
|
||||
value = ReadPrimitiveFromSource<ValueType>(source);
|
||||
size_t const contoursCount = ReadPrimitiveFromSource<uint32_t>(source);
|
||||
@@ -90,8 +89,7 @@ private:
|
||||
DeserializeContour(source, contour);
|
||||
}
|
||||
|
||||
void DeserializeContour(NonOwningReaderSource & source,
|
||||
topography_generator::Contour & contour)
|
||||
void DeserializeContour(NonOwningReaderSource & source, topography_generator::Contour & contour)
|
||||
{
|
||||
serial::GeometryCodingParams codingParams;
|
||||
codingParams.Load(source);
|
||||
@@ -102,8 +100,7 @@ private:
|
||||
};
|
||||
|
||||
template <typename ValueType>
|
||||
bool SaveContrours(std::string const & filePath,
|
||||
Contours<ValueType> && contours)
|
||||
bool SaveContrours(std::string const & filePath, Contours<ValueType> && contours)
|
||||
{
|
||||
auto const tmpFilePath = filePath + ".tmp";
|
||||
try
|
||||
|
||||
@@ -33,8 +33,7 @@ vector<DataPoint> ReadDataPoints(string const & data)
|
||||
|
||||
try
|
||||
{
|
||||
coding::TrafficGPSEncoder::DeserializeDataPoints(coding::TrafficGPSEncoder::kLatestVersion, src,
|
||||
points);
|
||||
coding::TrafficGPSEncoder::DeserializeDataPoints(coding::TrafficGPSEncoder::kLatestVersion, src, points);
|
||||
}
|
||||
catch (Reader::SizeException const & e)
|
||||
{
|
||||
@@ -48,11 +47,12 @@ vector<DataPoint> ReadDataPoints(string const & data)
|
||||
class PointToMwmId final
|
||||
{
|
||||
public:
|
||||
PointToMwmId(shared_ptr<m4::Tree<routing::NumMwmId>> mwmTree,
|
||||
routing::NumMwmIds const & numMwmIds, string const & dataDir)
|
||||
PointToMwmId(shared_ptr<m4::Tree<routing::NumMwmId>> mwmTree, routing::NumMwmIds const & numMwmIds,
|
||||
string const & dataDir)
|
||||
: m_mwmTree(mwmTree)
|
||||
{
|
||||
numMwmIds.ForEachId([&](routing::NumMwmId numMwmId) {
|
||||
numMwmIds.ForEachId([&](routing::NumMwmId numMwmId)
|
||||
{
|
||||
string const & mwmName = numMwmIds.GetFile(numMwmId).GetName();
|
||||
string const polyFile = base::JoinPath(dataDir, BORDERS_DIR, mwmName + BORDERS_EXTENSION);
|
||||
borders::LoadBorders(polyFile, m_borders[numMwmId]);
|
||||
@@ -66,7 +66,8 @@ public:
|
||||
|
||||
routing::NumMwmId result = routing::kFakeNumMwmId;
|
||||
m2::RectD const rect = mercator::RectByCenterXYAndSizeInMeters(point, 1);
|
||||
m_mwmTree->ForEachInRect(rect, [&](routing::NumMwmId numMwmId) {
|
||||
m_mwmTree->ForEachInRect(rect, [&](routing::NumMwmId numMwmId)
|
||||
{
|
||||
if (result == routing::kFakeNumMwmId && m2::RegionsContain(GetBorders(numMwmId), point))
|
||||
result = numMwmId;
|
||||
});
|
||||
@@ -89,9 +90,11 @@ private:
|
||||
|
||||
namespace track_analyzing
|
||||
{
|
||||
LogParser::LogParser(shared_ptr<routing::NumMwmIds> numMwmIds,
|
||||
unique_ptr<m4::Tree<routing::NumMwmId>> mwmTree, string const & dataDir)
|
||||
: m_numMwmIds(std::move(numMwmIds)), m_mwmTree(std::move(mwmTree)), m_dataDir(dataDir)
|
||||
LogParser::LogParser(shared_ptr<routing::NumMwmIds> numMwmIds, unique_ptr<m4::Tree<routing::NumMwmId>> mwmTree,
|
||||
string const & dataDir)
|
||||
: m_numMwmIds(std::move(numMwmIds))
|
||||
, m_mwmTree(std::move(mwmTree))
|
||||
, m_dataDir(dataDir)
|
||||
{
|
||||
CHECK(m_numMwmIds, ());
|
||||
CHECK(m_mwmTree, ());
|
||||
@@ -145,10 +148,9 @@ void LogParser::ParseUserTracks(string const & logFile, UserToTrack & userToTrac
|
||||
pointsCount += packet.size();
|
||||
};
|
||||
|
||||
LOG(LINFO, ("Tracks parsing finished, elapsed:", timer.ElapsedSeconds(), "seconds, lines:",
|
||||
linesCount, ", points", pointsCount));
|
||||
LOG(LINFO, ("Users with current version:", userToTrack.size(), ", old version:",
|
||||
usersWithOldVersion.size()));
|
||||
LOG(LINFO, ("Tracks parsing finished, elapsed:", timer.ElapsedSeconds(), "seconds, lines:", linesCount, ", points",
|
||||
pointsCount));
|
||||
LOG(LINFO, ("Users with current version:", userToTrack.size(), ", old version:", usersWithOldVersion.size()));
|
||||
}
|
||||
|
||||
void LogParser::SplitIntoMwms(UserToTrack const & userToTrack, MwmToTracks & mwmToTracks) const
|
||||
@@ -173,7 +175,6 @@ void LogParser::SplitIntoMwms(UserToTrack const & userToTrack, MwmToTracks & mwm
|
||||
}
|
||||
}
|
||||
|
||||
LOG(LINFO, ("Data was split into", mwmToTracks.size(), "mwms, elapsed:", timer.ElapsedSeconds(),
|
||||
"seconds"));
|
||||
LOG(LINFO, ("Data was split into", mwmToTracks.size(), "mwms, elapsed:", timer.ElapsedSeconds(), "seconds"));
|
||||
}
|
||||
} // namespace track_analyzing
|
||||
|
||||
@@ -14,8 +14,8 @@ namespace track_analyzing
|
||||
class LogParser final
|
||||
{
|
||||
public:
|
||||
LogParser(std::shared_ptr<routing::NumMwmIds> numMwmIds,
|
||||
std::unique_ptr<m4::Tree<routing::NumMwmId>> mwmTree, std::string const & dataDir);
|
||||
LogParser(std::shared_ptr<routing::NumMwmIds> numMwmIds, std::unique_ptr<m4::Tree<routing::NumMwmId>> mwmTree,
|
||||
std::string const & dataDir);
|
||||
|
||||
void Parse(std::string const & logFile, MwmToTracks & mwmToTracks) const;
|
||||
|
||||
|
||||
@@ -27,10 +27,7 @@ namespace track_analyzing
|
||||
class MwmToMatchedTracksSerializer final
|
||||
{
|
||||
public:
|
||||
MwmToMatchedTracksSerializer(std::shared_ptr<routing::NumMwmIds> numMwmIds)
|
||||
: m_numMwmIds(std::move(numMwmIds))
|
||||
{
|
||||
}
|
||||
MwmToMatchedTracksSerializer(std::shared_ptr<routing::NumMwmIds> numMwmIds) : m_numMwmIds(std::move(numMwmIds)) {}
|
||||
|
||||
template <typename Sink>
|
||||
void Serialize(MwmToMatchedTracks const & mwmToMatchedTracks, Sink & sink)
|
||||
@@ -68,8 +65,8 @@ public:
|
||||
|
||||
std::vector<uint8_t> buffer;
|
||||
MemWriter<decltype(buffer)> memWriter(buffer);
|
||||
coding::TrafficGPSEncoder::SerializeDataPoints(coding::TrafficGPSEncoder::kLatestVersion,
|
||||
memWriter, dataPoints);
|
||||
coding::TrafficGPSEncoder::SerializeDataPoints(coding::TrafficGPSEncoder::kLatestVersion, memWriter,
|
||||
dataPoints);
|
||||
|
||||
WriteSize(sink, buffer.size());
|
||||
sink.Write(buffer.data(), buffer.size());
|
||||
@@ -123,8 +120,8 @@ public:
|
||||
ReaderSource<MemReader> memSrc(memReader);
|
||||
|
||||
std::vector<DataPoint> dataPoints;
|
||||
coding::TrafficGPSEncoder::DeserializeDataPoints(
|
||||
coding::TrafficGPSEncoder::kLatestVersion, memSrc, dataPoints);
|
||||
coding::TrafficGPSEncoder::DeserializeDataPoints(coding::TrafficGPSEncoder::kLatestVersion, memSrc,
|
||||
dataPoints);
|
||||
CHECK_EQUAL(numSegments, dataPoints.size(), ("mwm:", mwmName, "user:", user));
|
||||
|
||||
MatchedTrack & track = tracks[iTrack];
|
||||
|
||||
@@ -10,8 +10,7 @@ TemporaryFile::TemporaryFile() : m_filePath(GetPlatform().TmpPathForFile()) {}
|
||||
|
||||
TemporaryFile::TemporaryFile(std::string const & namePrefix, std::string const & nameSuffix)
|
||||
: m_filePath(GetPlatform().TmpPathForFile(namePrefix, nameSuffix))
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
TemporaryFile::~TemporaryFile()
|
||||
{
|
||||
|
||||
@@ -13,10 +13,7 @@ public:
|
||||
|
||||
~TemporaryFile();
|
||||
|
||||
std::string const & GetFilePath() const
|
||||
{
|
||||
return m_filePath;
|
||||
}
|
||||
std::string const & GetFilePath() const { return m_filePath; }
|
||||
|
||||
void WriteData(std::string const & data);
|
||||
|
||||
|
||||
@@ -2,18 +2,15 @@
|
||||
|
||||
namespace track_analyzing
|
||||
{
|
||||
TrackFilter::TrackFilter(uint64_t minDuration, double minLength, double minSpeed, double maxSpeed,
|
||||
bool ignoreTraffic)
|
||||
TrackFilter::TrackFilter(uint64_t minDuration, double minLength, double minSpeed, double maxSpeed, bool ignoreTraffic)
|
||||
: m_minDuration(minDuration)
|
||||
, m_minLength(minLength)
|
||||
, m_minSpeed(minSpeed)
|
||||
, m_maxSpeed(maxSpeed)
|
||||
, m_ignoreTraffic(ignoreTraffic)
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
bool TrackFilter::Passes(uint64_t duration, double length, double speed,
|
||||
bool hasTrafficPoints) const
|
||||
bool TrackFilter::Passes(uint64_t duration, double length, double speed, bool hasTrafficPoints) const
|
||||
{
|
||||
if (duration < m_minDuration)
|
||||
return false;
|
||||
|
||||
@@ -21,9 +21,9 @@ class MatchedTrackPoint final
|
||||
{
|
||||
public:
|
||||
MatchedTrackPoint(DataPoint const & dataPoint, routing::Segment const & segment)
|
||||
: m_dataPoint(dataPoint), m_segment(segment)
|
||||
{
|
||||
}
|
||||
: m_dataPoint(dataPoint)
|
||||
, m_segment(segment)
|
||||
{}
|
||||
|
||||
DataPoint const & GetDataPoint() const { return m_dataPoint; }
|
||||
routing::Segment const & GetSegment() const { return m_segment; }
|
||||
@@ -40,8 +40,7 @@ using MwmToMatchedTracks = std::unordered_map<routing::NumMwmId, UserToMatchedTr
|
||||
class TrackFilter final
|
||||
{
|
||||
public:
|
||||
TrackFilter(uint64_t minDuration, double minLength, double minSpeed, double maxSpeed,
|
||||
bool ignoreTraffic);
|
||||
TrackFilter(uint64_t minDuration, double minLength, double minSpeed, double maxSpeed, bool ignoreTraffic);
|
||||
|
||||
bool Passes(uint64_t duration, double length, double speed, bool hasTrafficPoints) const;
|
||||
|
||||
|
||||
@@ -26,11 +26,10 @@ namespace track_analyzing
|
||||
{
|
||||
using namespace std;
|
||||
|
||||
void FillTable(basic_istream<char> & tableCsvStream, MwmToDataPoints & matchedDataPoints,
|
||||
vector<TableRow> & table)
|
||||
void FillTable(basic_istream<char> & tableCsvStream, MwmToDataPoints & matchedDataPoints, vector<TableRow> & table)
|
||||
{
|
||||
for (auto const & row : coding::CSVRunner(
|
||||
coding::CSVReader(tableCsvStream, true /* hasHeader */, ',' /* delimiter */)))
|
||||
for (auto const & row :
|
||||
coding::CSVRunner(coding::CSVReader(tableCsvStream, true /* hasHeader */, ',' /* delimiter */)))
|
||||
{
|
||||
CHECK_EQUAL(row.size(), kTableColumns, (row));
|
||||
auto const & mwmName = row[kMwmNameCsvColumn];
|
||||
@@ -39,13 +38,12 @@ void FillTable(basic_istream<char> & tableCsvStream, MwmToDataPoints & matchedDa
|
||||
}
|
||||
}
|
||||
|
||||
void RemoveKeysSmallValue(MwmToDataPoints & checkedMap, MwmToDataPoints & additionalMap,
|
||||
uint64_t ignoreDataPointNumber)
|
||||
void RemoveKeysSmallValue(MwmToDataPoints & checkedMap, MwmToDataPoints & additionalMap, uint64_t ignoreDataPointNumber)
|
||||
{
|
||||
CHECK(AreKeysEqual(additionalMap, checkedMap),
|
||||
("Mwms in |checkedMap| and in |additionalMap| should have the same set of keys."));
|
||||
|
||||
for (auto it = checkedMap.begin() ; it != checkedMap.end();)
|
||||
for (auto it = checkedMap.begin(); it != checkedMap.end();)
|
||||
{
|
||||
auto const dataPointNumberAfterMatching = it->second;
|
||||
if (dataPointNumberAfterMatching > ignoreDataPointNumber)
|
||||
@@ -72,14 +70,13 @@ MwmToDataPointFraction GetMwmToDataPointFraction(MwmToDataPoints const & numberM
|
||||
return fractionMapping;
|
||||
}
|
||||
|
||||
MwmToDataPoints CalcsMatchedDataPointsToKeepDistribution(
|
||||
MwmToDataPoints const & matchedDataPoints, MwmToDataPointFraction const & distributionFractions)
|
||||
MwmToDataPoints CalcsMatchedDataPointsToKeepDistribution(MwmToDataPoints const & matchedDataPoints,
|
||||
MwmToDataPointFraction const & distributionFractions)
|
||||
{
|
||||
CHECK(!matchedDataPoints.empty(), ());
|
||||
CHECK(AreKeysEqual(matchedDataPoints, distributionFractions),
|
||||
("Mwms in |matchedDataPoints| and in |distributionFractions| should have the same set of keys."));
|
||||
CHECK(AlmostEqualAbs(ValueSum(distributionFractions), 1.0, kSumFractionEps),
|
||||
(ValueSum(distributionFractions)));
|
||||
CHECK(AlmostEqualAbs(ValueSum(distributionFractions), 1.0, kSumFractionEps), (ValueSum(distributionFractions)));
|
||||
|
||||
auto const matchedFractions = GetMwmToDataPointFraction(matchedDataPoints);
|
||||
|
||||
@@ -137,17 +134,14 @@ MwmToDataPoints CalcsMatchedDataPointsToKeepDistribution(
|
||||
|
||||
if (matchedDataPointsToKeepDistributionForMwm == 0)
|
||||
{
|
||||
LOG(LWARNING, ("Zero points should be put to", mwm,
|
||||
"to keep the distribution. Distribution fraction:", fraction,
|
||||
"totalMatchedPointNumberToKeepDistribution:",
|
||||
totalMatchedPointNumberToKeepDistribution));
|
||||
LOG(LWARNING, ("Zero points should be put to", mwm, "to keep the distribution. Distribution fraction:", fraction,
|
||||
"totalMatchedPointNumberToKeepDistribution:", totalMatchedPointNumberToKeepDistribution));
|
||||
}
|
||||
}
|
||||
return matchedDataPointsToKeepDistribution;
|
||||
}
|
||||
|
||||
MwmToDataPoints BalancedDataPointNumber(MwmToDataPoints && matchedDataPoints,
|
||||
MwmToDataPoints && distribution,
|
||||
MwmToDataPoints BalancedDataPointNumber(MwmToDataPoints && matchedDataPoints, MwmToDataPoints && distribution,
|
||||
uint64_t ignoreDataPointsNumber)
|
||||
{
|
||||
// Removing every mwm from |distribution| and |matchedDataPoints| if it has
|
||||
@@ -188,7 +182,7 @@ void FilterTable(MwmToDataPoints const & balancedDataPointNumbers, vector<TableR
|
||||
auto it = balancedDataPointNumbers.find(mwmName);
|
||||
if (it == balancedDataPointNumbers.end())
|
||||
{
|
||||
mwmRecordsIndices.resize(0); // No indices.
|
||||
mwmRecordsIndices.resize(0); // No indices.
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -201,16 +195,13 @@ void FilterTable(MwmToDataPoints const & balancedDataPointNumbers, vector<TableR
|
||||
// Refilling |table| with part of its items to corresponds |balancedDataPointNumbers| distribution.
|
||||
vector<TableRow> balancedTable;
|
||||
for (auto const & kv : tableIdx)
|
||||
{
|
||||
for (auto const idx : kv.second)
|
||||
balancedTable.emplace_back(std::move(table[idx]));
|
||||
}
|
||||
table = std::move(balancedTable);
|
||||
}
|
||||
|
||||
void BalanceDataPoints(basic_istream<char> & tableCsvStream,
|
||||
basic_istream<char> & distributionCsvStream, uint64_t ignoreDataPointsNumber,
|
||||
vector<TableRow> & balancedTable)
|
||||
void BalanceDataPoints(basic_istream<char> & tableCsvStream, basic_istream<char> & distributionCsvStream,
|
||||
uint64_t ignoreDataPointsNumber, vector<TableRow> & balancedTable)
|
||||
{
|
||||
LOG(LINFO, ("Balancing data points..."));
|
||||
// Filling a map mwm to DataPoints number according to distribution csv file.
|
||||
@@ -232,15 +223,14 @@ void BalanceDataPoints(basic_istream<char> & tableCsvStream,
|
||||
|
||||
// Removing every mwm from |distribution| if there is no such mwm in |matchedDataPoints|.
|
||||
for (auto it = distribution.begin(); it != distribution.end();)
|
||||
{
|
||||
if (matchedDataPoints.count(it->first) == 0)
|
||||
it = distribution.erase(it);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
|
||||
CHECK(AreKeysEqual(distribution, matchedDataPoints),
|
||||
("Mwms in |distribution| and in |matchedDataPoints| should have the same set of keys.", distribution, matchedDataPoints));
|
||||
("Mwms in |distribution| and in |matchedDataPoints| should have the same set of keys.", distribution,
|
||||
matchedDataPoints));
|
||||
|
||||
// Calculating how many points should have every mwm to keep the |distribution|.
|
||||
MwmToDataPoints const balancedDataPointNumber =
|
||||
@@ -252,18 +242,15 @@ void BalanceDataPoints(basic_istream<char> & tableCsvStream,
|
||||
// Removing some items form |tableCsvStream| (if it's necessary) to correspond to
|
||||
// the distribution.
|
||||
FilterTable(balancedDataPointNumber, balancedTable);
|
||||
LOG(LINFO, ("Data points have balanced. Total distribution data points number:",
|
||||
totalDistributionDataPointsNumber,
|
||||
LOG(LINFO, ("Data points have balanced. Total distribution data points number:", totalDistributionDataPointsNumber,
|
||||
"Total matched data points number:", totalMatchedDataPointsNumber,
|
||||
"Total balanced data points number:", totalBalancedDataPointsNumber));
|
||||
}
|
||||
|
||||
void CmdBalanceCsv(string const & csvPath, string const & distributionPath,
|
||||
uint64_t ignoreDataPointsNumber)
|
||||
void CmdBalanceCsv(string const & csvPath, string const & distributionPath, uint64_t ignoreDataPointsNumber)
|
||||
{
|
||||
LOG(LINFO, ("Balancing csv file", csvPath, "with distribution set in", distributionPath,
|
||||
". If an mwm has", ignoreDataPointsNumber,
|
||||
"data points or less it will not be considered."));
|
||||
LOG(LINFO, ("Balancing csv file", csvPath, "with distribution set in", distributionPath, ". If an mwm has",
|
||||
ignoreDataPointsNumber, "data points or less it will not be considered."));
|
||||
ifstream table(csvPath);
|
||||
CHECK(table.is_open(), ("Cannot open", csvPath));
|
||||
ifstream distribution(distributionPath);
|
||||
|
||||
@@ -32,17 +32,17 @@ typename MapCont::mapped_type ValueSum(MapCont const & mapCont)
|
||||
}
|
||||
|
||||
/// \returns true if |map1| and |map2| have the same key and false otherwise.
|
||||
template<typename Map1, typename Map2>
|
||||
template <typename Map1, typename Map2>
|
||||
bool AreKeysEqual(Map1 const & map1, Map2 const & map2)
|
||||
{
|
||||
if (map1.size() != map2.size())
|
||||
{
|
||||
LOG(LINFO,
|
||||
("AreKeysEqual() returns false. map1.size():", map1.size(), "map2.size()", map2.size()));
|
||||
LOG(LINFO, ("AreKeysEqual() returns false. map1.size():", map1.size(), "map2.size()", map2.size()));
|
||||
return false;
|
||||
}
|
||||
|
||||
return std::equal(map1.begin(), map1.end(), map2.begin(), [](auto const & kv1, auto const & kv2) {
|
||||
return std::equal(map1.begin(), map1.end(), map2.begin(), [](auto const & kv1, auto const & kv2)
|
||||
{
|
||||
if (kv1.first == kv2.first)
|
||||
return true;
|
||||
|
||||
@@ -68,13 +68,11 @@ MwmToDataPointFraction GetMwmToDataPointFraction(MwmToDataPoints const & numberM
|
||||
/// * number of data points in the returned mapping is less than or equal to
|
||||
/// number of data points in |matchedDataPoints| for every mwm
|
||||
/// * distribution defined by |distributionFraction| is kept
|
||||
MwmToDataPoints CalcsMatchedDataPointsToKeepDistribution(
|
||||
MwmToDataPoints const & matchedDataPoints,
|
||||
MwmToDataPointFraction const & distributionFractions);
|
||||
MwmToDataPoints CalcsMatchedDataPointsToKeepDistribution(MwmToDataPoints const & matchedDataPoints,
|
||||
MwmToDataPointFraction const & distributionFractions);
|
||||
|
||||
/// \returns mapping with number of matched data points for every mwm to correspond to |distribution|.
|
||||
MwmToDataPoints BalancedDataPointNumber(MwmToDataPoints && matchedDataPoints,
|
||||
MwmToDataPoints && distribution,
|
||||
MwmToDataPoints BalancedDataPointNumber(MwmToDataPoints && matchedDataPoints, MwmToDataPoints && distribution,
|
||||
uint64_t ignoreDataPointsNumber);
|
||||
|
||||
/// \breif Leaves in |table| only number of items according to |balancedDataPointNumbers|.
|
||||
@@ -83,13 +81,11 @@ void FilterTable(MwmToDataPoints const & balancedDataPointNumbers, std::vector<T
|
||||
|
||||
/// \brief Fills |balancedTable| with TableRow(s) according to the distribution set in
|
||||
/// |distributionCsvStream|.
|
||||
void BalanceDataPoints(std::basic_istream<char> & tableCsvStream,
|
||||
std::basic_istream<char> & distributionCsvStream,
|
||||
void BalanceDataPoints(std::basic_istream<char> & tableCsvStream, std::basic_istream<char> & distributionCsvStream,
|
||||
uint64_t ignoreDataPointsNumber, std::vector<TableRow> & balancedTable);
|
||||
|
||||
/// \brief Removes some data point for every mwm from |csvPath| to correspond distribution
|
||||
/// set in |distributionPath|. If an mwm in |csvPath| contains data points less of equal to
|
||||
/// |ignoreDataPointsNumber| than the mwm will not be taken into acount while balancing.
|
||||
void CmdBalanceCsv(std::string const & csvPath, std::string const & distributionPath,
|
||||
uint64_t ignoreDataPointsNumber);
|
||||
void CmdBalanceCsv(std::string const & csvPath, std::string const & distributionPath, uint64_t ignoreDataPointsNumber);
|
||||
} // namespace track_analyzing
|
||||
|
||||
@@ -9,24 +9,19 @@ using namespace std;
|
||||
|
||||
namespace track_analyzing
|
||||
{
|
||||
void CmdCppTrack(string const & trackFile, string const & mwmName, string const & user,
|
||||
size_t trackIdx)
|
||||
void CmdCppTrack(string const & trackFile, string const & mwmName, string const & user, size_t trackIdx)
|
||||
{
|
||||
storage::Storage storage;
|
||||
auto const numMwmIds = CreateNumMwmIds(storage);
|
||||
MwmToMatchedTracks mwmToMatchedTracks;
|
||||
ReadTracks(numMwmIds, trackFile, mwmToMatchedTracks);
|
||||
|
||||
MatchedTrack const & track =
|
||||
GetMatchedTrack(mwmToMatchedTracks, *numMwmIds, mwmName, user, trackIdx);
|
||||
MatchedTrack const & track = GetMatchedTrack(mwmToMatchedTracks, *numMwmIds, mwmName, user, trackIdx);
|
||||
|
||||
auto const backupPrecision = cout.precision();
|
||||
cout.precision(8);
|
||||
for (MatchedTrackPoint const & point : track)
|
||||
{
|
||||
cout << " {" << point.GetDataPoint().m_latLon.m_lat << ", " << point.GetDataPoint().m_latLon.m_lon
|
||||
<< "}," << endl;
|
||||
}
|
||||
cout << " {" << point.GetDataPoint().m_latLon.m_lat << ", " << point.GetDataPoint().m_latLon.m_lon << "}," << endl;
|
||||
cout.precision(backupPrecision);
|
||||
}
|
||||
} // namespace track_analyzing
|
||||
|
||||
@@ -48,10 +48,7 @@ void CmdGPX(string const & logFile, string const & outputDirName, string const &
|
||||
ofs << "</metadata>\n";
|
||||
for (auto const & point : track.second)
|
||||
{
|
||||
ofs << "<wpt lat=\""
|
||||
<< point.m_latLon.m_lat
|
||||
<< "\" lon=\""
|
||||
<< point.m_latLon.m_lon << "\">"
|
||||
ofs << "<wpt lat=\"" << point.m_latLon.m_lat << "\" lon=\"" << point.m_latLon.m_lon << "\">"
|
||||
<< "</wpt>\n";
|
||||
}
|
||||
|
||||
|
||||
@@ -37,8 +37,8 @@ namespace
|
||||
{
|
||||
using Iter = typename vector<string>::iterator;
|
||||
|
||||
void MatchTracks(MwmToTracks const & mwmToTracks, storage::Storage const & storage,
|
||||
NumMwmIds const & numMwmIds, MwmToMatchedTracks & mwmToMatchedTracks)
|
||||
void MatchTracks(MwmToTracks const & mwmToTracks, storage::Storage const & storage, NumMwmIds const & numMwmIds,
|
||||
MwmToMatchedTracks & mwmToMatchedTracks)
|
||||
{
|
||||
base::Timer timer;
|
||||
|
||||
@@ -46,7 +46,8 @@ void MatchTracks(MwmToTracks const & mwmToTracks, storage::Storage const & stora
|
||||
uint64_t pointsCount = 0;
|
||||
uint64_t nonMatchedPointsCount = 0;
|
||||
|
||||
auto processMwm = [&](string const & mwmName, UserToTrack const & userToTrack) {
|
||||
auto processMwm = [&](string const & mwmName, UserToTrack const & userToTrack)
|
||||
{
|
||||
auto const countryFile = platform::CountryFile(mwmName);
|
||||
auto const mwmId = numMwmIds.GetId(countryFile);
|
||||
TrackMatcher matcher(storage, mwmId, countryFile);
|
||||
@@ -78,23 +79,22 @@ void MatchTracks(MwmToTracks const & mwmToTracks, storage::Storage const & stora
|
||||
pointsCount += matcher.GetPointsCount();
|
||||
nonMatchedPointsCount += matcher.GetNonMatchedPointsCount();
|
||||
|
||||
LOG(LINFO, (numMwmIds.GetFile(mwmId).GetName(), ", users:", userToTrack.size(), ", tracks:",
|
||||
matcher.GetTracksCount(), ", points:", matcher.GetPointsCount(),
|
||||
", non matched points:", matcher.GetNonMatchedPointsCount()));
|
||||
LOG(LINFO,
|
||||
(numMwmIds.GetFile(mwmId).GetName(), ", users:", userToTrack.size(), ", tracks:", matcher.GetTracksCount(),
|
||||
", points:", matcher.GetPointsCount(), ", non matched points:", matcher.GetNonMatchedPointsCount()));
|
||||
};
|
||||
|
||||
ForTracksSortedByMwmName(mwmToTracks, numMwmIds, processMwm);
|
||||
|
||||
LOG(LINFO,
|
||||
("Matching finished, elapsed:", timer.ElapsedSeconds(), "seconds, tracks:", tracksCount,
|
||||
", points:", pointsCount, ", non matched points:", nonMatchedPointsCount));
|
||||
LOG(LINFO, ("Matching finished, elapsed:", timer.ElapsedSeconds(), "seconds, tracks:", tracksCount,
|
||||
", points:", pointsCount, ", non matched points:", nonMatchedPointsCount));
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace track_analyzing
|
||||
{
|
||||
void CmdMatch(string const & logFile, string const & trackFile,
|
||||
shared_ptr<NumMwmIds> const & numMwmIds, Storage const & storage, Stats & stats)
|
||||
void CmdMatch(string const & logFile, string const & trackFile, shared_ptr<NumMwmIds> const & numMwmIds,
|
||||
Storage const & storage, Stats & stats)
|
||||
{
|
||||
MwmToTracks mwmToTracks;
|
||||
ParseTracks(logFile, numMwmIds, mwmToTracks);
|
||||
@@ -165,8 +165,7 @@ void UnzipAndMatch(Iter begin, Iter end, string const & trackExt, Stats & stats)
|
||||
|
||||
void CmdMatchDir(string const & logDir, string const & trackExt, string const & inputDistribution)
|
||||
{
|
||||
LOG(LINFO,
|
||||
("Matching dir:", logDir, ". Input distribution will be saved to:", inputDistribution));
|
||||
LOG(LINFO, ("Matching dir:", logDir, ". Input distribution will be saved to:", inputDistribution));
|
||||
Platform::EFileType fileType = Platform::EFileType::Unknown;
|
||||
Platform::EError const result = Platform::GetFileType(logDir, fileType);
|
||||
|
||||
|
||||
@@ -69,11 +69,9 @@ bool DayTimeToBool(DayTimeType type)
|
||||
switch (type)
|
||||
{
|
||||
case DayTimeType::Day:
|
||||
case DayTimeType::PolarDay:
|
||||
return true;
|
||||
case DayTimeType::PolarDay: return true;
|
||||
case DayTimeType::Night:
|
||||
case DayTimeType::PolarNight:
|
||||
return false;
|
||||
case DayTimeType::PolarNight: return false;
|
||||
}
|
||||
|
||||
UNREACHABLE();
|
||||
@@ -100,15 +98,9 @@ public:
|
||||
return tie(m_hwType, m_surfaceType) < tie(rhs.m_hwType, rhs.m_surfaceType);
|
||||
}
|
||||
|
||||
bool operator==(Type const & rhs) const
|
||||
{
|
||||
return tie(m_hwType, m_surfaceType) == tie(rhs.m_hwType, m_surfaceType);
|
||||
}
|
||||
bool operator==(Type const & rhs) const { return tie(m_hwType, m_surfaceType) == tie(rhs.m_hwType, m_surfaceType); }
|
||||
|
||||
bool operator!=(Type const & rhs) const
|
||||
{
|
||||
return !(*this == rhs);
|
||||
}
|
||||
bool operator!=(Type const & rhs) const { return !(*this == rhs); }
|
||||
|
||||
string GetSummary() const
|
||||
{
|
||||
@@ -158,10 +150,7 @@ struct RoadInfo
|
||||
tie(rhs.m_type, rhs.m_maxspeedKMpH, rhs.m_isCityRoad, rhs.m_isOneWay);
|
||||
}
|
||||
|
||||
bool operator!=(RoadInfo const & rhs) const
|
||||
{
|
||||
return !(*this == rhs);
|
||||
}
|
||||
bool operator!=(RoadInfo const & rhs) const { return !(*this == rhs); }
|
||||
|
||||
bool operator<(RoadInfo const & rhs) const
|
||||
{
|
||||
@@ -172,11 +161,8 @@ struct RoadInfo
|
||||
string GetSummary() const
|
||||
{
|
||||
ostringstream out;
|
||||
out << TypeToString(m_type.m_hwType) << ","
|
||||
<< TypeToString(m_type.m_surfaceType) << ","
|
||||
<< m_maxspeedKMpH << ","
|
||||
<< m_isCityRoad << ","
|
||||
<< m_isOneWay;
|
||||
out << TypeToString(m_type.m_hwType) << "," << TypeToString(m_type.m_surfaceType) << "," << m_maxspeedKMpH << ","
|
||||
<< m_isCityRoad << "," << m_isOneWay;
|
||||
|
||||
return out.str();
|
||||
}
|
||||
@@ -193,7 +179,9 @@ public:
|
||||
MoveType() = default;
|
||||
|
||||
MoveType(RoadInfo const & roadType, traffic::SpeedGroup speedGroup, DataPoint const & dataPoint)
|
||||
: m_roadInfo(roadType), m_speedGroup(speedGroup), m_latLon(dataPoint.m_latLon)
|
||||
: m_roadInfo(roadType)
|
||||
, m_speedGroup(speedGroup)
|
||||
, m_latLon(dataPoint.m_latLon)
|
||||
{
|
||||
m_isDayTime = DayTimeToBool(GetDayTime(dataPoint.m_timestamp, m_latLon.m_lat, m_latLon.m_lon));
|
||||
}
|
||||
@@ -213,17 +201,14 @@ public:
|
||||
bool IsValid() const
|
||||
{
|
||||
// In order to collect cleaner data we don't use speed group lower than G5.
|
||||
return m_roadInfo.m_type.m_hwType != 0 &&
|
||||
m_roadInfo.m_type.m_surfaceType != 0 &&
|
||||
return m_roadInfo.m_type.m_hwType != 0 && m_roadInfo.m_type.m_surfaceType != 0 &&
|
||||
m_speedGroup == kValidTrafficValue;
|
||||
}
|
||||
|
||||
string GetSummary() const
|
||||
{
|
||||
ostringstream out;
|
||||
out << m_roadInfo.GetSummary() << ","
|
||||
<< m_isDayTime << ","
|
||||
<< m_latLon.m_lat << " " << m_latLon.m_lon;
|
||||
out << m_roadInfo.GetSummary() << "," << m_isDayTime << "," << m_latLon.m_lat << " " << m_latLon.m_lon;
|
||||
|
||||
return out.str();
|
||||
}
|
||||
@@ -250,9 +235,7 @@ public:
|
||||
string GetSummary() const
|
||||
{
|
||||
ostringstream out;
|
||||
out << m_totalDistance << ","
|
||||
<< m_totalTime << ","
|
||||
<< CalcSpeedKMpH(m_totalDistance, m_totalTime) << ",";
|
||||
out << m_totalDistance << "," << m_totalTime << "," << CalcSpeedKMpH(m_totalDistance, m_totalTime) << ",";
|
||||
|
||||
for (size_t i = 0; i < m_crossroads.size(); ++i)
|
||||
{
|
||||
@@ -276,8 +259,8 @@ private:
|
||||
class MoveTypeAggregator final
|
||||
{
|
||||
public:
|
||||
void Add(MoveType && moveType, IsCrossroadChecker::CrossroadInfo const & crossroads, MatchedTrack::const_iterator begin,
|
||||
MatchedTrack::const_iterator end, Geometry & geometry)
|
||||
void Add(MoveType && moveType, IsCrossroadChecker::CrossroadInfo const & crossroads,
|
||||
MatchedTrack::const_iterator begin, MatchedTrack::const_iterator end, Geometry & geometry)
|
||||
{
|
||||
if (begin + 1 >= end)
|
||||
return;
|
||||
@@ -288,9 +271,9 @@ public:
|
||||
|
||||
if (time == 0)
|
||||
{
|
||||
LOG(LWARNING, ("Track with the same time at the beginning and at the end. Beginning:",
|
||||
beginDataPoint.m_latLon, " End:", endDataPoint.m_latLon,
|
||||
" Timestamp:", beginDataPoint.m_timestamp, " Segment:", begin->GetSegment()));
|
||||
LOG(LWARNING, ("Track with the same time at the beginning and at the end. Beginning:", beginDataPoint.m_latLon,
|
||||
" End:", endDataPoint.m_latLon, " Timestamp:", beginDataPoint.m_timestamp,
|
||||
" Segment:", begin->GetSegment()));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -298,8 +281,7 @@ public:
|
||||
m_moveInfos[moveType].Add(length, time, crossroads, static_cast<uint32_t>(distance(begin, end)));
|
||||
}
|
||||
|
||||
string GetSummary(string const & user, string const & mwmName, string const & countryName,
|
||||
Stats & stats) const
|
||||
string GetSummary(string const & user, string const & mwmName, string const & countryName, Stats & stats) const
|
||||
{
|
||||
ostringstream out;
|
||||
for (auto const & it : m_moveInfos)
|
||||
@@ -307,8 +289,7 @@ public:
|
||||
if (!it.first.IsValid())
|
||||
continue;
|
||||
|
||||
out << user << "," << mwmName << "," << it.first.GetSummary() << ","
|
||||
<< it.second.GetSummary() << '\n';
|
||||
out << user << "," << mwmName << "," << it.first.GetSummary() << "," << it.second.GetSummary() << '\n';
|
||||
|
||||
stats.AddDataPoints(mwmName, countryName, it.second.GetDataPointsNumber());
|
||||
}
|
||||
@@ -324,7 +305,8 @@ class MatchedTrackPointToMoveType final
|
||||
{
|
||||
public:
|
||||
MatchedTrackPointToMoveType(FilesContainerR const & container, VehicleModelInterface & vehicleModel)
|
||||
: m_featuresVector(container), m_vehicleModel(vehicleModel)
|
||||
: m_featuresVector(container)
|
||||
, m_vehicleModel(vehicleModel)
|
||||
{
|
||||
if (container.IsExist(CITY_ROADS_FILE_TAG))
|
||||
m_cityRoads.Load(container.GetReader(CITY_ROADS_FILE_TAG));
|
||||
@@ -336,9 +318,7 @@ public:
|
||||
MoveType GetMoveType(MatchedTrackPoint const & point)
|
||||
{
|
||||
auto const & dataPoint = point.GetDataPoint();
|
||||
return MoveType(GetRoadInfo(point.GetSegment()),
|
||||
static_cast<traffic::SpeedGroup>(dataPoint.m_traffic),
|
||||
dataPoint);
|
||||
return MoveType(GetRoadInfo(point.GetSegment()), static_cast<traffic::SpeedGroup>(dataPoint.m_traffic), dataPoint);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -352,15 +332,14 @@ private:
|
||||
CHECK(feature, ());
|
||||
|
||||
auto const maxspeed = m_maxspeeds.GetMaxspeed(featureId);
|
||||
auto const maxspeedValueKMpH = maxspeed.IsValid() ?
|
||||
min(maxspeed.GetSpeedKmPH(segment.IsForward()), kMaxspeedTopBound) :
|
||||
kInvalidSpeed;
|
||||
auto const maxspeedValueKMpH =
|
||||
maxspeed.IsValid() ? min(maxspeed.GetSpeedKmPH(segment.IsForward()), kMaxspeedTopBound) : kInvalidSpeed;
|
||||
|
||||
m_prevFeatureId = featureId;
|
||||
|
||||
feature::TypesHolder const types(*feature);
|
||||
m_prevRoadInfo = {m_carModelTypes.GetType(types), maxspeedValueKMpH,
|
||||
m_cityRoads.IsCityRoad(featureId), m_vehicleModel.IsOneWay(types)};
|
||||
m_prevRoadInfo = {m_carModelTypes.GetType(types), maxspeedValueKMpH, m_cityRoads.IsCityRoad(featureId),
|
||||
m_vehicleModel.IsOneWay(types)};
|
||||
return m_prevRoadInfo;
|
||||
}
|
||||
|
||||
@@ -374,7 +353,6 @@ private:
|
||||
};
|
||||
} // namespace
|
||||
|
||||
|
||||
void CmdTagsTable(string const & filepath, string const & trackExtension, StringFilter mwmFilter,
|
||||
StringFilter userFilter)
|
||||
{
|
||||
@@ -393,18 +371,17 @@ void CmdTagsTable(string const & filepath, string const & trackExtension, String
|
||||
|
||||
auto const countryName = storage.GetTopmostParentFor(mwmName);
|
||||
auto const carModelFactory = make_shared<CarModelFactory>(VehicleModelFactory::CountryParentNameGetterFn{});
|
||||
shared_ptr<VehicleModelInterface> vehicleModel =
|
||||
carModelFactory->GetVehicleModelForCountry(mwmName);
|
||||
shared_ptr<VehicleModelInterface> vehicleModel = carModelFactory->GetVehicleModelForCountry(mwmName);
|
||||
string const mwmFile = GetCurrentVersionMwmFile(storage, mwmName);
|
||||
MatchedTrackPointToMoveType pointToMoveType(FilesContainerR(make_unique<FileReader>(mwmFile)), *vehicleModel);
|
||||
Geometry geometry(GeometryLoader::CreateFromFile(mwmFile, vehicleModel));
|
||||
auto const vehicleType = VehicleType::Car;
|
||||
auto const edgeEstimator = EdgeEstimator::Create(vehicleType, *vehicleModel,
|
||||
nullptr /* trafficStash */, &dataSource, numMwmIds);
|
||||
auto const edgeEstimator =
|
||||
EdgeEstimator::Create(vehicleType, *vehicleModel, nullptr /* trafficStash */, &dataSource, numMwmIds);
|
||||
|
||||
MwmDataSource routingSource(dataSource, numMwmIds);
|
||||
auto indexGraphLoader = IndexGraphLoader::Create(vehicleType, false /* loadAltitudes */,
|
||||
carModelFactory, edgeEstimator, routingSource);
|
||||
auto indexGraphLoader =
|
||||
IndexGraphLoader::Create(vehicleType, false /* loadAltitudes */, carModelFactory, edgeEstimator, routingSource);
|
||||
|
||||
platform::CountryFile const countryFile(mwmName);
|
||||
auto localCountryFile = storage.GetLatestLocalFile(countryFile);
|
||||
@@ -412,8 +389,7 @@ void CmdTagsTable(string const & filepath, string const & trackExtension, String
|
||||
if (!dataSource.IsLoaded(countryFile))
|
||||
{
|
||||
auto registerResult = dataSource.Register(*localCountryFile);
|
||||
CHECK_EQUAL(registerResult.second, MwmSet::RegResult::Success,
|
||||
("Can't register mwm", countryFile.GetName()));
|
||||
CHECK_EQUAL(registerResult.second, MwmSet::RegResult::Success, ("Can't register mwm", countryFile.GetName()));
|
||||
}
|
||||
|
||||
auto const mwmId = numMwmIds->GetId(countryFile);
|
||||
@@ -440,18 +416,14 @@ void CmdTagsTable(string const & filepath, string const & trackExtension, String
|
||||
// Splitting track with points where MoveType is changed.
|
||||
while (end != track.end() && pointToMoveType.GetMoveType(*end) == moveType)
|
||||
{
|
||||
IsCrossroadChecker::MergeCrossroads(checker(prev->GetSegment(), end->GetSegment()),
|
||||
info);
|
||||
IsCrossroadChecker::MergeCrossroads(checker(prev->GetSegment(), end->GetSegment()), info);
|
||||
prev = end;
|
||||
++end;
|
||||
}
|
||||
|
||||
// If it's not the end of the track than it could be a crossroad.
|
||||
if (end != track.end())
|
||||
{
|
||||
IsCrossroadChecker::MergeCrossroads(checker(prev->GetSegment(), end->GetSegment()),
|
||||
info);
|
||||
}
|
||||
IsCrossroadChecker::MergeCrossroads(checker(prev->GetSegment(), end->GetSegment()), info);
|
||||
|
||||
aggregator.Add(std::move(moveType), info, subtrackBegin, end, geometry);
|
||||
subtrackBegin = end;
|
||||
|
||||
@@ -23,28 +23,24 @@ using namespace std;
|
||||
|
||||
namespace track_analyzing
|
||||
{
|
||||
void CmdTrack(string const & trackFile, string const & mwmName, string const & user,
|
||||
size_t trackIdx)
|
||||
void CmdTrack(string const & trackFile, string const & mwmName, string const & user, size_t trackIdx)
|
||||
{
|
||||
storage::Storage storage;
|
||||
auto const numMwmIds = CreateNumMwmIds(storage);
|
||||
MwmToMatchedTracks mwmToMatchedTracks;
|
||||
ReadTracks(numMwmIds, trackFile, mwmToMatchedTracks);
|
||||
|
||||
MatchedTrack const & track =
|
||||
GetMatchedTrack(mwmToMatchedTracks, *numMwmIds, mwmName, user, trackIdx);
|
||||
MatchedTrack const & track = GetMatchedTrack(mwmToMatchedTracks, *numMwmIds, mwmName, user, trackIdx);
|
||||
|
||||
string const mwmFile = GetCurrentVersionMwmFile(storage, mwmName);
|
||||
shared_ptr<VehicleModelInterface> vehicleModel =
|
||||
CarModelFactory({}).GetVehicleModelForCountry(mwmName);
|
||||
shared_ptr<VehicleModelInterface> vehicleModel = CarModelFactory({}).GetVehicleModelForCountry(mwmName);
|
||||
Geometry geometry(GeometryLoader::CreateFromFile(mwmFile, vehicleModel));
|
||||
|
||||
uint64_t const duration =
|
||||
track.back().GetDataPoint().m_timestamp - track.front().GetDataPoint().m_timestamp;
|
||||
uint64_t const duration = track.back().GetDataPoint().m_timestamp - track.front().GetDataPoint().m_timestamp;
|
||||
double const length = CalcTrackLength(track, geometry);
|
||||
double const averageSpeed = CalcSpeedKMpH(length, duration);
|
||||
LOG(LINFO, ("Mwm:", mwmName, ", user:", user, ", points:", track.size(), "duration:", duration,
|
||||
"length:", length, ", speed:", averageSpeed, "km/h"));
|
||||
LOG(LINFO, ("Mwm:", mwmName, ", user:", user, ", points:", track.size(), "duration:", duration, "length:", length,
|
||||
", speed:", averageSpeed, "km/h"));
|
||||
|
||||
for (size_t i = 0; i < track.size(); ++i)
|
||||
{
|
||||
@@ -64,10 +60,9 @@ void CmdTrack(string const & trackFile, string const & mwmName, string const & u
|
||||
if (elapsed != 0)
|
||||
speed = CalcSpeedKMpH(distance, elapsed);
|
||||
|
||||
LOG(LINFO, (base::SecondsSinceEpochToString(point.GetDataPoint().m_timestamp),
|
||||
point.GetDataPoint().m_latLon, point.GetSegment(), ", traffic:",
|
||||
point.GetDataPoint().m_traffic, ", distance:", distance, ", elapsed:", elapsed,
|
||||
", speed:", speed));
|
||||
LOG(LINFO, (base::SecondsSinceEpochToString(point.GetDataPoint().m_timestamp), point.GetDataPoint().m_latLon,
|
||||
point.GetSegment(), ", traffic:", point.GetDataPoint().m_traffic, ", distance:", distance,
|
||||
", elapsed:", elapsed, ", speed:", speed));
|
||||
}
|
||||
}
|
||||
} // namespace track_analyzing
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
|
||||
namespace track_analyzing
|
||||
{
|
||||
using namespace routing;
|
||||
@@ -105,8 +104,7 @@ bool TrackHasTrafficPoints(MatchedTrack const & track)
|
||||
return false;
|
||||
}
|
||||
|
||||
double EstimateDuration(MatchedTrack const & track, shared_ptr<EdgeEstimator> estimator,
|
||||
Geometry & geometry)
|
||||
double EstimateDuration(MatchedTrack const & track, shared_ptr<EdgeEstimator> estimator, Geometry & geometry)
|
||||
{
|
||||
double result = 0.0;
|
||||
Segment segment;
|
||||
@@ -117,16 +115,15 @@ double EstimateDuration(MatchedTrack const & track, shared_ptr<EdgeEstimator> es
|
||||
continue;
|
||||
|
||||
segment = point.GetSegment();
|
||||
result += estimator->CalcSegmentWeight(segment, geometry.GetRoad(segment.GetFeatureId()),
|
||||
EdgeEstimator::Purpose::ETA);
|
||||
result +=
|
||||
estimator->CalcSegmentWeight(segment, geometry.GetRoad(segment.GetFeatureId()), EdgeEstimator::Purpose::ETA);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void CmdTracks(string const & filepath, string const & trackExtension, StringFilter mwmFilter,
|
||||
StringFilter userFilter, TrackFilter const & filter, bool noTrackLogs,
|
||||
bool noMwmLogs, bool noWorldLogs)
|
||||
void CmdTracks(string const & filepath, string const & trackExtension, StringFilter mwmFilter, StringFilter userFilter,
|
||||
TrackFilter const & filter, bool noTrackLogs, bool noMwmLogs, bool noWorldLogs)
|
||||
{
|
||||
storage::Storage storage;
|
||||
auto numMwmIds = CreateNumMwmIds(storage);
|
||||
@@ -135,21 +132,19 @@ void CmdTracks(string const & filepath, string const & trackExtension, StringFil
|
||||
ErrorStat absoluteError;
|
||||
ErrorStat relativeError;
|
||||
|
||||
auto processMwm = [&](string const & mwmName, UserToMatchedTracks const & userToMatchedTracks) {
|
||||
auto processMwm = [&](string const & mwmName, UserToMatchedTracks const & userToMatchedTracks)
|
||||
{
|
||||
if (mwmFilter(mwmName))
|
||||
return;
|
||||
|
||||
TrackStats & mwmStats = mwmToStats[mwmName];
|
||||
|
||||
shared_ptr<VehicleModelInterface> vehicleModel =
|
||||
CarModelFactory({}).GetVehicleModelForCountry(mwmName);
|
||||
shared_ptr<VehicleModelInterface> vehicleModel = CarModelFactory({}).GetVehicleModelForCountry(mwmName);
|
||||
|
||||
Geometry geometry(
|
||||
GeometryLoader::CreateFromFile(GetCurrentVersionMwmFile(storage, mwmName), vehicleModel));
|
||||
Geometry geometry(GeometryLoader::CreateFromFile(GetCurrentVersionMwmFile(storage, mwmName), vehicleModel));
|
||||
|
||||
shared_ptr<EdgeEstimator> estimator =
|
||||
EdgeEstimator::Create(VehicleType::Car, *vehicleModel,
|
||||
nullptr /* trafficStash */, nullptr /* dataSource */, nullptr /* numMwmIds */);
|
||||
shared_ptr<EdgeEstimator> estimator = EdgeEstimator::Create(
|
||||
VehicleType::Car, *vehicleModel, nullptr /* trafficStash */, nullptr /* dataSource */, nullptr /* numMwmIds */);
|
||||
|
||||
for (auto const & it : userToMatchedTracks)
|
||||
{
|
||||
@@ -181,13 +176,13 @@ void CmdTracks(string const & filepath, string const & trackExtension, StringFil
|
||||
if (!noTrackLogs)
|
||||
{
|
||||
cout << fixed << setprecision(1) << " points: " << track.size() << ", length: " << length
|
||||
<< ", duration: " << duration << ", estimated duration: " << estimatedDuration
|
||||
<< ", speed: " << speed << ", traffic: " << hasTrafficPoints
|
||||
<< ", duration: " << duration << ", estimated duration: " << estimatedDuration << ", speed: " << speed
|
||||
<< ", traffic: " << hasTrafficPoints
|
||||
<< ", departure: " << base::SecondsSinceEpochToString(start.m_timestamp)
|
||||
<< ", arrival: " << base::SecondsSinceEpochToString(finish.m_timestamp)
|
||||
<< setprecision(numeric_limits<double>::max_digits10)
|
||||
<< ", start: " << start.m_latLon.m_lat << ", " << start.m_latLon.m_lon
|
||||
<< ", finish: " << finish.m_latLon.m_lat << ", " << finish.m_latLon.m_lon << endl;
|
||||
<< setprecision(numeric_limits<double>::max_digits10) << ", start: " << start.m_latLon.m_lat << ", "
|
||||
<< start.m_latLon.m_lon << ", finish: " << finish.m_latLon.m_lat << ", " << finish.m_latLon.m_lon
|
||||
<< endl;
|
||||
}
|
||||
|
||||
mwmStats.AddTracks(1);
|
||||
@@ -202,7 +197,8 @@ void CmdTracks(string const & filepath, string const & trackExtension, StringFil
|
||||
}
|
||||
};
|
||||
|
||||
auto processFile = [&](string const & filename, MwmToMatchedTracks const & mwmToMatchedTracks) {
|
||||
auto processFile = [&](string const & filename, MwmToMatchedTracks const & mwmToMatchedTracks)
|
||||
{
|
||||
LOG(LINFO, ("Processing", filename));
|
||||
ForTracksSortedByMwmName(mwmToMatchedTracks, *numMwmIds, processMwm);
|
||||
};
|
||||
@@ -213,10 +209,8 @@ void CmdTracks(string const & filepath, string const & trackExtension, StringFil
|
||||
{
|
||||
cout << endl;
|
||||
for (auto const & it : mwmToStats)
|
||||
{
|
||||
if (!it.second.IsEmpty())
|
||||
cout << it.first << ": " << it.second.GetSummary() << endl;
|
||||
}
|
||||
}
|
||||
|
||||
if (!noWorldLogs)
|
||||
@@ -226,11 +220,9 @@ void CmdTracks(string const & filepath, string const & trackExtension, StringFil
|
||||
worldStats.Add(it.second);
|
||||
|
||||
cout << endl << "World: " << worldStats.GetSummary() << endl;
|
||||
cout << fixed << setprecision(1)
|
||||
<< "Absolute error: deviation: " << absoluteError.GetStdDevString()
|
||||
cout << fixed << setprecision(1) << "Absolute error: deviation: " << absoluteError.GetStdDevString()
|
||||
<< ", min: " << absoluteError.GetMin() << ", max: " << absoluteError.GetMax() << endl;
|
||||
cout << fixed << setprecision(3)
|
||||
<< "Relative error: deviation: " << relativeError.GetStdDevString()
|
||||
cout << fixed << setprecision(3) << "Relative error: deviation: " << relativeError.GetStdDevString()
|
||||
<< ", min: " << relativeError.GetMin() << ", max: " << relativeError.GetMax() << endl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,10 +23,8 @@ bool IsHighwayLink(HighwayType type)
|
||||
case HighwayType::HighwayTrunkLink:
|
||||
case HighwayType::HighwayPrimaryLink:
|
||||
case HighwayType::HighwaySecondaryLink:
|
||||
case HighwayType::HighwayTertiaryLink:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
case HighwayType::HighwayTertiaryLink: return true;
|
||||
default: return false;
|
||||
}
|
||||
|
||||
UNREACHABLE();
|
||||
@@ -40,10 +38,8 @@ bool IsBigHighway(HighwayType type)
|
||||
case HighwayType::HighwayTrunk:
|
||||
case HighwayType::HighwayPrimary:
|
||||
case HighwayType::HighwaySecondary:
|
||||
case HighwayType::HighwayTertiary:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
case HighwayType::HighwayTertiary: return true;
|
||||
default: return false;
|
||||
}
|
||||
|
||||
UNREACHABLE();
|
||||
@@ -54,12 +50,8 @@ bool FromSmallerToBigger(HighwayType lhs, HighwayType rhs)
|
||||
CHECK_NOT_EQUAL(lhs, rhs, ());
|
||||
|
||||
static std::array<HighwayType, 5> constexpr kHighwayTypes = {
|
||||
HighwayType::HighwayTertiary,
|
||||
HighwayType::HighwaySecondary,
|
||||
HighwayType::HighwayPrimary,
|
||||
HighwayType::HighwayTrunk,
|
||||
HighwayType::HighwayMotorway
|
||||
};
|
||||
HighwayType::HighwayTertiary, HighwayType::HighwaySecondary, HighwayType::HighwayPrimary,
|
||||
HighwayType::HighwayTrunk, HighwayType::HighwayMotorway};
|
||||
|
||||
auto const lhsIt = find(kHighwayTypes.begin(), kHighwayTypes.end(), lhs);
|
||||
auto const rhsIt = find(kHighwayTypes.begin(), kHighwayTypes.end(), rhs);
|
||||
@@ -112,7 +104,8 @@ IsCrossroadChecker::Type IsCrossroadChecker::operator()(Segment const & current,
|
||||
|
||||
Type retType = Type::Count;
|
||||
auto const nextRoadPoint = next.GetRoadPoint(false /* isFront */);
|
||||
m_indexGraph.ForEachPoint(jointId, [&](RoadPoint const & point) {
|
||||
m_indexGraph.ForEachPoint(jointId, [&](RoadPoint const & point)
|
||||
{
|
||||
if (retType != IsCrossroadChecker::Type::Count)
|
||||
return;
|
||||
|
||||
@@ -129,11 +122,8 @@ IsCrossroadChecker::Type IsCrossroadChecker::operator()(Segment const & current,
|
||||
if (pointHwType == nextSegmentHwType)
|
||||
{
|
||||
// Is the same road but parted on different features.
|
||||
if (roadGeometry.IsEndPointId(point.GetPointId()) &&
|
||||
roadGeometry.IsEndPointId(nextRoadPoint.GetPointId()))
|
||||
{
|
||||
if (roadGeometry.IsEndPointId(point.GetPointId()) && roadGeometry.IsEndPointId(nextRoadPoint.GetPointId()))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (isCurrentLink && IsBigHighway(*pointHwType))
|
||||
|
||||
@@ -30,8 +30,7 @@ public:
|
||||
Type operator()(Segment const & current, Segment const & next) const;
|
||||
|
||||
static void MergeCrossroads(Type from, CrossroadInfo & to);
|
||||
static void MergeCrossroads(IsCrossroadChecker::CrossroadInfo const & from,
|
||||
IsCrossroadChecker::CrossroadInfo & to);
|
||||
static void MergeCrossroads(IsCrossroadChecker::CrossroadInfo const & from, IsCrossroadChecker::CrossroadInfo & to);
|
||||
|
||||
private:
|
||||
IndexGraph & m_indexGraph;
|
||||
|
||||
@@ -51,19 +51,17 @@ DEFINE_string_ext(output_dir, "", "output dir for gpx files");
|
||||
DEFINE_string_ext(mwm, "", "short mwm name");
|
||||
DEFINE_string_ext(user, "", "user id");
|
||||
DEFINE_int32(track, -1, "track index");
|
||||
DEFINE_string(
|
||||
input_distribution, "",
|
||||
"path to input data point distribution file. It's a csv file with data point count for "
|
||||
"some mwms. Usage:\n"
|
||||
"- It may be used with match and match_dir command. If so it's a path to save file with "
|
||||
"data point distribution by mwm. If it's empty no file is saved.\n"
|
||||
"- It may be used with balance_csv command. If so it's a path of a file with distribution which "
|
||||
"will be used for normalization (balancing) the result of the command. It should not be empty.");
|
||||
DEFINE_uint64(
|
||||
ignore_datapoints_number, 100,
|
||||
"The number of datapoints in an mwm to exclude the mwm from balancing process. If this number "
|
||||
"of datapoints or less number is in an mwm after matching and tabling, the mwm will not used "
|
||||
"for balancing. This param should be used with balance_csv command.");
|
||||
DEFINE_string(input_distribution, "",
|
||||
"path to input data point distribution file. It's a csv file with data point count for "
|
||||
"some mwms. Usage:\n"
|
||||
"- It may be used with match and match_dir command. If so it's a path to save file with "
|
||||
"data point distribution by mwm. If it's empty no file is saved.\n"
|
||||
"- It may be used with balance_csv command. If so it's a path of a file with distribution which "
|
||||
"will be used for normalization (balancing) the result of the command. It should not be empty.");
|
||||
DEFINE_uint64(ignore_datapoints_number, 100,
|
||||
"The number of datapoints in an mwm to exclude the mwm from balancing process. If this number "
|
||||
"of datapoints or less number is in an mwm after matching and tabling, the mwm will not used "
|
||||
"for balancing. This param should be used with balance_csv command.");
|
||||
|
||||
DEFINE_string(track_extension, ".track", "track files extension");
|
||||
DEFINE_bool(no_world_logs, false, "don't print world summary logs");
|
||||
@@ -86,7 +84,8 @@ size_t Checked_track()
|
||||
|
||||
StringFilter MakeFilter(string const & filter)
|
||||
{
|
||||
return [&](string const & value) {
|
||||
return [&](string const & value)
|
||||
{
|
||||
if (filter.empty())
|
||||
return false;
|
||||
return value != filter;
|
||||
@@ -97,8 +96,7 @@ StringFilter MakeFilter(string const & filter)
|
||||
namespace track_analyzing
|
||||
{
|
||||
// Print the specified track in C++ form that you can copy paste to C++ source for debugging.
|
||||
void CmdCppTrack(string const & trackFile, string const & mwmName, string const & user,
|
||||
size_t trackIdx);
|
||||
void CmdCppTrack(string const & trackFile, string const & mwmName, string const & user, size_t trackIdx);
|
||||
// Match raw gps logs to tracks.
|
||||
void CmdMatch(string const & logFile, string const & trackFile, string const & inputDistribution);
|
||||
// The same as match but applies for the directory with raw logs.
|
||||
@@ -106,15 +104,13 @@ void CmdMatchDir(string const & logDir, string const & trackExt, string const &
|
||||
// Parse |logFile| and save tracks (mwm name, aloha id, lats, lons, timestamps in seconds in csv).
|
||||
void CmdUnmatchedTracks(string const & logFile, string const & trackFileCsv);
|
||||
// Print aggregated tracks to csv table.
|
||||
void CmdTagsTable(string const & filepath, string const & trackExtension,
|
||||
StringFilter mwmIsFiltered, StringFilter userFilter);
|
||||
void CmdTagsTable(string const & filepath, string const & trackExtension, StringFilter mwmIsFiltered,
|
||||
StringFilter userFilter);
|
||||
// Print track information.
|
||||
void CmdTrack(string const & trackFile, string const & mwmName, string const & user,
|
||||
size_t trackIdx);
|
||||
void CmdTrack(string const & trackFile, string const & mwmName, string const & user, size_t trackIdx);
|
||||
// Print tracks statistics.
|
||||
void CmdTracks(string const & filepath, string const & trackExtension, StringFilter mwmFilter,
|
||||
StringFilter userFilter, TrackFilter const & filter, bool noTrackLogs,
|
||||
bool noMwmLogs, bool noWorldLogs);
|
||||
void CmdTracks(string const & filepath, string const & trackExtension, StringFilter mwmFilter, StringFilter userFilter,
|
||||
TrackFilter const & filter, bool noTrackLogs, bool noMwmLogs, bool noWorldLogs);
|
||||
|
||||
void CmdGPX(string const & logFile, string const & outputFilesDir, string const & userID);
|
||||
} // namespace track_analyzing
|
||||
@@ -145,10 +141,10 @@ int main(int argc, char ** argv)
|
||||
}
|
||||
else if (cmd == "tracks")
|
||||
{
|
||||
TrackFilter const filter(FLAGS_min_duration, FLAGS_min_length, FLAGS_min_speed,
|
||||
FLAGS_max_speed, FLAGS_ignore_traffic);
|
||||
CmdTracks(Checked_in(), FLAGS_track_extension, MakeFilter(FLAGS_mwm), MakeFilter(FLAGS_user),
|
||||
filter, FLAGS_no_track_logs, FLAGS_no_mwm_logs, FLAGS_no_world_logs);
|
||||
TrackFilter const filter(FLAGS_min_duration, FLAGS_min_length, FLAGS_min_speed, FLAGS_max_speed,
|
||||
FLAGS_ignore_traffic);
|
||||
CmdTracks(Checked_in(), FLAGS_track_extension, MakeFilter(FLAGS_mwm), MakeFilter(FLAGS_user), filter,
|
||||
FLAGS_no_track_logs, FLAGS_no_mwm_logs, FLAGS_no_world_logs);
|
||||
}
|
||||
else if (cmd == "track")
|
||||
{
|
||||
@@ -160,8 +156,7 @@ int main(int argc, char ** argv)
|
||||
}
|
||||
else if (cmd == "table")
|
||||
{
|
||||
CmdTagsTable(Checked_in(), FLAGS_track_extension, MakeFilter(FLAGS_mwm),
|
||||
MakeFilter(FLAGS_user));
|
||||
CmdTagsTable(Checked_in(), FLAGS_track_extension, MakeFilter(FLAGS_mwm), MakeFilter(FLAGS_user));
|
||||
}
|
||||
else if (cmd == "balance_csv")
|
||||
{
|
||||
@@ -171,8 +166,7 @@ int main(int argc, char ** argv)
|
||||
"distribution. Hint: this file may be saved by match or match_dir command."));
|
||||
return 1;
|
||||
}
|
||||
CmdBalanceCsv(FLAGS_in, FLAGS_input_distribution,
|
||||
base::checked_cast<uint64_t>(FLAGS_ignore_datapoints_number));
|
||||
CmdBalanceCsv(FLAGS_in, FLAGS_input_distribution, base::checked_cast<uint64_t>(FLAGS_ignore_datapoints_number));
|
||||
}
|
||||
else if (cmd == "gpx")
|
||||
{
|
||||
|
||||
@@ -31,8 +31,7 @@ namespace
|
||||
set<string> GetKeys(Stats::NameToCountMapping const & mapping)
|
||||
{
|
||||
set<string> keys;
|
||||
transform(mapping.begin(), mapping.end(), inserter(keys, keys.end()),
|
||||
[](auto const & kv) { return kv.first; });
|
||||
transform(mapping.begin(), mapping.end(), inserter(keys, keys.end()), [](auto const & kv) { return kv.first; });
|
||||
return keys;
|
||||
}
|
||||
|
||||
@@ -57,8 +56,8 @@ void Add(Stats::NameToCountMapping const & addition, Stats::NameToCountMapping &
|
||||
}
|
||||
}
|
||||
|
||||
void PrintMap(string const & keyName, string const & descr,
|
||||
Stats::NameToCountMapping const & mapping, ostringstream & ss)
|
||||
void PrintMap(string const & keyName, string const & descr, Stats::NameToCountMapping const & mapping,
|
||||
ostringstream & ss)
|
||||
{
|
||||
ss << descr << '\n';
|
||||
if (mapping.empty())
|
||||
@@ -74,17 +73,15 @@ void PrintMap(string const & keyName, string const & descr,
|
||||
namespace track_analyzing
|
||||
{
|
||||
// Stats ===========================================================================================
|
||||
Stats::Stats(NameToCountMapping const & mwmToTotalDataPoints,
|
||||
NameToCountMapping const & countryToTotalDataPoint)
|
||||
Stats::Stats(NameToCountMapping const & mwmToTotalDataPoints, NameToCountMapping const & countryToTotalDataPoint)
|
||||
: m_mwmToTotalDataPoints(mwmToTotalDataPoints)
|
||||
, m_countryToTotalDataPoints(countryToTotalDataPoint)
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
bool Stats::operator==(Stats const & stats) const
|
||||
{
|
||||
return m_mwmToTotalDataPoints == stats.m_mwmToTotalDataPoints &&
|
||||
m_countryToTotalDataPoints == stats.m_countryToTotalDataPoints;
|
||||
m_countryToTotalDataPoints == stats.m_countryToTotalDataPoints;
|
||||
}
|
||||
|
||||
void Stats::Add(Stats const & stats)
|
||||
@@ -93,8 +90,7 @@ void Stats::Add(Stats const & stats)
|
||||
::Add(stats.m_countryToTotalDataPoints, m_countryToTotalDataPoints);
|
||||
}
|
||||
|
||||
void Stats::AddTracksStats(MwmToTracks const & mwmToTracks, NumMwmIds const & numMwmIds,
|
||||
Storage const & storage)
|
||||
void Stats::AddTracksStats(MwmToTracks const & mwmToTracks, NumMwmIds const & numMwmIds, Storage const & storage)
|
||||
{
|
||||
for (auto const & kv : mwmToTracks)
|
||||
{
|
||||
@@ -109,15 +105,13 @@ void Stats::AddTracksStats(MwmToTracks const & mwmToTracks, NumMwmIds const & nu
|
||||
}
|
||||
}
|
||||
|
||||
void Stats::AddDataPoints(string const & mwmName, string const & countryName,
|
||||
uint64_t dataPointNum)
|
||||
void Stats::AddDataPoints(string const & mwmName, string const & countryName, uint64_t dataPointNum)
|
||||
{
|
||||
m_mwmToTotalDataPoints[mwmName] += dataPointNum;
|
||||
m_countryToTotalDataPoints[countryName] += dataPointNum;
|
||||
}
|
||||
|
||||
void Stats::AddDataPoints(string const & mwmName, storage::Storage const & storage,
|
||||
uint64_t dataPointNum)
|
||||
void Stats::AddDataPoints(string const & mwmName, storage::Storage const & storage, uint64_t dataPointNum)
|
||||
{
|
||||
auto const countryName = storage.GetTopmostParentFor(mwmName);
|
||||
// Note. In case of disputed mwms |countryName| will be empty.
|
||||
@@ -126,8 +120,7 @@ void Stats::AddDataPoints(string const & mwmName, storage::Storage const & stora
|
||||
|
||||
void Stats::SaveMwmDistributionToCsv(string const & csvPath) const
|
||||
{
|
||||
LOG(LINFO, ("Saving mwm distribution to", csvPath, "m_mwmToTotalDataPoints size is",
|
||||
m_mwmToTotalDataPoints.size()));
|
||||
LOG(LINFO, ("Saving mwm distribution to", csvPath, "m_mwmToTotalDataPoints size is", m_mwmToTotalDataPoints.size()));
|
||||
if (csvPath.empty())
|
||||
return;
|
||||
|
||||
@@ -162,8 +155,8 @@ void Stats::LogCountries() const
|
||||
LogNameToCountMapping("country", "Country name to data points number:", m_countryToTotalDataPoints);
|
||||
}
|
||||
|
||||
void MappingToCsv(string const & keyName, Stats::NameToCountMapping const & mapping,
|
||||
bool printPercentage, basic_ostream<char> & ss)
|
||||
void MappingToCsv(string const & keyName, Stats::NameToCountMapping const & mapping, bool printPercentage,
|
||||
basic_ostream<char> & ss)
|
||||
{
|
||||
struct KeyValue
|
||||
{
|
||||
@@ -208,8 +201,7 @@ void MappingToCsv(string const & keyName, Stats::NameToCountMapping const & mapp
|
||||
|
||||
void MappingFromCsv(basic_istream<char> & ss, Stats::NameToCountMapping & mapping)
|
||||
{
|
||||
for (auto const & row :
|
||||
coding::CSVRunner(coding::CSVReader(ss, true /* hasHeader */, ',' /* kCsvDelimiter */)))
|
||||
for (auto const & row : coding::CSVRunner(coding::CSVReader(ss, true /* hasHeader */, ',' /* kCsvDelimiter */)))
|
||||
{
|
||||
CHECK_EQUAL(row.size(), 2, (row));
|
||||
auto const & key = row[0];
|
||||
@@ -220,8 +212,7 @@ void MappingFromCsv(basic_istream<char> & ss, Stats::NameToCountMapping & mappin
|
||||
}
|
||||
}
|
||||
|
||||
void ParseTracks(string const & logFile, shared_ptr<NumMwmIds> const & numMwmIds,
|
||||
MwmToTracks & mwmToTracks)
|
||||
void ParseTracks(string const & logFile, shared_ptr<NumMwmIds> const & numMwmIds, MwmToTracks & mwmToTracks)
|
||||
{
|
||||
Platform const & platform = GetPlatform();
|
||||
string const dataDir = platform.WritableDir();
|
||||
@@ -240,8 +231,7 @@ void WriteCsvTableHeader(basic_ostream<char> & stream)
|
||||
"intersection with big\n";
|
||||
}
|
||||
|
||||
void LogNameToCountMapping(string const & keyName, string const & descr,
|
||||
Stats::NameToCountMapping const & mapping)
|
||||
void LogNameToCountMapping(string const & keyName, string const & descr, Stats::NameToCountMapping const & mapping)
|
||||
{
|
||||
ostringstream ss;
|
||||
LOG(LINFO, ("\n"));
|
||||
|
||||
@@ -23,8 +23,7 @@ public:
|
||||
using NameToCountMapping = std::map<std::string, uint64_t>;
|
||||
|
||||
Stats() = default;
|
||||
Stats(NameToCountMapping const & mwmToTotalDataPoints,
|
||||
NameToCountMapping const & countryToTotalDataPoint);
|
||||
Stats(NameToCountMapping const & mwmToTotalDataPoints, NameToCountMapping const & countryToTotalDataPoint);
|
||||
|
||||
bool operator==(Stats const & stats) const;
|
||||
void Add(Stats const & stats);
|
||||
@@ -34,11 +33,9 @@ public:
|
||||
storage::Storage const & storage);
|
||||
|
||||
/// \brief Adds |dataPointNum| to |m_mwmToTotalDataPoints| and |m_countryToTotalDataPoints|.
|
||||
void AddDataPoints(std::string const & mwmName, std::string const & countryName,
|
||||
uint64_t dataPointNum);
|
||||
void AddDataPoints(std::string const & mwmName, std::string const & countryName, uint64_t dataPointNum);
|
||||
|
||||
void AddDataPoints(std::string const & mwmName, storage::Storage const & storage,
|
||||
uint64_t dataPointNum);
|
||||
void AddDataPoints(std::string const & mwmName, storage::Storage const & storage, uint64_t dataPointNum);
|
||||
|
||||
/// \brief Saves csv file with numbers of DataPoints for each mwm to |csvPath|.
|
||||
/// If |csvPath| is empty it does nothing.
|
||||
@@ -60,8 +57,8 @@ private:
|
||||
};
|
||||
|
||||
/// \brief Saves |mapping| as csv to |ss|.
|
||||
void MappingToCsv(std::string const & keyName, Stats::NameToCountMapping const & mapping,
|
||||
bool printPercentage, std::basic_ostream<char> & ss);
|
||||
void MappingToCsv(std::string const & keyName, Stats::NameToCountMapping const & mapping, bool printPercentage,
|
||||
std::basic_ostream<char> & ss);
|
||||
/// \breif Fills |mapping| according to csv in |ss|. Csv header is skipped.
|
||||
void MappingFromCsv(std::basic_istream<char> & ss, Stats::NameToCountMapping & mapping);
|
||||
|
||||
|
||||
@@ -13,7 +13,8 @@ namespace
|
||||
using namespace std;
|
||||
using namespace track_analyzing;
|
||||
|
||||
string const csv = R"(user,mwm,hw type,surface type,maxspeed km/h,is city road,is one way,is day,lat lon,distance,time,mean speed km/h,turn from smaller to bigger,turn from bigger to smaller,from link,to link,intersection with big,intersection with small,intersection with link
|
||||
string const csv =
|
||||
R"(user,mwm,hw type,surface type,maxspeed km/h,is city road,is one way,is day,lat lon,distance,time,mean speed km/h,turn from smaller to bigger,turn from bigger to smaller,from link,to link,intersection with big,intersection with small,intersection with link
|
||||
I:D923B4DC-09E0-4B0B-B7F8-153965396B55,New Zealand,highway-trunk,psurface-paved_good,80,0,0,1,-41.4832 173.844,163.984,6,98.3902,0,0,0,0,0,1,0
|
||||
I:D923B4DC-09E0-4B0B-B7F8-153965396B55,New Zealand,highway-trunk,psurface-paved_good,80,0,0,1,-41.4831 173.845,2274.59,108,75.8196,0,0,0,0,0,4,0
|
||||
A:b6e31294-5c90-4105-9f7b-51a382eabfa0,Poland,highway-primary,psurface-paved_good,50,0,0,0,53.8524 21.3061,1199.34,60,71.9604,0,0,0,0,0,10,0)";
|
||||
@@ -48,15 +49,12 @@ UNIT_TEST(FillTableTest)
|
||||
MwmToDataPoints const expectedMatchedDataPoints = {{"New Zealand", 2 /* data points */},
|
||||
{"Poland", 1 /* data points */}};
|
||||
std::vector<TableRow> expectedTable = {
|
||||
{"I:D923B4DC-09E0-4B0B-B7F8-153965396B55", "New Zealand", "highway-trunk",
|
||||
"psurface-paved_good", "80", "0", "0", "1", "-41.4832 173.844", "163.984", "6", "98.3902",
|
||||
"0", "0", "0", "0", "0", "1", "0"},
|
||||
{"I:D923B4DC-09E0-4B0B-B7F8-153965396B55", "New Zealand", "highway-trunk",
|
||||
"psurface-paved_good", "80", "0", "0", "1", "-41.4831 173.845", "2274.59", "108", "75.8196",
|
||||
"0", "0", "0", "0", "0", "4", "0"},
|
||||
{"A:b6e31294-5c90-4105-9f7b-51a382eabfa0", "Poland", "highway-primary", "psurface-paved_good",
|
||||
"50", "0", "0", "0", "53.8524 21.3061", "1199.34", "60", "71.9604", "0", "0", "0", "0", "0",
|
||||
"10", "0"}};
|
||||
{"I:D923B4DC-09E0-4B0B-B7F8-153965396B55", "New Zealand", "highway-trunk", "psurface-paved_good", "80", "0", "0",
|
||||
"1", "-41.4832 173.844", "163.984", "6", "98.3902", "0", "0", "0", "0", "0", "1", "0"},
|
||||
{"I:D923B4DC-09E0-4B0B-B7F8-153965396B55", "New Zealand", "highway-trunk", "psurface-paved_good", "80", "0", "0",
|
||||
"1", "-41.4831 173.845", "2274.59", "108", "75.8196", "0", "0", "0", "0", "0", "4", "0"},
|
||||
{"A:b6e31294-5c90-4105-9f7b-51a382eabfa0", "Poland", "highway-primary", "psurface-paved_good", "50", "0", "0",
|
||||
"0", "53.8524 21.3061", "1199.34", "60", "71.9604", "0", "0", "0", "0", "0", "10", "0"}};
|
||||
|
||||
TEST_EQUAL(matchedDataPoints, expectedMatchedDataPoints, ());
|
||||
TEST_EQUAL(table, expectedTable, ());
|
||||
@@ -69,10 +67,8 @@ UNIT_TEST(AreKeysEqualEmptyMapsTest)
|
||||
|
||||
UNIT_TEST(AreKeysEqualTest)
|
||||
{
|
||||
MwmToDataPoints const map1 = {{"Russia_Moscow", 5 /* data points */},
|
||||
{"San Marino", 7 /* data points */}};
|
||||
MwmToDataPoints map2 = {{"Russia_Moscow", 7 /* data points*/},
|
||||
{"San Marino", 9 /* data points */}};
|
||||
MwmToDataPoints const map1 = {{"Russia_Moscow", 5 /* data points */}, {"San Marino", 7 /* data points */}};
|
||||
MwmToDataPoints map2 = {{"Russia_Moscow", 7 /* data points*/}, {"San Marino", 9 /* data points */}};
|
||||
TEST(AreKeysEqual(map1, map2), ());
|
||||
|
||||
map2["Slovakia"] = 3;
|
||||
@@ -90,10 +86,8 @@ UNIT_TEST(RemoveKeysSmallValueEmptyTest)
|
||||
|
||||
UNIT_TEST(RemoveKeysSmallValueTest)
|
||||
{
|
||||
MwmToDataPoints checkedMap = {{"Russia_Moscow", 3 /* data points */},
|
||||
{"San Marino", 5 /* data points */}};
|
||||
MwmToDataPoints additionalMap = {{"Russia_Moscow", 7 /* data points*/},
|
||||
{"San Marino", 9 /* data points */}};
|
||||
MwmToDataPoints checkedMap = {{"Russia_Moscow", 3 /* data points */}, {"San Marino", 5 /* data points */}};
|
||||
MwmToDataPoints additionalMap = {{"Russia_Moscow", 7 /* data points*/}, {"San Marino", 9 /* data points */}};
|
||||
RemoveKeysSmallValue(checkedMap, additionalMap, 4 /* ignoreDataPointNumber */);
|
||||
|
||||
MwmToDataPoints expectedCheckedMap = {{"San Marino", 5 /* data points */}};
|
||||
@@ -110,9 +104,8 @@ UNIT_TEST(GetMwmToDataPointFractionTest)
|
||||
{"Slovakia", 50 /* data points */}};
|
||||
auto const fractionMapping = GetMwmToDataPointFraction(numberMapping);
|
||||
|
||||
MwmToDataPointFraction expectedFractionMapping{{"Russia_Moscow", 0.5 /* fraction */},
|
||||
{"San Marino", 0.25 /* fraction */},
|
||||
{"Slovakia", 0.25 /* fraction */}};
|
||||
MwmToDataPointFraction expectedFractionMapping{
|
||||
{"Russia_Moscow", 0.5 /* fraction */}, {"San Marino", 0.25 /* fraction */}, {"Slovakia", 0.25 /* fraction */}};
|
||||
TEST_EQUAL(fractionMapping, expectedFractionMapping, ());
|
||||
}
|
||||
|
||||
@@ -153,9 +146,8 @@ UNIT_TEST(BalancedDataPointNumberTheSameTest)
|
||||
MwmToDataPoints const distribution = {{"Russia_Moscow", 100 /* data points */},
|
||||
{"San Marino", 50 /* data points */},
|
||||
{"Slovakia", 50 /* data points */}};
|
||||
MwmToDataPoints const matchedDataPoints = {{"Russia_Moscow", 10 /* data points */},
|
||||
{"San Marino", 5 /* data points */},
|
||||
{"Slovakia", 5 /* data points */}};
|
||||
MwmToDataPoints const matchedDataPoints = {
|
||||
{"Russia_Moscow", 10 /* data points */}, {"San Marino", 5 /* data points */}, {"Slovakia", 5 /* data points */}};
|
||||
{
|
||||
// Case when the distribution is not changed. All mwms lose the same percent of data points.
|
||||
auto distr = distribution;
|
||||
@@ -226,7 +218,8 @@ UNIT_TEST(FilterTableTest)
|
||||
ss << csv;
|
||||
FillTable(ss, matchedDataPoints, csvTable);
|
||||
|
||||
auto const calcRecords = [](vector<TableRow> const & t, string const & mwmName) {
|
||||
auto const calcRecords = [](vector<TableRow> const & t, string const & mwmName)
|
||||
{
|
||||
return count_if(t.cbegin(), t.cend(),
|
||||
[&mwmName](TableRow const & row) { return row[kMwmNameCsvColumn] == mwmName; });
|
||||
};
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
|
||||
#include "geometry/latlon.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
namespace
|
||||
{
|
||||
@@ -43,27 +43,24 @@ UNIT_TEST(AddDataPointsTest)
|
||||
stats.AddDataPoints("mwm2", "country1", 5);
|
||||
stats.AddDataPoints("mwm3", "country3", 7);
|
||||
|
||||
Stats const expected = {
|
||||
{{"mwm1", 4}, {"mwm2", 5}, {"mwm3", 7} /* Mwm to number */},
|
||||
{{"country1", 9}, {"country3", 7} /* Country to number */}};
|
||||
Stats const expected = {{{"mwm1", 4}, {"mwm2", 5}, {"mwm3", 7} /* Mwm to number */},
|
||||
{{"country1", 9}, {"country3", 7} /* Country to number */}};
|
||||
|
||||
TEST_EQUAL(stats, expected, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(AddStatTest)
|
||||
{
|
||||
Stats stats1 = {
|
||||
{{"Belarus_Minsk Region", 1}, {"Uzbekistan", 7}, {"Russia_Moscow", 5} /* Mwm to number */},
|
||||
{{"Russian Federation", 10}, {"Poland", 5} /* Country to number */}};
|
||||
Stats stats1 = {{{"Belarus_Minsk Region", 1}, {"Uzbekistan", 7}, {"Russia_Moscow", 5} /* Mwm to number */},
|
||||
{{"Russian Federation", 10}, {"Poland", 5} /* Country to number */}};
|
||||
|
||||
Stats const stats2 = {{{"Belarus_Minsk Region", 2} /* Mwm to number */},
|
||||
{{"Russian Federation", 1}, {"Belarus", 8} /* Country to number */}};
|
||||
|
||||
stats1.Add(stats2);
|
||||
|
||||
Stats const expected = {
|
||||
{{"Belarus_Minsk Region", 3}, {"Uzbekistan", 7}, {"Russia_Moscow", 5} /* Mwm to number */},
|
||||
{{"Russian Federation", 11}, {"Poland", 5}, {"Belarus", 8} /* Country to number */}};
|
||||
Stats const expected = {{{"Belarus_Minsk Region", 3}, {"Uzbekistan", 7}, {"Russia_Moscow", 5} /* Mwm to number */},
|
||||
{{"Russian Federation", 11}, {"Poland", 5}, {"Belarus", 8} /* Country to number */}};
|
||||
|
||||
TEST_EQUAL(stats1, expected, ());
|
||||
}
|
||||
@@ -101,8 +98,7 @@ UNIT_TEST(AddTracksStatsTest)
|
||||
|
||||
UNIT_TEST(MappingToCsvTest)
|
||||
{
|
||||
Stats::NameToCountMapping const mapping = {
|
||||
{{"Belarus_Minsk Region", 2}, {"Uzbekistan", 5}, {"Russia_Moscow", 3}}};
|
||||
Stats::NameToCountMapping const mapping = {{{"Belarus_Minsk Region", 2}, {"Uzbekistan", 5}, {"Russia_Moscow", 3}}};
|
||||
{
|
||||
std::ostringstream ss;
|
||||
MappingToCsv("mwm", mapping, true /* printPercentage */, ss);
|
||||
@@ -127,8 +123,7 @@ Belarus_Minsk Region,2
|
||||
|
||||
UNIT_TEST(MappingToCsvUint64Test)
|
||||
{
|
||||
Stats::NameToCountMapping const mapping = {{"Belarus_Minsk Region", 5'000'000'000},
|
||||
{"Uzbekistan", 15'000'000'000}};
|
||||
Stats::NameToCountMapping const mapping = {{"Belarus_Minsk Region", 5'000'000'000}, {"Uzbekistan", 15'000'000'000}};
|
||||
std::stringstream ss;
|
||||
MappingToCsv("mwm", mapping, true /* printPercentage */, ss);
|
||||
std::string const expected = R"(mwm,number,percent
|
||||
@@ -140,21 +135,17 @@ Belarus_Minsk Region,5000000000,25
|
||||
|
||||
UNIT_TEST(SerializationToCsvTest)
|
||||
{
|
||||
Stats::NameToCountMapping const mapping1 = {{"Belarus_Minsk Region", 2},
|
||||
{"Uzbekistan", 5},
|
||||
{"Russia_Moscow", 1},
|
||||
{"Russia_Moscow Oblast_East", 2}};
|
||||
Stats::NameToCountMapping const mapping1 = {
|
||||
{"Belarus_Minsk Region", 2}, {"Uzbekistan", 5}, {"Russia_Moscow", 1}, {"Russia_Moscow Oblast_East", 2}};
|
||||
TestSerializationToCsv(mapping1);
|
||||
|
||||
Stats::NameToCountMapping const mapping2 = {
|
||||
{{"Belarus_Minsk Region", 2}, {"Uzbekistan", 5}, {"Russia_Moscow", 3}}};
|
||||
Stats::NameToCountMapping const mapping2 = {{{"Belarus_Minsk Region", 2}, {"Uzbekistan", 5}, {"Russia_Moscow", 3}}};
|
||||
TestSerializationToCsv(mapping2);
|
||||
}
|
||||
|
||||
UNIT_TEST(SerializationToCsvWithZeroValueTest)
|
||||
{
|
||||
Stats::NameToCountMapping const mapping = {{"Russia_Moscow Oblast_East", 2},
|
||||
{"Poland_Lesser Poland Voivodeship", 0}};
|
||||
Stats::NameToCountMapping const mapping = {{"Russia_Moscow Oblast_East", 2}, {"Poland_Lesser Poland Voivodeship", 0}};
|
||||
Stats::NameToCountMapping const expected = {{"Russia_Moscow Oblast_East", 2}};
|
||||
|
||||
std::stringstream ss;
|
||||
@@ -168,9 +159,8 @@ UNIT_TEST(SerializationToCsvWithZeroValueTest)
|
||||
|
||||
UNIT_TEST(SerializationToCsvUint64Test)
|
||||
{
|
||||
Stats::NameToCountMapping const mapping = {{"Belarus_Minsk Region", 20'000'000'000},
|
||||
{"Uzbekistan", 5},
|
||||
{"Russia_Moscow", 7'000'000'000}};
|
||||
Stats::NameToCountMapping const mapping = {
|
||||
{"Belarus_Minsk Region", 20'000'000'000}, {"Uzbekistan", 5}, {"Russia_Moscow", 7'000'000'000}};
|
||||
TestSerializationToCsv(mapping);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
#include "coding/zip_creator.hpp"
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include "3party/minizip/minizip.hpp"
|
||||
|
||||
@@ -31,8 +31,7 @@ struct UserTrackInfo
|
||||
Track m_track;
|
||||
};
|
||||
|
||||
std::optional<UserTrackInfo> ParseLogRecord(std::string const & record,
|
||||
TemporaryFile & tmpArchiveFile);
|
||||
std::optional<UserTrackInfo> ParseLogRecord(std::string const & record, TemporaryFile & tmpArchiveFile);
|
||||
std::optional<std::string> ParseMultipartData(std::string const & binaryData);
|
||||
bool ParseTrackFile(unzip::File & zipReader, Track & trackData) noexcept;
|
||||
template <typename Reader, typename Pack>
|
||||
@@ -83,8 +82,8 @@ UNIT_TEST(UnpackTrackArchiveDataTest)
|
||||
vector<string> trackFiles;
|
||||
trackFiles.push_back(archiveFileName);
|
||||
string const containerFileName("test_track_archive.zip");
|
||||
TEST_EQUAL(CreateZipFromFiles(trackFiles, containerFileName, CompressionLevel::NoCompression),
|
||||
true, ("Unable to create tracks archive"));
|
||||
TEST_EQUAL(CreateZipFromFiles(trackFiles, containerFileName, CompressionLevel::NoCompression), true,
|
||||
("Unable to create tracks archive"));
|
||||
FileWriter::DeleteFileX(archiveFileName);
|
||||
|
||||
// Step 2.3: Read batch archive content
|
||||
@@ -99,8 +98,7 @@ UNIT_TEST(UnpackTrackArchiveDataTest)
|
||||
// Step 2.4: Wrap as multipart data
|
||||
stringstream multipartStream;
|
||||
multipartStream << "------0000000000000\r\n";
|
||||
multipartStream << "Content-Disposition: form-data; name=\"file\"; filename=\""
|
||||
<< containerFileName << "\"\r\n";
|
||||
multipartStream << "Content-Disposition: form-data; name=\"file\"; filename=\"" << containerFileName << "\"\r\n";
|
||||
multipartStream << "Content-Type: application/zip\r\n";
|
||||
multipartStream << "\r\n";
|
||||
multipartStream.write(buffer.data(), buffer.size());
|
||||
@@ -110,16 +108,14 @@ UNIT_TEST(UnpackTrackArchiveDataTest)
|
||||
string multipartData = multipartStream.str();
|
||||
|
||||
stringstream logStream;
|
||||
logStream << testUserId << "\t1\t1577826010\t" << multipartData.size() << "\t"
|
||||
<< ToHex(multipartData);
|
||||
logStream << testUserId << "\t1\t1577826010\t" << multipartData.size() << "\t" << ToHex(multipartData);
|
||||
|
||||
string const logRecord = logStream.str();
|
||||
|
||||
// Unpack log record
|
||||
TemporaryFile tmpArchiveFile("tmp-unittest", ".zip");
|
||||
|
||||
optional<track_analyzing::details::UserTrackInfo> data =
|
||||
ParseLogRecord(logRecord, tmpArchiveFile);
|
||||
optional<track_analyzing::details::UserTrackInfo> data = ParseLogRecord(logRecord, tmpArchiveFile);
|
||||
TEST_EQUAL(bool(data), true, ("Unable parse track archive record"));
|
||||
|
||||
TEST_EQUAL(data->m_userId, testUserId, ());
|
||||
@@ -128,10 +124,8 @@ UNIT_TEST(UnpackTrackArchiveDataTest)
|
||||
for (size_t i = 0; i < testTrack.size(); ++i)
|
||||
{
|
||||
TEST_EQUAL(data->m_track[i].m_timestamp, testTrack[i].m_timestamp, ());
|
||||
TEST_ALMOST_EQUAL_ABS(data->m_track[i].m_latLon.m_lat, testTrack[i].m_latLon.m_lat,
|
||||
kAccuracyEps, ());
|
||||
TEST_ALMOST_EQUAL_ABS(data->m_track[i].m_latLon.m_lon, testTrack[i].m_latLon.m_lon,
|
||||
kAccuracyEps, ());
|
||||
TEST_ALMOST_EQUAL_ABS(data->m_track[i].m_latLon.m_lat, testTrack[i].m_latLon.m_lat, kAccuracyEps, ());
|
||||
TEST_ALMOST_EQUAL_ABS(data->m_track[i].m_latLon.m_lon, testTrack[i].m_latLon.m_lon, kAccuracyEps, ());
|
||||
TEST_EQUAL(data->m_track[i].m_traffic, testTrack[i].m_traffic, ());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ using namespace track_analyzing;
|
||||
|
||||
namespace track_analyzing
|
||||
{
|
||||
const string kTmpArchiveFileNameTemplate("-tmp-track-archive.zip");
|
||||
string const kTmpArchiveFileNameTemplate("-tmp-track-archive.zip");
|
||||
|
||||
// Track record fields:
|
||||
// 0: user ID
|
||||
@@ -124,8 +124,8 @@ optional<string> ParseMultipartData(string const & binaryData)
|
||||
{
|
||||
if (expectedContentType == header)
|
||||
hasContentTypeHeader = true;
|
||||
if (expectedContentDispositionPrefix.compare(0, string::npos, header, 0,
|
||||
expectedContentDispositionPrefix.size()) == 0)
|
||||
if (expectedContentDispositionPrefix.compare(0, string::npos, header, 0, expectedContentDispositionPrefix.size()) ==
|
||||
0)
|
||||
{
|
||||
hasContentDispositionHeader = true;
|
||||
}
|
||||
@@ -140,8 +140,8 @@ optional<string> ParseMultipartData(string const & binaryData)
|
||||
|
||||
bool HasZipSignature(string const & binaryData)
|
||||
{
|
||||
return binaryData.size() >= 4 && binaryData[0] == 0x50 && binaryData[1] == 0x4b &&
|
||||
binaryData[2] == 0x03 && binaryData[3] == 0x04;
|
||||
return binaryData.size() >= 4 && binaryData[0] == 0x50 && binaryData[1] == 0x4b && binaryData[2] == 0x03 &&
|
||||
binaryData[3] == 0x04;
|
||||
}
|
||||
|
||||
template <typename Reader, typename Pack>
|
||||
@@ -153,8 +153,7 @@ bool ReadTrackFromArchive(char const * data, size_t dataSize, Track & trackData)
|
||||
vector<uint8_t> buffer;
|
||||
inflate(data, dataSize, back_inserter(buffer));
|
||||
|
||||
ReaderSource<MemReaderWithExceptions> reader(
|
||||
MemReaderWithExceptions(buffer.data(), buffer.size()));
|
||||
ReaderSource<MemReaderWithExceptions> reader(MemReaderWithExceptions(buffer.data(), buffer.size()));
|
||||
if (reader.Size() == 0)
|
||||
return false;
|
||||
|
||||
@@ -209,13 +208,13 @@ bool ParseTrackFile(unzip::File & zipReader, Track & trackData) noexcept
|
||||
bool result = false;
|
||||
if (archiveInfo.m_trackType == routing::RouterType::Vehicle)
|
||||
{
|
||||
result = ReadTrackFromArchive<ReaderSource<MemReaderWithExceptions>, tracking::PacketCar>(
|
||||
fileData.data(), dataSize, trackData);
|
||||
result = ReadTrackFromArchive<ReaderSource<MemReaderWithExceptions>, tracking::PacketCar>(fileData.data(), dataSize,
|
||||
trackData);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = ReadTrackFromArchive<ReaderSource<MemReaderWithExceptions>, tracking::Packet>(
|
||||
fileData.data(), dataSize, trackData);
|
||||
result = ReadTrackFromArchive<ReaderSource<MemReaderWithExceptions>, tracking::Packet>(fileData.data(), dataSize,
|
||||
trackData);
|
||||
}
|
||||
|
||||
if (unzip::CloseCurrentFile(zipReader) != unzip::Code::Ok)
|
||||
@@ -254,9 +253,7 @@ optional<Track> ParseTrackArchiveData(string const & content, TemporaryFile & tm
|
||||
|
||||
bool result = ParseTrackFile(zipReader, trackData);
|
||||
while (result && unzip::GoToNextFile(zipReader) == unzip::Code::Ok)
|
||||
{
|
||||
result = ParseTrackFile(zipReader, trackData);
|
||||
}
|
||||
|
||||
if (unzip::Close(zipReader) != unzip::Code::Ok)
|
||||
LOG(LERROR, ("Unable to close temporary zip archive"));
|
||||
@@ -285,8 +282,7 @@ optional<UserTrackInfo> ParseLogRecord(string const & record, TemporaryFile & tm
|
||||
|
||||
} // namespace details
|
||||
|
||||
void TrackArchiveReader::ParseUserTracksFromFile(string const & logFile,
|
||||
UserToTrack & userToTrack) const
|
||||
void TrackArchiveReader::ParseUserTracksFromFile(string const & logFile, UserToTrack & userToTrack) const
|
||||
{
|
||||
// Read file content
|
||||
FileReader reader(logFile);
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
|
||||
#include "base/stl_helpers.hpp"
|
||||
|
||||
|
||||
namespace track_analyzing
|
||||
{
|
||||
using namespace routing;
|
||||
@@ -25,8 +24,7 @@ namespace
|
||||
double constexpr kMatchingRange = 20.0;
|
||||
|
||||
// Mercator distance from segment to point in meters.
|
||||
double DistanceToSegment(m2::PointD const & segmentBegin, m2::PointD const & segmentEnd,
|
||||
m2::PointD const & point)
|
||||
double DistanceToSegment(m2::PointD const & segmentBegin, m2::PointD const & segmentEnd, m2::PointD const & point)
|
||||
{
|
||||
m2::ParametrizedSegment<m2::PointD> const segment(segmentBegin, segmentEnd);
|
||||
m2::PointD const projectionPoint = segment.ClosestPointTo(point);
|
||||
@@ -36,41 +34,36 @@ double DistanceToSegment(m2::PointD const & segmentBegin, m2::PointD const & seg
|
||||
double DistanceToSegment(Segment const & segment, m2::PointD const & point, IndexGraph & indexGraph)
|
||||
{
|
||||
auto const & road = indexGraph.GetRoadGeometry(segment.GetFeatureId());
|
||||
return DistanceToSegment(
|
||||
mercator::FromLatLon(road.GetPoint(segment.GetPointId(false))),
|
||||
mercator::FromLatLon(road.GetPoint(segment.GetPointId(true))), point);
|
||||
return DistanceToSegment(mercator::FromLatLon(road.GetPoint(segment.GetPointId(false))),
|
||||
mercator::FromLatLon(road.GetPoint(segment.GetPointId(true))), point);
|
||||
}
|
||||
|
||||
bool EdgesContain(IndexGraph::SegmentEdgeListT const & edges, Segment const & segment)
|
||||
{
|
||||
for (auto const & edge : edges)
|
||||
{
|
||||
if (edge.GetTarget() == segment)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// TrackMatcher ------------------------------------------------------------------------------------
|
||||
TrackMatcher::TrackMatcher(storage::Storage const & storage, NumMwmId mwmId,
|
||||
platform::CountryFile const & countryFile)
|
||||
TrackMatcher::TrackMatcher(storage::Storage const & storage, NumMwmId mwmId, platform::CountryFile const & countryFile)
|
||||
: m_mwmId(mwmId)
|
||||
, m_vehicleModel(CarModelFactory({}).GetVehicleModelForCountry(countryFile.GetName()))
|
||||
{
|
||||
auto localCountryFile = storage.GetLatestLocalFile(countryFile);
|
||||
CHECK(localCountryFile, ("Can't find latest country file for", countryFile.GetName()));
|
||||
auto registerResult = m_dataSource.Register(*localCountryFile);
|
||||
CHECK_EQUAL(registerResult.second, MwmSet::RegResult::Success,
|
||||
("Can't register mwm", countryFile.GetName()));
|
||||
CHECK_EQUAL(registerResult.second, MwmSet::RegResult::Success, ("Can't register mwm", countryFile.GetName()));
|
||||
|
||||
MwmSet::MwmHandle handle = m_dataSource.GetMwmHandleByCountryFile(countryFile);
|
||||
|
||||
m_graph = make_unique<IndexGraph>(
|
||||
make_shared<Geometry>(GeometryLoader::Create(handle, m_vehicleModel, false /* loadAltitudes */)),
|
||||
EdgeEstimator::Create(VehicleType::Car, *m_vehicleModel, nullptr /* trafficStash */,
|
||||
nullptr /* dataSource */, nullptr /* numMvmIds */));
|
||||
EdgeEstimator::Create(VehicleType::Car, *m_vehicleModel, nullptr /* trafficStash */, nullptr /* dataSource */,
|
||||
nullptr /* numMvmIds */));
|
||||
|
||||
DeserializeIndexGraph(*handle.GetValue(), VehicleType::Car, *m_graph);
|
||||
}
|
||||
@@ -88,8 +81,7 @@ void TrackMatcher::MatchTrack(vector<DataPoint> const & track, vector<MatchedTra
|
||||
{
|
||||
for (; trackBegin < steps.size(); ++trackBegin)
|
||||
{
|
||||
steps[trackBegin].FillCandidatesWithNearbySegments(m_dataSource, *m_graph, *m_vehicleModel,
|
||||
m_mwmId);
|
||||
steps[trackBegin].FillCandidatesWithNearbySegments(m_dataSource, *m_graph, *m_vehicleModel, m_mwmId);
|
||||
if (steps[trackBegin].HasCandidates())
|
||||
break;
|
||||
|
||||
@@ -130,13 +122,12 @@ void TrackMatcher::MatchTrack(vector<DataPoint> const & track, vector<MatchedTra
|
||||
|
||||
// TrackMatcher::Step ------------------------------------------------------------------------------
|
||||
TrackMatcher::Step::Step(DataPoint const & dataPoint)
|
||||
: m_dataPoint(dataPoint), m_point(mercator::FromLatLon(dataPoint.m_latLon))
|
||||
{
|
||||
}
|
||||
: m_dataPoint(dataPoint)
|
||||
, m_point(mercator::FromLatLon(dataPoint.m_latLon))
|
||||
{}
|
||||
|
||||
void TrackMatcher::Step::FillCandidatesWithNearbySegments(
|
||||
DataSource const & dataSource, IndexGraph const & graph,
|
||||
VehicleModelInterface const & vehicleModel, NumMwmId mwmId)
|
||||
void TrackMatcher::Step::FillCandidatesWithNearbySegments(DataSource const & dataSource, IndexGraph const & graph,
|
||||
VehicleModelInterface const & vehicleModel, NumMwmId mwmId)
|
||||
{
|
||||
dataSource.ForEachInRect([&](FeatureType & ft)
|
||||
{
|
||||
@@ -154,25 +145,20 @@ void TrackMatcher::Step::FillCandidatesWithNearbySegments(
|
||||
|
||||
for (size_t segIdx = 0; segIdx + 1 < ft.GetPointsCount(); ++segIdx)
|
||||
{
|
||||
double const distance =
|
||||
DistanceToSegment(ft.GetPoint(segIdx), ft.GetPoint(segIdx + 1), m_point);
|
||||
double const distance = DistanceToSegment(ft.GetPoint(segIdx), ft.GetPoint(segIdx + 1), m_point);
|
||||
if (distance < kMatchingRange)
|
||||
{
|
||||
AddCandidate(Segment(mwmId, ft.GetID().m_index, static_cast<uint32_t>(segIdx),
|
||||
true /* forward */),
|
||||
distance, graph);
|
||||
AddCandidate(Segment(mwmId, ft.GetID().m_index, static_cast<uint32_t>(segIdx), true /* forward */), distance,
|
||||
graph);
|
||||
|
||||
if (!vehicleModel.IsOneWay(types))
|
||||
{
|
||||
AddCandidate(Segment(mwmId, ft.GetID().m_index, static_cast<uint32_t>(segIdx),
|
||||
false /* forward */),
|
||||
distance, graph);
|
||||
AddCandidate(Segment(mwmId, ft.GetID().m_index, static_cast<uint32_t>(segIdx), false /* forward */), distance,
|
||||
graph);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
mercator::RectByCenterXYAndSizeInMeters(m_point, kMatchingRange),
|
||||
scales::GetUpperScale());
|
||||
}, mercator::RectByCenterXYAndSizeInMeters(m_point, kMatchingRange), scales::GetUpperScale());
|
||||
}
|
||||
|
||||
void TrackMatcher::Step::FillCandidates(Step const & previousStep, IndexGraph & graph)
|
||||
@@ -198,9 +184,7 @@ void TrackMatcher::Step::FillCandidates(Step const & previousStep, IndexGraph &
|
||||
base::SortUnique(m_candidates);
|
||||
|
||||
m_candidates.erase(remove_if(m_candidates.begin(), m_candidates.end(),
|
||||
[&](Candidate const & candidate) {
|
||||
return candidate.GetDistance() > kMatchingRange;
|
||||
}),
|
||||
[&](Candidate const & candidate) { return candidate.GetDistance() > kMatchingRange; }),
|
||||
m_candidates.end());
|
||||
}
|
||||
|
||||
@@ -211,8 +195,7 @@ void TrackMatcher::Step::ChooseSegment(Step const & nextStep, IndexGraph & index
|
||||
double minDistance = numeric_limits<double>::max();
|
||||
|
||||
IndexGraph::SegmentEdgeListT edges;
|
||||
indexGraph.GetEdgeList(nextStep.m_segment, false /* isOutgoing */, true /* useRoutingOptions */,
|
||||
edges);
|
||||
indexGraph.GetEdgeList(nextStep.m_segment, false /* isOutgoing */, true /* useRoutingOptions */, edges);
|
||||
edges.emplace_back(nextStep.m_segment, GetAStarWeightZero<RouteWeight>());
|
||||
|
||||
for (Candidate const & candidate : m_candidates)
|
||||
@@ -244,8 +227,7 @@ void TrackMatcher::Step::ChooseNearestSegment()
|
||||
}
|
||||
}
|
||||
|
||||
void TrackMatcher::Step::AddCandidate(Segment const & segment, double distance,
|
||||
IndexGraph const & graph)
|
||||
void TrackMatcher::Step::AddCandidate(Segment const & segment, double distance, IndexGraph const & graph)
|
||||
{
|
||||
if (graph.GetAccessType(segment) == RoadAccess::Type::Yes)
|
||||
m_candidates.emplace_back(segment, distance);
|
||||
|
||||
@@ -22,8 +22,7 @@ namespace track_analyzing
|
||||
class TrackMatcher final
|
||||
{
|
||||
public:
|
||||
TrackMatcher(storage::Storage const & storage, routing::NumMwmId mwmId,
|
||||
platform::CountryFile const & countryFile);
|
||||
TrackMatcher(storage::Storage const & storage, routing::NumMwmId mwmId, platform::CountryFile const & countryFile);
|
||||
|
||||
void MatchTrack(std::vector<DataPoint> const & track, std::vector<MatchedTrack> & matchedTracks);
|
||||
|
||||
@@ -35,9 +34,7 @@ private:
|
||||
class Candidate final
|
||||
{
|
||||
public:
|
||||
Candidate(routing::Segment segment, double distance) : m_segment(segment), m_distance(distance)
|
||||
{
|
||||
}
|
||||
Candidate(routing::Segment segment, double distance) : m_segment(segment), m_distance(distance) {}
|
||||
|
||||
routing::Segment const & GetSegment() const { return m_segment; }
|
||||
double GetDistance() const { return m_distance; }
|
||||
@@ -57,17 +54,14 @@ private:
|
||||
DataPoint const & GetDataPoint() const { return m_dataPoint; }
|
||||
routing::Segment const & GetSegment() const { return m_segment; }
|
||||
bool HasCandidates() const { return !m_candidates.empty(); }
|
||||
void FillCandidatesWithNearbySegments(DataSource const & dataSource,
|
||||
routing::IndexGraph const & graph,
|
||||
routing::VehicleModelInterface const & vehicleModel,
|
||||
routing::NumMwmId mwmId);
|
||||
void FillCandidatesWithNearbySegments(DataSource const & dataSource, routing::IndexGraph const & graph,
|
||||
routing::VehicleModelInterface const & vehicleModel, routing::NumMwmId mwmId);
|
||||
void FillCandidates(Step const & previousStep, routing::IndexGraph & graph);
|
||||
void ChooseSegment(Step const & nextStep, routing::IndexGraph & indexGraph);
|
||||
void ChooseNearestSegment();
|
||||
|
||||
private:
|
||||
void AddCandidate(routing::Segment const & segment, double distance,
|
||||
routing::IndexGraph const & graph);
|
||||
void AddCandidate(routing::Segment const & segment, double distance, routing::IndexGraph const & graph);
|
||||
|
||||
DataPoint m_dataPoint;
|
||||
m2::PointD m_point;
|
||||
|
||||
@@ -17,8 +17,7 @@ using namespace std;
|
||||
|
||||
namespace track_analyzing
|
||||
{
|
||||
double CalcSubtrackLength(MatchedTrack::const_iterator begin, MatchedTrack::const_iterator end,
|
||||
Geometry & geometry)
|
||||
double CalcSubtrackLength(MatchedTrack::const_iterator begin, MatchedTrack::const_iterator end, Geometry & geometry)
|
||||
{
|
||||
double length = 0.0;
|
||||
|
||||
@@ -29,10 +28,8 @@ double CalcSubtrackLength(MatchedTrack::const_iterator begin, MatchedTrack::cons
|
||||
Segment const & segment = point.GetSegment();
|
||||
if (segment != prevSegment)
|
||||
{
|
||||
length +=
|
||||
ms::DistanceOnEarth(
|
||||
geometry.GetPoint(segment.GetRoadPoint(false /* front */)),
|
||||
geometry.GetPoint(segment.GetRoadPoint(true /* front */)));
|
||||
length += ms::DistanceOnEarth(geometry.GetPoint(segment.GetRoadPoint(false /* front */)),
|
||||
geometry.GetPoint(segment.GetRoadPoint(true /* front */)));
|
||||
prevSegment = segment;
|
||||
}
|
||||
}
|
||||
@@ -51,8 +48,7 @@ double CalcSpeedKMpH(double meters, uint64_t secondsElapsed)
|
||||
return measurement_utils::MpsToKmph(meters / static_cast<double>(secondsElapsed));
|
||||
}
|
||||
|
||||
void ReadTracks(shared_ptr<NumMwmIds> numMwmIds, string const & filename,
|
||||
MwmToMatchedTracks & mwmToMatchedTracks)
|
||||
void ReadTracks(shared_ptr<NumMwmIds> numMwmIds, string const & filename, MwmToMatchedTracks & mwmToMatchedTracks)
|
||||
{
|
||||
FileReader reader(filename);
|
||||
ReaderSource<FileReader> src(reader);
|
||||
@@ -60,9 +56,8 @@ void ReadTracks(shared_ptr<NumMwmIds> numMwmIds, string const & filename,
|
||||
serializer.Deserialize(mwmToMatchedTracks, src);
|
||||
}
|
||||
|
||||
MatchedTrack const & GetMatchedTrack(MwmToMatchedTracks const & mwmToMatchedTracks,
|
||||
NumMwmIds const & numMwmIds, string const & mwmName,
|
||||
string const & user, size_t trackIdx)
|
||||
MatchedTrack const & GetMatchedTrack(MwmToMatchedTracks const & mwmToMatchedTracks, NumMwmIds const & numMwmIds,
|
||||
string const & mwmName, string const & user, size_t trackIdx)
|
||||
{
|
||||
auto const countryFile = platform::CountryFile(mwmName);
|
||||
if (!numMwmIds.ContainsFile(countryFile))
|
||||
@@ -84,8 +79,8 @@ MatchedTrack const & GetMatchedTrack(MwmToMatchedTracks const & mwmToMatchedTrac
|
||||
|
||||
if (trackIdx >= tracks.size())
|
||||
{
|
||||
MYTHROW(MessageException, ("There is no track", trackIdx, "for user", user, ", she has",
|
||||
tracks.size(), "tracks only"));
|
||||
MYTHROW(MessageException,
|
||||
("There is no track", trackIdx, "for user", user, ", she has", tracks.size(), "tracks only"));
|
||||
}
|
||||
|
||||
return tracks[trackIdx];
|
||||
@@ -96,10 +91,9 @@ std::string GetCurrentVersionMwmFile(storage::Storage const & storage, std::stri
|
||||
return storage.GetFilePath(mwmName, MapFileType::Map);
|
||||
}
|
||||
|
||||
void ForEachTrackFile(
|
||||
std::string const & filepath, std::string const & extension,
|
||||
shared_ptr<routing::NumMwmIds> numMwmIds,
|
||||
std::function<void(std::string const & filename, MwmToMatchedTracks const &)> && toDo)
|
||||
void ForEachTrackFile(std::string const & filepath, std::string const & extension,
|
||||
shared_ptr<routing::NumMwmIds> numMwmIds,
|
||||
std::function<void(std::string const & filename, MwmToMatchedTracks const &)> && toDo)
|
||||
{
|
||||
Platform::EFileType fileType = Platform::EFileType::Unknown;
|
||||
Platform::EError const result = Platform::GetFileType(filepath, fileType);
|
||||
|
||||
@@ -29,14 +29,12 @@ double CalcSpeedKMpH(double meters, uint64_t secondsElapsed);
|
||||
void ReadTracks(std::shared_ptr<routing::NumMwmIds> numMwmIds, std::string const & filename,
|
||||
MwmToMatchedTracks & mwmToMatchedTracks);
|
||||
MatchedTrack const & GetMatchedTrack(MwmToMatchedTracks const & mwmToMatchedTracks,
|
||||
routing::NumMwmIds const & numMwmIds,
|
||||
std::string const & mwmName, std::string const & user,
|
||||
size_t trackIdx);
|
||||
routing::NumMwmIds const & numMwmIds, std::string const & mwmName,
|
||||
std::string const & user, size_t trackIdx);
|
||||
std::string GetCurrentVersionMwmFile(storage::Storage const & storage, std::string const & mwmName);
|
||||
|
||||
template <typename MwmToTracks, typename ToDo>
|
||||
void ForTracksSortedByMwmName(MwmToTracks const & mwmToTracks, routing::NumMwmIds const & numMwmIds,
|
||||
ToDo && toDo)
|
||||
void ForTracksSortedByMwmName(MwmToTracks const & mwmToTracks, routing::NumMwmIds const & numMwmIds, ToDo && toDo)
|
||||
{
|
||||
std::vector<std::string> mwmNames;
|
||||
mwmNames.reserve(mwmToTracks.size());
|
||||
@@ -53,8 +51,7 @@ void ForTracksSortedByMwmName(MwmToTracks const & mwmToTracks, routing::NumMwmId
|
||||
}
|
||||
}
|
||||
|
||||
void ForEachTrackFile(
|
||||
std::string const & filepath, std::string const & extension,
|
||||
std::shared_ptr<routing::NumMwmIds> numMwmIds,
|
||||
std::function<void(std::string const & filename, MwmToMatchedTracks const &)> && toDo);
|
||||
void ForEachTrackFile(std::string const & filepath, std::string const & extension,
|
||||
std::shared_ptr<routing::NumMwmIds> numMwmIds,
|
||||
std::function<void(std::string const & filename, MwmToMatchedTracks const &)> && toDo);
|
||||
} // namespace track_analyzing
|
||||
|
||||
@@ -13,20 +13,22 @@ DEFINE_string(inputDir, "", "Path to kmls.");
|
||||
|
||||
DEFINE_string(outputDir, "", "Path to converted kmls.");
|
||||
|
||||
DEFINE_int32(vehicleType, 0, "Numeric value of routing::VehicleType enum. "
|
||||
"Pedestrian by default.");
|
||||
DEFINE_int32(vehicleType, 0,
|
||||
"Numeric value of routing::VehicleType enum. "
|
||||
"Pedestrian by default.");
|
||||
|
||||
DEFINE_bool(showHelp, false, "Show help on all flags.");
|
||||
|
||||
int main(int argc, char ** argv)
|
||||
{
|
||||
gflags::SetUsageMessage("The tool is used to generate more smooth track based on "
|
||||
"waypoints from the kml. The kml has to contain points "
|
||||
"within LineString tag. If the router can't build the route "
|
||||
"than the specific path will be untouched. Multiple kmls into "
|
||||
" the directory are supported.\n\n"
|
||||
"Usage example: "
|
||||
"./track_generator_tool -inputDir=path/to/input/ -outputDir=/path/to/output/");
|
||||
gflags::SetUsageMessage(
|
||||
"The tool is used to generate more smooth track based on "
|
||||
"waypoints from the kml. The kml has to contain points "
|
||||
"within LineString tag. If the router can't build the route "
|
||||
"than the specific path will be untouched. Multiple kmls into "
|
||||
" the directory are supported.\n\n"
|
||||
"Usage example: "
|
||||
"./track_generator_tool -inputDir=path/to/input/ -outputDir=/path/to/output/");
|
||||
|
||||
gflags::ParseCommandLineFlags(&argc, &argv, false /* remove_flags */);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user