Change location data method to way:get_location_tags(key)

This commit is contained in:
Michael Krasnyk 2017-09-22 16:14:55 +02:00
parent 0f498d13f5
commit 095b345713
6 changed files with 89 additions and 98 deletions

View File

@ -38,9 +38,9 @@ Feature: osrm-extract lua ways:get_nodes()
functions = require('testbot') functions = require('testbot')
function way_function(profile, way, result, relations) function way_function(profile, way, result, relations)
location_data = way:get_location_tags() for _, key in ipairs({'answer', 'boolean', 'object', 'array'}) do
assert(location_data) print (key .. ' ' .. tostring(way:get_location_tag(key)))
for k, v in pairs(location_data) do print (k .. ' ' .. tostring(v)) end end
result.forward_mode = mode.driving result.forward_mode = mode.driving
result.forward_speed = 1 result.forward_speed = 1
end end
@ -60,7 +60,9 @@ Feature: osrm-extract lua ways:get_nodes()
When I run "osrm-extract --profile {profile_file} {osm_file} --location-dependent-data test/data/regions/null-island.geojson" When I run "osrm-extract --profile {profile_file} {osm_file} --location-dependent-data test/data/regions/null-island.geojson"
Then it should exit successfully Then it should exit successfully
And stdout should contain "answer 42" And stdout should contain "answer 42"
And stdout should not contain "array" And stdout should contain "boolean true"
And stdout should contain "array nil"
And stdout should contain "object nil"
Scenario: osrm-extract location-dependent data with multi-polygons Scenario: osrm-extract location-dependent data with multi-polygons
@ -69,9 +71,7 @@ Feature: osrm-extract lua ways:get_nodes()
functions = require('testbot') functions = require('testbot')
function way_function(profile, way, result, relations) function way_function(profile, way, result, relations)
location_data = way:get_location_tags() print('ISO3166-1 ' .. (way:get_location_tag('ISO3166-1') or 'none'))
assert(location_data)
print('ISO3166-1 ' .. (location_data['ISO3166-1'] or 'none'))
result.forward_mode = mode.driving result.forward_mode = mode.driving
result.forward_speed = 1 result.forward_speed = 1
end end
@ -104,9 +104,7 @@ Feature: osrm-extract lua ways:get_nodes()
functions = require('testbot') functions = require('testbot')
function way_function(profile, way, result, relations) function way_function(profile, way, result, relations)
location_data = way:get_location_tags() print ('answer ' .. tostring(way:get_location_tag('answer')))
assert(location_data)
for k, v in pairs(location_data) do print (k .. ' ' .. tostring(v)) end
result.forward_mode = mode.driving result.forward_mode = mode.driving
result.forward_speed = 1 result.forward_speed = 1
end end
@ -126,4 +124,3 @@ Feature: osrm-extract lua ways:get_nodes()
When I run "osrm-extract --profile {profile_file} {osm_file} --location-dependent-data test/data/regions/null-island.geojson" When I run "osrm-extract --profile {profile_file} {osm_file} --location-dependent-data test/data/regions/null-island.geojson"
Then it should exit successfully Then it should exit successfully
And stdout should contain "answer 42" And stdout should contain "answer 42"
And stdout should not contain "array"

View File

@ -38,7 +38,7 @@ struct LocationDependentData
bool empty() const { return rtree.empty(); } bool empty() const { return rtree.empty(); }
properties_t operator()(const point_t &point) const; property_t operator()(const point_t &point, const char *key) const;
private: private:
void loadLocationDependentData(const boost::filesystem::path &file_path); void loadLocationDependentData(const boost::filesystem::path &file_path);

View File

