146 lines
5.5 KiB
C++
146 lines
5.5 KiB
C++
#include <mbgl/renderer/sources/render_geojson_source.hpp>
|
|
#include <mbgl/renderer/render_tile.hpp>
|
|
#include <mbgl/renderer/paint_parameters.hpp>
|
|
#include <mbgl/tile/geojson_tile.hpp>
|
|
#include <mbgl/renderer/tile_parameters.hpp>
|
|
|
|
#include <mapbox/eternal.hpp>
|
|
|
|
namespace mbgl {
|
|
|
|
using namespace style;
|
|
|
|
namespace {
|
|
|
|
template <typename T, typename C>
|
|
std::optional<T> getProperty(const C& cont, const typename C::key_type& name) {
|
|
const auto it = cont.find(name);
|
|
if (it == cont.end() || !(it->second.template is<T>())) {
|
|
return std::nullopt;
|
|
}
|
|
return it->second.template get<T>();
|
|
}
|
|
|
|
using FeatureExtensionGetterPtr = FeatureExtensionValue (*)(std::shared_ptr<style::GeoJSONData>,
|
|
std::uint32_t,
|
|
const std::optional<std::map<std::string, Value>>&);
|
|
|
|
// NOLINTNEXTLINE(performance-unnecessary-value-param)
|
|
FeatureExtensionValue getChildren(std::shared_ptr<style::GeoJSONData> clusterData,
|
|
std::uint32_t clusterID,
|
|
const std::optional<std::map<std::string, Value>>&) {
|
|
return clusterData->getChildren(clusterID);
|
|
}
|
|
|
|
// NOLINTNEXTLINE(performance-unnecessary-value-param)
|
|
FeatureExtensionValue getLeaves(std::shared_ptr<style::GeoJSONData> clusterData,
|
|
std::uint32_t clusterID,
|
|
const std::optional<std::map<std::string, Value>>& args) {
|
|
if (args) {
|
|
const auto limit = getProperty<uint64_t>(*args, "limit");
|
|
const auto offset = getProperty<uint64_t>(*args, "offset");
|
|
// Offset cannot be set without limit.
|
|
if (limit) {
|
|
if (offset) {
|
|
return clusterData->getLeaves(
|
|
clusterID, static_cast<std::uint32_t>(*limit), static_cast<std::uint32_t>(*offset));
|
|
}
|
|
return clusterData->getLeaves(clusterID, static_cast<std::uint32_t>(*limit), 0u);
|
|
}
|
|
}
|
|
|
|
return clusterData->getLeaves(clusterID, 10u, 0u);
|
|
}
|
|
|
|
// NOLINTNEXTLINE(performance-unnecessary-value-param)
|
|
FeatureExtensionValue getClusterExpansionZoom(std::shared_ptr<style::GeoJSONData> clusterData,
|
|
std::uint32_t clusterID,
|
|
const std::optional<std::map<std::string, Value>>&) {
|
|
return Value{static_cast<uint64_t>(clusterData->getClusterExpansionZoom(clusterID))};
|
|
}
|
|
|
|
constexpr const auto extensionGetters = mapbox::eternal::hash_map<mapbox::eternal::string, FeatureExtensionGetterPtr>(
|
|
{{"children", &getChildren}, {"leaves", &getLeaves}, {"expansion-zoom", &getClusterExpansionZoom}});
|
|
|
|
} // namespace
|
|
|
|
RenderGeoJSONSource::RenderGeoJSONSource(Immutable<style::GeoJSONSource::Impl> impl_,
|
|
std::shared_ptr<Scheduler> threadPool_)
|
|
: RenderTileSource(std::move(impl_), std::move(threadPool_)) {}
|
|
|
|
RenderGeoJSONSource::~RenderGeoJSONSource() = default;
|
|
|
|
const style::GeoJSONSource::Impl& RenderGeoJSONSource::impl() const {
|
|
return static_cast<const style::GeoJSONSource::Impl&>(*baseImpl);
|
|
}
|
|
|
|
void RenderGeoJSONSource::update(Immutable<style::Source::Impl> baseImpl_,
|
|
const std::vector<Immutable<LayerProperties>>& layers,
|
|
const bool needsRendering,
|
|
const bool needsRelayout,
|
|
const TileParameters& parameters) {
|
|
std::swap(baseImpl, baseImpl_);
|
|
|
|
enabled = needsRendering;
|
|
|
|
auto data_ = impl().getData().lock();
|
|
if (data.lock() != data_) {
|
|
data = data_;
|
|
if (parameters.mode != MapMode::Continuous) {
|
|
// Clearing the tile pyramid in order to avoid render tests being flaky.
|
|
tilePyramid.clearAll();
|
|
} else if (data_) {
|
|
tilePyramid.reduceMemoryUse();
|
|
const uint8_t maxZ = impl().getZoomRange().max;
|
|
for (const auto& pair : tilePyramid.getTiles()) {
|
|
if (pair.first.canonical.z <= maxZ) {
|
|
static_cast<GeoJSONTile*>(pair.second.get())->updateData(data_, needsRelayout);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!data_) return;
|
|
|
|
tilePyramid.update(layers,
|
|
needsRendering,
|
|
needsRelayout,
|
|
parameters,
|
|
*baseImpl,
|
|
util::tileSize_I,
|
|
impl().getZoomRange(),
|
|
std::optional<LatLngBounds>{},
|
|
[&, data_](const OverscaledTileID& tileID) {
|
|
return std::make_unique<GeoJSONTile>(tileID, impl().id, parameters, data_);
|
|
});
|
|
}
|
|
|
|
mapbox::util::variant<Value, FeatureCollection> RenderGeoJSONSource::queryFeatureExtensions(
|
|
const Feature& feature,
|
|
const std::string& extension,
|
|
const std::string& extensionField,
|
|
const std::optional<std::map<std::string, Value>>& args) const {
|
|
if (extension != "supercluster") {
|
|
return {};
|
|
}
|
|
|
|
const auto extensionIt = extensionGetters.find(extensionField.c_str());
|
|
if (extensionIt == extensionGetters.end()) {
|
|
return {};
|
|
}
|
|
|
|
const auto clusterID = getProperty<uint64_t>(feature.properties, "cluster_id");
|
|
if (!clusterID) {
|
|
return {};
|
|
}
|
|
|
|
auto jsonData = data.lock();
|
|
if (!jsonData) {
|
|
return {};
|
|
}
|
|
|
|
return extensionIt->second(std::move(jsonData), static_cast<std::uint32_t>(*clusterID), args);
|
|
}
|
|
|
|
} // namespace mbgl
|