#include #include #include #include #include #include #include #include namespace mbgl { using namespace style; namespace { template optional getProperty(const C& cont, const typename C::key_type& name) { const auto it = cont.find(name); if (it == cont.end() || !(it->second.template is())) { return nullopt; } return it->second.template get(); } using FeatureExtensionGetterPtr = FeatureExtensionValue (*)(std::shared_ptr, std::uint32_t, const optional>&); FeatureExtensionValue getChildren(std::shared_ptr clusterData, std::uint32_t clusterID, const optional>&) { return clusterData->getChildren(clusterID); } FeatureExtensionValue getLeaves(std::shared_ptr clusterData, std::uint32_t clusterID, const optional>& args) { if (args) { const auto limit = getProperty(*args, "limit"); const auto offset = getProperty(*args, "offset"); // Offset cannot be set without limit. if (limit) { if (offset) { return clusterData->getLeaves(clusterID, static_cast(*limit), static_cast(*offset)); } return clusterData->getLeaves(clusterID, static_cast(*limit)); } } return clusterData->getLeaves(clusterID); } FeatureExtensionValue getClusterExpansionZoom(std::shared_ptr clusterData, std::uint32_t clusterID, const optional>&) { return Value{static_cast(clusterData->getClusterExpansionZoom(clusterID))}; } MAPBOX_ETERNAL_CONSTEXPR const auto extensionGetters = mapbox::eternal::hash_map({ {"children", &getChildren}, {"leaves", &getLeaves}, {"expansion-zoom", &getClusterExpansionZoom} }); } RenderGeoJSONSource::RenderGeoJSONSource(Immutable impl_) : RenderSource(impl_) { tilePyramid.setObserver(this); } RenderGeoJSONSource::~RenderGeoJSONSource() = default; const style::GeoJSONSource::Impl& RenderGeoJSONSource::impl() const { return static_cast(*baseImpl); } bool RenderGeoJSONSource::isLoaded() const { return tilePyramid.isLoaded(); } void RenderGeoJSONSource::update(Immutable baseImpl_, const std::vector>& 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_; tilePyramid.reduceMemoryUse(); if (data_) { const uint8_t maxZ = impl().getZoomRange().max; for (const auto& pair : tilePyramid.getTiles()) { if (pair.first.canonical.z <= maxZ) { static_cast(pair.second.get())->updateData(data_->getTile(pair.first.canonical)); } } } } if (!data_) { tilePyramid.clearAll(); return; } tilePyramid.update(layers, needsRendering, needsRelayout, parameters, SourceType::GeoJSON, util::tileSize, impl().getZoomRange(), optional{}, [&, data_] (const OverscaledTileID& tileID) { return std::make_unique(tileID, impl().id, parameters, data_->getTile(tileID.canonical)); }); } void RenderGeoJSONSource::startRender(PaintParameters& parameters) { parameters.clipIDGenerator.update(tilePyramid.getRenderTiles()); tilePyramid.startRender(parameters); } void RenderGeoJSONSource::finishRender(PaintParameters& parameters) { tilePyramid.finishRender(parameters); } std::vector> RenderGeoJSONSource::getRenderTiles() { return tilePyramid.getRenderTiles(); } std::unordered_map> RenderGeoJSONSource::queryRenderedFeatures(const ScreenLineString& geometry, const TransformState& transformState, const std::vector& layers, const RenderedQueryOptions& options, const mat4& projMatrix) const { return tilePyramid.queryRenderedFeatures(geometry, transformState, layers, options, projMatrix); } std::vector RenderGeoJSONSource::querySourceFeatures(const SourceQueryOptions& options) const { return tilePyramid.querySourceFeatures(options); } mapbox::util::variant RenderGeoJSONSource::queryFeatureExtensions(const Feature& feature, const std::string& extension, const std::string& extensionField, const optional>& args) const { if (extension != "supercluster") { return {}; } const auto extensionIt = extensionGetters.find(extensionField.c_str()); if (extensionIt == extensionGetters.end()) { return {}; } const auto clusterID = getProperty(feature.properties, "cluster_id"); if (!clusterID) { return {}; } auto jsonData = data.lock(); if (!jsonData) { return {}; } return extensionIt->second(std::move(jsonData), static_cast(*clusterID), args); } void RenderGeoJSONSource::reduceMemoryUse() { tilePyramid.reduceMemoryUse(); } void RenderGeoJSONSource::dumpDebugLogs() const { tilePyramid.dumpDebugLogs(); } } // namespace mbgl