@ -553,20 +553,19 @@ function WayHandlers.blocked_ways(profile,way,result,data)
end end
function WayHandlers.driving_side(profile, way, result, data) function WayHandlers.driving_side(profile, way, result, data)
local driving_side = way:get_value_by_key("driving_side") local driving_side = way:get_value_by_key('driving_side')
if driving_side == nil then
driving_side = way:get_location_tag('driving_side')
end
if driving_side == 'left' then if driving_side == 'left' then
result.is_left_hand_driving = true result.is_left_hand_driving = true
elseif driving_side == 'right' then elseif driving_side == 'right' then
result.is_left_hand_driving = false result.is_left_hand_driving = false
else
location_data = way:get_location_tags()
if location_data and location_data['driving_side'] then
result.is_left_hand_driving = location_data['driving_side'] == 'left'
else else
result.is_left_hand_driving = profile.left_hand_driving result.is_left_hand_driving = profile.left_hand_driving
end end
end end
end
-- Call a sequence of handlers, aborting in case a handler returns false. Example: -- Call a sequence of handlers, aborting in case a handler returns false. Example:

View File

@ -195,17 +195,25 @@ void LocationDependentData::loadLocationDependentData(const boost::filesystem::p
<< polygons.size() << " GeoJSON polygons"; << polygons.size() << " GeoJSON polygons";
} }
LocationDependentData::properties_t LocationDependentData::operator()(const point_t &point) const LocationDependentData::property_t LocationDependentData::operator()(const point_t &point,
const char *key) const
{ {
properties_t result; property_t result;
auto merger = [this, &result](const rtree_t::value_type &rtree_entry) { auto setter = [this, &result, &key](const rtree_t::value_type &rtree_entry) {
const auto &polygon_properties = properties[polygons[rtree_entry.second].second]; const auto properties_index = polygons[rtree_entry.second].second;
result.insert(polygon_properties.begin(), polygon_properties.end()); const auto &polygon_properties = properties[properties_index];
const auto it = polygon_properties.find(key);
if (it != polygon_properties.end())
{
result = it->second;
}
}; };
// Search the R-tree and collect a Lua table of tags that correspond to the location // Search the R-tree and collect a Lua table of tags that correspond to the location
rtree.query(boost::geometry::index::intersects(point) && rtree.query(boost::geometry::index::satisfies(
[&result](const rtree_t::value_type &) { return result.which() == 0; }) &&
boost::geometry::index::intersects(point) &&
boost::geometry::index::satisfies([this, &point](const rtree_t::value_type &v) { boost::geometry::index::satisfies([this, &point](const rtree_t::value_type &v) {
// Simple point-in-polygon algorithm adapted from // Simple point-in-polygon algorithm adapted from
@ -261,7 +269,7 @@ LocationDependentData::properties_t LocationDependentData::operator()(const poin
return inside; return inside;
}), }),
boost::make_function_output_iterator(std::ref(merger))); boost::make_function_output_iterator(std::ref(setter)));
return result; return result;
} }

View File

@ -82,26 +82,13 @@ template <class T> double lonToDouble(T const &object)
return static_cast<double>(util::toFloating(object.lon)); return static_cast<double>(util::toFloating(object.lon));
} }
// boost::variant visitor that inserts a key-value pair in a Lua table struct to_lua_object : public boost::static_visitor<sol::object>
struct table_setter : public boost::static_visitor<>
{ {
table_setter(sol::table &table, const std::string &key) : table(table), key(key) {} to_lua_object(sol::state &state) : state(state) {}
template <typename T> void operator()(const T &value) const { table.set(key, value); } template <typename T> auto operator()(T &v) const { return sol::make_object(state, v); }
void operator()(const boost::blank &) const { /* ignore */} auto operator()(boost::blank &) const { return sol::nil; }
sol::state &state;
sol::table &table;
const std::string &key;
}; };
// Converts a properties map into a Lua table
sol::table toLua(sol::state &state, const LocationDependentData::properties_t &properties)
{
auto table = sol::table(state, sol::create);
std::for_each(properties.begin(), properties.end(), [&table](const auto &property) {
boost::apply_visitor(table_setter(table, property.first), property.second);
});
return table;
}
} }
Sol2ScriptingEnvironment::Sol2ScriptingEnvironment( Sol2ScriptingEnvironment::Sol2ScriptingEnvironment(
@ -313,15 +300,15 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
&osmium::Way::version, &osmium::Way::version,
"get_nodes", "get_nodes",
[](const osmium::Way &way) { return sol::as_table(way.nodes()); }, [](const osmium::Way &way) { return sol::as_table(way.nodes()); },
"get_location_tags", "get_location_tag",
[&context](const osmium::Way &way) { [&context](const osmium::Way &way, const char *key) {
// HEURISTIC: use a single node (last) of the way to localize the way // HEURISTIC: use a single node (last) of the way to localize the way
// For more complicated scenarios a proper merging of multiple tags // For more complicated scenarios a proper merging of multiple tags
// at one or many locations must be provided // at one or many locations must be provided
const auto &nodes = way.nodes(); const auto &nodes = way.nodes();
const auto &location = nodes.back().location(); const auto &location = nodes.back().location();
return toLua(context.state, auto value = context.location_dependent_data({location.lon(), location.lat()}, key);
context.location_dependent_data({location.lon(), location.lat()})); return boost::apply_visitor(to_lua_object(context.state), value);
}); });
context.state.new_usertype<osmium::RelationMember>( context.state.new_usertype<osmium::RelationMember>(

View File

@ -50,15 +50,15 @@ BOOST_AUTO_TEST_CASE(polygon_tests)
]})json"); ]})json");
LocationDependentData data(fixture.temporary_file); LocationDependentData data(fixture.temporary_file);
BOOST_CHECK(data(point_t(0, 0)).empty()); BOOST_CHECK_EQUAL(data(point_t(0, 0), "answer").which(), 0);
BOOST_CHECK(!data(point_t(1, 1)).empty()); BOOST_CHECK_EQUAL(boost::get<double>(data(point_t(1, 1), "answer")), 42);
BOOST_CHECK(!data(point_t(0, 1)).empty()); BOOST_CHECK_EQUAL(boost::get<double>(data(point_t(0, 1), "answer")), 42);
BOOST_CHECK(!data(point_t(0.5, -0.5)).empty()); BOOST_CHECK_EQUAL(boost::get<double>(data(point_t(0.5, -0.5), "answer")), 42);
BOOST_CHECK(!data(point_t(0, -3)).empty()); BOOST_CHECK_EQUAL(boost::get<double>(data(point_t(0, -3), "answer")), 42);
BOOST_CHECK(!data(point_t(-0.75, 0.75)).empty()); BOOST_CHECK_EQUAL(boost::get<double>(data(point_t(-0.75, 0.75), "answer")), 42);
BOOST_CHECK(!data(point_t(-2, 6)).empty()); BOOST_CHECK_EQUAL(boost::get<double>(data(point_t(2, 0), "answer")), 42.);
BOOST_CHECK_EQUAL(boost::get<double>(data(point_t(2, 0))["answer"]), 42.); BOOST_CHECK_EQUAL(boost::get<bool>(data(point_t(1, 7), "answer")), true);
BOOST_CHECK_EQUAL(boost::get<bool>(data(point_t(1, 7))["answer"]), true); BOOST_CHECK_EQUAL(boost::get<bool>(data(point_t(-2, 6), "answer")), true);
} }
BOOST_AUTO_TEST_CASE(multy_polygon_tests) BOOST_AUTO_TEST_CASE(multy_polygon_tests)
@ -80,11 +80,11 @@ BOOST_AUTO_TEST_CASE(multy_polygon_tests)
]})json"); ]})json");
LocationDependentData data(fixture.temporary_file); LocationDependentData data(fixture.temporary_file);
BOOST_CHECK(data(point_t(0, 2)).empty()); BOOST_CHECK_EQUAL(data(point_t(0, 2), "answer").which(), 0);
BOOST_CHECK(data(point_t(0, -3)).empty()); BOOST_CHECK_EQUAL(data(point_t(0, -3), "answer").which(), 0);
BOOST_CHECK_EQUAL(boost::get<double>(data(point_t(0, 0))["answer"]), 42.); BOOST_CHECK_EQUAL(boost::get<double>(data(point_t(0, 0), "answer")), 42.);
BOOST_CHECK_EQUAL(boost::get<double>(data(point_t(5, 0))["answer"]), 42.); BOOST_CHECK_EQUAL(boost::get<double>(data(point_t(5, 0), "answer")), 42.);
BOOST_CHECK_EQUAL(boost::get<double>(data(point_t(-5, 0))["answer"]), 42.); BOOST_CHECK_EQUAL(boost::get<double>(data(point_t(-5, 0), "answer")), 42.);
} }
BOOST_AUTO_TEST_CASE(polygon_merging_tests) BOOST_AUTO_TEST_CASE(polygon_merging_tests)
@ -110,19 +110,19 @@ BOOST_AUTO_TEST_CASE(polygon_merging_tests)
]})json"); ]})json");
LocationDependentData data(fixture.temporary_file); LocationDependentData data(fixture.temporary_file);
BOOST_CHECK_EQUAL(boost::get<std::string>(data(point_t(-3, 3))["answer"]), "a"); BOOST_CHECK_EQUAL(boost::get<std::string>(data(point_t(-3, 3), "answer")), "a");
BOOST_CHECK_EQUAL(boost::get<std::string>(data(point_t(-3, 1))["answer"]), "a"); BOOST_CHECK_EQUAL(boost::get<std::string>(data(point_t(-3, 1), "answer")), "a");
BOOST_CHECK_EQUAL(boost::get<std::string>(data(point_t(-3, -3))["answer"]), "a"); BOOST_CHECK_EQUAL(boost::get<std::string>(data(point_t(-3, -3), "answer")), "a");
BOOST_CHECK_EQUAL(boost::get<std::string>(data(point_t(0, 3))["answer"]), "a"); BOOST_CHECK_EQUAL(boost::get<std::string>(data(point_t(0, 3), "answer")), "a");
BOOST_CHECK_EQUAL(boost::get<std::string>(data(point_t(1, 0))["answer"]), "a"); BOOST_CHECK_EQUAL(boost::get<std::string>(data(point_t(1, 0), "answer")), "a");
BOOST_CHECK_EQUAL(boost::get<std::string>(data(point_t(2, -3))["answer"]), "a"); BOOST_CHECK_EQUAL(boost::get<std::string>(data(point_t(2, -3), "answer")), "a");
BOOST_CHECK_EQUAL(boost::get<std::string>(data(point_t(3, 0))["answer"]), "a"); BOOST_CHECK_EQUAL(boost::get<std::string>(data(point_t(3, 0), "answer")), "a");
BOOST_CHECK_EQUAL(boost::get<std::string>(data(point_t(4, 3))["answer"]), "b"); BOOST_CHECK_EQUAL(boost::get<std::string>(data(point_t(4, 3), "answer")), "b");
BOOST_CHECK_EQUAL(boost::get<std::string>(data(point_t(6, 1))["answer"]), "b"); BOOST_CHECK_EQUAL(boost::get<std::string>(data(point_t(6, 1), "answer")), "b");
BOOST_CHECK_EQUAL(boost::get<std::string>(data(point_t(7, 0))["answer"]), "b"); BOOST_CHECK_EQUAL(boost::get<std::string>(data(point_t(7, 0), "answer")), "b");
BOOST_CHECK_EQUAL(boost::get<std::string>(data(point_t(8, 3))["answer"]), "c"); BOOST_CHECK_EQUAL(boost::get<std::string>(data(point_t(8, 3), "answer")), "c");
BOOST_CHECK_EQUAL(boost::get<std::string>(data(point_t(8, -1))["answer"]), "c"); BOOST_CHECK_EQUAL(boost::get<std::string>(data(point_t(8, -1), "answer")), "c");
BOOST_CHECK_EQUAL(boost::get<std::string>(data(point_t(8, -3))["answer"]), "c"); BOOST_CHECK_EQUAL(boost::get<std::string>(data(point_t(8, -3), "answer")), "c");
} }
BOOST_AUTO_TEST_CASE(staircase_polygon) BOOST_AUTO_TEST_CASE(staircase_polygon)
@ -140,31 +140,31 @@ BOOST_AUTO_TEST_CASE(staircase_polygon)
LocationDependentData data(fixture.temporary_file); LocationDependentData data(fixture.temporary_file);
// all corners // all corners
BOOST_CHECK(!data(point_t(0, 0)).empty()); BOOST_CHECK_NE(data(point_t(0, 0), "answer").which(), 0);
BOOST_CHECK(!data(point_t(0, 1)).empty()); BOOST_CHECK_NE(data(point_t(0, 1), "answer").which(), 0);
BOOST_CHECK(!data(point_t(1, 1)).empty()); BOOST_CHECK_NE(data(point_t(1, 1), "answer").which(), 0);
BOOST_CHECK(!data(point_t(1, 2)).empty()); BOOST_CHECK_NE(data(point_t(1, 2), "answer").which(), 0);
BOOST_CHECK(!data(point_t(2, 2)).empty()); BOOST_CHECK_NE(data(point_t(2, 2), "answer").which(), 0);
BOOST_CHECK(!data(point_t(2, 3)).empty()); BOOST_CHECK_NE(data(point_t(2, 3), "answer").which(), 0);
BOOST_CHECK(!data(point_t(3, 3)).empty()); BOOST_CHECK_NE(data(point_t(3, 3), "answer").which(), 0);
BOOST_CHECK(!data(point_t(3, 0)).empty()); BOOST_CHECK_NE(data(point_t(3, 0), "answer").which(), 0);
// at x = 1 // // at x = 1
BOOST_CHECK(data(point_t(1, -0.5)).empty()); BOOST_CHECK_EQUAL(data(point_t(1, -0.5), "answer").which(), 0);
BOOST_CHECK(!data(point_t(1, 0)).empty()); BOOST_CHECK_NE(data(point_t(1, 0), "answer").which(), 0);
BOOST_CHECK(!data(point_t(1, 0.5)).empty()); BOOST_CHECK_NE(data(point_t(1, 0.5), "answer").which(), 0);
BOOST_CHECK(!data(point_t(1, 1.5)).empty()); BOOST_CHECK_NE(data(point_t(1, 1.5), "answer").which(), 0);
BOOST_CHECK(data(point_t(1, 2.5)).empty()); BOOST_CHECK_EQUAL(data(point_t(1, 2.5), "answer").which(), 0);
BOOST_CHECK(data(point_t(3.5, 2)).empty()); BOOST_CHECK_EQUAL(data(point_t(3.5, 2), "answer").which(), 0);
// at y = 2 // // at y = 2
BOOST_CHECK(data(point_t(0.5, 2)).empty()); BOOST_CHECK_EQUAL(data(point_t(0.5, 2), "answer").which(), 0);
BOOST_CHECK(!data(point_t(1, 2)).empty()); BOOST_CHECK_NE(data(point_t(1, 2), "answer").which(), 0);
BOOST_CHECK(!data(point_t(1.5, 2)).empty()); BOOST_CHECK_NE(data(point_t(1.5, 2), "answer").which(), 0);
BOOST_CHECK(!data(point_t(2, 2)).empty()); BOOST_CHECK_NE(data(point_t(2, 2), "answer").which(), 0);
BOOST_CHECK(!data(point_t(2.5, 2)).empty()); BOOST_CHECK_NE(data(point_t(2.5, 2), "answer").which(), 0);
BOOST_CHECK(!data(point_t(3, 2)).empty()); BOOST_CHECK_NE(data(point_t(3, 2), "answer").which(), 0);
BOOST_CHECK(data(point_t(3.5, 2)).empty()); BOOST_CHECK_EQUAL(data(point_t(3.5, 2), "answer").which(), 0);
} }
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()