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')
function way_function(profile, way, result, relations)
location_data = way:get_location_tags()
assert(location_data)
for k, v in pairs(location_data) do print (k .. ' ' .. tostring(v)) end
for _, key in ipairs({'answer', 'boolean', 'object', 'array'}) do
print (key .. ' ' .. tostring(way:get_location_tag(key)))
end
result.forward_mode = mode.driving
result.forward_speed = 1
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"
Then it should exit successfully
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
@ -69,9 +71,7 @@ Feature: osrm-extract lua ways:get_nodes()
functions = require('testbot')
function way_function(profile, way, result, relations)
location_data = way:get_location_tags()
assert(location_data)
print('ISO3166-1 ' .. (location_data['ISO3166-1'] or 'none'))
print('ISO3166-1 ' .. (way:get_location_tag('ISO3166-1') or 'none'))
result.forward_mode = mode.driving
result.forward_speed = 1
end
@ -104,9 +104,7 @@ Feature: osrm-extract lua ways:get_nodes()
functions = require('testbot')
function way_function(profile, way, result, relations)
location_data = way:get_location_tags()
assert(location_data)
for k, v in pairs(location_data) do print (k .. ' ' .. tostring(v)) end
print ('answer ' .. tostring(way:get_location_tag('answer')))
result.forward_mode = mode.driving
result.forward_speed = 1
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"
Then it should exit successfully
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(); }
properties_t operator()(const point_t &point) const;
property_t operator()(const point_t &point, const char *key) const;
private:
void loadLocationDependentData(const boost::filesystem::path &file_path);

View File

@ -553,18 +553,17 @@ function WayHandlers.blocked_ways(profile,way,result,data)
end
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
result.is_left_hand_driving = true
elseif driving_side == 'right' then
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
result.is_left_hand_driving = profile.left_hand_driving
end
result.is_left_hand_driving = profile.left_hand_driving
end
end

View File

@ -195,17 +195,25 @@ void LocationDependentData::loadLocationDependentData(const boost::filesystem::p
<< 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) {
const auto &polygon_properties = properties[polygons[rtree_entry.second].second];
result.insert(polygon_properties.begin(), polygon_properties.end());
auto setter = [this, &result, &key](const rtree_t::value_type &rtree_entry) {
const auto properties_index = polygons[rtree_entry.second].second;
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
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) {
// Simple point-in-polygon algorithm adapted from
@ -261,7 +269,7 @@ LocationDependentData::properties_t LocationDependentData::operator()(const poin
return inside;
}),
boost::make_function_output_iterator(std::ref(merger)));
boost::make_function_output_iterator(std::ref(setter)));
return result;
}

View File

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

View File

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