#include "extractor/raster_source.hpp" #include "util/simple_logger.hpp" #include "util/timing_util.hpp" #include namespace osrm { namespace extractor { 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(std::move(_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(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(round((lon - xmin) / xstep)); const std::size_t yth = static_cast(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(fmax(floor(ythP), 0)); const std::size_t bottom = static_cast(fmin(ceil(ythP), height - 1)); const std::size_t left = static_cast(fmax(floor(xthP), 0)); const std::size_t right = static_cast(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(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(util::toFixed(util::FloatLongitude(xmin))); const auto _xmax = static_cast(util::toFixed(util::FloatLongitude(xmax))); const auto _ymin = static_cast(util::toFixed(util::FloatLatitude(ymin))); const auto _ymax = static_cast(util::toFixed(util::FloatLatitude(ymax))); const auto itr = LoadedSourcePaths.find(path_string); if (itr != LoadedSourcePaths.end()) { util::SimpleLogger().Write() << "[source loader] Already loaded source '" << path_string << "' at source_id " << itr->second; return itr->second; } int source_id = static_cast(LoadedSources.size()); util::SimpleLogger().Write() << "[source loader] Loading from " << path_string << " ... "; TIMER_START(loading_source); boost::filesystem::path filepath(path_string); if (!boost::filesystem::exists(filepath)) { throw util::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)); util::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, double lon, double lat) { if (LoadedSources.size() < source_id + 1) { throw util::exception("error reading: no such loaded source"); } BOOST_ASSERT(lat < 90); BOOST_ASSERT(lat > -90); BOOST_ASSERT(lon < 180); BOOST_ASSERT(lon > -180); const auto &found = LoadedSources[source_id]; return found.GetRasterData(static_cast(util::toFixed(util::FloatLongitude(lon))), static_cast(util::toFixed(util::FloatLatitude(lat)))); } // External function for looking up interpolated data from a specified source RasterDatum SourceContainer::GetRasterInterpolateFromSource(unsigned int source_id, double lon, double lat) { if (LoadedSources.size() < source_id + 1) { throw util::exception("error reading: no such loaded source"); } BOOST_ASSERT(lat < 90); BOOST_ASSERT(lat > -90); BOOST_ASSERT(lon < 180); BOOST_ASSERT(lon > -180); const auto &found = LoadedSources[source_id]; return found.GetRasterInterpolate(static_cast(util::toFixed(util::FloatLongitude(lon))), static_cast(util::toFixed(util::FloatLatitude(lat)))); } } }