summaryrefslogtreecommitdiff
path: root/include/mbgl
diff options
context:
space:
mode:
Diffstat (limited to 'include/mbgl')
-rw-r--r--include/mbgl/map/map.hpp5
-rw-r--r--include/mbgl/style/conversion/constant.hpp49
-rw-r--r--include/mbgl/style/conversion/layer.hpp3
-rw-r--r--include/mbgl/style/conversion/light.hpp122
-rw-r--r--include/mbgl/style/conversion/position.hpp29
-rw-r--r--include/mbgl/style/layer.hpp2
-rw-r--r--include/mbgl/style/light.hpp52
-rw-r--r--include/mbgl/style/position.hpp68
-rw-r--r--include/mbgl/style/types.hpp5
-rw-r--r--include/mbgl/util/indexed_tuple.hpp56
-rw-r--r--include/mbgl/util/interpolate.hpp12
-rw-r--r--include/mbgl/util/type_list.hpp40
12 files changed, 408 insertions, 35 deletions
diff --git a/include/mbgl/map/map.hpp b/include/mbgl/map/map.hpp
index 0e3cee4e70..84ea3104d8 100644
--- a/include/mbgl/map/map.hpp
+++ b/include/mbgl/map/map.hpp
@@ -30,6 +30,7 @@ namespace style {
class Image;
class Source;
class Layer;
+class Light;
} // namespace style
class Map : private util::noncopyable {
@@ -179,6 +180,10 @@ public:
void removeImage(const std::string&);
const style::Image* getImage(const std::string&);
+ // Light
+ void setLight(std::unique_ptr<style::Light>);
+ style::Light* getLight();
+
// Defaults
std::string getStyleName() const;
LatLng getDefaultLatLng() const;
diff --git a/include/mbgl/style/conversion/constant.hpp b/include/mbgl/style/conversion/constant.hpp
index 1e1fdc2ee8..07c0a35fae 100644
--- a/include/mbgl/style/conversion/constant.hpp
+++ b/include/mbgl/style/conversion/constant.hpp
@@ -4,6 +4,7 @@
#include <mbgl/util/optional.hpp>
#include <mbgl/util/color.hpp>
#include <mbgl/util/enum.hpp>
+#include <mbgl/util/string.hpp>
#include <array>
#include <string>
@@ -92,45 +93,25 @@ struct Converter<Color> {
}
};
-template <>
-struct Converter<std::array<float, 2>> {
+template <size_t N>
+struct Converter<std::array<float, N>> {
template <class V>
- optional<std::array<float, 2>> operator()(const V& value, Error& error) const {
- if (!isArray(value) || arrayLength(value) != 2) {
- error = { "value must be an array of two numbers" };
+ optional<std::array<float, N>> operator()(const V& value, Error& error) const {
+ if (!isArray(value) || arrayLength(value) != N) {
+ error = { "value must be an array of " + util::toString(N) + " numbers" };
return {};
}
- optional<float> first = toNumber(arrayMember(value, 0));
- optional<float> second = toNumber(arrayMember(value, 1));
- if (!first || !second) {
- error = { "value must be an array of two numbers" };
- return {};
- }
-
- return std::array<float, 2> {{ *first, *second }};
- }
-};
-
-template <>
-struct Converter<std::array<float, 4>> {
- template <class V>
- optional<std::array<float, 4>> operator()(const V& value, Error& error) const {
- if (!isArray(value) || arrayLength(value) != 4) {
- error = { "value must be an array of four numbers" };
- return {};
- }
-
- optional<float> first = toNumber(arrayMember(value, 0));
- optional<float> second = toNumber(arrayMember(value, 1));
- optional<float> third = toNumber(arrayMember(value, 2));
- optional<float> fourth = toNumber(arrayMember(value, 3));
- if (!first || !second) {
- error = { "value must be an array of four numbers" };
- return {};
+ std::array<float, N> result;
+ for (size_t i = 0; i < N; i++) {
+ optional<float> n = toNumber(arrayMember(value, i));
+ if (!n) {
+ error = { "value must be an array of " + util::toString(N) + " numbers" };
+ return {};
+ }
+ result[i] = *n;
}
-
- return std::array<float, 4> {{ *first, *second, *third, *fourth }};
+ return result;
}
};
diff --git a/include/mbgl/style/conversion/layer.hpp b/include/mbgl/style/conversion/layer.hpp
index efb1df8fef..3a64c36bf5 100644
--- a/include/mbgl/style/conversion/layer.hpp
+++ b/include/mbgl/style/conversion/layer.hpp
@@ -4,6 +4,7 @@
#include <mbgl/style/layers/background_layer.hpp>
#include <mbgl/style/layers/circle_layer.hpp>
#include <mbgl/style/layers/fill_layer.hpp>
+#include <mbgl/style/layers/fill_extrusion_layer.hpp>
#include <mbgl/style/layers/line_layer.hpp>
#include <mbgl/style/layers/raster_layer.hpp>
#include <mbgl/style/layers/symbol_layer.hpp>
@@ -92,6 +93,8 @@ public:
if (*type == "fill") {
converted = convertVectorLayer<FillLayer>(*id, value, error);
+ } else if (*type == "fill-extrusion") {
+ converted = convertVectorLayer<FillExtrusionLayer>(*id, value, error);
} else if (*type == "line") {
converted = convertVectorLayer<LineLayer>(*id, value, error);
} else if (*type == "circle") {
diff --git a/include/mbgl/style/conversion/light.hpp b/include/mbgl/style/conversion/light.hpp
new file mode 100644
index 0000000000..631ed04ccb
--- /dev/null
+++ b/include/mbgl/style/conversion/light.hpp
@@ -0,0 +1,122 @@
+#pragma once
+
+#include <mbgl/style/light.hpp>
+#include <mbgl/style/conversion.hpp>
+#include <mbgl/style/conversion/position.hpp>
+#include <mbgl/style/conversion/property_value.hpp>
+#include <mbgl/style/conversion/transition_options.hpp>
+
+namespace mbgl {
+namespace style {
+namespace conversion {
+
+template <>
+struct Converter<Light> {
+public:
+ template <class V>
+ optional<Light> operator()(const V& value, Error& error) const {
+ if (!isObject(value)) {
+ error = { "light must be an object" };
+ return {};
+ }
+
+ Light light;
+
+ const auto anchor = objectMember(value, "anchor");
+ if (anchor) {
+ optional<PropertyValue<LightAnchorType>> convertedAnchor =
+ convert<PropertyValue<LightAnchorType>>(*anchor, error);
+
+ if (convertedAnchor) {
+ light.get<LightAnchor>().value = *convertedAnchor;
+ } else {
+ return {};
+ }
+ }
+
+ const auto anchorTransition = objectMember(value, "anchor-transition");
+ if (anchorTransition) {
+ optional<TransitionOptions> transition =
+ convert<TransitionOptions>(*anchorTransition, error);
+ if (transition) {
+ light.get<LightAnchor>().transition = *transition;
+ } else {
+ return {};
+ }
+ }
+
+ const auto color = objectMember(value, "color");
+ if (color) {
+ optional<PropertyValue<Color>> convertedColor =
+ convert<PropertyValue<Color>>(*color, error);
+
+ if (convertedColor) {
+ light.get<LightColor>().value = *convertedColor;
+ } else {
+ return {};
+ }
+ }
+
+ const auto colorTransition = objectMember(value, "color-transition");
+ if (colorTransition) {
+ optional<TransitionOptions> transition =
+ convert<TransitionOptions>(*colorTransition, error);
+ if (transition) {
+ light.get<LightColor>().transition = *transition;
+ } else {
+ return {};
+ }
+ }
+
+ const auto position = objectMember(value, "position");
+ if (position) {
+ optional<PropertyValue<Position>> convertedPosition =
+ convert<PropertyValue<Position>>(*position, error);
+
+ if (convertedPosition) {
+ light.get<LightPosition>().value = *convertedPosition;
+ } else {
+ return {};
+ }
+ }
+
+ const auto positionTransition = objectMember(value, "position-transition");
+ if (positionTransition) {
+ optional<TransitionOptions> transition =
+ convert<TransitionOptions>(*positionTransition, error);
+ if (transition) {
+ light.get<LightPosition>().transition = *transition;
+ } else {
+ return {};
+ }
+ }
+
+ const auto intensity = objectMember(value, "intensity");
+ if (intensity) {
+ optional<PropertyValue<float>> convertedIntensity =
+ convert<PropertyValue<float>>(*intensity, error);
+
+ if (convertedIntensity) {
+ light.get<LightIntensity>().value = *convertedIntensity;
+ } else {
+ return {};
+ }
+ }
+
+ const auto intensityTransition = objectMember(value, "intensity-transition");
+ if (intensityTransition) {
+ optional<TransitionOptions> transition =
+ convert<TransitionOptions>(*intensityTransition, error);
+ if (transition) {
+ light.get<LightIntensity>().transition = *transition;
+ } else {
+ return {};
+ }
+ }
+ return { light };
+ };
+};
+
+} // namespace conversion
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/conversion/position.hpp b/include/mbgl/style/conversion/position.hpp
new file mode 100644
index 0000000000..7036b03822
--- /dev/null
+++ b/include/mbgl/style/conversion/position.hpp
@@ -0,0 +1,29 @@
+#pragma once
+
+#include <mbgl/style/conversion.hpp>
+#include <mbgl/style/position.hpp>
+#include <mbgl/util/optional.hpp>
+
+#include <array>
+
+namespace mbgl {
+namespace style {
+namespace conversion {
+
+template <>
+struct Converter<Position> {
+ template <class V>
+ optional<Position> operator()(const V& value, Error& error) const {
+ optional<std::array<float, 3>> spherical = convert<std::array<float, 3>>(value, error);
+
+ if (!spherical) {
+ return {};
+ }
+
+ return Position(*spherical);
+ }
+};
+
+} // namespace conversion
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/layer.hpp b/include/mbgl/style/layer.hpp
index f09eb0165a..56f2c48fa7 100644
--- a/include/mbgl/style/layer.hpp
+++ b/include/mbgl/style/layer.hpp
@@ -66,7 +66,7 @@ public:
// Convenience method for dynamic dispatch on the concrete layer type. Using
// method overloading, this allows consolidation of logic common to vector-based
- // layers (Fill, Line, Circle, or Symbol). For example:
+ // layers (Fill, FillExtrusion, Line, Circle, or Symbol). For example:
//
// struct Visitor {
// void operator()(CustomLayer&) { ... }
diff --git a/include/mbgl/style/light.hpp b/include/mbgl/style/light.hpp
new file mode 100644
index 0000000000..bec8e6ddeb
--- /dev/null
+++ b/include/mbgl/style/light.hpp
@@ -0,0 +1,52 @@
+#pragma once
+
+#include <mbgl/style/property_value.hpp>
+#include <mbgl/style/transition_options.hpp>
+#include <mbgl/style/types.hpp>
+#include <mbgl/style/position.hpp>
+#include <mbgl/util/color.hpp>
+#include <mbgl/util/indexed_tuple.hpp>
+
+namespace mbgl {
+namespace style {
+
+template <class T>
+class LightProperty {
+public:
+ using Type = T;
+ using ValueType = PropertyValue<T>;
+
+ PropertyValue<T> value;
+ TransitionOptions transition;
+};
+
+struct LightAnchor : LightProperty<LightAnchorType> {
+ static LightAnchorType defaultValue() {
+ return LightAnchorType::Viewport;
+ }
+};
+
+struct LightPosition : LightProperty<Position> {
+ static Position defaultValue() {
+ std::array<float, 3> default_ = { { 1.15, 210, 30 } };
+ return Position{ { default_ } };
+ }
+};
+
+struct LightColor : LightProperty<Color> {
+ static Color defaultValue() {
+ return Color::white();
+ }
+};
+
+struct LightIntensity : LightProperty<float> {
+ static float defaultValue() {
+ return 0.5;
+ }
+};
+
+using LightProperties = TypeList<LightAnchor, LightPosition, LightColor, LightIntensity>;
+class Light : public IndexedTuple<LightProperties, LightProperties> {};
+
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/position.hpp b/include/mbgl/style/position.hpp
new file mode 100644
index 0000000000..3be8d1c55e
--- /dev/null
+++ b/include/mbgl/style/position.hpp
@@ -0,0 +1,68 @@
+#pragma once
+
+#include <mbgl/util/constants.hpp>
+
+#include <array>
+
+namespace mbgl {
+namespace style {
+class Position {
+public:
+ Position() = default;
+ Position(std::array<float, 3>& position_)
+ : radial(position_[0]), azimuthal(position_[1]), polar(position_[2]) {
+ calculateCartesian();
+ };
+
+ friend bool operator==(const Position& lhs, const Position& rhs) {
+ return lhs.radial == rhs.radial && lhs.azimuthal == rhs.azimuthal && lhs.polar == rhs.polar;
+ // TODO this doesn't address wrapping, which would be better addressed by comparing cartesian coordinates but being calculated floats are ont to be trusted.
+ }
+
+ friend bool operator!=(const Position& lhs, const Position& rhs) {
+ return !(lhs == rhs);
+ }
+
+ const std::array<float, 3> getCartesian() const {
+ return { { x, y, z } };
+ };
+
+ const std::array<float, 3> getSpherical() const {
+ return { { radial, azimuthal, polar } };
+ };
+
+ void set(std::array<float, 3>& position_) {
+ radial = position_[0];
+ azimuthal = position_[1];
+ polar = position_[2];
+ calculateCartesian();
+ };
+
+ // Utility function to be used only during interpolation; this leaves spherical coordinates undefined.
+ void setCartesian(std::array<float, 3>& position_) {
+ x = position_[0];
+ y = position_[1];
+ z = position_[2];
+ }
+
+private:
+ float radial;
+ float azimuthal;
+ float polar;
+ float x;
+ float y;
+ float z;
+
+ void calculateCartesian() {
+ // We abstract "north"/"up" (compass-wise) to be 0° when really this is 90° (π/2): we
+ // correct for that here
+ const float _a = (azimuthal + 90) * util::DEG2RAD;
+ const float _p = polar * util::DEG2RAD;
+
+ x = radial * std::cos(_a) * std::sin(_p);
+ y = radial * std::sin(_a) * std::sin(_p);
+ z = radial * std::cos(_p);
+ };
+};
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/types.hpp b/include/mbgl/style/types.hpp
index 1f2f5c3105..e0436efb67 100644
--- a/include/mbgl/style/types.hpp
+++ b/include/mbgl/style/types.hpp
@@ -92,5 +92,10 @@ enum class IconTextFitType : uint8_t {
Height
};
+enum class LightAnchorType: bool {
+ Map,
+ Viewport
+};
+
} // namespace style
} // namespace mbgl
diff --git a/include/mbgl/util/indexed_tuple.hpp b/include/mbgl/util/indexed_tuple.hpp
new file mode 100644
index 0000000000..a414639530
--- /dev/null
+++ b/include/mbgl/util/indexed_tuple.hpp
@@ -0,0 +1,56 @@
+#pragma once
+
+#include <mbgl/util/type_list.hpp>
+
+#include <type_traits>
+#include <tuple>
+
+namespace mbgl {
+
+template <class T, class... Ts>
+struct TypeIndex;
+
+template <class T, class... Ts>
+struct TypeIndex<T, T, Ts...> : std::integral_constant<std::size_t, 0> {};
+
+template <class T, class U, class... Ts>
+struct TypeIndex<T, U, Ts...> : std::integral_constant<std::size_t, 1 + TypeIndex<T, Ts...>::value> {};
+
+template <class...> class IndexedTuple;
+
+// A tuple of Ts, where individual members can be accessed via `t.get<I>()` for I ∈ Is.
+//
+// See https://github.com/mapbox/cpp/blob/master/C%2B%2B%20Structural%20Metaprogramming.md
+// for motivation.
+//
+template <class... Is, class... Ts>
+class IndexedTuple<TypeList<Is...>, TypeList<Ts...>> : public std::tuple<Ts...> {
+public:
+ static_assert(sizeof...(Is) == sizeof...(Ts), "IndexedTuple size mismatch");
+
+ using std::tuple<Ts...>::tuple;
+
+ template <class I>
+ static constexpr std::size_t Index = TypeIndex<I, Is...>::value;
+
+ template <class I>
+ auto& get() {
+ return std::get<Index<I>>(*this);
+ }
+
+ template <class I>
+ const auto& get() const {
+ return std::get<Index<I>>(*this);
+ }
+
+ template <class... Js, class... Us>
+ IndexedTuple<TypeList<Is..., Js...>, TypeList<Ts..., Us...>>
+ concat(const IndexedTuple<TypeList<Js...>, TypeList<Us...>>& other) const {
+ return IndexedTuple<TypeList<Is..., Js...>, TypeList<Ts..., Us...>> {
+ get<Is>()...,
+ other.template get<Js>()...
+ };
+ }
+};
+
+} // namespace mbgl
diff --git a/include/mbgl/util/interpolate.hpp b/include/mbgl/util/interpolate.hpp
index d463ffc056..a2103f18b2 100644
--- a/include/mbgl/util/interpolate.hpp
+++ b/include/mbgl/util/interpolate.hpp
@@ -2,6 +2,7 @@
#include <mbgl/util/color.hpp>
#include <mbgl/util/range.hpp>
+#include <mbgl/style/position.hpp>
#include <array>
#include <vector>
@@ -47,6 +48,17 @@ public:
};
template <>
+struct Interpolator<style::Position> {
+public:
+ style::Position operator()(const style::Position& a, const style::Position& b, const double t) {
+ auto pos = style::Position();
+ auto interpolated = interpolate(a.getCartesian(), b.getCartesian(), t);
+ pos.setCartesian(interpolated);
+ return { pos };
+ }
+};
+
+template <>
struct Interpolator<Color> {
public:
Color operator()(const Color& a, const Color& b, const double t) {
diff --git a/include/mbgl/util/type_list.hpp b/include/mbgl/util/type_list.hpp
new file mode 100644
index 0000000000..4a5e95c8a4
--- /dev/null
+++ b/include/mbgl/util/type_list.hpp
@@ -0,0 +1,40 @@
+#pragma once
+
+#include <type_traits>
+#include <tuple>
+
+namespace mbgl {
+
+template <class...>
+class TypeList {};
+
+namespace detail {
+
+template <class, class>
+struct TypeCons;
+
+template <class T, class... Ts>
+struct TypeCons<T, TypeList<Ts...>> {
+ using Type = TypeList<T, Ts...>;
+};
+
+template <class, template <class> class>
+struct TypeFilter;
+
+template <template <class> class Predicate>
+struct TypeFilter<TypeList<>, Predicate> {
+ using Type = TypeList<>;
+};
+
+template <template <class> class Predicate, class T, class... Ts>
+struct TypeFilter<TypeList<T, Ts...>, Predicate> {
+ using Tail = typename TypeFilter<TypeList<Ts...>, Predicate>::Type;
+ using Type = std::conditional_t<Predicate<T>::value, typename TypeCons<T, Tail>::Type, Tail>;
+};
+
+} // namespace detail
+
+template <class TypeList, template <class> class Predicate>
+using FilteredTypeList = typename detail::TypeFilter<TypeList, Predicate>::Type;
+
+} // namespace mbgl