[core, ios, macos] Refactor composite stop types and conversions

This commit is contained in:
John Firebaugh
2017-02-07 12:35:27 -08:00
parent 9df24addfb
commit f35ca0d9df
13 changed files with 268 additions and 149 deletions

View File

@@ -282,6 +282,72 @@ struct Converter<CompositeValue<S>> {
}
};
template <class T>
struct Converter<CompositeExponentialStops<T>> {
static constexpr const char * type = "exponential";
template <class V>
Result<CompositeExponentialStops<T>> operator()(const V& value) const {
auto stops = convertStops<CompositeValue<float>, T>(value);
if (!stops) {
return stops.error();
}
auto base = 1.0f;
auto baseValue = objectMember(value, "base");
if (baseValue && toNumber(*baseValue)) {
base = *toNumber(*baseValue);
}
std::map<float, std::map<float, T>> convertedStops;
for (const auto& stop : *stops) {
convertedStops[stop.first.first].emplace(stop.first.second, stop.second);
}
return CompositeExponentialStops<T>(convertedStops, base);
}
};
template <class T>
struct Converter<CompositeIntervalStops<T>> {
static constexpr const char * type = "interval";
template <class V>
Result<CompositeIntervalStops<T>> operator()(const V& value) const {
auto stops = convertStops<CompositeValue<float>, T>(value);
if (!stops) {
return stops.error();
}
std::map<float, std::map<float, T>> convertedStops;
for (const auto& stop : *stops) {
convertedStops[stop.first.first].emplace(stop.first.second, stop.second);
}
return CompositeIntervalStops<T>(convertedStops);
}
};
template <class T>
struct Converter<CompositeCategoricalStops<T>> {
static constexpr const char * type = "categorical";
template <class V>
Result<CompositeCategoricalStops<T>> operator()(const V& value) const {
auto stops = convertStops<CompositeValue<CategoricalValue>, T>(value);
if (!stops) {
return stops.error();
}
std::map<float, std::map<CategoricalValue, T>> convertedStops;
for (const auto& stop : *stops) {
convertedStops[stop.first.first].emplace(stop.first.second, stop.second);
}
return CompositeCategoricalStops<T>(convertedStops);
}
};
template <class T>
struct Converter<CompositeFunction<T>> {
template <class V>
@@ -300,66 +366,17 @@ struct Converter<CompositeFunction<T>> {
return Error { "function property must be a string" };
}
auto stops = StopsConverter<T, typename CompositeFunction<T>::Stops>()(value);
if (!stops) {
return stops.error();
}
auto defaultValue = convertDefaultValue<T>(value);
if (!defaultValue) {
return defaultValue.error();
}
std::string type = "exponential";
auto typeValue = objectMember(value, "type");
if (typeValue && toString(*typeValue)) {
type = *toString(*typeValue);
}
if (type == "exponential") {
auto stops = convertStops<CompositeValue<float>, T>(value);
if (!stops) {
return stops.error();
}
auto base = 1.0f;
auto baseValue = objectMember(value, "base");
if (baseValue && toNumber(*baseValue)) {
base = *toNumber(*baseValue);
}
std::map<float, ExponentialStops<T>> convertedStops;
for (const auto& stop : *stops) {
auto& inner = convertedStops[stop.first.first];
inner.base = base;
inner.stops.emplace(stop.first.second, stop.second);
}
return CompositeFunction<T>(*propertyString, convertedStops, *defaultValue);
} else if (type == "interval") {
auto stops = convertStops<CompositeValue<float>, T>(value);
if (!stops) {
return stops.error();
}
std::map<float, IntervalStops<T>> convertedStops;
for (const auto& stop : *stops) {
auto& inner = convertedStops[stop.first.first];
inner.stops.emplace(stop.first.second, stop.second);
}
return CompositeFunction<T>(*propertyString, convertedStops, *defaultValue);
} else if (type == "categorical") {
auto stops = convertStops<CompositeValue<CategoricalValue>, T>(value);
if (!stops) {
return stops.error();
}
std::map<float, CategoricalStops<T>> convertedStops;
for (const auto& stop : *stops) {
auto& inner = convertedStops[stop.first.first];
inner.stops.emplace(stop.first.second, stop.second);
}
return CompositeFunction<T>(*propertyString, convertedStops, *defaultValue);
} else {
return Error { "unsupported function type" };
}
return CompositeFunction<T>(*propertyString, *stops, *defaultValue);
}
};

View File

