diff --git a/src/mjolnir/admin.cc b/src/mjolnir/admin.cc index 2424517cd9..ed495af61c 100644 --- a/src/mjolnir/admin.cc +++ b/src/mjolnir/admin.cc @@ -37,7 +37,7 @@ uint32_t GetMultiPolyId(const std::multimap& polys uint32_t index = 0; point_type p(ll.lng(), ll.lat()); for (const auto& poly : polys) { - if (boost::geometry::covered_by(p, poly.second)) { + if (bg::covered_by(p, poly.second, bg::strategy::within::crossings_multiply())) { const auto& admin = graphtile.admins_builder(poly.first); if (!admin.state_offset()) index = poly.first; @@ -55,8 +55,9 @@ uint32_t GetMultiPolyId(const std::multimap& polys point_type p(ll.lng(), ll.lat()); for (const auto& poly : polys) { // TODO: we recently discovered that boost::geometry doesn't do bbox checks to speed things up - if (boost::geometry::covered_by(p, poly.second)) + if (bg::covered_by(p, poly.second, bg::strategy::within::crossings_multiply())) { return poly.first; + } } return index; } @@ -70,50 +71,31 @@ uint32_t GetMultiPolyId(const std::multimap& polys // languages that will be considered for any name* or destination* keys. Basically, we only support // the languages that are on the signs in that area. Note: The first pair always contains an empty // language which makes the name key with no language the most important key. -std::vector> GetMultiPolyIndexes( - const language_poly_index& polys, - const PointLL& ll) { - - auto process_languages = [](const std::vector& langs, bool is_default, - std::vector>& languages) { - for (const auto& l : langs) { - if (stringLanguage(l) != Language::kNone) { - auto it = std::find_if(languages.begin(), languages.end(), - [&l](const std::pair& p) { return p.first == l; }); - if (it == languages.end()) { - languages.emplace_back(l, false); - } else if (is_default) { // fr - nl or fr;en in default lang column - it->second = false; - } - } - } - }; - +std::vector> GetMultiPolyIndexes(const language_poly_index& polys, + const PointLL& ll) { std::vector> languages; - std::vector>::iterator it; - std::string lang; // first entry is blank for the default name languages.emplace_back("", false); point_type p(ll.lng(), ll.lat()); - for (auto poly = polys.qbegin(boost::geometry::index::contains(p)); poly != polys.qend(); ++poly) { - lang = std::get<2>(*poly); - auto is_default = std::get<3>(*poly); - it = std::find_if(languages.begin(), languages.end(), - [&lang](const std::pair& p) { return p.first == lang; }); - - if (it == languages.end()) { - std::vector langs = GetTagTokens(lang, " - "); - if (langs.size() >= 2) { - process_languages(langs, is_default, languages); - } else { - langs = GetTagTokens(lang); - if (langs.size() >= 2) { - process_languages(langs, is_default, languages); - } else { - languages.emplace_back(lang, is_default); + for (auto it = polys.qbegin(bg::index::covers(p)); it != polys.qend(); ++it) { + // Make sure the point is in the admin poly (not just its envelope) + if (bg::covered_by(p, std::get<1>(*it), bg::strategy::within::crossings_multiply())) { + auto& langs = std::get<2>(*it); + bool is_default = std::get<3>(*it); + + for (const auto& l : langs) { + if (stringLanguage(l) != Language::kNone) { + auto needle = + std::find_if(languages.begin(), languages.end(), + [&l](const std::pair& p) { return p.first == l; }); + if (needle == languages.end()) { + languages.emplace_back(l, false); + } else if (is_default) { // fr - nl or fr;en in default lang column + needle->second = false; + } } } } @@ -178,6 +160,18 @@ std::multimap GetTimeZones(sqlite3* db_handle, return polys; } +/*** + * Parses a language tag into a vector of individual tokens. + */ +std::vector ParseLanguageTokens(const std::string& lang_tag) { + auto langs = GetTagTokens(lang_tag, " - "); + if (langs.size() == 1) { + langs = GetTagTokens(langs.at(0)); + } + + return langs; +} + void GetData(sqlite3* db_handle, sqlite3_stmt* stmt, const std::string& sql, @@ -250,17 +244,21 @@ void GetData(sqlite3* db_handle, uint32_t index = tilebuilder.AddAdmin(country_name, state_name, country_iso, state_iso); multi_polygon_type multi_poly; - boost::geometry::read_wkt(geom, multi_poly); + bg::read_wkt(geom, multi_poly); polys.emplace(index, multi_poly); drive_on_right.emplace(index, dor); allow_intersection_names.emplace(index, intersection_name); - boost::geometry::model::box box; - boost::geometry::envelope(multi_poly, box); - if (!default_language.empty()) - language_ploys.insert(std::make_tuple(box, multi_poly, default_language, true)); - if (!supported_languages.empty()) - language_ploys.insert(std::make_tuple(box, multi_poly, supported_languages, false)); + bg::model::box box{}; + bg::envelope(multi_poly, box); + if (!default_language.empty()) { + auto langs = ParseLanguageTokens(default_language); + language_ploys.insert(std::make_tuple(box, multi_poly, langs, true)); + } + if (!supported_languages.empty()) { + auto langs = ParseLanguageTokens(supported_languages); + language_ploys.insert(std::make_tuple(box, multi_poly, langs, false)); + } } else { @@ -280,14 +278,18 @@ void GetData(sqlite3* db_handle, } multi_polygon_type multi_poly; - boost::geometry::read_wkt(geom, multi_poly); - boost::geometry::model::box box; - boost::geometry::envelope(multi_poly, box); + bg::read_wkt(geom, multi_poly); + bg::model::box box{}; + bg::envelope(multi_poly, box); - if (!default_language.empty()) - language_ploys.insert(std::make_tuple(box, multi_poly, default_language, true)); - if (!supported_languages.empty()) - language_ploys.insert(std::make_tuple(box, multi_poly, supported_languages, false)); + if (!default_language.empty()) { + auto langs = ParseLanguageTokens(default_language); + language_ploys.insert(std::make_tuple(box, multi_poly, langs, true)); + } + if (!supported_languages.empty()) { + auto langs = ParseLanguageTokens(supported_languages); + language_ploys.insert(std::make_tuple(box, multi_poly, langs, false)); + } } result = sqlite3_step(stmt); diff --git a/src/mjolnir/graphbuilder.cc b/src/mjolnir/graphbuilder.cc index 74ff28e2f6..c874b70ffd 100644 --- a/src/mjolnir/graphbuilder.cc +++ b/src/mjolnir/graphbuilder.cc @@ -1394,7 +1394,9 @@ void GraphBuilder::Build(const boost::property_tree::ptree& pt, pt.get("mjolnir.concurrency", std::thread::hardware_concurrency())); // Build tiles at the local level. Form connected graph from nodes and edges. - std::string tile_dir = pt.get("mjolnir.tile_dir"); + auto tile_dir = pt.get("mjolnir.tile_dir"); + // Disable sqlite3 internal memory tracking (results in a high-contention mutex, and we don't care about marginal sqlite memory usage). + sqlite3_config(SQLITE_CONFIG_MEMSTATUS, false); BuildLocalTiles(threads, osmdata, ways_file, way_nodes_file, nodes_file, edges_file, complex_from_restriction_file, complex_to_restriction_file, tiles, tile_dir, stats, pt); diff --git a/valhalla/mjolnir/admin.h b/valhalla/mjolnir/admin.h index fc6c83097d..efe80f5984 100644 --- a/valhalla/mjolnir/admin.h +++ b/valhalla/mjolnir/admin.h @@ -23,12 +23,13 @@ namespace valhalla::mjolnir { namespace bg = boost::geometry; // Geometry types for admin queries -typedef boost::geometry::model::d2::point_xy point_type; -typedef boost::geometry::model::polygon polygon_type; -typedef boost::geometry::model::multi_polygon multi_polygon_type; -typedef boost::geometry::index::rtree< - std::tuple, multi_polygon_type, std::string, bool>, - boost::geometry::index::rstar<1000>> language_poly_index; +typedef bg::model::d2::point_xy point_type; +typedef bg::model::polygon polygon_type; +typedef bg::model::multi_polygon multi_polygon_type; +typedef bg::index::rtree< + std::tuple, multi_polygon_type, std::vector, bool>, + bg::index::rstar<16>> + language_poly_index; /** * Get the dbhandle of a sqlite db. Used for timezones and admins DBs. @@ -62,9 +63,8 @@ uint32_t GetMultiPolyId(const std::multimap& polys * @param ll point that needs to be checked. * @return Returns the vector of pairs {language, is_default_language} */ -std::vector> GetMultiPolyIndexes( - const language_poly_index& language_ploys, - const PointLL& ll); +std::vector> +GetMultiPolyIndexes(const language_poly_index& language_ploys, const PointLL& ll); /** * Get the timezone polys from the db