diff options
author | Sudarsana Babu Nagineni <sudarsana.babu@mapbox.com> | 2018-07-30 15:30:57 +0300 |
---|---|---|
committer | Sudarsana Babu Nagineni <sudarsana.babu@mapbox.com> | 2018-08-06 16:55:30 +0300 |
commit | 0130c58fdd74edbbfe668f3125a9377554d7d605 (patch) | |
tree | 6be1c1d25d146e9273f04f40f2283e18048c17ac /src/mbgl/util | |
parent | 7373abef92ed4911b91f9fca3d97784ed0d9e02e (diff) | |
download | qtlocation-mapboxgl-0130c58fdd74edbbfe668f3125a9377554d7d605.tar.gz |
Bump Mapbox GL Native
Bump version.
mapbox-gl-native @ 377a6e42d687c419e6ae1012b8626336f5dfc1b6
Diffstat (limited to 'src/mbgl/util')
-rw-r--r-- | src/mbgl/util/chrono.cpp | 2 | ||||
-rw-r--r-- | src/mbgl/util/event.cpp | 1 | ||||
-rw-r--r-- | src/mbgl/util/http_header.cpp | 3 | ||||
-rw-r--r-- | src/mbgl/util/interpolate.cpp | 3 | ||||
-rw-r--r-- | src/mbgl/util/io.cpp | 25 | ||||
-rw-r--r-- | src/mbgl/util/io.hpp | 4 | ||||
-rw-r--r-- | src/mbgl/util/logging.cpp | 10 | ||||
-rw-r--r-- | src/mbgl/util/stopwatch.hpp | 15 | ||||
-rw-r--r-- | src/mbgl/util/tile_coordinate.hpp | 2 | ||||
-rw-r--r-- | src/mbgl/util/tile_cover.cpp | 2 | ||||
-rw-r--r-- | src/mbgl/util/tile_cover_impl.cpp | 129 | ||||
-rw-r--r-- | src/mbgl/util/tile_cover_impl.hpp | 16 | ||||
-rw-r--r-- | src/mbgl/util/token.hpp | 11 | ||||
-rw-r--r-- | src/mbgl/util/url.cpp | 5 |
14 files changed, 144 insertions, 84 deletions
diff --git a/src/mbgl/util/chrono.cpp b/src/mbgl/util/chrono.cpp index a880093b74..c304548cf1 100644 --- a/src/mbgl/util/chrono.cpp +++ b/src/mbgl/util/chrono.cpp @@ -1,6 +1,6 @@ #include <mbgl/util/chrono.hpp> -#include <parsedate/parsedate.h> +#include <parsedate/parsedate.hpp> #include <cstdio> #include <ctime> diff --git a/src/mbgl/util/event.cpp b/src/mbgl/util/event.cpp index 3a3be20f5c..0c08d72a8c 100644 --- a/src/mbgl/util/event.cpp +++ b/src/mbgl/util/event.cpp @@ -28,6 +28,7 @@ MBGL_DEFINE_ENUM(Event, { { Event::Android, "Android" }, { Event::Crash, "Crash" }, { Event::Glyph, "Glyph" }, + { Event::Timing, "Timing" }, { Event(-1), "Unknown" }, }); diff --git a/src/mbgl/util/http_header.cpp b/src/mbgl/util/http_header.cpp index 5921edfb14..4d9e2bf84c 100644 --- a/src/mbgl/util/http_header.cpp +++ b/src/mbgl/util/http_header.cpp @@ -7,7 +7,10 @@ #pragma GCC diagnostic ignored "-Wunused-parameter" #pragma GCC diagnostic ignored "-Wshadow" #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wshorten-64-to-32" +#pragma clang diagnostic ignored "-Wunknown-warning-option" +#pragma clang diagnostic ignored "-Wtautological-constant-compare" #include <boost/spirit/include/qi.hpp> #include <boost/spirit/include/phoenix_core.hpp> #include <boost/spirit/include/phoenix_operator.hpp> diff --git a/src/mbgl/util/interpolate.cpp b/src/mbgl/util/interpolate.cpp index 066fa9c462..6b5736f15f 100644 --- a/src/mbgl/util/interpolate.cpp +++ b/src/mbgl/util/interpolate.cpp @@ -13,7 +13,8 @@ float interpolationFactor(float base, Range<float> range, float z) { } else if (base == 1.0f) { return zoomProgress / zoomDiff; } else { - return (std::pow(base, zoomProgress) - 1) / (std::pow(base, zoomDiff) - 1); + return (std::pow(static_cast<double>(base), zoomProgress) - 1) / + (std::pow(static_cast<double>(base), zoomDiff) - 1); } } diff --git a/src/mbgl/util/io.cpp b/src/mbgl/util/io.cpp index 6a6ed7b250..c84634ac88 100644 --- a/src/mbgl/util/io.cpp +++ b/src/mbgl/util/io.cpp @@ -2,6 +2,7 @@ #include <cstdio> #include <cerrno> +#include <cstring> #include <iostream> #include <sstream> #include <fstream> @@ -9,6 +10,10 @@ namespace mbgl { namespace util { +IOException::IOException(int err, const std::string& msg) + : std::runtime_error(msg + ": " + std::strerror(errno)), code(err) { +} + void write_file(const std::string &filename, const std::string &data) { FILE *fd = fopen(filename.c_str(), "wb"); if (fd) { @@ -20,7 +25,7 @@ void write_file(const std::string &filename, const std::string &data) { } std::string read_file(const std::string &filename) { - std::ifstream file(filename); + std::ifstream file(filename, std::ios::binary); if (file.good()) { std::stringstream data; data << file.rdbuf(); @@ -31,7 +36,7 @@ std::string read_file(const std::string &filename) { } optional<std::string> readFile(const std::string &filename) { - std::ifstream file(filename); + std::ifstream file(filename, std::ios::binary); if (file.good()) { std::stringstream data; data << file.rdbuf(); @@ -42,9 +47,21 @@ optional<std::string> readFile(const std::string &filename) { void deleteFile(const std::string& filename) { const int ret = std::remove(filename.c_str()); - if (ret != 0) { - throw IOException(errno, "failed to unlink file"); + if (ret != 0 && errno != ENOENT) { + throw IOException(errno, "Could not delete file " + filename); + } +} + +void copyFile(const std::string& destination, const std::string& source) { + std::ifstream src(source, std::ios::binary); + if (!src.good()) { + throw IOException(errno, "Cannot read file " + destination); + } + std::ofstream dst(destination, std::ios::binary); + if (!dst.good()) { + throw IOException(errno, "Cannot write file " + destination); } + dst << src.rdbuf(); } } // namespace util diff --git a/src/mbgl/util/io.hpp b/src/mbgl/util/io.hpp index 847271acf0..e628e82124 100644 --- a/src/mbgl/util/io.hpp +++ b/src/mbgl/util/io.hpp @@ -9,8 +9,7 @@ namespace mbgl { namespace util { struct IOException : std::runtime_error { - IOException(int err, const char* msg) : std::runtime_error(msg), code(err) { - } + IOException(int err, const std::string& msg); const int code = 0; }; @@ -19,6 +18,7 @@ std::string read_file(const std::string &filename); optional<std::string> readFile(const std::string &filename); void deleteFile(const std::string& filename); +void copyFile(const std::string& destination, const std::string& source); } // namespace util } // namespace mbgl diff --git a/src/mbgl/util/logging.cpp b/src/mbgl/util/logging.cpp index 0552eb36cb..d322bd3670 100644 --- a/src/mbgl/util/logging.cpp +++ b/src/mbgl/util/logging.cpp @@ -38,8 +38,14 @@ void Log::record(EventSeverity severity, Event event, const char* format, ...) { record(severity, event, -1, msg); } -void Log::record(EventSeverity severity, Event event, int64_t code) { - record(severity, event, code, std::string()); +void Log::record(EventSeverity severity, Event event, int64_t code, const char* format, ...) { + va_list args; + va_start(args, format); + char msg[4096]; + vsnprintf(msg, sizeof(msg), format, args); + va_end(args); + + record(severity, event, code, std::string{ msg }); } void Log::record(EventSeverity severity, Event event, int64_t code, const std::string &msg) { diff --git a/src/mbgl/util/stopwatch.hpp b/src/mbgl/util/stopwatch.hpp index 6214dae958..0c91342a57 100644 --- a/src/mbgl/util/stopwatch.hpp +++ b/src/mbgl/util/stopwatch.hpp @@ -4,9 +4,24 @@ #include <mbgl/util/chrono.hpp> #include <string> +#include <sstream> namespace mbgl { namespace util { + +#ifdef MBGL_TIMING +// Declare 'watch' as a shared_ptr so it can be captured by value in a lambda function +#define MBGL_TIMING_START(watch) std::shared_ptr<util::stopwatch> watch = std::make_unique<util::stopwatch>(Event::Timing); +#define MBGL_TIMING_FINISH(watch, message) \ + do { \ + std::stringstream messageStream; \ + messageStream << message; \ + watch->report(messageStream.str()); \ + } while (0); +#else +#define MBGL_TIMING_START(watch) +#define MBGL_TIMING_FINISH(watch, message) +#endif #ifndef DISABLE_STOPWATCH class stopwatch { diff --git a/src/mbgl/util/tile_coordinate.hpp b/src/mbgl/util/tile_coordinate.hpp index bcd1c8444f..b6bdc5f590 100644 --- a/src/mbgl/util/tile_coordinate.hpp +++ b/src/mbgl/util/tile_coordinate.hpp @@ -20,7 +20,7 @@ public: static TileCoordinate fromLatLng(double zoom, const LatLng& latLng) { const double scale = std::pow(2.0, zoom); - return { Projection::project(latLng, scale) / double(util::tileSize), zoom }; + return { Projection::project(latLng, scale) / util::tileSize, zoom }; } static TileCoordinate fromScreenCoordinate(const TransformState& state, double zoom, const ScreenCoordinate& screenCoordinate) { diff --git a/src/mbgl/util/tile_cover.cpp b/src/mbgl/util/tile_cover.cpp index 488e6b88ce..3f39e53d40 100644 --- a/src/mbgl/util/tile_cover.cpp +++ b/src/mbgl/util/tile_cover.cpp @@ -130,7 +130,7 @@ std::vector<UnwrappedTileID> tileCover(const Point<double>& tl, } // namespace int32_t coveringZoomLevel(double zoom, style::SourceType type, uint16_t size) { - zoom += std::log(util::tileSize / size) / std::log(2); + zoom += ::log2(util::tileSize / size); if (type == style::SourceType::Raster || type == style::SourceType::Video) { return ::round(zoom); } else { diff --git a/src/mbgl/util/tile_cover_impl.cpp b/src/mbgl/util/tile_cover_impl.cpp index b3fc07f7dd..799ff2666a 100644 --- a/src/mbgl/util/tile_cover_impl.cpp +++ b/src/mbgl/util/tile_cover_impl.cpp @@ -17,8 +17,7 @@ struct TileSpan { bool winding; }; - -// Find the first local minimum going forward in the list. +// Reorder a ring of points such that it starts at a point with a local minimum y-coordinate void start_list_on_local_minimum(PointList& points) { auto prev_pt = std::prev(points.end(), 2); auto pt = points.begin(); @@ -33,6 +32,8 @@ void start_list_on_local_minimum(PointList& points) { next_pt++; if (next_pt == points.end()) { next_pt = std::next(points.begin()); } } + if (pt == points.end()) + return; //Re-close linear rings with first_pt = last_pt if (points.back() == points.front()) { points.pop_back(); @@ -42,37 +43,25 @@ void start_list_on_local_minimum(PointList& points) { } //Create a bound towards a local maximum point, starting from pt. +// Traverse from current pt until the next pt changes y-direction, and copy +// all points from start to end (inclusive) into a Bound. Bound create_bound_towards_maximum(PointList& points, PointList::iterator& pt) { if (std::distance(pt, points.end()) < 2) { return {}; } - if (std::distance(pt, points.end()) == 2) { - Bound bnd; - if (pt->y < std::next(pt)->y) { - std::copy(pt, points.end(), std::back_inserter(bnd.points)); - bnd.winding = true; - } - else { - std::reverse_copy(pt, points.end(), std::back_inserter(bnd.points)); - bnd.winding = false; - } - pt = points.end(); - return bnd; - } + const auto begin = pt; - auto prev_pt = pt == points.begin() ? std::prev(points.end(), 2) : std::prev(pt); - auto next_pt = std::next(pt) == points.end() ? std::next(points.begin()) : std::next(pt); - while (pt != points.end()) { - if ((pt->y >= prev_pt->y) && - (pt->y > next_pt->y )) { - break; - } - prev_pt = pt; + auto next_pt = std::next(begin); + while (pt->y <= next_pt->y) { pt++; next_pt++; - if (next_pt == points.end()) { next_pt = std::next(points.begin()); } + if (next_pt == points.end()) { pt++; break; } + } + + const auto pt_distance = std::distance(begin, next_pt); + if (pt_distance < 2) { + return {}; } Bound bnd; - if (std::next(pt) == points.end()) { next_pt = points.end(); pt++; }; bnd.points.reserve(static_cast<std::size_t>(std::distance(begin, next_pt))); std::copy(begin, next_pt, std::back_inserter(bnd.points)); bnd.winding = true; @@ -80,37 +69,24 @@ Bound create_bound_towards_maximum(PointList& points, PointList::iterator& pt) { } //Create a bound towards a local minimum point, starting from pt. +// Traverse from current pt until the next pt changes y-direction, and copy +// all points from start to end (inclusive) into a Bound. Bound create_bound_towards_minimum(PointList& points, PointList::iterator& pt) { if (std::distance(pt, points.end()) < 2) { return {}; } - if (std::distance(pt, points.end()) == 2) { - Bound bnd; - if (pt->y < std::next(pt)->y) { - std::copy(pt, points.end(), std::back_inserter(bnd.points)); - bnd.winding = true; - } - else { - std::reverse_copy(pt, points.end(), std::back_inserter(bnd.points)); - bnd.winding = false; - } - pt = points.end(); - return bnd; - } + auto begin = pt; - auto prev_pt = pt == points.begin() ? std::prev(points.end(), 2) : std::prev(pt); - auto next_pt = std::next(pt) == points.end() ? std::next(points.begin()) : std::next(pt); - while (pt != points.end()) { - if ((pt->y <= prev_pt->y) && - (pt->y < next_pt->y)) { - break; - } - prev_pt = pt; + auto next_pt = std::next(begin); + while (pt->y > next_pt->y) { pt++; next_pt++; - if (next_pt == points.end()) { next_pt = std::next(points.begin()); } + if (next_pt == points.end()) { pt++; break; } } + const auto pt_distance = std::distance(begin, next_pt); + if (pt_distance < 2) { + return {}; + } Bound bnd; - if (std::next(pt) == points.end()) { next_pt = points.end(); pt++; }; bnd.points.reserve(static_cast<std::size_t>(std::distance(begin, next_pt))); //For bounds that start at a max, reverse copy so that all bounds start at a min std::reverse_copy(begin, next_pt, std::back_inserter(bnd.points)); @@ -118,10 +94,14 @@ Bound create_bound_towards_minimum(PointList& points, PointList::iterator& pt) { return bnd; } -//Build a map of bounds and their starting Y tile coordinate. +// Given a set of points (ring or list) representing a shape, compute a set of +// Bounds, where each Bound represents edges going from a local minima to a local +// maxima point. The BoundsMap is an edge table indexed on the starting Y-tile +// of each Bound. void build_bounds_map(PointList& points, uint32_t maxTile, BoundsMap& et, bool closed = false) { if (points.size() < 2) return; - //While traversing closed rings, start the bounds at a local minimum + //While traversing closed rings, start the bounds at a local minimum. + // (For linestrings the starting point is always a local maxima/minima) if (closed) { start_list_on_local_minimum(points); } @@ -131,12 +111,12 @@ void build_bounds_map(PointList& points, uint32_t maxTile, BoundsMap& et, bool c Bound to_max = create_bound_towards_maximum(points, pointsIter); Bound to_min = create_bound_towards_minimum(points, pointsIter); - if (to_max.points.size() > 0) { + if (to_max.points.size() >= 2) { // Projections may result in values beyond the bounds, clamp to max tile coordinates const auto y = static_cast<uint32_t>(std::floor(clamp(to_max.points.front().y, 0.0, (double)maxTile))); et[y].push_back(to_max); } - if (to_min.points.size() > 0) { + if (to_min.points.size() >= 2) { const auto y = static_cast<uint32_t>(std::floor(clamp(to_min.points.front().y, 0.0, (double)maxTile))); et[y].push_back(to_min); } @@ -149,16 +129,19 @@ void update_span(TileSpan& xp, double x) { xp.xmax = std::max(xp.xmax, static_cast<int32_t>(std::ceil(x))); } -//Build a vector of X tile-coordinates spanned by each bound. -std::vector<TileSpan> scan_row(uint32_t y, Bounds& aet) { +// Use the active bounds, an accumulation of all bounds that enter the y tile row, +// or start in that row. +// Iterate all points of a bound until it exits the row (or ends) and compute the +// set of X tiles it spans across. The winding direction of the bound is also +// captured for each span to later fill tiles between bounds for polygons +std::vector<TileSpan> scan_row(uint32_t y, Bounds& activeBounds) { std::vector<TileSpan> tile_range; - tile_range.reserve(aet.size()); + tile_range.reserve(activeBounds.size()); - for(Bound& b: aet) { + for(Bound& b: activeBounds) { TileSpan xp = { INT_MAX, 0, b.winding }; double x; const auto numEdges = b.points.size() - 1; - assert(numEdges >= 1); while (b.currentPoint < numEdges) { x = b.interpolate(y); update_span(xp, x); @@ -170,7 +153,7 @@ std::vector<TileSpan> scan_row(uint32_t y, Bounds& aet) { x = b.interpolate(y+1); update_span(xp, x); break; - } else if(b.currentPoint == numEdges - 1) { + } else if (b.currentPoint == numEdges - 1) { // For last edge, consider x-intercept at the end of the edge. x = p1.x; update_span(xp, x); @@ -181,11 +164,11 @@ std::vector<TileSpan> scan_row(uint32_t y, Bounds& aet) { } // Erase bounds in the active table whose current edge ends inside this row, // or there are no more edges - auto bound = aet.begin(); - while (bound != aet.end()) { + auto bound = activeBounds.begin(); + while (bound != activeBounds.end()) { if ( bound->currentPoint == bound->points.size() - 1 && bound->points[bound->currentPoint].y <= y+1) { - bound = aet.erase(bound); + bound = activeBounds.erase(bound); } else { bound++; } @@ -225,7 +208,7 @@ struct BuildBoundsMap { BoundsMap operator()(const Point<double>&p) const { Bound bnd; auto point = p; - if(project) { + if (project) { point = Projection::project(LatLng{p.y, p.x}, zoom); } bnd.points.insert(bnd.points.end(), 2, point); @@ -241,7 +224,7 @@ struct BuildBoundsMap { for (const Point<double>& p: points) { Bound bnd; auto point = p; - if(project) { + if (project) { point = Projection::project(LatLng{p.y, p.x}, zoom); } bnd.points.insert(bnd.points.end(), 2, point); @@ -302,20 +285,26 @@ TileCover::Impl::Impl(int32_t z, const Geometry<double>& geom, bool project) tileX = tileXSpans.front().first; } +// Aggregate all Bounds that start in or enter into the next tileY row. Multi-geoms +// may have discontinuity in the BoundMap, so skip forward to the next tileY row +// when the current/next row has no more bounds in it. +// Use scan_row to generate the tileX spans. Merge spans to avoid duplicate tiles +// in TileCoverImpl::next(). For closed geometry, use the non-zero rule to expand +// (fill) tiles between pairs of spans. void TileCover::Impl::nextRow() { - // Update AET for next row + // Update activeBounds for next row if (currentBounds != boundsMap.end()) { if (activeBounds.size() == 0 && currentBounds->first > tileY) { //For multi-geoms: use the next row with an edge table starting point tileY = currentBounds->first; } if (tileY == currentBounds->first) { - - std::move(currentBounds->second.begin(), currentBounds->second.end(), std::back_inserter(activeBounds)); + std::move(currentBounds->second.begin(), currentBounds->second.end(), + std::back_inserter(activeBounds)); currentBounds++; } } - //Scan aet and update currenRange with x_min, x_max pairs + //Scan the active bounds and update currentRange with x_min, x_max pairs auto xps = util::scan_row(tileY, activeBounds); if (xps.size() == 0) { return; @@ -339,7 +328,9 @@ void TileCover::Impl::nextRow() { } bool TileCover::Impl::hasNext() const { - return (!tileXSpans.empty() && tileX < tileXSpans.front().second && tileY < (1u << zoom)); + return (!tileXSpans.empty() + && tileX < tileXSpans.front().second + && tileY < (1u << zoom)); } optional<UnwrappedTileID> TileCover::Impl::next() { @@ -350,7 +341,7 @@ optional<UnwrappedTileID> TileCover::Impl::next() { tileX++; if (tileX >= tileXSpans.front().second) { tileXSpans.pop(); - if(tileXSpans.empty()) { + if (tileXSpans.empty()) { tileY++; nextRow(); } diff --git a/src/mbgl/util/tile_cover_impl.hpp b/src/mbgl/util/tile_cover_impl.hpp index 7c16718984..e9c06e44aa 100644 --- a/src/mbgl/util/tile_cover_impl.hpp +++ b/src/mbgl/util/tile_cover_impl.hpp @@ -60,6 +60,22 @@ struct Bound { } }; +// Implements a modified scan-line algorithm to provide a streaming interface for +// tile cover on arbitrary shapes. +// A `BoundsMap` is genereted from the input geometry where each tuple indicates +// the set of Bounds that start at a y tile coordinate. Each bound represents +// a chain of edges from a local y-minima to a local y-maxima. +// For each row, the activeBounds list aggregates all bounds that enter into or +// begin in that row. This running list of bounds is scanned, capturing the +// x-coordinates spanned by edges in a bound until the bound exits the row (or +// ends). The result is a set of (possibly overlapping) min,max pairs of x coordinates +// (spans). In the simplest case a span represents the x-coordinates at which a +// single edge intersects the top and bottom of a tile row. Interior tiles of a +// polygon are captured by merging spans using the non-zero rule. +// The result of a scan using `nextRow()` is a list of spans (tileXSpans) of x-coordinates +// that includes edges and interiors of polygons. +// next() returns a tileID for each x-coordinate from (first, second] in each +// span in tileXSpans. class TileCover::Impl { public: Impl(int32_t z, const Geometry<double>& geom, bool project = true); diff --git a/src/mbgl/util/token.hpp b/src/mbgl/util/token.hpp index 149661e47e..dea12f9412 100644 --- a/src/mbgl/util/token.hpp +++ b/src/mbgl/util/token.hpp @@ -1,5 +1,7 @@ #pragma once +#include <mbgl/util/optional.hpp> + #include <map> #include <string> #include <algorithm> @@ -25,7 +27,14 @@ std::string replaceTokens(const std::string &source, const Lookup &lookup) { if (pos != end) { for (brace++; brace != end && tokenReservedChars.find(*brace) == std::string::npos; brace++); if (brace != end && *brace == '}') { - result.append(lookup({ pos + 1, brace })); + std::string key { pos + 1, brace }; + if (optional<std::string> replacement = lookup(key)) { + result.append(*replacement); + } else { + result.append("{"); + result.append(key); + result.append("}"); + } pos = brace + 1; } else { result.append(pos, brace); diff --git a/src/mbgl/util/url.cpp b/src/mbgl/util/url.cpp index 1f6dab9639..a4263502ef 100644 --- a/src/mbgl/util/url.cpp +++ b/src/mbgl/util/url.cpp @@ -130,7 +130,7 @@ Path::Path(const std::string& str, const size_t pos, const size_t count) } std::string transformURL(const std::string& tpl, const std::string& str, const URL& url) { - auto result = util::replaceTokens(tpl, [&](const std::string& token) -> std::string { + auto result = util::replaceTokens(tpl, [&](const std::string& token) -> optional<std::string> { if (token == "path") { return str.substr(url.path.first, url.path.second); } else if (token == "domain") { @@ -146,8 +146,9 @@ std::string transformURL(const std::string& tpl, const std::string& str, const U } else if (token == "extension") { const Path path(str, url.path.first, url.path.second); return str.substr(path.extension.first, path.extension.second); + } else { + return {}; } - return ""; }); // Append the query string if it exists. |