diff --git a/topography_generator/generator.cpp b/topography_generator/generator.cpp index 582a64517b..9ffd744b1e 100644 --- a/topography_generator/generator.cpp +++ b/topography_generator/generator.cpp @@ -9,6 +9,7 @@ #include "geometry/mercator.hpp" +#include "base/string_utils.hpp" #include "base/thread_pool_computational.hpp" #include @@ -124,7 +125,7 @@ public: auto const col = static_cast(std::round(kArcSecondsInDegree * ln)); auto const ix = row * (kArcSecondsInDegree + 1) + col; - CHECK(ix < m_values.size(), ()); + CHECK(ix < m_values.size(), (pos)); return m_values[ix]; } @@ -198,6 +199,11 @@ private: void ProcessTile(int lat, int lon) { auto const tileName = generator::SrtmTile::GetBase(ms::LatLon(lat, lon)); + + std::ostringstream os; + os << tileName << " (" << lat << ", " << lon << ")"; + m_debugId = os.str(); + if (!GetPlatform().IsFileExistsByFullPath(generator::SrtmTile::GetPath(m_strmDir, tileName))) { LOG(LINFO, ("SRTM tile", tileName, "doesn't exist, skip processing.")); @@ -226,6 +232,8 @@ private: LOG(LINFO, ("Isolines for tile", tileName, "min altitude", contours.m_minValue, "max altitude", contours.m_maxValue, "invalid values count", contours.m_invalidValuesCount)); + if (m_params.m_simplificationZoom > 0) + SimplifyContours(m_params.m_simplificationZoom, contours); SaveContrours(GetIsolinesFilePath(lat, lon, m_params.m_outputDir), std::move(contours)); LOG(LINFO, ("End generating isolines for tile", tileName)); @@ -274,6 +282,7 @@ private: MarchingSquares squares(leftBottom, rightTop, squaresStep, m_params.m_alitudesStep, altProvider); + squares.SetDebugId(m_debugId); squares.GenerateContours(contours); } @@ -284,17 +293,14 @@ private: std::string m_strmDir; SrtmProvider m_srtmProvider; TileIsolinesParams const & m_params; + std::string m_debugId; }; Generator::Generator(std::string const & srtmPath, size_t threadsCount, size_t maxCachedTilesPerThread) : m_threadsCount(threadsCount) , m_maxCachedTilesPerThread(maxCachedTilesPerThread) , m_srtmPath(srtmPath) -{ - m_infoGetter = storage::CountryInfoReader::CreateCountryInfoReader(GetPlatform()); - CHECK(m_infoGetter, ()); - m_infoReader = static_cast(m_infoGetter.get()); -} +{} void Generator::GenerateIsolines(int left, int bottom, int right, int top, TileIsolinesParams const & params) @@ -337,6 +343,17 @@ void Generator::GenerateIsolines(int left, int bottom, int right, int top, } } +void Generator::InitCountryInfoGetter(std::string const & dataDir) +{ + CHECK(m_infoReader == nullptr, ()); + + GetPlatform().SetResourceDir(dataDir); + + m_infoGetter = storage::CountryInfoReader::CreateCountryInfoReader(GetPlatform()); + CHECK(m_infoGetter, ()); + m_infoReader = static_cast(m_infoGetter.get()); +} + void Generator::GetCountryRegions(storage::CountryId const & countryId, m2::RectD & countryRect, std::vector & countryRegions) { @@ -354,10 +371,11 @@ void Generator::GetCountryRegions(storage::CountryId const & countryId, m2::Rect } void Generator::PackIsolinesForCountry(storage::CountryId const & countryId, - std::string const & isolinesPath, - std::string const & outDir, - CountryIsolinesParams const & params) + CountryIsolinesParams const & params, + std::string const & outDir) { + LOG(LINFO, ("Begin packing isolines for country", countryId)); + m2::RectD countryRect; std::vector countryRegions; GetCountryRegions(countryId, countryRect, countryRegions); @@ -379,9 +397,12 @@ void Generator::PackIsolinesForCountry(storage::CountryId const & countryId, for (int lon = left; lon <= right; ++lon) { Contours isolines; - if (!LoadContours(GetIsolinesFilePath(lat, lon, isolinesPath), isolines)) + auto const tileFilePath = GetIsolinesFilePath(lat, lon, params.m_isolinesTilesPath); + if (!LoadContours(tileFilePath, isolines)) continue; + LOG(LINFO, ("Begin packing isolines from tile", tileFilePath)); + CropContours(countryRect, countryRegions, params.m_maxIsolineLength, params.m_alitudesStepFactor, isolines); if (params.m_simplificationZoom > 0) @@ -398,9 +419,18 @@ void Generator::PackIsolinesForCountry(storage::CountryId const & countryId, std::move(levelIsolines.second.begin(), levelIsolines.second.end(), std::back_inserter(dst)); } + + LOG(LINFO, ("End packing isolines from tile", tileFilePath)); } } - SaveContrours(GetIsolinesFilePath(countryId, outDir), std::move(countryIsolines)); + LOG(LINFO, ("End packing isolines for country", countryId, + "min altitude", countryIsolines.m_minValue, + "max altitude", countryIsolines.m_maxValue)); + + auto const outFile = GetIsolinesFilePath(countryId, outDir); + SaveContrours(outFile, std::move(countryIsolines)); + + LOG(LINFO, ("Isolines saved to", outFile)); } } // namespace topography_generator diff --git a/topography_generator/generator.hpp b/topography_generator/generator.hpp index c38038a5a8..f8a2d7fa9c 100644 --- a/topography_generator/generator.hpp +++ b/topography_generator/generator.hpp @@ -17,6 +17,7 @@ struct TileIsolinesParams { Altitude m_alitudesStep = 10; size_t m_latLonStepFactor = 1; + int m_simplificationZoom = 17; FiltersSequence m_filters; std::string m_outputDir; }; @@ -26,6 +27,7 @@ struct CountryIsolinesParams size_t m_maxIsolineLength = 1000; int m_simplificationZoom = 17; size_t m_alitudesStepFactor = 1; + std::string m_isolinesTilesPath; }; class Generator @@ -36,9 +38,11 @@ public: void GenerateIsolines(int left, int bottom, int right, int top, TileIsolinesParams const & params); + void InitCountryInfoGetter(std::string const & dataDir); + void PackIsolinesForCountry(storage::CountryId const & countryId, - std::string const & isolinesPath, - std::string const & outDir, CountryIsolinesParams const & params); + CountryIsolinesParams const & params, + std::string const & outDir); private: void GetCountryRegions(storage::CountryId const & countryId, m2::RectD & countryRect, diff --git a/topography_generator/main.cpp b/topography_generator/main.cpp index 07aca2f7ac..65df2da3e0 100644 --- a/topography_generator/main.cpp +++ b/topography_generator/main.cpp @@ -7,33 +7,14 @@ #include -/* The tool for isoline generating works in two modes: - * 1. Isolines generating mode. Generates binary tile with isolines for each STRM tile in tile rect. - * An isoline would be generated for each height isolines_step difference in height. - * Tiles for lat >= 60.0 && lat < -60.0 (converted from ASTER source) can be filtered by - * median and/or gaussian filters. - * Median filter activates by nonzero filter kernel radius median_r. - * Gaussian filter activates by gaussian_st_dev > 0.0 && gaussian_r_factor > 0.0 parameters. - * Contours generating steps through altitudes matrix of SRTM tile can be adjusted by - * latlon_step_factor parameter. - * Mode activates by passing a valid tiles rect (left, right, top, bottom params are integer). - * - * 2. Packing isolines from ready tiles into a binary file for specified country id. - * Tool gets isolines from the tiles, covered by the country regions, selects - * altitude levels with alt_step_factor (if a tile stores altitudes for each 10 meters - * and alt_step_factor == 5, the result binary file will store altitudes for each 50 meters). - * While packing isolines being cropped by the country regions, cut by max_length - * and simplified for simpl_zoom. - * Mode activates by passing a country id. - */ - DEFINE_string(out_dir, "", "Path to output directory."); +DEFINE_uint64(simpl_zoom, 16, "Isolines simplification zoom."); DEFINE_string(countryId, "", "Isolines packing mode. Pack isolines for countryId."); +DEFINE_string(data_dir, "", "Isolines packing mode. Path to data directory."); DEFINE_string(isolines_path, "", "Isolines packing mode. Path to the directory with isolines tiles."); -DEFINE_uint64(simpl_zoom, 16, "Isolines packing mode. Isolines simplification zoom."); DEFINE_uint64(max_length, 1000, "Isolines packing mode. Isolines max length."); DEFINE_uint64(alt_step_factor, 1, "Isolines packing mode. Altitude step factor."); @@ -51,9 +32,30 @@ DEFINE_uint64(median_r, 1, "Isolines generating mode. Median filter radius."); DEFINE_uint64(threads, 4, "Number of threads."); DEFINE_uint64(tiles_per_thread, 9, "Max cached tiles per thread"); - int main(int argc, char ** argv) { + google::SetUsageMessage( + "\n\nThis tool generates isolines and works in two modes:\n" + "1. 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" + "2. 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"); + google::ParseCommandLineFlags(&argc, &argv, true); if (FLAGS_out_dir.empty()) @@ -86,6 +88,12 @@ int main(int argc, char ** argv) FLAGS_tiles_per_thread); if (isPackingMode) { + if (FLAGS_data_dir.empty()) + { + LOG(LERROR, ("data_dir must be set.")); + return EXIT_FAILURE; + } + if (FLAGS_isolines_path.empty()) { LOG(LERROR, ("isolines_path must be set.")); @@ -96,8 +104,11 @@ int main(int argc, char ** argv) params.m_simplificationZoom = static_cast(FLAGS_simpl_zoom); params.m_maxIsolineLength = FLAGS_max_length; params.m_alitudesStepFactor = FLAGS_alt_step_factor; + params.m_isolinesTilesPath = FLAGS_isolines_path; + + generator.InitCountryInfoGetter(FLAGS_data_dir); + generator.PackIsolinesForCountry(FLAGS_countryId, params, FLAGS_out_dir); - generator.PackIsolinesForCountry(FLAGS_countryId, FLAGS_isolines_path, FLAGS_out_dir, params); return EXIT_SUCCESS; } @@ -126,6 +137,7 @@ int main(int argc, char ** argv) params.m_outputDir = FLAGS_out_dir; params.m_alitudesStep = FLAGS_isolines_step; params.m_latLonStepFactor = FLAGS_latlon_step_factor; + params.m_simplificationZoom = static_cast(FLAGS_simpl_zoom); generator.GenerateIsolines(FLAGS_left, FLAGS_bottom, FLAGS_right, FLAGS_top, params); diff --git a/topography_generator/marching_squares/contours_builder.cpp b/topography_generator/marching_squares/contours_builder.cpp index 701be024e1..56df0bc2f2 100644 --- a/topography_generator/marching_squares/contours_builder.cpp +++ b/topography_generator/marching_squares/contours_builder.cpp @@ -17,7 +17,7 @@ void ContoursBuilder::AddSegment(size_t levelInd, ms::LatLon const & beginPos, m if (beginPos.EqualDxDy(endPos, kEps)) return; - CHECK_LESS(levelInd, m_levelsCount, ()); + CHECK_LESS(levelInd, m_levelsCount, (m_debugId)); auto contourItBefore = FindContourWithEndPoint(levelInd, beginPos); auto contourItAfter = FindContourWithStartPoint(levelInd, endPos); diff --git a/topography_generator/marching_squares/contours_builder.hpp b/topography_generator/marching_squares/contours_builder.hpp index 4bbbab3ec6..8211c3fee1 100644 --- a/topography_generator/marching_squares/contours_builder.hpp +++ b/topography_generator/marching_squares/contours_builder.hpp @@ -42,6 +42,8 @@ public: } } + void SetDebugId(std::string const & debugId) { m_debugId = debugId; } + private: using ContourRaw = std::deque; using ContoursList = std::list; @@ -65,5 +67,7 @@ private: std::vector m_finalizedContours; std::vector m_activeContours; + + std::string m_debugId; }; } // namespace topography_generator diff --git a/topography_generator/marching_squares/marching_squares.hpp b/topography_generator/marching_squares/marching_squares.hpp index 03f8bc4737..2be6114bf4 100644 --- a/topography_generator/marching_squares/marching_squares.hpp +++ b/topography_generator/marching_squares/marching_squares.hpp @@ -43,6 +43,7 @@ public: } ContoursBuilder contoursBuilder(levelsCount); + contoursBuilder.SetDebugId(m_debugId); for (size_t i = 0; i < m_stepsCountLat; ++i) { @@ -51,6 +52,7 @@ public: { auto const pos = ms::LatLon(m_leftBottom.m_lat + m_step * i, m_leftBottom.m_lon + m_step * j); Square square(pos, m_step, result.m_minValue, m_valueStep, m_valuesProvider); + square.SetDebugId(m_debugId); square.GenerateSegments(contoursBuilder); } auto const isLastLine = i == m_stepsCountLat - 1; @@ -60,6 +62,8 @@ public: contoursBuilder.GetContours(result.m_minValue, result.m_valueStep, result.m_contours); } + void SetDebugId(std::string const & debugId) { m_debugId = debugId; } + private: void ScanValuesInRect(ValueType & minValue, ValueType & maxValue, size_t & invalidValuesCount) const { @@ -87,7 +91,7 @@ private: Square::ToLevelsRange(m_valueStep, minValue, maxValue); - CHECK_GREATER_OR_EQUAL(maxValue, minValue, ()); + CHECK_GREATER_OR_EQUAL(maxValue, minValue, (m_debugId)); } ms::LatLon const m_leftBottom; @@ -98,5 +102,7 @@ private: size_t m_stepsCountLon; size_t m_stepsCountLat; + + std::string m_debugId; }; } // namespace topography_generator diff --git a/topography_generator/marching_squares/square.hpp b/topography_generator/marching_squares/square.hpp index 4f17524987..c533bf5c10 100644 --- a/topography_generator/marching_squares/square.hpp +++ b/topography_generator/marching_squares/square.hpp @@ -34,7 +34,7 @@ public: ToLevelsRange(m_valueStep, minVal, maxVal); - CHECK_GREATER_OR_EQUAL(minVal, m_minValue, ()); + CHECK_GREATER_OR_EQUAL(minVal, m_minValue, (m_debugId)); for (auto val = minVal; val < maxVal; val += m_valueStep) AddSegments(val, (val - m_minValue) / m_valueStep, builder); @@ -53,6 +53,8 @@ public: maxVal = step * ((maxVal + 1) / step); } + void SetDebugId(std::string const & debugId) { m_debugId = debugId; } + private: enum class Rib { @@ -179,7 +181,7 @@ private: UNREACHABLE(); } - CHECK_NOT_EQUAL(val, val2, ()); + CHECK_NOT_EQUAL(val, val2, (m_debugId)); double const coeff = (val1 - val) / (val - val2); switch (rib) @@ -211,5 +213,7 @@ private: ValueType m_valueLT; ValueType m_valueRT; ValueType m_valueRB; + + std::string m_debugId; }; } // topography_generator