summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzmiao <zmiao.jamie@gmail.com>2019-07-23 15:54:44 +0300
committerzmiao <zmiao.jamie@gmail.com>2019-07-23 15:54:44 +0300
commit962769aab9e628e69d5a1eb2a747765037f9086f (patch)
treed0b3578ec73a69c8515f877f50db774e120b09a0
parent570b871b910aae375ce202398f205c6cda863f24 (diff)
downloadqtlocation-mapboxgl-upstream/enable_cluster_properties_aggregation.tar.gz
create map and reduce expressions from raw stringsupstream/enable_cluster_properties_aggregation
-rw-r--r--include/mbgl/style/expression/expression.hpp8
-rw-r--r--include/mbgl/style/property_expression.hpp22
-rw-r--r--include/mbgl/style/sources/geojson_source.hpp7
-rw-r--r--src/mbgl/style/expression/expression.cpp6
-rw-r--r--src/mbgl/style/sources/geojson_source_impl.cpp111
5 files changed, 81 insertions, 73 deletions
diff --git a/include/mbgl/style/expression/expression.hpp b/include/mbgl/style/expression/expression.hpp
index 9a2f7b3b41..9ba5c72bce 100644
--- a/include/mbgl/style/expression/expression.hpp
+++ b/include/mbgl/style/expression/expression.hpp
@@ -32,6 +32,9 @@ public:
EvaluationContext(float zoom_, GeometryTileFeature const * feature_) :
zoom(zoom_), feature(feature_)
{}
+ EvaluationContext(optional<double> accumulated_, GeometryTileFeature const * feature_) :
+ accumulated(std::move(accumulated_)), feature(feature_)
+ {}
EvaluationContext(optional<float> zoom_, GeometryTileFeature const * feature_, optional<double> colorRampParameter_) :
zoom(std::move(zoom_)), feature(feature_), colorRampParameter(std::move(colorRampParameter_))
{}
@@ -42,9 +45,10 @@ public:
};
optional<float> zoom;
+ optional<double> accumulated;
GeometryTileFeature const * feature = nullptr;
optional<double> colorRampParameter;
- optional<double> accumulated;
+
// Contains formatted section object, std::unordered_map<std::string, Value>.
const Value* formattedSection = nullptr;
};
@@ -164,7 +168,7 @@ public:
type::Type getType() const { return type; };
EvaluationResult evaluate(optional<float> zoom, const Feature& feature, optional<double> colorRampParameter) const;
- EvaluationResult evaluate(const Feature& feature) const;
+ EvaluationResult evaluate(optional<double> accumulated, const Feature& feature) const;
/**
* Statically analyze the expression, attempting to enumerate possible outputs. Returns
* an array of values plus the sentinel null optional value, used to indicate that the
diff --git a/include/mbgl/style/property_expression.hpp b/include/mbgl/style/property_expression.hpp
index 89a0cff418..1cf6e9683d 100644
--- a/include/mbgl/style/property_expression.hpp
+++ b/include/mbgl/style/property_expression.hpp
@@ -1,10 +1,10 @@
#pragma once
#include <mbgl/style/expression/expression.hpp>
-#include <mbgl/style/expression/is_constant.hpp>
+#include <mbgl/style/expression/find_zoom_curve.hpp>
#include <mbgl/style/expression/interpolate.hpp>
+#include <mbgl/style/expression/is_constant.hpp>
#include <mbgl/style/expression/step.hpp>
-#include <mbgl/style/expression/find_zoom_curve.hpp>
#include <mbgl/util/range.hpp>
namespace mbgl {
@@ -34,11 +34,10 @@ template <class T>
class PropertyExpression final : public PropertyExpressionBase {
public:
// Second parameter to be used only for conversions from legacy functions.
- PropertyExpression(std::unique_ptr<expression::Expression> expression_, optional<T> defaultValue_ = nullopt)
- : PropertyExpressionBase(std::move(expression_)),
- defaultValue(std::move(defaultValue_)) {
+ PropertyExpression(std::unique_ptr<expression::Expression> expression_,
+ optional<T> defaultValue_ = nullopt)
+ : PropertyExpressionBase(std::move(expression_)), defaultValue(std::move(defaultValue_)) {
}
-
T evaluate(const expression::EvaluationContext& context, T finalDefaultValue = T()) const {
assert(canEvaluateWith(context));
const expression::EvaluationResult result = expression->evaluate(context);
@@ -52,9 +51,11 @@ public:
T evaluate(float zoom) const {
return evaluate(expression::EvaluationContext(zoom));
}
-
- T evaluate(mapbox::feature::feature<double>& f, T finalDefaultValue = T()) const {
- const expression::EvaluationResult result = expression->evaluate(f);
+
+ T evaluate(optional<double> accumulated,
+ mapbox::feature::feature<double>& f,
+ T finalDefaultValue = T()) const {
+ const expression::EvaluationResult result = expression->evaluate(accumulated, f);
if (result) {
const optional<T> typed = expression::fromExpressionValue<T>(*result);
return typed ? *typed : defaultValue ? *defaultValue : finalDefaultValue;
@@ -74,8 +75,7 @@ public:
return expression::fromExpressionValues<T>(expression->possibleOutputs());
}
- friend bool operator==(const PropertyExpression& lhs,
- const PropertyExpression& rhs) {
+ friend bool operator==(const PropertyExpression& lhs, const PropertyExpression& rhs) {
return *lhs.expression == *rhs.expression;
}
diff --git a/include/mbgl/style/sources/geojson_source.hpp b/include/mbgl/style/sources/geojson_source.hpp
index a03b910279..cf84704ee8 100644
--- a/include/mbgl/style/sources/geojson_source.hpp
+++ b/include/mbgl/style/sources/geojson_source.hpp
@@ -1,9 +1,13 @@
#pragma once
#include <mbgl/style/source.hpp>
+#include <mbgl/util/constants.hpp>
#include <mbgl/util/geojson.hpp>
#include <mbgl/util/optional.hpp>
-#include <mbgl/util/constants.hpp>
+
+#include <string>
+#include <unordered_map>
+#include <utility>
namespace mbgl {
@@ -24,6 +28,7 @@ struct GeoJSONOptions {
bool cluster = false;
uint16_t clusterRadius = 50;
uint8_t clusterMaxZoom = 17;
+ std::unordered_map<std::string, std::pair<std::string, std::string>> clusterProperties;
};
class GeoJSONSource : public Source {
diff --git a/src/mbgl/style/expression/expression.cpp b/src/mbgl/style/expression/expression.cpp
index e826cf6ec0..4a7c10fa74 100644
--- a/src/mbgl/style/expression/expression.cpp
+++ b/src/mbgl/style/expression/expression.cpp
@@ -30,12 +30,12 @@ public:
EvaluationResult Expression::evaluate(optional<float> zoom, const Feature& feature, optional<double> colorRampParameter) const {
GeoJSONFeature f(feature);
- return this->evaluate(EvaluationContext(zoom, &f, colorRampParameter));
+ return this->evaluate(EvaluationContext(zoom, &f, colorRampParameter));
}
-EvaluationResult Expression::evaluate(const Feature& feature) const{
+EvaluationResult Expression::evaluate(optional<double> accumulated, const Feature& feature) const{
GeoJSONFeature f(feature);
- return this->evaluate(EvaluationContext(&f));
+ return this->evaluate(EvaluationContext(accumulated,&f));
}
} // namespace expression
diff --git a/src/mbgl/style/sources/geojson_source_impl.cpp b/src/mbgl/style/sources/geojson_source_impl.cpp
index e1d3edbe08..425f8489ea 100644
--- a/src/mbgl/style/sources/geojson_source_impl.cpp
+++ b/src/mbgl/style/sources/geojson_source_impl.cpp
@@ -13,11 +13,9 @@
#include <rapidjson/error/en.h>
#include <mapbox/geojsonvt.hpp>
-#include <supercluster.hpp>
-#include <mbgl/style/conversion/json.hpp>
#include <mbgl/style/conversion/constant.hpp>
-#include <mbgl/style/conversion/property_value.hpp>
-#include <mbgl/style/expression/dsl.hpp>
+#include <mbgl/style/conversion/json.hpp>
+#include <supercluster.hpp>
#include <cmath>
#include <functional>
@@ -25,6 +23,21 @@
namespace mbgl {
namespace style {
+template <class T>
+PropertyExpression<T> createPropertyExpression(const char* expr) {
+ using JSValue = rapidjson::GenericValue<rapidjson::UTF8<>, rapidjson::CrtAllocator>;
+ rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator> document;
+ document.Parse<0>(expr);
+ assert(!document.HasParseError());
+
+ // optional<expression::TypeAnnotationOption> typeAnnotationOption;
+ const JSValue* expression = &document;
+ expression::ParsingContext ctx;
+ expression::ParseResult parsed =
+ ctx.parseExpression(mbgl::style::conversion::Convertible(expression));
+ return PropertyExpression<T>(std::move(*parsed));
+}
+
class GeoJSONVTData : public GeoJSONData {
public:
GeoJSONVTData(const GeoJSON& geoJSON, const mapbox::geojsonvt::Options& options)
@@ -85,18 +98,13 @@ GeoJSONSource::Impl::Impl(std::string id_, GeoJSONOptions options_)
: Source::Impl(SourceType::GeoJSON, std::move(id_)), options(std::move(options_)) {
}
-std::unique_ptr<style::expression::Expression>
-createExpression(const char* op, std::vector<std::unique_ptr<style::expression::Expression>> args) {
- style::expression::ParsingContext ctx;
- style::expression::ParseResult result =
- style::expression::createCompoundExpression(op, std::move(args), ctx);
- assert(result);
- return std::move(*result);
-}
-
GeoJSONSource::Impl::Impl(const Impl& other, const GeoJSON& geoJSON)
: Source::Impl(other), options(other.options) {
constexpr double scale = util::EXTENT / util::tileSize;
+ options.clusterProperties =
+ std::unordered_map<std::string, std::pair<std::string, std::string>>{
+ { "max", { "+", R"(["get", "scalerank"])" } }
+ };
if (options.cluster && geoJSON.is<mapbox::feature::feature_collection<double>>() &&
!geoJSON.get<mapbox::feature::feature_collection<double>>().empty()) {
@@ -104,51 +112,42 @@ GeoJSONSource::Impl::Impl(const Impl& other, const GeoJSON& geoJSON)
clusterOptions.maxZoom = options.clusterMaxZoom;
clusterOptions.extent = util::EXTENT;
clusterOptions.radius = ::round(scale * options.clusterRadius);
- // process here, taking the cluster propeties into consideration
-
- using namespace mbgl::style::expression::dsl;
- using namespace mbgl;
- using namespace mbgl::style;
-
- using JSValue = rapidjson::GenericValue<rapidjson::UTF8<>, rapidjson::CrtAllocator>;
-
-
-// std::unordered_map<std::string, const char*>
-// properties{{std::string("max"), expr1}};
- const char* expr1 = R"(["get", "scalerank"])";
- rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator> document;
- document.Parse<0>(expr1);
- assert(!document.HasParseError());
- expression::ParsingContext ctx;
-// optional<expression::TypeAnnotationOption> typeAnnotationOption;
- const JSValue* expression = &document;
- expression::ParseResult parsed = ctx.parseExpression(mbgl::style::conversion::Convertible(expression));
- auto mapExpression = PropertyExpression<double>(std::move(*parsed));
-
- const char* expr2 = R"(["+",["accumulated"], ["get", "max"]])";
- rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator> document2;
- document2.Parse<0>(expr2);
- assert(!document2.HasParseError());
- expression::ParsingContext ctx2;
- // optional<expression::TypeAnnotationOption> typeAnnotationOption;
- const JSValue* expression2 = &document2;
- expression::ParseResult parsed2 = ctx.parseExpression(mbgl::style::conversion::Convertible(expression2));
- auto reduceExpression = PropertyExpression<double>(std::move(*parsed2));
-
-
-// auto mapExpression = PropertyExpression<double>(get("scalerank"));
-// auto reduceExpression = PropertyExpression<double>(get("max"));
- clusterOptions.map = [&](const mapbox::feature::property_map& properties) ->
- mapbox::feature::property_map {mapbox::feature::property_map ret{};
- auto feature = mapbox::feature::feature<double>();
- feature.properties = properties;
- ret["max"] = mapExpression.evaluate(feature);
+ std::unordered_map<std::string, PropertyExpression<double>> mapExpressions;
+ std::unordered_map<std::string, PropertyExpression<double>> reduceExpressions;
+ for (const auto& p : options.clusterProperties) {
+ mapExpressions.emplace(p.first,
+ createPropertyExpression<double>(p.second.second.c_str()));
+ std::stringstream ss;
+ // [operator, ['accumulated'], ['get', key]]
+ ss << std::string(R"([")") << p.second.first
+ << std::string(R"(", ["accumulated"], ["get", ")") << p.first
+ << std::string(R"("]])");
+ reduceExpressions.emplace(p.first, createPropertyExpression<double>(ss.str().c_str()));
+ }
+ clusterOptions.map =
+ [&](const mapbox::feature::property_map& properties) -> mapbox::feature::property_map {
+ mapbox::feature::property_map ret{};
+ for (const auto& p : options.clusterProperties) {
+ auto feature = mapbox::feature::feature<double>();
+ feature.properties = properties;
+ auto iter = mapExpressions.find(p.first);
+ if (iter != mapExpressions.end()) {
+ ret[p.first] = iter->second.evaluate(nullopt, feature);
+ }
+ }
return ret;
};
- clusterOptions.reduce = [&](mapbox::feature::property_map & toReturn, const mapbox::feature::property_map &toFill){
- auto feature = mapbox::feature::feature<double>();
- feature.properties = toFill;
- toReturn["max"] = reduceExpression.evaluate( feature);
+ clusterOptions.reduce = [&](mapbox::feature::property_map& toReturn,
+ const mapbox::feature::property_map& toFill) {
+ for (const auto& p : options.clusterProperties) {
+ auto feature = mapbox::feature::feature<double>();
+ feature.properties = toFill;
+ optional<double> accumulated(toReturn[p.first].get<double>());
+ auto iter = reduceExpressions.find(p.first);
+ if (iter != reduceExpressions.end()) {
+ toReturn[p.first] = iter->second.evaluate(accumulated, feature);
+ }
+ }
};
data = std::make_shared<SuperclusterData>(
geoJSON.get<mapbox::feature::feature_collection<double>>(), clusterOptions);