Skip to content

Commit

Permalink
Replace language_poly vector with rtree in graph building for 6x spee…
Browse files Browse the repository at this point in the history
…d-up.
  • Loading branch information
lseelenbinder committed Mar 28, 2024
1 parent b0cd4ea commit 54f7128
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 54 deletions.
61 changes: 31 additions & 30 deletions src/mjolnir/admin.cc
Original file line number Diff line number Diff line change
Expand Up @@ -70,17 +70,16 @@ uint32_t GetMultiPolyId(const std::multimap<uint32_t, multi_polygon_type>& 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<std::pair<std::string, bool>>
GetMultiPolyIndexes(const std::vector<std::tuple<std::string, multi_polygon_type, bool>>& polys,
const PointLL& ll) {
std::vector<std::pair<std::string, bool>> GetMultiPolyIndexes(
const language_poly_index& polys,
const PointLL& ll) {

auto process_languages = [](const std::vector<std::string>& langs, bool is_default,
std::vector<std::pair<std::string, bool>>& languages) {
for (const auto& l : langs) {
if (stringLanguage(l) != Language::kNone) {
std::vector<std::pair<std::string, bool>>::iterator it =
std::find_if(languages.begin(), languages.end(),
[&l](const std::pair<std::string, bool>& p) { return p.first == l; });
auto it = std::find_if(languages.begin(), languages.end(),
[&l](const std::pair<std::string, bool>& 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
Expand All @@ -99,24 +98,22 @@ GetMultiPolyIndexes(const std::vector<std::tuple<std::string, multi_polygon_type

point_type p(ll.lng(), ll.lat());

for (const auto& poly : polys) {

if (boost::geometry::covered_by(p, std::get<1>(poly))) {
lang = std::get<0>(poly);
it = std::find_if(languages.begin(), languages.end(),
[&lang](const std::pair<std::string, bool>& p) { return p.first == lang; });
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<std::string, bool>& p) { return p.first == lang; });

if (it == languages.end()) {
std::vector<std::string> langs = GetTagTokens(std::get<0>(poly), " - ");
if (it == languages.end()) {
std::vector<std::string> langs = GetTagTokens(lang, " - ");
if (langs.size() >= 2) {
process_languages(langs, is_default, languages);
} else {
langs = GetTagTokens(lang);
if (langs.size() >= 2) {
process_languages(langs, std::get<2>(poly), languages);
process_languages(langs, is_default, languages);
} else {
langs = GetTagTokens(std::get<0>(poly));
if (langs.size() >= 2) {
process_languages(langs, std::get<2>(poly), languages);
} else {
languages.emplace_back(std::get<0>(poly), std::get<2>(poly));
}
languages.emplace_back(lang, is_default);
}
}
}
Expand Down Expand Up @@ -188,7 +185,7 @@ void GetData(sqlite3* db_handle,
std::multimap<uint32_t, multi_polygon_type>& polys,
std::unordered_map<uint32_t, bool>& drive_on_right,
std::unordered_map<uint32_t, bool>& allow_intersection_names,
std::vector<std::tuple<std::string, multi_polygon_type, bool>>& language_ploys,
language_poly_index& language_ploys,
bool languages_only = false) {
uint32_t result = 0;
bool dor = true;
Expand Down Expand Up @@ -258,10 +255,12 @@ void GetData(sqlite3* db_handle,
drive_on_right.emplace(index, dor);
allow_intersection_names.emplace(index, intersection_name);

boost::geometry::model::box<point_type> box;
boost::geometry::envelope(multi_poly, box);
if (!default_language.empty())
language_ploys.push_back(std::make_tuple(default_language, multi_poly, true));
language_ploys.insert(std::make_tuple(box, multi_poly, default_language, true));
if (!supported_languages.empty())
language_ploys.push_back(std::make_tuple(supported_languages, multi_poly, false));
language_ploys.insert(std::make_tuple(box, multi_poly, supported_languages, false));

} else {

Expand All @@ -282,11 +281,13 @@ void GetData(sqlite3* db_handle,

multi_polygon_type multi_poly;
boost::geometry::read_wkt(geom, multi_poly);
boost::geometry::model::box<point_type> box;
boost::geometry::envelope(multi_poly, box);

if (!default_language.empty())
language_ploys.push_back(std::make_tuple(default_language, multi_poly, true));
language_ploys.insert(std::make_tuple(box, multi_poly, default_language, true));
if (!supported_languages.empty())
language_ploys.push_back(std::make_tuple(supported_languages, multi_poly, false));
language_ploys.insert(std::make_tuple(box, multi_poly, supported_languages, false));
}

result = sqlite3_step(stmt);
Expand All @@ -303,7 +304,7 @@ std::multimap<uint32_t, multi_polygon_type>
GetAdminInfo(sqlite3* db_handle,
std::unordered_map<uint32_t, bool>& drive_on_right,
std::unordered_map<uint32_t, bool>& allow_intersection_names,
std::vector<std::tuple<std::string, multi_polygon_type, bool>>& language_ploys,
language_poly_index& language_polys,
const AABB2<PointLL>& aabb,
GraphTileBuilder& tilebuilder) {
std::multimap<uint32_t, multi_polygon_type> polys;
Expand All @@ -326,7 +327,7 @@ GetAdminInfo(sqlite3* db_handle,
sql += std::to_string(aabb.miny()) + ", " + std::to_string(aabb.maxx()) + ",";
sql += std::to_string(aabb.maxy()) + ")) order by admin_level desc, name;";
GetData(db_handle, stmt, sql, tilebuilder, polys, drive_on_right, allow_intersection_names,
language_ploys, true);
language_polys, true);

// state query
sql = "SELECT country.name, state.name, country.iso_code, ";
Expand All @@ -342,7 +343,7 @@ GetAdminInfo(sqlite3* db_handle,
sql += std::to_string(aabb.miny()) + ", " + std::to_string(aabb.maxx()) + ",";
sql += std::to_string(aabb.maxy()) + ")) order by state.name, country.name;";
GetData(db_handle, stmt, sql, tilebuilder, polys, drive_on_right, allow_intersection_names,
language_ploys);
language_polys);

// country query
sql = "SELECT name, \"\", iso_code, \"\", drive_on_right, allow_intersection_names, admin_level, ";
Expand All @@ -356,7 +357,7 @@ GetAdminInfo(sqlite3* db_handle,
sql += std::to_string(aabb.miny()) + ", " + std::to_string(aabb.maxx()) + ",";
sql += std::to_string(aabb.maxy()) + ")) order by name;";
GetData(db_handle, stmt, sql, tilebuilder, polys, drive_on_right, allow_intersection_names,
language_ploys);
language_polys);

if (stmt) { // just in case something bad happened.
sqlite3_finalize(stmt);
Expand Down
6 changes: 3 additions & 3 deletions src/mjolnir/graphbuilder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -485,11 +485,11 @@ void BuildTileSet(const std::string& ways_file,
std::multimap<uint32_t, multi_polygon_type> admin_polys;
std::unordered_map<uint32_t, bool> drive_on_right;
std::unordered_map<uint32_t, bool> allow_intersection_names;
std::vector<std::tuple<std::string, multi_polygon_type, bool>> language_ploys;
language_poly_index language_polys;

if (admin_db_handle) {
admin_polys = GetAdminInfo(admin_db_handle, drive_on_right, allow_intersection_names,
language_ploys, tiling.TileBounds(id), graphtile);
language_polys, tiling.TileBounds(id), graphtile);
if (admin_polys.size() == 1) {
// TODO - check if tile bounding box is entirely inside the polygon...
tile_within_one_admin = true;
Expand Down Expand Up @@ -537,7 +537,7 @@ void BuildTileSet(const std::string& ways_file,
admin_index = (tile_within_one_admin) ? admin_polys.begin()->first
: GetMultiPolyId(admin_polys, node_ll, graphtile);
dor = drive_on_right[admin_index];
default_languages = GetMultiPolyIndexes(language_ploys, node_ll);
default_languages = GetMultiPolyIndexes(language_polys, node_ll);

} else {
admin_index = graphtile.AddAdmin("", "", osmdata.node_names.name(node.country_iso_index()),
Expand Down
46 changes: 25 additions & 21 deletions valhalla/mjolnir/admin.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ namespace mjolnir {
typedef boost::geometry::model::d2::point_xy<double> point_type;
typedef boost::geometry::model::polygon<point_type> polygon_type;
typedef boost::geometry::model::multi_polygon<polygon_type> multi_polygon_type;
typedef boost::geometry::index::rtree<
std::tuple<boost::geometry::model::box<point_type>, multi_polygon_type, std::string, bool>,
boost::geometry::index::rstar<1000>> language_poly_index;

/**
* Get the dbhandle of a sqlite db. Used for timezones and admins DBs.
Expand Down Expand Up @@ -54,13 +57,13 @@ uint32_t GetMultiPolyId(const std::multimap<uint32_t, multi_polygon_type>& polys
/**
* Get the vector of languages for this LL. Used by admin areas. Checks if the pointLL is covered_by
* the poly.
* @param polys tuple that contains a language, poly, is_default_language.
* @param language_polys tuple that contains a language, poly, is_default_language.
* @param ll point that needs to be checked.
* @return Returns the vector of pairs {language, is_default_language}
*/
std::vector<std::pair<std::string, bool>>
GetMultiPolyIndexes(const std::vector<std::tuple<std::string, multi_polygon_type, bool>>& polys,
const PointLL& ll);
std::vector<std::pair<std::string, bool>> GetMultiPolyIndexes(
const language_poly_index& language_ploys,
const PointLL& ll);

/**
* Get the timezone polys from the db
Expand All @@ -80,18 +83,19 @@ std::multimap<uint32_t, multi_polygon_type> GetTimeZones(sqlite3* db_handle,
* road
* @param default_languages ordered map that is used for lower admins that have an
* default language set
* @param language_ploys ordered map that is used for lower admins that have an
* @param language_polys ordered map that is used for lower admins that have an
* default language set
* @param languages_only should we only process the languages with this query
*/
void GetData(sqlite3* db_handle,
sqlite3_stmt* stmt,
const std::string& sql,
GraphTileBuilder& tilebuilder,
std::multimap<uint32_t, multi_polygon_type>& polys,
std::unordered_map<uint32_t, bool>& drive_on_right,
std::vector<std::tuple<std::string, multi_polygon_type, bool>>& language_ploys,
bool languages_only);
void GetData(
sqlite3* db_handle,
sqlite3_stmt* stmt,
const std::string& sql,
GraphTileBuilder& tilebuilder,
std::multimap<uint32_t, multi_polygon_type>& polys,
std::unordered_map<uint32_t, bool>& drive_on_right,
language_poly_index& language_polys,
bool languages_only);

/**
* Get the admin polys that intersect with the tile bounding box.
Expand All @@ -102,18 +106,18 @@ void GetData(sqlite3* db_handle,
* names for this country
* @param default_languages ordered map that is used for lower admins that have an
* default language set
* @param language_ploys ordered map that is used for lower admins that have an
* @param language_polys ordered map that is used for lower admins that have an
* default language set
* @param aabb bb of the tile
* @param tilebuilder Graph tile builder
*/
std::multimap<uint32_t, multi_polygon_type>
GetAdminInfo(sqlite3* db_handle,
std::unordered_map<uint32_t, bool>& drive_on_right,
std::unordered_map<uint32_t, bool>& allow_intersection_names,
std::vector<std::tuple<std::string, multi_polygon_type, bool>>& language_ploys,
const AABB2<PointLL>& aabb,
GraphTileBuilder& tilebuilder);
std::multimap<uint32_t, multi_polygon_type> GetAdminInfo(
sqlite3* db_handle,
std::unordered_map<uint32_t, bool>& drive_on_right,
std::unordered_map<uint32_t, bool>& allow_intersection_names,
language_poly_index& language_polys,
const AABB2<PointLL>& aabb,
GraphTileBuilder& tilebuilder);

/**
* Get all the country access records from the db and save them to a map.
Expand Down

0 comments on commit 54f7128

Please sign in to comment.