CameraOptions Map::cameraForLatLngBounds(const LatLngBounds& bounds, optional<EdgeInsets> padding) const { return cameraForLatLngs({ bounds.northwest(), bounds.southwest(), bounds.southeast(), bounds.northeast(), }, padding); }
LatLngBounds ShapeAnnotationImpl::bounds() const { LatLngBounds result; for (const auto& segment : shape.segments) { for (const auto& point : segment) { result.extend(point); } } return result; }
LatLngBounds AnnotationManager::getBoundsForAnnotations(const AnnotationIDs& ids) const { LatLngBounds bounds; for (auto id : ids) { const auto annotation_it = annotations.find(id); if (annotation_it != annotations.end()) { bounds.extend(annotation_it->second->getBounds()); } } return bounds; }
LatLngBounds AnnotationManager::getBoundsForAnnotations(const AnnotationIDs& ids) const { std::lock_guard<std::mutex> lock(mtx); LatLngBounds bounds; for (auto id : ids) { const auto annotation_it = annotations.find(id); if (annotation_it != annotations.end()) { bounds.extend(annotation_it->second->getPoint()); } } return bounds; }
LatLngBounds AnnotationManager::getBoundsForAnnotations(const AnnotationIDs& ids) const { LatLngBounds result = LatLngBounds::getExtendable(); for (const auto& id : ids) { if (pointAnnotations.find(id) != pointAnnotations.end()) { result.extend(pointAnnotations.at(id)->bounds()); } else if (shapeAnnotations.find(id) != shapeAnnotations.end()) { result.extend(shapeAnnotations.at(id)->bounds()); } } return result; }
// Taken from https://github.com/mapbox/sphericalmercator#xyzbbox-zoom-tms_style-srs // Computes the projected tiles for the lower left and upper right points of the bounds // and uses that to compute the tile cover count uint64_t tileCount(const LatLngBounds& bounds, uint8_t zoom){ if (zoom == 0) { return 1; } auto sw = Projection::project(bounds.southwest(), zoom); auto ne = Projection::project(bounds.northeast(), zoom); auto maxTile = std::pow(2.0, zoom); auto x1 = floor(sw.x); auto x2 = ceil(ne.x) - 1; auto y1 = util::clamp(floor(sw.y), 0.0, maxTile - 1); auto y2 = util::clamp(floor(ne.y), 0.0, maxTile - 1); auto dx = x1 > x2 ? (maxTile - x1) + x2 : x2 - x1; auto dy = y1 - y2; return (dx + 1) * (dy + 1); }
// Taken from https://github.com/mapbox/sphericalmercator#xyzbbox-zoom-tms_style-srs // Computes the projected tiles for the lower left and upper right points of the bounds // and uses that to compute the tile cover count uint64_t tileCount(const LatLngBounds& bounds, uint8_t zoom, uint16_t tileSize_){ auto sw = Projection::project(bounds.southwest().wrapped(), zoom, tileSize_); auto ne = Projection::project(bounds.northeast().wrapped(), zoom, tileSize_); auto x1 = floor(sw.x/ tileSize_); auto x2 = floor((ne.x - 1) / tileSize_); auto y1 = floor(sw.y/ tileSize_); auto y2 = floor((ne.y - 1) / tileSize_); auto minX = ::fmax(std::min(x1, x2), 0); auto maxX = std::max(x1, x2); auto minY = (std::pow(2, zoom) - 1) - std::max(y1, y2); auto maxY = (std::pow(2, zoom) - 1) - ::fmax(std::min(y1, y2), 0); return (maxX - minX + 1) * (maxY - minY + 1); }
TileCover::TileCover(const LatLngBounds&bounds_, int32_t z) { LatLngBounds bounds = LatLngBounds::hull( { std::max(bounds_.south(), -util::LATITUDE_MAX), bounds_.west() }, { std::min(bounds_.north(), util::LATITUDE_MAX), bounds_.east() }); if (bounds.isEmpty() || bounds.south() > util::LATITUDE_MAX || bounds.north() < -util::LATITUDE_MAX) { bounds = LatLngBounds::world(); } auto sw = Projection::project(bounds.southwest(), z); auto ne = Projection::project(bounds.northeast(), z); auto se = Projection::project(bounds.southeast(), z); auto nw = Projection::project(bounds.northwest(), z); Polygon<double> p({ {sw, nw, ne, se, sw} }); impl = std::make_unique<TileCover::Impl>(z, p, false); }
std::vector<UnwrappedTileID> tileCover(const LatLngBounds& bounds_, int32_t z) { if (bounds_.isEmpty() || bounds_.south() > util::LATITUDE_MAX || bounds_.north() < -util::LATITUDE_MAX) { return {}; } LatLngBounds bounds = LatLngBounds::hull( { std::max(bounds_.south(), -util::LATITUDE_MAX), bounds_.west() }, { std::min(bounds_.north(), util::LATITUDE_MAX), bounds_.east() }); return tileCover( Projection::project(bounds.northwest(), z), Projection::project(bounds.northeast(), z), Projection::project(bounds.southeast(), z), Projection::project(bounds.southwest(), z), Projection::project(bounds.center(), z), z); }
void MapSnapshotter::Impl::setRegion(LatLngBounds region) { mbgl::EdgeInsets insets = { 0, 0, 0, 0 }; std::vector<LatLng> latLngs = { region.southwest(), region.northeast() }; map.jumpTo(map.cameraForLatLngs(latLngs, insets)); }
std::vector<UnwrappedTileID> tileCover(const LatLngBounds& bounds_, int32_t z) { if (bounds_.isEmpty() || bounds_.south() > util::LATITUDE_MAX || bounds_.north() < -util::LATITUDE_MAX) { return {}; } LatLngBounds bounds = LatLngBounds::hull( { std::max(bounds_.south(), -util::LATITUDE_MAX), bounds_.west() }, { std::min(bounds_.north(), util::LATITUDE_MAX), bounds_.east() }); const TransformState state; return tileCover( TileCoordinate::fromLatLng(state, z, bounds.northwest()).p, TileCoordinate::fromLatLng(state, z, bounds.northeast()).p, TileCoordinate::fromLatLng(state, z, bounds.southeast()).p, TileCoordinate::fromLatLng(state, z, bounds.southwest()).p, TileCoordinate::fromLatLng(state, z, bounds.center()).p, z); }
AnnotationIDs AnnotationManager::getAnnotationsInBounds(const LatLngBounds& queryBounds, const uint8_t maxZoom, const AnnotationType& type) const { const uint8_t z = maxZoom; const uint32_t z2 = 1 << z; const vec2<double> swPoint = projectPoint(queryBounds.sw); const vec2<double> nePoint = projectPoint(queryBounds.ne); // tiles number y from top down const TileID nwTile(z, swPoint.x * z2, nePoint.y * z2, z); const TileID seTile(z, nePoint.x * z2, swPoint.y * z2, z); std::unordered_set<uint32_t> matchingAnnotations; for (auto& tile : tiles) { TileID id = tile.first; if (id.z == z) { if (id.x >= nwTile.x && id.x <= seTile.x && id.y >= nwTile.y && id.y <= seTile.y) { if (id.x > nwTile.x && id.x < seTile.x && id.y > nwTile.y && id.y < seTile.y) { // Trivial accept; this tile is completely inside the query bounds, so // we'll return all of its annotations that match type (if specified). if (type != AnnotationType::Any) { std::copy_if(tile.second.first.begin(), tile.second.first.end(), std::inserter(matchingAnnotations, matchingAnnotations.begin()), [&](const uint32_t annotationID) -> bool { const auto it = annotations.find(annotationID); if (it != annotations.end()) { return (it->second->type == type); } else { return false; } }); } else { std::copy(tile.second.first.begin(), tile.second.first.end(), std::inserter(matchingAnnotations, matchingAnnotations.begin())); } } else { // This tile is intersected by the query bounds. We need to check the // tile's annotations' bounding boxes individually. std::copy_if(tile.second.first.begin(), tile.second.first.end(), std::inserter(matchingAnnotations, matchingAnnotations.begin()), [&](const uint32_t annotationID) -> bool { const auto it = annotations.find(annotationID); if (it != annotations.end()) { // check type if (type != AnnotationType::Any && it->second->type != type) { return false; } // check bounds if (it->second->type == AnnotationType::Point) { return queryBounds.contains(it->second->getPoint()); } else if (it->second->type == AnnotationType::Shape) { return queryBounds.intersects(it->second->getBounds()); } } return false; }); } } } } return AnnotationIDs(matchingAnnotations.begin(), matchingAnnotations.end()); }