Implement raster source feature to read data from third-party sources, to be used in lua profiles.
* Adds a data structure, RasterSource, to store parsed + queryable data * Adds bindings for that and relevant data structures as well as source_function and segment_function * Adds relevant unit tests and cucumber tests * Bring-your-own-data feature
This commit is contained in:
parent
6cbbd1e5a1
commit
bac6703f8e
@ -51,10 +51,11 @@ configure_file(
|
|||||||
${CMAKE_CURRENT_SOURCE_DIR}/util/git_sha.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/util/git_sha.cpp
|
||||||
)
|
)
|
||||||
file(GLOB ExtractorGlob extractor/*.cpp)
|
file(GLOB ExtractorGlob extractor/*.cpp)
|
||||||
file(GLOB ImporterGlob data_structures/import_edge.cpp data_structures/external_memory_node.cpp)
|
file(GLOB ImporterGlob data_structures/import_edge.cpp data_structures/external_memory_node.cpp data_structures/raster_source.cpp)
|
||||||
add_library(IMPORT OBJECT ${ImporterGlob})
|
add_library(IMPORT OBJECT ${ImporterGlob})
|
||||||
add_library(LOGGER OBJECT util/simple_logger.cpp)
|
add_library(LOGGER OBJECT util/simple_logger.cpp)
|
||||||
add_library(PHANTOMNODE OBJECT data_structures/phantom_node.cpp)
|
add_library(PHANTOMNODE OBJECT data_structures/phantom_node.cpp)
|
||||||
|
add_library(RASTERSOURCE OBJECT data_structures/raster_source.cpp)
|
||||||
add_library(EXCEPTION OBJECT util/osrm_exception.cpp)
|
add_library(EXCEPTION OBJECT util/osrm_exception.cpp)
|
||||||
add_library(MERCATOR OBJECT util/mercator.cpp)
|
add_library(MERCATOR OBJECT util/mercator.cpp)
|
||||||
add_library(ANGLE OBJECT util/compute_angle.cpp)
|
add_library(ANGLE OBJECT util/compute_angle.cpp)
|
||||||
@ -102,7 +103,7 @@ add_executable(osrm-routed routed.cpp ${ServerGlob} $<TARGET_OBJECTS:EXCEPTION>)
|
|||||||
add_executable(osrm-datastore datastore.cpp $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:MERCATOR>)
|
add_executable(osrm-datastore datastore.cpp $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:MERCATOR>)
|
||||||
|
|
||||||
# Unit tests
|
# Unit tests
|
||||||
add_executable(datastructure-tests EXCLUDE_FROM_ALL unit_tests/datastructure_tests.cpp ${DataStructureTestsGlob} $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:PHANTOMNODE> $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:MERCATOR> $<TARGET_OBJECTS:COMPRESSEDEDGE> $<TARGET_OBJECTS:GRAPHCOMPRESSOR> $<TARGET_OBJECTS:RESTRICTION>)
|
add_executable(datastructure-tests EXCLUDE_FROM_ALL unit_tests/datastructure_tests.cpp ${DataStructureTestsGlob} $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:PHANTOMNODE> $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:MERCATOR> $<TARGET_OBJECTS:COMPRESSEDEDGE> $<TARGET_OBJECTS:GRAPHCOMPRESSOR> $<TARGET_OBJECTS:RESTRICTION> $<TARGET_OBJECTS:RASTERSOURCE>)
|
||||||
add_executable(algorithm-tests EXCLUDE_FROM_ALL unit_tests/algorithm_tests.cpp ${AlgorithmTestsGlob} $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:PHANTOMNODE> $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:RESTRICTION> $<TARGET_OBJECTS:COMPRESSEDEDGE>)
|
add_executable(algorithm-tests EXCLUDE_FROM_ALL unit_tests/algorithm_tests.cpp ${AlgorithmTestsGlob} $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:PHANTOMNODE> $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:RESTRICTION> $<TARGET_OBJECTS:COMPRESSEDEDGE>)
|
||||||
|
|
||||||
# Benchmarks
|
# Benchmarks
|
||||||
|
@ -65,12 +65,14 @@ IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
|||||||
|
|
||||||
SET PATH=c:\projects\osrm\osrm-deps\libs\bin;%PATH%
|
SET PATH=c:\projects\osrm\osrm-deps\libs\bin;%PATH%
|
||||||
|
|
||||||
|
CD ..
|
||||||
ECHO running datastructure-tests.exe ...
|
ECHO running datastructure-tests.exe ...
|
||||||
datastructure-tests.exe
|
%Configuration%\datastructure-tests.exe
|
||||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||||
ECHO running algorithm-tests.exe ...
|
ECHO running algorithm-tests.exe ...
|
||||||
algorithm-tests.exe
|
%Configuration%\algorithm-tests.exe
|
||||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||||
|
cd %Configuration%
|
||||||
|
|
||||||
IF NOT "%APPVEYOR_REPO_BRANCH%"=="develop" GOTO DONE
|
IF NOT "%APPVEYOR_REPO_BRANCH%"=="develop" GOTO DONE
|
||||||
ECHO ========= CREATING PACKAGES ==========
|
ECHO ========= CREATING PACKAGES ==========
|
||||||
|
178
data_structures/raster_source.cpp
Normal file
178
data_structures/raster_source.cpp
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2015, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "raster_source.hpp"
|
||||||
|
|
||||||
|
#include "../util/simple_logger.hpp"
|
||||||
|
#include "../util/timing_util.hpp"
|
||||||
|
|
||||||
|
#include <osrm/coordinate.hpp>
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
RasterSource::RasterSource(RasterGrid _raster_data,
|
||||||
|
std::size_t _width,
|
||||||
|
std::size_t _height,
|
||||||
|
int _xmin,
|
||||||
|
int _xmax,
|
||||||
|
int _ymin,
|
||||||
|
int _ymax)
|
||||||
|
: xstep(calcSize(_xmin, _xmax, _width)), ystep(calcSize(_ymin, _ymax, _height)),
|
||||||
|
raster_data(_raster_data), width(_width), height(_height), xmin(_xmin), xmax(_xmax),
|
||||||
|
ymin(_ymin), ymax(_ymax)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(xstep != 0);
|
||||||
|
BOOST_ASSERT(ystep != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
float RasterSource::calcSize(int min, int max, std::size_t count) const
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(count > 0);
|
||||||
|
return (max - min) / (static_cast<float>(count) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Query raster source for nearest data point
|
||||||
|
RasterDatum RasterSource::getRasterData(const int lon, const int lat) const
|
||||||
|
{
|
||||||
|
if (lon < xmin || lon > xmax || lat < ymin || lat > ymax)
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::size_t xth = static_cast<std::size_t>(round((lon - xmin) / xstep));
|
||||||
|
const std::size_t yth = static_cast<std::size_t>(round((ymax - lat) / ystep));
|
||||||
|
|
||||||
|
return {raster_data(xth, yth)};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Query raster source using bilinear interpolation
|
||||||
|
RasterDatum RasterSource::getRasterInterpolate(const int lon, const int lat) const
|
||||||
|
{
|
||||||
|
if (lon < xmin || lon > xmax || lat < ymin || lat > ymax)
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto xthP = (lon - xmin) / xstep;
|
||||||
|
const auto ythP = (ymax - lat) / ystep;
|
||||||
|
|
||||||
|
const std::size_t top = static_cast<std::size_t>(fmax(floor(ythP), 0));
|
||||||
|
const std::size_t bottom = static_cast<std::size_t>(fmin(ceil(ythP), height - 1));
|
||||||
|
const std::size_t left = static_cast<std::size_t>(fmax(floor(xthP), 0));
|
||||||
|
const std::size_t right = static_cast<std::size_t>(fmin(ceil(xthP), width - 1));
|
||||||
|
|
||||||
|
// Calculate distances from corners for bilinear interpolation
|
||||||
|
const float fromLeft = (lon - left * xstep + xmin) / xstep;
|
||||||
|
const float fromTop = (ymax - top * ystep - lat) / ystep;
|
||||||
|
const float fromRight = 1 - fromLeft;
|
||||||
|
const float fromBottom = 1 - fromTop;
|
||||||
|
|
||||||
|
return {static_cast<std::int32_t>(raster_data(left, top) * (fromRight * fromBottom) +
|
||||||
|
raster_data(right, top) * (fromLeft * fromBottom) +
|
||||||
|
raster_data(left, bottom) * (fromRight * fromTop) +
|
||||||
|
raster_data(right, bottom) * (fromLeft * fromTop))};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load raster source into memory
|
||||||
|
int SourceContainer::loadRasterSource(const std::string &path_string,
|
||||||
|
double xmin,
|
||||||
|
double xmax,
|
||||||
|
double ymin,
|
||||||
|
double ymax,
|
||||||
|
std::size_t nrows,
|
||||||
|
std::size_t ncols)
|
||||||
|
{
|
||||||
|
const auto _xmin = static_cast<int>(xmin * COORDINATE_PRECISION);
|
||||||
|
const auto _xmax = static_cast<int>(xmax * COORDINATE_PRECISION);
|
||||||
|
const auto _ymin = static_cast<int>(ymin * COORDINATE_PRECISION);
|
||||||
|
const auto _ymax = static_cast<int>(ymax * COORDINATE_PRECISION);
|
||||||
|
|
||||||
|
const auto itr = LoadedSourcePaths.find(path_string);
|
||||||
|
if (itr != LoadedSourcePaths.end())
|
||||||
|
{
|
||||||
|
SimpleLogger().Write() << "[source loader] Already loaded source '" << path_string
|
||||||
|
<< "' at source_id " << itr->second;
|
||||||
|
return itr->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
int source_id = static_cast<int>(LoadedSources.size());
|
||||||
|
|
||||||
|
SimpleLogger().Write() << "[source loader] Loading from " << path_string << " ... ";
|
||||||
|
TIMER_START(loading_source);
|
||||||
|
|
||||||
|
boost::filesystem::path filepath(path_string);
|
||||||
|
if (!boost::filesystem::exists(filepath))
|
||||||
|
{
|
||||||
|
throw osrm::exception("error reading: no such path");
|
||||||
|
}
|
||||||
|
|
||||||
|
RasterGrid rasterData{filepath, ncols, nrows};
|
||||||
|
|
||||||
|
RasterSource source{std::move(rasterData), ncols, nrows, _xmin, _xmax, _ymin, _ymax};
|
||||||
|
TIMER_STOP(loading_source);
|
||||||
|
LoadedSourcePaths.emplace(path_string, source_id);
|
||||||
|
LoadedSources.push_back(std::move(source));
|
||||||
|
|
||||||
|
SimpleLogger().Write() << "[source loader] ok, after " << TIMER_SEC(loading_source) << "s";
|
||||||
|
|
||||||
|
return source_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
// External function for looking up nearest data point from a specified source
|
||||||
|
RasterDatum SourceContainer::getRasterDataFromSource(unsigned int source_id, int lon, int lat)
|
||||||
|
{
|
||||||
|
if (LoadedSources.size() < source_id + 1)
|
||||||
|
{
|
||||||
|
throw osrm::exception("error reading: no such loaded source");
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_ASSERT(lat < (90 * COORDINATE_PRECISION));
|
||||||
|
BOOST_ASSERT(lat > (-90 * COORDINATE_PRECISION));
|
||||||
|
BOOST_ASSERT(lon < (180 * COORDINATE_PRECISION));
|
||||||
|
BOOST_ASSERT(lon > (-180 * COORDINATE_PRECISION));
|
||||||
|
|
||||||
|
const auto &found = LoadedSources[source_id];
|
||||||
|
return found.getRasterData(lon, lat);
|
||||||
|
}
|
||||||
|
|
||||||
|
// External function for looking up interpolated data from a specified source
|
||||||
|
RasterDatum
|
||||||
|
SourceContainer::getRasterInterpolateFromSource(unsigned int source_id, int lon, int lat)
|
||||||
|
{
|
||||||
|
if (LoadedSources.size() < source_id + 1)
|
||||||
|
{
|
||||||
|
throw osrm::exception("error reading: no such loaded source");
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_ASSERT(lat < (90 * COORDINATE_PRECISION));
|
||||||
|
BOOST_ASSERT(lat > (-90 * COORDINATE_PRECISION));
|
||||||
|
BOOST_ASSERT(lon < (180 * COORDINATE_PRECISION));
|
||||||
|
BOOST_ASSERT(lon > (-180 * COORDINATE_PRECISION));
|
||||||
|
|
||||||
|
const auto &found = LoadedSources[source_id];
|
||||||
|
return found.getRasterInterpolate(lon, lat);
|
||||||
|
}
|
175
data_structures/raster_source.hpp
Normal file
175
data_structures/raster_source.hpp
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2015, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef RASTER_SOURCE_HPP
|
||||||
|
#define RASTER_SOURCE_HPP
|
||||||
|
|
||||||
|
#include "../util/osrm_exception.hpp"
|
||||||
|
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
#include <boost/filesystem/fstream.hpp>
|
||||||
|
#include <boost/spirit/include/qi_int.hpp>
|
||||||
|
#include <boost/spirit/include/qi.hpp>
|
||||||
|
#include <boost/algorithm/string/trim.hpp>
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <iterator>
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Small wrapper around raster source queries to optionally provide results
|
||||||
|
gracefully, depending on source bounds
|
||||||
|
*/
|
||||||
|
struct RasterDatum
|
||||||
|
{
|
||||||
|
static std::int32_t get_invalid() { return std::numeric_limits<std::int32_t>::max(); }
|
||||||
|
|
||||||
|
std::int32_t datum = get_invalid();
|
||||||
|
|
||||||
|
RasterDatum() = default;
|
||||||
|
|
||||||
|
RasterDatum(std::int32_t _datum) : datum(_datum) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class RasterGrid
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RasterGrid(const boost::filesystem::path &filepath, std::size_t _xdim, std::size_t _ydim)
|
||||||
|
{
|
||||||
|
xdim = _xdim;
|
||||||
|
ydim = _ydim;
|
||||||
|
_data.reserve(ydim * xdim);
|
||||||
|
|
||||||
|
boost::filesystem::ifstream stream(filepath);
|
||||||
|
if (!stream)
|
||||||
|
{
|
||||||
|
throw osrm::exception("Unable to open raster file.");
|
||||||
|
}
|
||||||
|
|
||||||
|
stream.seekg(0, std::ios_base::end);
|
||||||
|
std::string buffer;
|
||||||
|
buffer.resize(static_cast<std::size_t>(stream.tellg()));
|
||||||
|
|
||||||
|
stream.seekg(0, std::ios_base::beg);
|
||||||
|
|
||||||
|
BOOST_ASSERT(buffer.size() > 1);
|
||||||
|
stream.read(&buffer[0], static_cast<std::streamsize>(buffer.size()));
|
||||||
|
|
||||||
|
boost::algorithm::trim(buffer);
|
||||||
|
|
||||||
|
auto itr = buffer.begin();
|
||||||
|
auto end = buffer.end();
|
||||||
|
|
||||||
|
bool r = false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
r = boost::spirit::qi::parse(
|
||||||
|
itr, end, +boost::spirit::qi::int_ % +boost::spirit::qi::space, _data);
|
||||||
|
}
|
||||||
|
catch (std::exception const &ex)
|
||||||
|
{
|
||||||
|
throw osrm::exception(
|
||||||
|
std::string("Failed to read from raster source with exception: ") + ex.what());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!r || itr != end)
|
||||||
|
{
|
||||||
|
throw osrm::exception("Failed to parse raster source correctly.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RasterGrid(const RasterGrid &) = default;
|
||||||
|
RasterGrid &operator=(const RasterGrid &) = default;
|
||||||
|
|
||||||
|
RasterGrid(RasterGrid &&) = default;
|
||||||
|
RasterGrid &operator=(RasterGrid &&) = default;
|
||||||
|
|
||||||
|
std::int32_t operator()(std::size_t x, std::size_t y) { return _data[y * xdim + x]; }
|
||||||
|
std::int32_t operator()(std::size_t x, std::size_t y) const { return _data[(y)*xdim + (x)]; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<std::int32_t> _data;
|
||||||
|
std::size_t xdim, ydim;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Stores raster source data in memory and provides lookup functions.
|
||||||
|
*/
|
||||||
|
class RasterSource
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
const float xstep;
|
||||||
|
const float ystep;
|
||||||
|
|
||||||
|
float calcSize(int min, int max, std::size_t count) const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
RasterGrid raster_data;
|
||||||
|
|
||||||
|
const std::size_t width;
|
||||||
|
const std::size_t height;
|
||||||
|
const int xmin;
|
||||||
|
const int xmax;
|
||||||
|
const int ymin;
|
||||||
|
const int ymax;
|
||||||
|
|
||||||
|
RasterDatum getRasterData(const int lon, const int lat) const;
|
||||||
|
|
||||||
|
RasterDatum getRasterInterpolate(const int lon, const int lat) const;
|
||||||
|
|
||||||
|
RasterSource(RasterGrid _raster_data,
|
||||||
|
std::size_t width,
|
||||||
|
std::size_t height,
|
||||||
|
int _xmin,
|
||||||
|
int _xmax,
|
||||||
|
int _ymin,
|
||||||
|
int _ymax);
|
||||||
|
};
|
||||||
|
|
||||||
|
class SourceContainer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SourceContainer() = default;
|
||||||
|
|
||||||
|
int loadRasterSource(const std::string &path_string,
|
||||||
|
double xmin,
|
||||||
|
double xmax,
|
||||||
|
double ymin,
|
||||||
|
double ymax,
|
||||||
|
std::size_t nrows,
|
||||||
|
std::size_t ncols);
|
||||||
|
|
||||||
|
RasterDatum getRasterDataFromSource(unsigned int source_id, int lon, int lat);
|
||||||
|
|
||||||
|
RasterDatum getRasterInterpolateFromSource(unsigned int source_id, int lon, int lat);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<RasterSource> LoadedSources;
|
||||||
|
std::unordered_map<std::string, int> LoadedSourcePaths;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* RASTER_SOURCE_HPP */
|
@ -36,10 +36,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "../util/simple_logger.hpp"
|
#include "../util/simple_logger.hpp"
|
||||||
#include "../util/timing_util.hpp"
|
#include "../util/timing_util.hpp"
|
||||||
#include "../util/fingerprint.hpp"
|
#include "../util/fingerprint.hpp"
|
||||||
|
#include "../util/lua_util.hpp"
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
#include <boost/filesystem/fstream.hpp>
|
#include <boost/filesystem/fstream.hpp>
|
||||||
|
#include <boost/ref.hpp>
|
||||||
|
|
||||||
|
#include <luabind/luabind.hpp>
|
||||||
|
|
||||||
#include <stxxl/sort>
|
#include <stxxl/sort>
|
||||||
|
|
||||||
@ -76,7 +80,8 @@ ExtractionContainers::~ExtractionContainers()
|
|||||||
*/
|
*/
|
||||||
void ExtractionContainers::PrepareData(const std::string &output_file_name,
|
void ExtractionContainers::PrepareData(const std::string &output_file_name,
|
||||||
const std::string &restrictions_file_name,
|
const std::string &restrictions_file_name,
|
||||||
const std::string &name_file_name)
|
const std::string &name_file_name,
|
||||||
|
lua_State *segment_state)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -87,7 +92,7 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name,
|
|||||||
|
|
||||||
PrepareNodes();
|
PrepareNodes();
|
||||||
WriteNodes(file_out_stream);
|
WriteNodes(file_out_stream);
|
||||||
PrepareEdges();
|
PrepareEdges(segment_state);
|
||||||
WriteEdges(file_out_stream);
|
WriteEdges(file_out_stream);
|
||||||
|
|
||||||
file_out_stream.close();
|
file_out_stream.close();
|
||||||
@ -168,7 +173,7 @@ void ExtractionContainers::PrepareNodes()
|
|||||||
std::cout << "ok, after " << TIMER_SEC(sorting_nodes) << "s" << std::endl;
|
std::cout << "ok, after " << TIMER_SEC(sorting_nodes) << "s" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExtractionContainers::PrepareEdges()
|
void ExtractionContainers::PrepareEdges(lua_State *segment_state)
|
||||||
{
|
{
|
||||||
// Sort edges by start.
|
// Sort edges by start.
|
||||||
std::cout << "[extractor] Sorting edges by start ... " << std::flush;
|
std::cout << "[extractor] Sorting edges by start ... " << std::flush;
|
||||||
@ -264,6 +269,16 @@ void ExtractionContainers::PrepareEdges()
|
|||||||
edge_iterator->source_coordinate.lat, edge_iterator->source_coordinate.lon,
|
edge_iterator->source_coordinate.lat, edge_iterator->source_coordinate.lon,
|
||||||
node_iterator->lat, node_iterator->lon);
|
node_iterator->lat, node_iterator->lon);
|
||||||
|
|
||||||
|
if (lua_function_exists(segment_state, "segment_function"))
|
||||||
|
{
|
||||||
|
luabind::call_function<void>(
|
||||||
|
segment_state, "segment_function",
|
||||||
|
boost::cref(edge_iterator->source_coordinate),
|
||||||
|
boost::cref(*node_iterator),
|
||||||
|
distance,
|
||||||
|
boost::ref(edge_iterator->weight_data));
|
||||||
|
}
|
||||||
|
|
||||||
const double weight = [distance](const InternalExtractorEdge::WeightData& data) {
|
const double weight = [distance](const InternalExtractorEdge::WeightData& data) {
|
||||||
switch (data.type)
|
switch (data.type)
|
||||||
{
|
{
|
||||||
|
@ -30,6 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include "internal_extractor_edge.hpp"
|
#include "internal_extractor_edge.hpp"
|
||||||
#include "first_and_last_segment_of_way.hpp"
|
#include "first_and_last_segment_of_way.hpp"
|
||||||
|
#include "scripting_environment.hpp"
|
||||||
#include "../data_structures/external_memory_node.hpp"
|
#include "../data_structures/external_memory_node.hpp"
|
||||||
#include "../data_structures/restriction.hpp"
|
#include "../data_structures/restriction.hpp"
|
||||||
|
|
||||||
@ -53,7 +54,7 @@ class ExtractionContainers
|
|||||||
#endif
|
#endif
|
||||||
void PrepareNodes();
|
void PrepareNodes();
|
||||||
void PrepareRestrictions();
|
void PrepareRestrictions();
|
||||||
void PrepareEdges();
|
void PrepareEdges(lua_State *segment_state);
|
||||||
|
|
||||||
void WriteNodes(std::ofstream& file_out_stream) const;
|
void WriteNodes(std::ofstream& file_out_stream) const;
|
||||||
void WriteRestrictions(const std::string& restrictions_file_name) const;
|
void WriteRestrictions(const std::string& restrictions_file_name) const;
|
||||||
@ -81,7 +82,8 @@ class ExtractionContainers
|
|||||||
|
|
||||||
void PrepareData(const std::string &output_file_name,
|
void PrepareData(const std::string &output_file_name,
|
||||||
const std::string &restrictions_file_name,
|
const std::string &restrictions_file_name,
|
||||||
const std::string &names_file_name);
|
const std::string &names_file_name,
|
||||||
|
lua_State *segment_state);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* EXTRACTION_CONTAINERS_HPP */
|
#endif /* EXTRACTION_CONTAINERS_HPP */
|
||||||
|
@ -34,10 +34,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "restriction_parser.hpp"
|
#include "restriction_parser.hpp"
|
||||||
#include "scripting_environment.hpp"
|
#include "scripting_environment.hpp"
|
||||||
|
|
||||||
|
#include "../data_structures/raster_source.hpp"
|
||||||
#include "../util/git_sha.hpp"
|
#include "../util/git_sha.hpp"
|
||||||
#include "../util/make_unique.hpp"
|
#include "../util/make_unique.hpp"
|
||||||
#include "../util/simple_logger.hpp"
|
#include "../util/simple_logger.hpp"
|
||||||
#include "../util/timing_util.hpp"
|
#include "../util/timing_util.hpp"
|
||||||
|
#include "../util/lua_util.hpp"
|
||||||
|
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
@ -116,6 +118,17 @@ int extractor::run()
|
|||||||
SimpleLogger().Write() << "Parsing in progress..";
|
SimpleLogger().Write() << "Parsing in progress..";
|
||||||
TIMER_START(parsing);
|
TIMER_START(parsing);
|
||||||
|
|
||||||
|
lua_State *segment_state = scripting_environment.get_lua_state();
|
||||||
|
|
||||||
|
if (lua_function_exists(segment_state, "source_function"))
|
||||||
|
{
|
||||||
|
// bind a single instance of SourceContainer class to relevant lua state
|
||||||
|
SourceContainer sources;
|
||||||
|
luabind::globals(segment_state)["sources"] = sources;
|
||||||
|
|
||||||
|
luabind::call_function<void>(segment_state, "source_function");
|
||||||
|
}
|
||||||
|
|
||||||
std::string generator = header.get("generator");
|
std::string generator = header.get("generator");
|
||||||
if (generator.empty())
|
if (generator.empty())
|
||||||
{
|
{
|
||||||
@ -238,7 +251,9 @@ int extractor::run()
|
|||||||
|
|
||||||
extraction_containers.PrepareData(config.output_file_name,
|
extraction_containers.PrepareData(config.output_file_name,
|
||||||
config.restriction_file_name,
|
config.restriction_file_name,
|
||||||
config.names_file_name);
|
config.names_file_name,
|
||||||
|
segment_state);
|
||||||
|
|
||||||
TIMER_STOP(extracting);
|
TIMER_STOP(extracting);
|
||||||
SimpleLogger().Write() << "extraction finished after " << TIMER_SEC(extracting) << "s";
|
SimpleLogger().Write() << "extraction finished after " << TIMER_SEC(extracting) << "s";
|
||||||
SimpleLogger().Write() << "To prepare the data for routing, run: "
|
SimpleLogger().Write() << "To prepare the data for routing, run: "
|
||||||
|
0
extractor/lat
Normal file
0
extractor/lat
Normal file
@ -30,13 +30,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "extraction_helper_functions.hpp"
|
#include "extraction_helper_functions.hpp"
|
||||||
#include "extraction_node.hpp"
|
#include "extraction_node.hpp"
|
||||||
#include "extraction_way.hpp"
|
#include "extraction_way.hpp"
|
||||||
|
#include "internal_extractor_edge.hpp"
|
||||||
#include "../data_structures/external_memory_node.hpp"
|
#include "../data_structures/external_memory_node.hpp"
|
||||||
|
#include "../data_structures/raster_source.hpp"
|
||||||
#include "../util/lua_util.hpp"
|
#include "../util/lua_util.hpp"
|
||||||
#include "../util/osrm_exception.hpp"
|
#include "../util/osrm_exception.hpp"
|
||||||
#include "../util/simple_logger.hpp"
|
#include "../util/simple_logger.hpp"
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
#include <luabind/tag_function.hpp>
|
#include <luabind/tag_function.hpp>
|
||||||
|
#include <luabind/operator.hpp>
|
||||||
|
|
||||||
#include <osmium/osm.hpp>
|
#include <osmium/osm.hpp>
|
||||||
|
|
||||||
@ -80,6 +83,13 @@ void ScriptingEnvironment::init_lua_state(lua_State *lua_state)
|
|||||||
luabind::def("print", LUA_print<std::string>),
|
luabind::def("print", LUA_print<std::string>),
|
||||||
luabind::def("durationIsValid", durationIsValid),
|
luabind::def("durationIsValid", durationIsValid),
|
||||||
luabind::def("parseDuration", parseDuration),
|
luabind::def("parseDuration", parseDuration),
|
||||||
|
luabind::class_<SourceContainer>("sources")
|
||||||
|
.def(luabind::constructor<>())
|
||||||
|
.def("load", &SourceContainer::loadRasterSource)
|
||||||
|
.def("query", &SourceContainer::getRasterDataFromSource)
|
||||||
|
.def("interpolate", &SourceContainer::getRasterInterpolateFromSource),
|
||||||
|
luabind::class_<const float>("constants")
|
||||||
|
.enum_("enums")[luabind::value("precision", COORDINATE_PRECISION)],
|
||||||
|
|
||||||
luabind::class_<std::vector<std::string>>("vector")
|
luabind::class_<std::vector<std::string>>("vector")
|
||||||
.def("Add", static_cast<void (std::vector<std::string>::*)(const std::string &)>(
|
.def("Add", static_cast<void (std::vector<std::string>::*)(const std::string &)>(
|
||||||
@ -121,7 +131,21 @@ void ScriptingEnvironment::init_lua_state(lua_State *lua_state)
|
|||||||
luabind::class_<osmium::Way>("Way")
|
luabind::class_<osmium::Way>("Way")
|
||||||
.def("get_value_by_key", &osmium::Way::get_value_by_key)
|
.def("get_value_by_key", &osmium::Way::get_value_by_key)
|
||||||
.def("get_value_by_key", &get_value_by_key<osmium::Way>)
|
.def("get_value_by_key", &get_value_by_key<osmium::Way>)
|
||||||
.def("id", &osmium::Way::id)
|
.def("id", &osmium::Way::id),
|
||||||
|
luabind::class_<InternalExtractorEdge>("EdgeSource")
|
||||||
|
.property("source_coordinate", &InternalExtractorEdge::source_coordinate)
|
||||||
|
.property("weight_data", &InternalExtractorEdge::weight_data),
|
||||||
|
luabind::class_<InternalExtractorEdge::WeightData>("WeightData")
|
||||||
|
.def_readwrite("speed", &InternalExtractorEdge::WeightData::speed),
|
||||||
|
luabind::class_<ExternalMemoryNode>("EdgeTarget")
|
||||||
|
.property("lat", &ExternalMemoryNode::lat)
|
||||||
|
.property("lon", &ExternalMemoryNode::lon),
|
||||||
|
luabind::class_<FixedPointCoordinate>("Coordinate")
|
||||||
|
.property("lat", &FixedPointCoordinate::lat)
|
||||||
|
.property("lon", &FixedPointCoordinate::lon),
|
||||||
|
luabind::class_<RasterDatum>("RasterDatum")
|
||||||
|
.property("datum", &RasterDatum::datum)
|
||||||
|
.def("invalid_data", &RasterDatum::get_invalid)
|
||||||
];
|
];
|
||||||
|
|
||||||
if (0 != luaL_dofile(lua_state, file_name.c_str()))
|
if (0 != luaL_dofile(lua_state, file_name.c_str()))
|
||||||
|
0
extractor/source_coordinate.lat
Normal file
0
extractor/source_coordinate.lat
Normal file
18
features/raster/extract.feature
Normal file
18
features/raster/extract.feature
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
@raster @extract
|
||||||
|
Feature: osrm-extract with a profile containing raster source
|
||||||
|
# expansions:
|
||||||
|
# {osm_base} => path to current input file
|
||||||
|
# {profile} => path to current profile script
|
||||||
|
|
||||||
|
Scenario: osrm-extract on a valid profile
|
||||||
|
Given the profile "rasterbot"
|
||||||
|
And the node map
|
||||||
|
| a | b |
|
||||||
|
And the ways
|
||||||
|
| nodes |
|
||||||
|
| ab |
|
||||||
|
And the data has been saved to disk
|
||||||
|
When I run "osrm-extract {osm_base}.osm -p {profile}"
|
||||||
|
Then stderr should be empty
|
||||||
|
And stdout should contain "source loader"
|
||||||
|
And it should exit with code 0
|
78
features/raster/weights.feature
Normal file
78
features/raster/weights.feature
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
@routing @speed @raster
|
||||||
|
Feature: Raster - weights
|
||||||
|
|
||||||
|
Background: Use specific speeds
|
||||||
|
Given the node locations
|
||||||
|
| node | lat | lon |
|
||||||
|
| a | 0.1 | 0.1 |
|
||||||
|
| b | .05 | 0.1 |
|
||||||
|
| c | 0.0 | 0.1 |
|
||||||
|
| d | .05 | .03 |
|
||||||
|
| e | .05 | .066 |
|
||||||
|
| f | .075 | .066 |
|
||||||
|
And the ways
|
||||||
|
| nodes | highway |
|
||||||
|
| ab | primary |
|
||||||
|
| ad | primary |
|
||||||
|
| bc | primary |
|
||||||
|
| dc | primary |
|
||||||
|
| de | primary |
|
||||||
|
| eb | primary |
|
||||||
|
| df | primary |
|
||||||
|
| fb | primary |
|
||||||
|
And the raster source
|
||||||
|
"""
|
||||||
|
0 0 0 0
|
||||||
|
0 0 0 250
|
||||||
|
0 0 250 500
|
||||||
|
0 0 0 250
|
||||||
|
0 0 0 0
|
||||||
|
"""
|
||||||
|
|
||||||
|
Scenario: Weighting not based on raster sources
|
||||||
|
Given the profile "testbot"
|
||||||
|
When I run "osrm-extract {osm_base}.osm -p {profile}"
|
||||||
|
And I run "osrm-prepare {osm_base}.osm"
|
||||||
|
And I route I should get
|
||||||
|
| from | to | route | speed |
|
||||||
|
| a | b | ab | 36 km/h |
|
||||||
|
| a | c | ab,bc | 36 km/h |
|
||||||
|
| b | c | bc | 36 km/h |
|
||||||
|
| a | d | ad | 36 km/h |
|
||||||
|
| d | c | dc | 36 km/h |
|
||||||
|
|
||||||
|
Scenario: Weighting based on raster sources
|
||||||
|
Given the profile "rasterbot"
|
||||||
|
When I run "osrm-extract {osm_base}.osm -p {profile}"
|
||||||
|
Then stdout should contain "evaluating segment"
|
||||||
|
And I run "osrm-prepare {osm_base}.osm"
|
||||||
|
And I route I should get
|
||||||
|
| from | to | route | speed |
|
||||||
|
| a | b | ab | 8 km/h |
|
||||||
|
| a | c | ad,dc | 15 km/h |
|
||||||
|
| b | c | bc | 8 km/h |
|
||||||
|
| a | d | ad | 15 km/h |
|
||||||
|
| d | c | dc | 15 km/h |
|
||||||
|
| d | e | de | 10 km/h |
|
||||||
|
| e | b | eb | 10 km/h |
|
||||||
|
| d | f | df | 15 km/h |
|
||||||
|
| f | b | fb | 7 km/h |
|
||||||
|
| d | b | de,eb | 10 km/h |
|
||||||
|
|
||||||
|
Scenario: Weighting based on raster sources
|
||||||
|
Given the profile "rasterbot-interp"
|
||||||
|
When I run "osrm-extract {osm_base}.osm -p {profile}"
|
||||||
|
Then stdout should contain "evaluating segment"
|
||||||
|
And I run "osrm-prepare {osm_base}.osm"
|
||||||
|
And I route I should get
|
||||||
|
| from | to | route | speed |
|
||||||
|
| a | b | ab | 8 km/h |
|
||||||
|
| a | c | ad,dc | 15 km/h |
|
||||||
|
| b | c | bc | 8 km/h |
|
||||||
|
| a | d | ad | 15 km/h |
|
||||||
|
| d | c | dc | 15 km/h |
|
||||||
|
| d | e | de | 10 km/h |
|
||||||
|
| e | b | eb | 10 km/h |
|
||||||
|
| d | f | df | 15 km/h |
|
||||||
|
| f | b | fb | 7 km/h |
|
||||||
|
| d | b | de,eb | 10 km/h |
|
@ -134,6 +134,12 @@ Given /^the input file ([^"]*)$/ do |file|
|
|||||||
@osm_str = File.read file
|
@osm_str = File.read file
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Given /^the raster source$/ do |data|
|
||||||
|
Dir.chdir TEST_FOLDER do
|
||||||
|
File.open("rastersource.asc", "w") {|f| f.write(data)}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
Given /^the data has been saved to disk$/ do
|
Given /^the data has been saved to disk$/ do
|
||||||
begin
|
begin
|
||||||
write_input_data
|
write_input_data
|
||||||
|
@ -14,6 +14,7 @@ DEFAULT_SPEEDPROFILE = 'bicycle'
|
|||||||
WAY_SPACING = 100
|
WAY_SPACING = 100
|
||||||
DEFAULT_GRID_SIZE = 100 #meters
|
DEFAULT_GRID_SIZE = 100 #meters
|
||||||
PROFILES_PATH = File.join ROOT_FOLDER, 'profiles'
|
PROFILES_PATH = File.join ROOT_FOLDER, 'profiles'
|
||||||
|
FIXTURES_PATH = File.join ROOT_FOLDER, 'unit_tests/fixtures'
|
||||||
BIN_PATH = File.join ROOT_FOLDER, 'build'
|
BIN_PATH = File.join ROOT_FOLDER, 'build'
|
||||||
DEFAULT_INPUT_FORMAT = 'osm'
|
DEFAULT_INPUT_FORMAT = 'osm'
|
||||||
DEFAULT_ORIGIN = [1,1]
|
DEFAULT_ORIGIN = [1,1]
|
||||||
@ -71,7 +72,7 @@ def verify_osrm_is_not_running
|
|||||||
end
|
end
|
||||||
|
|
||||||
def verify_existance_of_binaries
|
def verify_existance_of_binaries
|
||||||
["osrm-extract", "osrm-prepare", "osrm-routed"].each do |bin|
|
["osrm-extract", "osrm-prepare", "osrm-routed"].each do |bin|
|
||||||
unless File.exists? "#{BIN_PATH}/#{bin}#{EXE}"
|
unless File.exists? "#{BIN_PATH}/#{bin}#{EXE}"
|
||||||
raise "*** #{BIN_PATH}/#{bin}#{EXE} is missing. Build failed?"
|
raise "*** #{BIN_PATH}/#{bin}#{EXE} is missing. Build failed?"
|
||||||
end
|
end
|
||||||
|
46
profiles/rasterbot-interp.lua
Normal file
46
profiles/rasterbot-interp.lua
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
-- Rasterbot profile
|
||||||
|
|
||||||
|
-- Minimalist node_ and way_functions in order to test source_ and segment_functions
|
||||||
|
|
||||||
|
function node_function (node, result)
|
||||||
|
end
|
||||||
|
|
||||||
|
function way_function (way, result)
|
||||||
|
local highway = way:get_value_by_key("highway")
|
||||||
|
local name = way:get_value_by_key("name")
|
||||||
|
|
||||||
|
if name then
|
||||||
|
result.name = name
|
||||||
|
end
|
||||||
|
|
||||||
|
result.forward_speed = 15
|
||||||
|
result.backward_speed = 15
|
||||||
|
end
|
||||||
|
|
||||||
|
function source_function ()
|
||||||
|
raster_source = sources:load(
|
||||||
|
"../test/rastersource.asc",
|
||||||
|
0, -- lon_min
|
||||||
|
0.1, -- lon_max
|
||||||
|
0, -- lat_min
|
||||||
|
0.1, -- lat_max
|
||||||
|
5, -- nrows
|
||||||
|
4 -- ncols
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
function segment_function (source, target, distance, weight)
|
||||||
|
local sourceData = sources:interpolate(raster_source, source.lon, source.lat)
|
||||||
|
local targetData = sources:interpolate(raster_source, target.lon, target.lat)
|
||||||
|
print ("evaluating segment: " .. sourceData.datum .. " " .. targetData.datum)
|
||||||
|
local invalid = sourceData.invalid_data()
|
||||||
|
|
||||||
|
if sourceData.datum ~= invalid and targetData.datum ~= invalid then
|
||||||
|
local slope = math.abs(sourceData.datum - targetData.datum) / distance
|
||||||
|
print (" slope: " .. slope)
|
||||||
|
print (" was speed: " .. weight.speed)
|
||||||
|
|
||||||
|
weight.speed = weight.speed * (1 - (slope * 5))
|
||||||
|
print (" new speed: " .. weight.speed)
|
||||||
|
end
|
||||||
|
end
|
46
profiles/rasterbot.lua
Normal file
46
profiles/rasterbot.lua
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
-- Rasterbot profile
|
||||||
|
|
||||||
|
-- Minimalist node_ and way_functions in order to test source_ and segment_functions
|
||||||
|
|
||||||
|
function node_function (node, result)
|
||||||
|
end
|
||||||
|
|
||||||
|
function way_function (way, result)
|
||||||
|
local highway = way:get_value_by_key("highway")
|
||||||
|
local name = way:get_value_by_key("name")
|
||||||
|
|
||||||
|
if name then
|
||||||
|
result.name = name
|
||||||
|
end
|
||||||
|
|
||||||
|
result.forward_speed = 15
|
||||||
|
result.backward_speed = 15
|
||||||
|
end
|
||||||
|
|
||||||
|
function source_function ()
|
||||||
|
raster_source = sources:load(
|
||||||
|
"../test/rastersource.asc",
|
||||||
|
0, -- lon_min
|
||||||
|
0.1, -- lon_max
|
||||||
|
0, -- lat_min
|
||||||
|
0.1, -- lat_max
|
||||||
|
5, -- nrows
|
||||||
|
4 -- ncols
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
function segment_function (source, target, distance, weight)
|
||||||
|
local sourceData = sources:query(raster_source, source.lon, source.lat)
|
||||||
|
local targetData = sources:query(raster_source, target.lon, target.lat)
|
||||||
|
print ("evaluating segment: " .. sourceData.datum .. " " .. targetData.datum)
|
||||||
|
local invalid = sourceData.invalid_data()
|
||||||
|
|
||||||
|
if sourceData.datum ~= invalid and targetData.datum ~= invalid then
|
||||||
|
local slope = math.abs(sourceData.datum - targetData.datum) / distance
|
||||||
|
print (" slope: " .. slope)
|
||||||
|
print (" was speed: " .. weight.speed)
|
||||||
|
|
||||||
|
weight.speed = weight.speed * (1 - (slope * 5))
|
||||||
|
print (" new speed: " .. weight.speed)
|
||||||
|
end
|
||||||
|
end
|
5
test/rastersource.asc
Normal file
5
test/rastersource.asc
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
0 0 0 0
|
||||||
|
0 0 0 250
|
||||||
|
0 0 250 500
|
||||||
|
0 0 0 250
|
||||||
|
0 0 0 0
|
110
unit_tests/data_structures/raster_source.cpp
Normal file
110
unit_tests/data_structures/raster_source.cpp
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2014, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../../data_structures/raster_source.hpp"
|
||||||
|
#include "../../typedefs.h"
|
||||||
|
#include "../../util/osrm_exception.hpp"
|
||||||
|
|
||||||
|
#include <osrm/coordinate.hpp>
|
||||||
|
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
#include <boost/test/unit_test.hpp>
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_SUITE(raster_source)
|
||||||
|
|
||||||
|
int normalize(double coord) { return static_cast<int>(coord * COORDINATE_PRECISION); }
|
||||||
|
|
||||||
|
#define CHECK_QUERY(source_id, lon, lat, expected) \
|
||||||
|
BOOST_CHECK_EQUAL( \
|
||||||
|
sources.getRasterDataFromSource(source_id, normalize(lon), normalize(lat)).datum, \
|
||||||
|
expected)
|
||||||
|
|
||||||
|
#define CHECK_INTERPOLATE(source_id, lon, lat, expected) \
|
||||||
|
BOOST_CHECK_EQUAL( \
|
||||||
|
sources.getRasterInterpolateFromSource(source_id, normalize(lon), normalize(lat)).datum, \
|
||||||
|
expected)
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(raster_test)
|
||||||
|
{
|
||||||
|
SourceContainer sources;
|
||||||
|
int source_id = sources.loadRasterSource("../unit_tests/fixtures/raster_data.asc", 0, 0.09, 0,
|
||||||
|
0.09, 10, 10);
|
||||||
|
BOOST_CHECK_EQUAL(source_id, 0);
|
||||||
|
|
||||||
|
// Expected nearest-neighbor queries
|
||||||
|
// EDGES
|
||||||
|
CHECK_QUERY(0, 0.00, 0.00, 10);
|
||||||
|
CHECK_QUERY(0, 0.00, 0.09, 10);
|
||||||
|
CHECK_QUERY(0, 0.09, 0.00, 40);
|
||||||
|
CHECK_QUERY(0, 0.09, 0.09, 100);
|
||||||
|
CHECK_QUERY(0, 0.09, 0.07, 140);
|
||||||
|
// OUT OF BOUNDS
|
||||||
|
CHECK_QUERY(0, -0.1, 0.07, RasterDatum::get_invalid());
|
||||||
|
CHECK_QUERY(0, -0.1, -3.0, RasterDatum::get_invalid());
|
||||||
|
CHECK_QUERY(0, 0.3, 23.0, RasterDatum::get_invalid());
|
||||||
|
// ARBITRARY - AT DATA
|
||||||
|
CHECK_QUERY(0, 0.06, 0.06, 100);
|
||||||
|
CHECK_QUERY(0, 0.08, 0.05, 160);
|
||||||
|
CHECK_QUERY(0, 0.01, 0.05, 20);
|
||||||
|
// ARBITRARY - BETWEEN DATA
|
||||||
|
CHECK_QUERY(0, 0.054, 0.023, 40);
|
||||||
|
CHECK_QUERY(0, 0.056, 0.028, 80);
|
||||||
|
CHECK_QUERY(0, 0.05, 0.028, 60);
|
||||||
|
|
||||||
|
// Expected bilinear interpolation queries
|
||||||
|
// EDGES - same as above
|
||||||
|
CHECK_INTERPOLATE(0, 0.00, 0.00, 10);
|
||||||
|
CHECK_INTERPOLATE(0, 0.00, 0.09, 10);
|
||||||
|
CHECK_INTERPOLATE(0, 0.09, 0.00, 40);
|
||||||
|
CHECK_INTERPOLATE(0, 0.09, 0.09, 100);
|
||||||
|
CHECK_INTERPOLATE(0, 0.09, 0.07, 140);
|
||||||
|
// OUT OF BOUNDS - same as above
|
||||||
|
CHECK_INTERPOLATE(0, -0.1, 0.07, RasterDatum::get_invalid());
|
||||||
|
CHECK_INTERPOLATE(0, -0.1, -3.0, RasterDatum::get_invalid());
|
||||||
|
CHECK_INTERPOLATE(0, 0.3, 23.0, RasterDatum::get_invalid());
|
||||||
|
// ARBITRARY - AT DATA - same as above
|
||||||
|
CHECK_INTERPOLATE(0, 0.06, 0.06, 100);
|
||||||
|
CHECK_INTERPOLATE(0, 0.08, 0.05, 160);
|
||||||
|
CHECK_INTERPOLATE(0, 0.01, 0.05, 20);
|
||||||
|
// ARBITRARY - BETWEEN DATA
|
||||||
|
CHECK_INTERPOLATE(0, 0.054, 0.023, 54);
|
||||||
|
CHECK_INTERPOLATE(0, 0.056, 0.028, 68);
|
||||||
|
CHECK_INTERPOLATE(0, 0.05, 0.028, 56);
|
||||||
|
|
||||||
|
int source_already_loaded_id = sources.loadRasterSource(
|
||||||
|
"../unit_tests/fixtures/raster_data.asc", 0, 0.09, 0, 0.09, 10, 10);
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(source_already_loaded_id, 0);
|
||||||
|
BOOST_CHECK_THROW(sources.getRasterDataFromSource(1, normalize(0.02), normalize(0.02)),
|
||||||
|
osrm::exception);
|
||||||
|
|
||||||
|
BOOST_CHECK_THROW(
|
||||||
|
sources.loadRasterSource("../unit_tests/fixtures/nonexistent.asc", 0, 0.1, 0, 0.1, 7, 7),
|
||||||
|
osrm::exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_SUITE_END()
|
10
unit_tests/fixtures/raster_data.asc
Normal file
10
unit_tests/fixtures/raster_data.asc
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
10 10 10 10 10 20 40 60 80 100
|
||||||
|
10 10 10 10 20 40 60 80 100 120
|
||||||
|
10 10 10 20 40 60 80 100 120 140
|
||||||
|
10 10 20 40 60 80 100 120 140 160
|
||||||
|
10 20 40 60 80 100 120 140 160 180
|
||||||
|
10 10 20 40 60 80 100 120 140 160
|
||||||
|
10 10 10 20 40 60 80 100 120 140
|
||||||
|
10 10 10 10 20 40 60 80 100 80
|
||||||
|
10 10 10 10 10 20 40 60 80 60
|
||||||
|
10 10 10 10 10 10 20 40 60 40
|
Loading…
Reference in New Issue
Block a user