@@ -0,0 +1,30 @@
#pragma once
#include <mbgl/style/function/categorical_stops.hpp>
namespace mbgl {
namespace style {
template <class T>
class CompositeCategoricalStops {
public:
using Stops = std::map<float, std::map<CategoricalValue, T>>;
Stops stops;
CompositeCategoricalStops() = default;
CompositeCategoricalStops(Stops stops_)
: stops(std::move(stops_)) {
}
CategoricalStops<T> innerStops(const std::map<CategoricalValue, T>& stops_) const {
return CategoricalStops<T>(stops_);
}
friend bool operator==(const CompositeCategoricalStops& lhs,
const CompositeCategoricalStops& rhs) {
return lhs.stops == rhs.stops;
}
};
} // namespace style
} // namespace mbgl

View File

@@ -0,0 +1,35 @@
#pragma once
#include <mbgl/style/function/exponential_stops.hpp>
#include <map>
namespace mbgl {
namespace style {
template <class T>
class CompositeExponentialStops {
public:
using Stops = std::map<float, std::map<float, T>>;
Stops stops;
float base = 1.0f;
CompositeExponentialStops() = default;
CompositeExponentialStops(Stops stops_, float base_ = 1.0f)
: stops(std::move(stops_)),
base(base_) {
}
ExponentialStops<T> innerStops(const std::map<float, T>& stops_) const {
return ExponentialStops<T>(stops_, base);
}
friend bool operator==(const CompositeExponentialStops& lhs,
const CompositeExponentialStops& rhs) {
return lhs.stops == rhs.stops && lhs.base == rhs.base;
}
};
} // namespace style
} // namespace mbgl

View File

@@ -1,8 +1,8 @@
#pragma once
#include <mbgl/style/function/exponential_stops.hpp>
#include <mbgl/style/function/interval_stops.hpp>
#include <mbgl/style/function/categorical_stops.hpp>
#include <mbgl/style/function/composite_exponential_stops.hpp>
#include <mbgl/style/function/composite_interval_stops.hpp>
#include <mbgl/style/function/composite_categorical_stops.hpp>
#include <mbgl/util/interpolate.hpp>
#include <mbgl/util/range.hpp>
#include <mbgl/util/variant.hpp>
@@ -36,12 +36,12 @@ public:
using Stops = std::conditional_t<
util::Interpolatable<T>,
variant<
std::map<float, ExponentialStops<T>>,
std::map<float, IntervalStops<T>>,
std::map<float, CategoricalStops<T>>>,
CompositeExponentialStops<T>,
CompositeIntervalStops<T>,
CompositeCategoricalStops<T>>,
variant<
std::map<float, IntervalStops<T>>,
std::map<float, CategoricalStops<T>>>>;
CompositeIntervalStops<T>,
CompositeCategoricalStops<T>>>;
CompositeFunction(std::string property_, Stops stops_, optional<T> defaultValue_ = {})
: property(std::move(property_)),
@@ -53,20 +53,20 @@ public:
coveringRanges(float zoom) const {
return stops.match(
[&] (const auto& s) {
assert(!s.empty());
auto minIt = s.lower_bound(zoom);
auto maxIt = s.upper_bound(zoom);
if (minIt != s.begin()) {
assert(!s.stops.empty());
auto minIt = s.stops.lower_bound(zoom);
auto maxIt = s.stops.upper_bound(zoom);
if (minIt != s.stops.begin()) {
minIt--;
}
return std::make_tuple(
Range<float> {
minIt == s.end() ? s.rbegin()->first : minIt->first,
maxIt == s.end() ? s.rbegin()->first : maxIt->first
minIt == s.stops.end() ? s.stops.rbegin()->first : minIt->first,
maxIt == s.stops.end() ? s.stops.rbegin()->first : maxIt->first
},
Range<InnerStops> {
minIt == s.end() ? s.rbegin()->second : minIt->second,
maxIt == s.end() ? s.rbegin()->second : maxIt->second
s.innerStops(minIt == s.stops.end() ? s.stops.rbegin()->second : minIt->second),
s.innerStops(maxIt == s.stops.end() ? s.stops.rbegin()->second : maxIt->second)
}
);
}

View File

@@ -0,0 +1,32 @@
#pragma once
#include <mbgl/style/function/interval_stops.hpp>
#include <map>
namespace mbgl {
namespace style {
template <class T>
class CompositeIntervalStops {
public:
using Stops = std::map<float, std::map<float, T>>;
Stops stops;
CompositeIntervalStops() = default;
CompositeIntervalStops(Stops stops_)
: stops(std::move(stops_)) {
}
IntervalStops<T> innerStops(const std::map<float, T>& stops_) const {
return IntervalStops<T>(stops_);
}
friend bool operator==(const CompositeIntervalStops& lhs,
const CompositeIntervalStops& rhs) {
return lhs.stops == rhs.stops;
}
};
} // namespace style
} // namespace mbgl