Files
MapLibreParticleLab/src/mbgl/renderer/sources/render_geojson_source.cpp

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