[core, ios, macos, android, node] Heatmap layer (#11046)
Co-Authored-By: Konstantin Käfer <mail@kkaefer.com> Co-Authored-By: Anand Thakker <anandthakker@users.noreply.github.com> Co-Authored-By: Minh Nguyễn <1ec5@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
1fdec7a5c1
commit
82de856c94
@@ -146,6 +146,10 @@ set(MBGL_CORE_FILES
|
||||
src/mbgl/programs/fill_extrusion_program.hpp
|
||||
src/mbgl/programs/fill_program.cpp
|
||||
src/mbgl/programs/fill_program.hpp
|
||||
src/mbgl/programs/heatmap_program.cpp
|
||||
src/mbgl/programs/heatmap_program.hpp
|
||||
src/mbgl/programs/heatmap_texture_program.cpp
|
||||
src/mbgl/programs/heatmap_texture_program.hpp
|
||||
src/mbgl/programs/hillshade_prepare_program.cpp
|
||||
src/mbgl/programs/hillshade_prepare_program.hpp
|
||||
src/mbgl/programs/hillshade_program.cpp
|
||||
@@ -225,6 +229,8 @@ set(MBGL_CORE_FILES
|
||||
src/mbgl/renderer/buckets/fill_bucket.hpp
|
||||
src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp
|
||||
src/mbgl/renderer/buckets/fill_extrusion_bucket.hpp
|
||||
src/mbgl/renderer/buckets/heatmap_bucket.cpp
|
||||
src/mbgl/renderer/buckets/heatmap_bucket.hpp
|
||||
src/mbgl/renderer/buckets/hillshade_bucket.cpp
|
||||
src/mbgl/renderer/buckets/hillshade_bucket.hpp
|
||||
src/mbgl/renderer/buckets/line_bucket.cpp
|
||||
@@ -245,6 +251,8 @@ set(MBGL_CORE_FILES
|
||||
src/mbgl/renderer/layers/render_fill_extrusion_layer.hpp
|
||||
src/mbgl/renderer/layers/render_fill_layer.cpp
|
||||
src/mbgl/renderer/layers/render_fill_layer.hpp
|
||||
src/mbgl/renderer/layers/render_heatmap_layer.cpp
|
||||
src/mbgl/renderer/layers/render_heatmap_layer.hpp
|
||||
src/mbgl/renderer/layers/render_hillshade_layer.cpp
|
||||
src/mbgl/renderer/layers/render_hillshade_layer.hpp
|
||||
src/mbgl/renderer/layers/render_line_layer.cpp
|
||||
@@ -297,6 +305,10 @@ set(MBGL_CORE_FILES
|
||||
src/mbgl/shaders/fill_outline_pattern.hpp
|
||||
src/mbgl/shaders/fill_pattern.cpp
|
||||
src/mbgl/shaders/fill_pattern.hpp
|
||||
src/mbgl/shaders/heatmap.cpp
|
||||
src/mbgl/shaders/heatmap.hpp
|
||||
src/mbgl/shaders/heatmap_texture.cpp
|
||||
src/mbgl/shaders/heatmap_texture.hpp
|
||||
src/mbgl/shaders/hillshade.cpp
|
||||
src/mbgl/shaders/hillshade.hpp
|
||||
src/mbgl/shaders/hillshade_prepare.cpp
|
||||
@@ -349,6 +361,7 @@ set(MBGL_CORE_FILES
|
||||
include/mbgl/style/data_driven_property_value.hpp
|
||||
include/mbgl/style/filter.hpp
|
||||
include/mbgl/style/filter_evaluator.hpp
|
||||
include/mbgl/style/heatmap_color_property_value.hpp
|
||||
include/mbgl/style/image.hpp
|
||||
include/mbgl/style/layer.hpp
|
||||
include/mbgl/style/layer_type.hpp
|
||||
@@ -401,6 +414,7 @@ set(MBGL_CORE_FILES
|
||||
include/mbgl/style/conversion/geojson.hpp
|
||||
include/mbgl/style/conversion/geojson_options.hpp
|
||||
include/mbgl/style/conversion/get_json_type.hpp
|
||||
include/mbgl/style/conversion/heatmap_color_property_value.hpp
|
||||
include/mbgl/style/conversion/layer.hpp
|
||||
include/mbgl/style/conversion/light.hpp
|
||||
include/mbgl/style/conversion/position.hpp
|
||||
@@ -495,6 +509,7 @@ set(MBGL_CORE_FILES
|
||||
include/mbgl/style/layers/custom_layer.hpp
|
||||
include/mbgl/style/layers/fill_extrusion_layer.hpp
|
||||
include/mbgl/style/layers/fill_layer.hpp
|
||||
include/mbgl/style/layers/heatmap_layer.hpp
|
||||
include/mbgl/style/layers/hillshade_layer.hpp
|
||||
include/mbgl/style/layers/line_layer.hpp
|
||||
include/mbgl/style/layers/raster_layer.hpp
|
||||
@@ -522,6 +537,11 @@ set(MBGL_CORE_FILES
|
||||
src/mbgl/style/layers/fill_layer_impl.hpp
|
||||
src/mbgl/style/layers/fill_layer_properties.cpp
|
||||
src/mbgl/style/layers/fill_layer_properties.hpp
|
||||
src/mbgl/style/layers/heatmap_layer.cpp
|
||||
src/mbgl/style/layers/heatmap_layer_impl.cpp
|
||||
src/mbgl/style/layers/heatmap_layer_impl.hpp
|
||||
src/mbgl/style/layers/heatmap_layer_properties.cpp
|
||||
src/mbgl/style/layers/heatmap_layer_properties.hpp
|
||||
src/mbgl/style/layers/hillshade_layer.cpp
|
||||
src/mbgl/style/layers/hillshade_layer_impl.cpp
|
||||
src/mbgl/style/layers/hillshade_layer_impl.hpp
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/style/heatmap_color_property_value.hpp>
|
||||
#include <mbgl/style/conversion.hpp>
|
||||
#include <mbgl/style/conversion/constant.hpp>
|
||||
#include <mbgl/style/conversion/function.hpp>
|
||||
#include <mbgl/style/conversion/expression.hpp>
|
||||
#include <mbgl/style/expression/value.hpp>
|
||||
#include <mbgl/style/expression/is_constant.hpp>
|
||||
#include <mbgl/style/expression/is_expression.hpp>
|
||||
#include <mbgl/style/expression/find_zoom_curve.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace style {
|
||||
namespace conversion {
|
||||
|
||||
template <>
|
||||
struct Converter<HeatmapColorPropertyValue> {
|
||||
optional<HeatmapColorPropertyValue> operator()(const Convertible& value, Error& error) const {
|
||||
if (isUndefined(value)) {
|
||||
return HeatmapColorPropertyValue();
|
||||
} else if (isExpression(value)) {
|
||||
optional<std::unique_ptr<Expression>> expression = convert<std::unique_ptr<Expression>>(value, error, expression::type::Color);
|
||||
if (!expression) {
|
||||
return {};
|
||||
}
|
||||
assert(*expression);
|
||||
if (!isFeatureConstant(**expression)) {
|
||||
error = { "property expressions not supported" };
|
||||
return {};
|
||||
}
|
||||
if (!isZoomConstant(**expression)) {
|
||||
error = { "zoom expressions not supported" };
|
||||
return {};
|
||||
}
|
||||
return {HeatmapColorPropertyValue(std::move(*expression))};
|
||||
} else {
|
||||
error = { "heatmap-color must be an expression" };
|
||||
return {};
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace conversion
|
||||
} // namespace style
|
||||
} // namespace mbgl
|
||||
49
include/mbgl/style/heatmap_color_property_value.hpp
Normal file
49
include/mbgl/style/heatmap_color_property_value.hpp
Normal file
@@ -0,0 +1,49 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/variant.hpp>
|
||||
#include <mbgl/style/undefined.hpp>
|
||||
#include <mbgl/style/function/camera_function.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace style {
|
||||
|
||||
/*
|
||||
* Special-case implementation of (a subset of) the PropertyValue<T> interface
|
||||
* used for building the HeatmapColor paint property traits class.
|
||||
*/
|
||||
class HeatmapColorPropertyValue {
|
||||
private:
|
||||
std::shared_ptr<expression::Expression> value;
|
||||
|
||||
friend bool operator==(const HeatmapColorPropertyValue& lhs, const HeatmapColorPropertyValue& rhs) {
|
||||
return (lhs.isUndefined() && rhs.isUndefined()) || (lhs.value && rhs.value && *(lhs.value) == *(rhs.value));
|
||||
}
|
||||
|
||||
friend bool operator!=(const HeatmapColorPropertyValue& lhs, const HeatmapColorPropertyValue& rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
public:
|
||||
HeatmapColorPropertyValue() : value(nullptr) {}
|
||||
HeatmapColorPropertyValue(std::shared_ptr<expression::Expression> value_) : value(std::move(value_)) {}
|
||||
|
||||
bool isUndefined() const { return value.get() == nullptr; }
|
||||
|
||||
// noop, needed for batch evaluation of paint property values to compile
|
||||
template <typename Evaluator>
|
||||
Color evaluate(const Evaluator&, TimePoint = {}) const { return {}; }
|
||||
|
||||
Color evaluate(double heatmapDensity) const {
|
||||
const auto result = value->evaluate(expression::EvaluationContext({}, nullptr, {heatmapDensity}));
|
||||
return *expression::fromExpressionValue<Color>(*result);
|
||||
}
|
||||
|
||||
bool isDataDriven() const { return false; }
|
||||
bool hasDataDrivenPropertyDifference(const HeatmapColorPropertyValue&) const { return false; }
|
||||
|
||||
const expression::Expression& getExpression() const { return *value; }
|
||||
};
|
||||
|
||||
|
||||
} // namespace style
|
||||
} // namespace mbgl
|
||||
@@ -23,6 +23,7 @@ class HillshadeLayer;
|
||||
class BackgroundLayer;
|
||||
class CustomLayer;
|
||||
class FillExtrusionLayer;
|
||||
class HeatmapLayer;
|
||||
class LayerObserver;
|
||||
|
||||
/**
|
||||
@@ -93,6 +94,8 @@ public:
|
||||
return std::forward<V>(visitor)(*as<CustomLayer>());
|
||||
case LayerType::FillExtrusion:
|
||||
return std::forward<V>(visitor)(*as<FillExtrusionLayer>());
|
||||
case LayerType::Heatmap:
|
||||
return std::forward<V>(visitor)(*as<HeatmapLayer>());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ enum class LayerType {
|
||||
Background,
|
||||
Custom,
|
||||
FillExtrusion,
|
||||
Heatmap,
|
||||
};
|
||||
|
||||
} // namespace style
|
||||
|
||||
86
include/mbgl/style/layers/heatmap_layer.hpp
Normal file
86
include/mbgl/style/layers/heatmap_layer.hpp
Normal file
@@ -0,0 +1,86 @@
|
||||
// This file is generated. Do not edit.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/style/layer.hpp>
|
||||
#include <mbgl/style/filter.hpp>
|
||||
#include <mbgl/style/property_value.hpp>
|
||||
#include <mbgl/style/data_driven_property_value.hpp>
|
||||
#include <mbgl/style/heatmap_color_property_value.hpp>
|
||||
|
||||
#include <mbgl/util/color.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace style {
|
||||
|
||||
class TransitionOptions;
|
||||
|
||||
class HeatmapLayer : public Layer {
|
||||
public:
|
||||
HeatmapLayer(const std::string& layerID, const std::string& sourceID);
|
||||
~HeatmapLayer() final;
|
||||
|
||||
// Source
|
||||
const std::string& getSourceID() const;
|
||||
const std::string& getSourceLayer() const;
|
||||
void setSourceLayer(const std::string& sourceLayer);
|
||||
|
||||
void setFilter(const Filter&);
|
||||
const Filter& getFilter() const;
|
||||
|
||||
// Visibility
|
||||
void setVisibility(VisibilityType) final;
|
||||
|
||||
// Zoom range
|
||||
void setMinZoom(float) final;
|
||||
void setMaxZoom(float) final;
|
||||
|
||||
// Paint properties
|
||||
|
||||
static DataDrivenPropertyValue<float> getDefaultHeatmapRadius();
|
||||
DataDrivenPropertyValue<float> getHeatmapRadius() const;
|
||||
void setHeatmapRadius(DataDrivenPropertyValue<float>);
|
||||
void setHeatmapRadiusTransition(const TransitionOptions&);
|
||||
TransitionOptions getHeatmapRadiusTransition() const;
|
||||
|
||||
static DataDrivenPropertyValue<float> getDefaultHeatmapWeight();
|
||||
DataDrivenPropertyValue<float> getHeatmapWeight() const;
|
||||
void setHeatmapWeight(DataDrivenPropertyValue<float>);
|
||||
void setHeatmapWeightTransition(const TransitionOptions&);
|
||||
TransitionOptions getHeatmapWeightTransition() const;
|
||||
|
||||
static PropertyValue<float> getDefaultHeatmapIntensity();
|
||||
PropertyValue<float> getHeatmapIntensity() const;
|
||||
void setHeatmapIntensity(PropertyValue<float>);
|
||||
void setHeatmapIntensityTransition(const TransitionOptions&);
|
||||
TransitionOptions getHeatmapIntensityTransition() const;
|
||||
|
||||
static HeatmapColorPropertyValue getDefaultHeatmapColor();
|
||||
HeatmapColorPropertyValue getHeatmapColor() const;
|
||||
void setHeatmapColor(HeatmapColorPropertyValue);
|
||||
void setHeatmapColorTransition(const TransitionOptions&);
|
||||
TransitionOptions getHeatmapColorTransition() const;
|
||||
|
||||
static PropertyValue<float> getDefaultHeatmapOpacity();
|
||||
PropertyValue<float> getHeatmapOpacity() const;
|
||||
void setHeatmapOpacity(PropertyValue<float>);
|
||||
void setHeatmapOpacityTransition(const TransitionOptions&);
|
||||
TransitionOptions getHeatmapOpacityTransition() const;
|
||||
|
||||
// Private implementation
|
||||
|
||||
class Impl;
|
||||
const Impl& impl() const;
|
||||
|
||||
Mutable<Impl> mutableImpl() const;
|
||||
HeatmapLayer(Immutable<Impl>);
|
||||
std::unique_ptr<Layer> cloneRef(const std::string& id) const final;
|
||||
};
|
||||
|
||||
template <>
|
||||
inline bool Layer::is<HeatmapLayer>() const {
|
||||
return getType() == LayerType::Heatmap;
|
||||
}
|
||||
|
||||
} // namespace style
|
||||
} // namespace mbgl
|
||||
@@ -11,6 +11,9 @@
|
||||
#include <mbgl/style/filter.hpp>
|
||||
#include <mbgl/style/property_value.hpp>
|
||||
#include <mbgl/style/data_driven_property_value.hpp>
|
||||
<% if (type === 'heatmap') { -%>
|
||||
#include <mbgl/style/heatmap_color_property_value.hpp>
|
||||
<% } -%>
|
||||
|
||||
#include <mbgl/util/color.hpp>
|
||||
|
||||
|
||||
Submodule mapbox-gl-js updated: f13c86ea35...d61850a6bd
@@ -2,6 +2,10 @@
|
||||
|
||||
Mapbox welcomes participation and contributions from everyone. If you'd like to do so please see the [`Contributing Guide`](https://github.com/mapbox/mapbox-gl-native/blob/master/CONTRIBUTING.md) first to get started.
|
||||
|
||||
## master
|
||||
|
||||
- HeatmapLayer [#11046](https://github.com/mapbox/mapbox-gl-native/pull/11046)
|
||||
|
||||
## 6.0.0-beta.2 - February 13, 2018
|
||||
- Deprecate LocationEngine [#11185](https://github.com/mapbox/mapbox-gl-native/pull/11185)
|
||||
- Remove LOST from SDK [11186](https://github.com/mapbox/mapbox-gl-native/pull/11186)
|
||||
|
||||
@@ -0,0 +1,221 @@
|
||||
// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`.
|
||||
|
||||
package com.mapbox.mapboxsdk.style.layers;
|
||||
|
||||
import android.support.annotation.ColorInt;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.UiThread;
|
||||
|
||||
import static com.mapbox.mapboxsdk.utils.ColorUtils.rgbaToColor;
|
||||
|
||||
import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
|
||||
|
||||
/**
|
||||
* A heatmap.
|
||||
*
|
||||
* @see <a href="https://www.mapbox.com/mapbox-gl-style-spec/#layers-heatmap">The online documentation</a>
|
||||
*/
|
||||
@UiThread
|
||||
public class HeatmapLayer extends Layer {
|
||||
|
||||
/**
|
||||
* Creates a HeatmapLayer.
|
||||
*
|
||||
* @param nativePtr pointer used by core
|
||||
*/
|
||||
public HeatmapLayer(long nativePtr) {
|
||||
super(nativePtr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a HeatmapLayer.
|
||||
*
|
||||
* @param layerId the id of the layer
|
||||
* @param sourceId the id of the source
|
||||
*/
|
||||
public HeatmapLayer(String layerId, String sourceId) {
|
||||
initialize(layerId, sourceId);
|
||||
}
|
||||
|
||||
protected native void initialize(String layerId, String sourceId);
|
||||
|
||||
/**
|
||||
* Set the source layer.
|
||||
*
|
||||
* @param sourceLayer the source layer to set
|
||||
*/
|
||||
public void setSourceLayer(String sourceLayer) {
|
||||
nativeSetSourceLayer(sourceLayer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the source Layer.
|
||||
*
|
||||
* @param sourceLayer the source layer to set
|
||||
* @return This
|
||||
*/
|
||||
public HeatmapLayer withSourceLayer(String sourceLayer) {
|
||||
setSourceLayer(sourceLayer);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the source layer.
|
||||
*
|
||||
* @return sourceLayer the source layer to get
|
||||
*/
|
||||
public String getSourceLayer() {
|
||||
return nativeGetSourceLayer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a single filter.
|
||||
*
|
||||
* @param filter the filter to set
|
||||
*/
|
||||
public void setFilter(Filter.Statement filter) {
|
||||
nativeSetFilter(filter.toArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a single filter.
|
||||
*
|
||||
* @param filter the filter to set
|
||||
* @return This
|
||||
*/
|
||||
public HeatmapLayer withFilter(Filter.Statement filter) {
|
||||
setFilter(filter);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a property or properties.
|
||||
*
|
||||
* @param properties the var-args properties
|
||||
* @return This
|
||||
*/
|
||||
public HeatmapLayer withProperties(@NonNull PropertyValue<?>... properties) {
|
||||
setProperties(properties);
|
||||
return this;
|
||||
}
|
||||
|
||||
// Property getters
|
||||
|
||||
/**
|
||||
* Get the HeatmapRadius property
|
||||
*
|
||||
* @return property wrapper value around Float
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public PropertyValue<Float> getHeatmapRadius() {
|
||||
return (PropertyValue<Float>) new PropertyValue("heatmap-radius", nativeGetHeatmapRadius());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the HeatmapRadius property transition options
|
||||
*
|
||||
* @return transition options for Float
|
||||
*/
|
||||
public TransitionOptions getHeatmapRadiusTransition() {
|
||||
return nativeGetHeatmapRadiusTransition();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the HeatmapRadius property transition options
|
||||
*
|
||||
* @param options transition options for Float
|
||||
*/
|
||||
public void setHeatmapRadiusTransition(TransitionOptions options) {
|
||||
nativeSetHeatmapRadiusTransition(options.getDuration(), options.getDelay());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the HeatmapWeight property
|
||||
*
|
||||
* @return property wrapper value around Float
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public PropertyValue<Float> getHeatmapWeight() {
|
||||
return (PropertyValue<Float>) new PropertyValue("heatmap-weight", nativeGetHeatmapWeight());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the HeatmapIntensity property
|
||||
*
|
||||
* @return property wrapper value around Float
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public PropertyValue<Float> getHeatmapIntensity() {
|
||||
return (PropertyValue<Float>) new PropertyValue("heatmap-intensity", nativeGetHeatmapIntensity());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the HeatmapIntensity property transition options
|
||||
*
|
||||
* @return transition options for Float
|
||||
*/
|
||||
public TransitionOptions getHeatmapIntensityTransition() {
|
||||
return nativeGetHeatmapIntensityTransition();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the HeatmapIntensity property transition options
|
||||
*
|
||||
* @param options transition options for Float
|
||||
*/
|
||||
public void setHeatmapIntensityTransition(TransitionOptions options) {
|
||||
nativeSetHeatmapIntensityTransition(options.getDuration(), options.getDelay());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the HeatmapOpacity property
|
||||
*
|
||||
* @return property wrapper value around Float
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public PropertyValue<Float> getHeatmapOpacity() {
|
||||
return (PropertyValue<Float>) new PropertyValue("heatmap-opacity", nativeGetHeatmapOpacity());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the HeatmapOpacity property transition options
|
||||
*
|
||||
* @return transition options for Float
|
||||
*/
|
||||
public TransitionOptions getHeatmapOpacityTransition() {
|
||||
return nativeGetHeatmapOpacityTransition();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the HeatmapOpacity property transition options
|
||||
*
|
||||
* @param options transition options for Float
|
||||
*/
|
||||
public void setHeatmapOpacityTransition(TransitionOptions options) {
|
||||
nativeSetHeatmapOpacityTransition(options.getDuration(), options.getDelay());
|
||||
}
|
||||
|
||||
private native Object nativeGetHeatmapRadius();
|
||||
|
||||
private native TransitionOptions nativeGetHeatmapRadiusTransition();
|
||||
|
||||
private native void nativeSetHeatmapRadiusTransition(long duration, long delay);
|
||||
|
||||
private native Object nativeGetHeatmapWeight();
|
||||
|
||||
private native Object nativeGetHeatmapIntensity();
|
||||
|
||||
private native TransitionOptions nativeGetHeatmapIntensityTransition();
|
||||
|
||||
private native void nativeSetHeatmapIntensityTransition(long duration, long delay);
|
||||
|
||||
private native Object nativeGetHeatmapOpacity();
|
||||
|
||||
private native TransitionOptions nativeGetHeatmapOpacityTransition();
|
||||
|
||||
private native void nativeSetHeatmapOpacityTransition(long duration, long delay);
|
||||
|
||||
@Override
|
||||
protected native void finalize() throws Throwable;
|
||||
|
||||
}
|
||||
@@ -1515,6 +1515,138 @@ public class PropertyFactory {
|
||||
return new PaintPropertyValue<>("circle-stroke-opacity", function);
|
||||
}
|
||||
|
||||
/**
|
||||
* Radius of influence of one heatmap point in density-independent pixels. Increasing the value makes the heatmap smoother, but less detailed.
|
||||
*
|
||||
* @param value a Float value
|
||||
* @return property wrapper around Float
|
||||
*/
|
||||
public static PropertyValue<Float> heatmapRadius(Float value) {
|
||||
return new PaintPropertyValue<>("heatmap-radius", value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Radius of influence of one heatmap point in density-independent pixels. Increasing the value makes the heatmap smoother, but less detailed.
|
||||
*
|
||||
* @param expression an expression statement
|
||||
* @return property wrapper around an expression statement
|
||||
*/
|
||||
public static PropertyValue<Expression> heatmapRadius(Expression expression) {
|
||||
return new PaintPropertyValue<>("heatmap-radius", expression);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Radius of influence of one heatmap point in density-independent pixels. Increasing the value makes the heatmap smoother, but less detailed.
|
||||
*
|
||||
* @param <T> the function input type
|
||||
* @param function a wrapper function for Float
|
||||
* @return property wrapper around a Float function
|
||||
*/
|
||||
@Deprecated
|
||||
public static <T> PropertyValue<Function<T, Float>> heatmapRadius(Function<T, Float> function) {
|
||||
return new PaintPropertyValue<>("heatmap-radius", function);
|
||||
}
|
||||
|
||||
/**
|
||||
* A measure of how much an individual point contributes to the heatmap. A value of 10 would be equivalent to having 10 points of weight 1 in the same spot. Especially useful when combined with clustering.
|
||||
*
|
||||
* @param value a Float value
|
||||
* @return property wrapper around Float
|
||||
*/
|
||||
public static PropertyValue<Float> heatmapWeight(Float value) {
|
||||
return new PaintPropertyValue<>("heatmap-weight", value);
|
||||
}
|
||||
|
||||
/**
|
||||
* A measure of how much an individual point contributes to the heatmap. A value of 10 would be equivalent to having 10 points of weight 1 in the same spot. Especially useful when combined with clustering.
|
||||
*
|
||||
* @param expression an expression statement
|
||||
* @return property wrapper around an expression statement
|
||||
*/
|
||||
public static PropertyValue<Expression> heatmapWeight(Expression expression) {
|
||||
return new PaintPropertyValue<>("heatmap-weight", expression);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A measure of how much an individual point contributes to the heatmap. A value of 10 would be equivalent to having 10 points of weight 1 in the same spot. Especially useful when combined with clustering.
|
||||
*
|
||||
* @param <T> the function input type
|
||||
* @param function a wrapper function for Float
|
||||
* @return property wrapper around a Float function
|
||||
*/
|
||||
@Deprecated
|
||||
public static <T> PropertyValue<Function<T, Float>> heatmapWeight(Function<T, Float> function) {
|
||||
return new PaintPropertyValue<>("heatmap-weight", function);
|
||||
}
|
||||
|
||||
/**
|
||||
* Similar to {@link PropertyFactory#heatmapWeight} but controls the intensity of the heatmap globally. Primarily used for adjusting the heatmap based on zoom level.
|
||||
*
|
||||
* @param value a Float value
|
||||
* @return property wrapper around Float
|
||||
*/
|
||||
public static PropertyValue<Float> heatmapIntensity(Float value) {
|
||||
return new PaintPropertyValue<>("heatmap-intensity", value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Similar to {@link PropertyFactory#heatmapWeight} but controls the intensity of the heatmap globally. Primarily used for adjusting the heatmap based on zoom level.
|
||||
*
|
||||
* @param expression an expression statement
|
||||
* @return property wrapper around an expression statement
|
||||
*/
|
||||
public static PropertyValue<Expression> heatmapIntensity(Expression expression) {
|
||||
return new PaintPropertyValue<>("heatmap-intensity", expression);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Similar to {@link PropertyFactory#heatmapWeight} but controls the intensity of the heatmap globally. Primarily used for adjusting the heatmap based on zoom level.
|
||||
*
|
||||
* @param <Z> the zoom parameter type
|
||||
* @param function a wrapper {@link CameraFunction} for Float
|
||||
* @return property wrapper around a Float function
|
||||
*/
|
||||
@Deprecated
|
||||
public static <Z extends Number> PropertyValue<CameraFunction<Z, Float>> heatmapIntensity(CameraFunction<Z, Float> function) {
|
||||
return new PaintPropertyValue<>("heatmap-intensity", function);
|
||||
}
|
||||
|
||||
/**
|
||||
* The global opacity at which the heatmap layer will be drawn.
|
||||
*
|
||||
* @param value a Float value
|
||||
* @return property wrapper around Float
|
||||
*/
|
||||
public static PropertyValue<Float> heatmapOpacity(Float value) {
|
||||
return new PaintPropertyValue<>("heatmap-opacity", value);
|
||||
}
|
||||
|
||||
/**
|
||||
* The global opacity at which the heatmap layer will be drawn.
|
||||
*
|
||||
* @param expression an expression statement
|
||||
* @return property wrapper around an expression statement
|
||||
*/
|
||||
public static PropertyValue<Expression> heatmapOpacity(Expression expression) {
|
||||
return new PaintPropertyValue<>("heatmap-opacity", expression);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The global opacity at which the heatmap layer will be drawn.
|
||||
*
|
||||
* @param <Z> the zoom parameter type
|
||||
* @param function a wrapper {@link CameraFunction} for Float
|
||||
* @return property wrapper around a Float function
|
||||
*/
|
||||
@Deprecated
|
||||
public static <Z extends Number> PropertyValue<CameraFunction<Z, Float>> heatmapOpacity(CameraFunction<Z, Float> function) {
|
||||
return new PaintPropertyValue<>("heatmap-opacity", function);
|
||||
}
|
||||
|
||||
/**
|
||||
* The opacity of the entire fill extrusion layer. This is rendered on a per-layer, not per-feature, basis, and data-driven styling is not available.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,626 @@
|
||||
// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`.
|
||||
|
||||
package com.mapbox.mapboxsdk.testapp.style;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.support.test.espresso.UiController;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
|
||||
import timber.log.Timber;
|
||||
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap;
|
||||
import com.mapbox.mapboxsdk.style.functions.CompositeFunction;
|
||||
import com.mapbox.mapboxsdk.style.functions.CameraFunction;
|
||||
import com.mapbox.mapboxsdk.style.functions.SourceFunction;
|
||||
import com.mapbox.mapboxsdk.style.functions.stops.CategoricalStops;
|
||||
import com.mapbox.mapboxsdk.style.functions.stops.ExponentialStops;
|
||||
import com.mapbox.mapboxsdk.style.functions.stops.IdentityStops;
|
||||
import com.mapbox.mapboxsdk.style.functions.stops.IntervalStops;
|
||||
import com.mapbox.mapboxsdk.style.functions.stops.Stop;
|
||||
import com.mapbox.mapboxsdk.style.functions.stops.Stops;
|
||||
import com.mapbox.mapboxsdk.style.layers.HeatmapLayer;
|
||||
import com.mapbox.mapboxsdk.testapp.action.MapboxMapAction;
|
||||
import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static com.mapbox.mapboxsdk.style.functions.Function.*;
|
||||
import static com.mapbox.mapboxsdk.style.functions.stops.Stop.stop;
|
||||
import static com.mapbox.mapboxsdk.style.functions.stops.Stops.*;
|
||||
import static com.mapbox.mapboxsdk.testapp.action.MapboxMapAction.invoke;
|
||||
import static org.junit.Assert.*;
|
||||
import static com.mapbox.mapboxsdk.style.layers.Property.*;
|
||||
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.*;
|
||||
|
||||
import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
|
||||
import com.mapbox.mapboxsdk.testapp.activity.espresso.EspressoTestActivity;
|
||||
|
||||
/**
|
||||
* Basic smoke tests for HeatmapLayer
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class HeatmapLayerTest extends BaseActivityTest {
|
||||
|
||||
private HeatmapLayer layer;
|
||||
|
||||
@Override
|
||||
protected Class getActivityClass() {
|
||||
return EspressoTestActivity.class;
|
||||
}
|
||||
|
||||
private void setupLayer() {
|
||||
Timber.i("Retrieving layer");
|
||||
invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
|
||||
@Override
|
||||
public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
|
||||
if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
|
||||
Timber.i("Adding layer");
|
||||
layer = new HeatmapLayer("my-layer", "composite");
|
||||
layer.setSourceLayer("composite");
|
||||
mapboxMap.addLayer(layer);
|
||||
// Layer reference is now stale, get new reference
|
||||
layer = mapboxMap.getLayerAs("my-layer");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetVisibility() {
|
||||
validateTestSetup();
|
||||
setupLayer();
|
||||
Timber.i("Visibility");
|
||||
invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
|
||||
@Override
|
||||
public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
|
||||
assertNotNull(layer);
|
||||
|
||||
// Get initial
|
||||
assertEquals(layer.getVisibility().getValue(), VISIBLE);
|
||||
|
||||
// Set
|
||||
layer.setProperties(visibility(NONE));
|
||||
assertEquals(layer.getVisibility().getValue(), NONE);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSourceLayer() {
|
||||
validateTestSetup();
|
||||
setupLayer();
|
||||
Timber.i("SourceLayer");
|
||||
invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
|
||||
@Override
|
||||
public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
|
||||
assertNotNull(layer);
|
||||
|
||||
// Get initial
|
||||
assertEquals(layer.getSourceLayer(), "composite");
|
||||
|
||||
// Set
|
||||
final String sourceLayer = "test";
|
||||
layer.setSourceLayer(sourceLayer);
|
||||
assertEquals(layer.getSourceLayer(), sourceLayer);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHeatmapRadiusTransition() {
|
||||
validateTestSetup();
|
||||
setupLayer();
|
||||
Timber.i("heatmap-radiusTransitionOptions");
|
||||
invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
|
||||
@Override
|
||||
public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
|
||||
assertNotNull(layer);
|
||||
|
||||
// Set and Get
|
||||
TransitionOptions options = new TransitionOptions(300, 100);
|
||||
layer.setHeatmapRadiusTransition(options);
|
||||
assertEquals(layer.getHeatmapRadiusTransition(), options);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHeatmapRadiusAsConstant() {
|
||||
validateTestSetup();
|
||||
setupLayer();
|
||||
Timber.i("heatmap-radius");
|
||||
invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
|
||||
@Override
|
||||
public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
|
||||
assertNotNull(layer);
|
||||
|
||||
// Set and Get
|
||||
layer.setProperties(heatmapRadius(0.3f));
|
||||
assertEquals((Float) layer.getHeatmapRadius().getValue(), (Float) 0.3f);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHeatmapRadiusAsCameraFunction() {
|
||||
validateTestSetup();
|
||||
setupLayer();
|
||||
Timber.i("heatmap-radius");
|
||||
invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
|
||||
@Override
|
||||
public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
|
||||
assertNotNull(layer);
|
||||
|
||||
// Set
|
||||
layer.setProperties(
|
||||
heatmapRadius(
|
||||
zoom(
|
||||
exponential(
|
||||
stop(2, heatmapRadius(0.3f))
|
||||
).withBase(0.5f)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
// Verify
|
||||
assertNotNull(layer.getHeatmapRadius());
|
||||
assertNotNull(layer.getHeatmapRadius().getFunction());
|
||||
assertEquals(CameraFunction.class, layer.getHeatmapRadius().getFunction().getClass());
|
||||
assertEquals(ExponentialStops.class, layer.getHeatmapRadius().getFunction().getStops().getClass());
|
||||
assertEquals(0.5f, ((ExponentialStops) layer.getHeatmapRadius().getFunction().getStops()).getBase(), 0.001);
|
||||
assertEquals(1, ((ExponentialStops) layer.getHeatmapRadius().getFunction().getStops()).size());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHeatmapRadiusAsIdentitySourceFunction() {
|
||||
validateTestSetup();
|
||||
setupLayer();
|
||||
Timber.i("heatmap-radius");
|
||||
invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
|
||||
@Override
|
||||
public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
|
||||
assertNotNull(layer);
|
||||
|
||||
// Set
|
||||
layer.setProperties(
|
||||
heatmapRadius(property("FeaturePropertyA", Stops.<Float>identity()))
|
||||
);
|
||||
|
||||
// Verify
|
||||
assertNotNull(layer.getHeatmapRadius());
|
||||
assertNotNull(layer.getHeatmapRadius().getFunction());
|
||||
assertEquals(SourceFunction.class, layer.getHeatmapRadius().getFunction().getClass());
|
||||
assertEquals("FeaturePropertyA", ((SourceFunction) layer.getHeatmapRadius().getFunction()).getProperty());
|
||||
assertEquals(IdentityStops.class, layer.getHeatmapRadius().getFunction().getStops().getClass());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHeatmapRadiusAsExponentialSourceFunction() {
|
||||
validateTestSetup();
|
||||
setupLayer();
|
||||
Timber.i("heatmap-radius");
|
||||
invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
|
||||
@Override
|
||||
public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
|
||||
assertNotNull(layer);
|
||||
|
||||
// Set
|
||||
layer.setProperties(
|
||||
heatmapRadius(
|
||||
property(
|
||||
"FeaturePropertyA",
|
||||
exponential(
|
||||
stop(0.3f, heatmapRadius(0.3f))
|
||||
).withBase(0.5f)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
// Verify
|
||||
assertNotNull(layer.getHeatmapRadius());
|
||||
assertNotNull(layer.getHeatmapRadius().getFunction());
|
||||
assertEquals(SourceFunction.class, layer.getHeatmapRadius().getFunction().getClass());
|
||||
assertEquals("FeaturePropertyA", ((SourceFunction) layer.getHeatmapRadius().getFunction()).getProperty());
|
||||
assertEquals(ExponentialStops.class, layer.getHeatmapRadius().getFunction().getStops().getClass());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHeatmapRadiusAsCategoricalSourceFunction() {
|
||||
validateTestSetup();
|
||||
setupLayer();
|
||||
Timber.i("heatmap-radius");
|
||||
invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
|
||||
@Override
|
||||
public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
|
||||
assertNotNull(layer);
|
||||
|
||||
// Set
|
||||
layer.setProperties(
|
||||
heatmapRadius(
|
||||
property(
|
||||
"FeaturePropertyA",
|
||||
categorical(
|
||||
stop(1.0f, heatmapRadius(0.3f))
|
||||
)
|
||||
).withDefaultValue(heatmapRadius(0.3f))
|
||||
)
|
||||
);
|
||||
|
||||
// Verify
|
||||
assertNotNull(layer.getHeatmapRadius());
|
||||
assertNotNull(layer.getHeatmapRadius().getFunction());
|
||||
assertEquals(SourceFunction.class, layer.getHeatmapRadius().getFunction().getClass());
|
||||
assertEquals("FeaturePropertyA", ((SourceFunction) layer.getHeatmapRadius().getFunction()).getProperty());
|
||||
assertEquals(CategoricalStops.class, layer.getHeatmapRadius().getFunction().getStops().getClass());
|
||||
assertNotNull(((SourceFunction) layer.getHeatmapRadius().getFunction()).getDefaultValue());
|
||||
assertNotNull(((SourceFunction) layer.getHeatmapRadius().getFunction()).getDefaultValue().getValue());
|
||||
assertEquals(0.3f, ((SourceFunction) layer.getHeatmapRadius().getFunction()).getDefaultValue().getValue());
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHeatmapRadiusAsCompositeFunction() {
|
||||
validateTestSetup();
|
||||
setupLayer();
|
||||
Timber.i("heatmap-radius");
|
||||
invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
|
||||
@Override
|
||||
public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
|
||||
assertNotNull(layer);
|
||||
|
||||
// Set
|
||||
layer.setProperties(
|
||||
heatmapRadius(
|
||||
composite(
|
||||
"FeaturePropertyA",
|
||||
exponential(
|
||||
stop(0, 0.3f, heatmapRadius(0.9f))
|
||||
).withBase(0.5f)
|
||||
).withDefaultValue(heatmapRadius(0.3f))
|
||||
)
|
||||
);
|
||||
|
||||
// Verify
|
||||
assertNotNull(layer.getHeatmapRadius());
|
||||
assertNotNull(layer.getHeatmapRadius().getFunction());
|
||||
assertEquals(CompositeFunction.class, layer.getHeatmapRadius().getFunction().getClass());
|
||||
assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getHeatmapRadius().getFunction()).getProperty());
|
||||
assertEquals(ExponentialStops.class, layer.getHeatmapRadius().getFunction().getStops().getClass());
|
||||
assertEquals(1, ((ExponentialStops) layer.getHeatmapRadius().getFunction().getStops()).size());
|
||||
|
||||
ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
|
||||
(ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getHeatmapRadius().getFunction().getStops();
|
||||
Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
|
||||
assertEquals(0f, stop.in.zoom, 0.001);
|
||||
assertEquals(0.3f, stop.in.value, 0.001f);
|
||||
assertEquals(0.9f, stop.out, 0.001f);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHeatmapWeightAsConstant() {
|
||||
validateTestSetup();
|
||||
setupLayer();
|
||||
Timber.i("heatmap-weight");
|
||||
invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
|
||||
@Override
|
||||
public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
|
||||
assertNotNull(layer);
|
||||
|
||||
// Set and Get
|
||||
layer.setProperties(heatmapWeight(0.3f));
|
||||
assertEquals((Float) layer.getHeatmapWeight().getValue(), (Float) 0.3f);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHeatmapWeightAsCameraFunction() {
|
||||
validateTestSetup();
|
||||
setupLayer();
|
||||
Timber.i("heatmap-weight");
|
||||
invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
|
||||
@Override
|
||||
public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
|
||||
assertNotNull(layer);
|
||||
|
||||
// Set
|
||||
layer.setProperties(
|
||||
heatmapWeight(
|
||||
zoom(
|
||||
exponential(
|
||||
stop(2, heatmapWeight(0.3f))
|
||||
).withBase(0.5f)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
// Verify
|
||||
assertNotNull(layer.getHeatmapWeight());
|
||||
assertNotNull(layer.getHeatmapWeight().getFunction());
|
||||
assertEquals(CameraFunction.class, layer.getHeatmapWeight().getFunction().getClass());
|
||||
assertEquals(ExponentialStops.class, layer.getHeatmapWeight().getFunction().getStops().getClass());
|
||||
assertEquals(0.5f, ((ExponentialStops) layer.getHeatmapWeight().getFunction().getStops()).getBase(), 0.001);
|
||||
assertEquals(1, ((ExponentialStops) layer.getHeatmapWeight().getFunction().getStops()).size());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHeatmapWeightAsIdentitySourceFunction() {
|
||||
validateTestSetup();
|
||||
setupLayer();
|
||||
Timber.i("heatmap-weight");
|
||||
invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
|
||||
@Override
|
||||
public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
|
||||
assertNotNull(layer);
|
||||
|
||||
// Set
|
||||
layer.setProperties(
|
||||
heatmapWeight(property("FeaturePropertyA", Stops.<Float>identity()))
|
||||
);
|
||||
|
||||
// Verify
|
||||
assertNotNull(layer.getHeatmapWeight());
|
||||
assertNotNull(layer.getHeatmapWeight().getFunction());
|
||||
assertEquals(SourceFunction.class, layer.getHeatmapWeight().getFunction().getClass());
|
||||
assertEquals("FeaturePropertyA", ((SourceFunction) layer.getHeatmapWeight().getFunction()).getProperty());
|
||||
assertEquals(IdentityStops.class, layer.getHeatmapWeight().getFunction().getStops().getClass());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHeatmapWeightAsExponentialSourceFunction() {
|
||||
validateTestSetup();
|
||||
setupLayer();
|
||||
Timber.i("heatmap-weight");
|
||||
invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
|
||||
@Override
|
||||
public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
|
||||
assertNotNull(layer);
|
||||
|
||||
// Set
|
||||
layer.setProperties(
|
||||
heatmapWeight(
|
||||
property(
|
||||
"FeaturePropertyA",
|
||||
exponential(
|
||||
stop(0.3f, heatmapWeight(0.3f))
|
||||
).withBase(0.5f)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
// Verify
|
||||
assertNotNull(layer.getHeatmapWeight());
|
||||
assertNotNull(layer.getHeatmapWeight().getFunction());
|
||||
assertEquals(SourceFunction.class, layer.getHeatmapWeight().getFunction().getClass());
|
||||
assertEquals("FeaturePropertyA", ((SourceFunction) layer.getHeatmapWeight().getFunction()).getProperty());
|
||||
assertEquals(ExponentialStops.class, layer.getHeatmapWeight().getFunction().getStops().getClass());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHeatmapWeightAsCategoricalSourceFunction() {
|
||||
validateTestSetup();
|
||||
setupLayer();
|
||||
Timber.i("heatmap-weight");
|
||||
invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
|
||||
@Override
|
||||
public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
|
||||
assertNotNull(layer);
|
||||
|
||||
// Set
|
||||
layer.setProperties(
|
||||
heatmapWeight(
|
||||
property(
|
||||
"FeaturePropertyA",
|
||||
categorical(
|
||||
stop(1.0f, heatmapWeight(0.3f))
|
||||
)
|
||||
).withDefaultValue(heatmapWeight(0.3f))
|
||||
)
|
||||
);
|
||||
|
||||
// Verify
|
||||
assertNotNull(layer.getHeatmapWeight());
|
||||
assertNotNull(layer.getHeatmapWeight().getFunction());
|
||||
assertEquals(SourceFunction.class, layer.getHeatmapWeight().getFunction().getClass());
|
||||
assertEquals("FeaturePropertyA", ((SourceFunction) layer.getHeatmapWeight().getFunction()).getProperty());
|
||||
assertEquals(CategoricalStops.class, layer.getHeatmapWeight().getFunction().getStops().getClass());
|
||||
assertNotNull(((SourceFunction) layer.getHeatmapWeight().getFunction()).getDefaultValue());
|
||||
assertNotNull(((SourceFunction) layer.getHeatmapWeight().getFunction()).getDefaultValue().getValue());
|
||||
assertEquals(0.3f, ((SourceFunction) layer.getHeatmapWeight().getFunction()).getDefaultValue().getValue());
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHeatmapWeightAsCompositeFunction() {
|
||||
validateTestSetup();
|
||||
setupLayer();
|
||||
Timber.i("heatmap-weight");
|
||||
invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
|
||||
@Override
|
||||
public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
|
||||
assertNotNull(layer);
|
||||
|
||||
// Set
|
||||
layer.setProperties(
|
||||
heatmapWeight(
|
||||
composite(
|
||||
"FeaturePropertyA",
|
||||
exponential(
|
||||
stop(0, 0.3f, heatmapWeight(0.9f))
|
||||
).withBase(0.5f)
|
||||
).withDefaultValue(heatmapWeight(0.3f))
|
||||
)
|
||||
);
|
||||
|
||||
// Verify
|
||||
assertNotNull(layer.getHeatmapWeight());
|
||||
assertNotNull(layer.getHeatmapWeight().getFunction());
|
||||
assertEquals(CompositeFunction.class, layer.getHeatmapWeight().getFunction().getClass());
|
||||
assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getHeatmapWeight().getFunction()).getProperty());
|
||||
assertEquals(ExponentialStops.class, layer.getHeatmapWeight().getFunction().getStops().getClass());
|
||||
assertEquals(1, ((ExponentialStops) layer.getHeatmapWeight().getFunction().getStops()).size());
|
||||
|
||||
ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
|
||||
(ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getHeatmapWeight().getFunction().getStops();
|
||||
Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
|
||||
assertEquals(0f, stop.in.zoom, 0.001);
|
||||
assertEquals(0.3f, stop.in.value, 0.001f);
|
||||
assertEquals(0.9f, stop.out, 0.001f);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHeatmapIntensityTransition() {
|
||||
validateTestSetup();
|
||||
setupLayer();
|
||||
Timber.i("heatmap-intensityTransitionOptions");
|
||||
invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
|
||||
@Override
|
||||
public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
|
||||
assertNotNull(layer);
|
||||
|
||||
// Set and Get
|
||||
TransitionOptions options = new TransitionOptions(300, 100);
|
||||
layer.setHeatmapIntensityTransition(options);
|
||||
assertEquals(layer.getHeatmapIntensityTransition(), options);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHeatmapIntensityAsConstant() {
|
||||
validateTestSetup();
|
||||
setupLayer();
|
||||
Timber.i("heatmap-intensity");
|
||||
invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
|
||||
@Override
|
||||
public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
|
||||
assertNotNull(layer);
|
||||
|
||||
// Set and Get
|
||||
layer.setProperties(heatmapIntensity(0.3f));
|
||||
assertEquals((Float) layer.getHeatmapIntensity().getValue(), (Float) 0.3f);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHeatmapIntensityAsCameraFunction() {
|
||||
validateTestSetup();
|
||||
setupLayer();
|
||||
Timber.i("heatmap-intensity");
|
||||
invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
|
||||
@Override
|
||||
public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
|
||||
assertNotNull(layer);
|
||||
|
||||
// Set
|
||||
layer.setProperties(
|
||||
heatmapIntensity(
|
||||
zoom(
|
||||
exponential(
|
||||
stop(2, heatmapIntensity(0.3f))
|
||||
).withBase(0.5f)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
// Verify
|
||||
assertNotNull(layer.getHeatmapIntensity());
|
||||
assertNotNull(layer.getHeatmapIntensity().getFunction());
|
||||
assertEquals(CameraFunction.class, layer.getHeatmapIntensity().getFunction().getClass());
|
||||
assertEquals(ExponentialStops.class, layer.getHeatmapIntensity().getFunction().getStops().getClass());
|
||||
assertEquals(0.5f, ((ExponentialStops) layer.getHeatmapIntensity().getFunction().getStops()).getBase(), 0.001);
|
||||
assertEquals(1, ((ExponentialStops) layer.getHeatmapIntensity().getFunction().getStops()).size());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHeatmapOpacityTransition() {
|
||||
validateTestSetup();
|
||||
setupLayer();
|
||||
Timber.i("heatmap-opacityTransitionOptions");
|
||||
invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
|
||||
@Override
|
||||
public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
|
||||
assertNotNull(layer);
|
||||
|
||||
// Set and Get
|
||||
TransitionOptions options = new TransitionOptions(300, 100);
|
||||
layer.setHeatmapOpacityTransition(options);
|
||||
assertEquals(layer.getHeatmapOpacityTransition(), options);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHeatmapOpacityAsConstant() {
|
||||
validateTestSetup();
|
||||
setupLayer();
|
||||
Timber.i("heatmap-opacity");
|
||||
invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
|
||||
@Override
|
||||
public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
|
||||
assertNotNull(layer);
|
||||
|
||||
// Set and Get
|
||||
layer.setProperties(heatmapOpacity(0.3f));
|
||||
assertEquals((Float) layer.getHeatmapOpacity().getValue(), (Float) 0.3f);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHeatmapOpacityAsCameraFunction() {
|
||||
validateTestSetup();
|
||||
setupLayer();
|
||||
Timber.i("heatmap-opacity");
|
||||
invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
|
||||
@Override
|
||||
public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
|
||||
assertNotNull(layer);
|
||||
|
||||
// Set
|
||||
layer.setProperties(
|
||||
heatmapOpacity(
|
||||
zoom(
|
||||
exponential(
|
||||
stop(2, heatmapOpacity(0.3f))
|
||||
).withBase(0.5f)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
// Verify
|
||||
assertNotNull(layer.getHeatmapOpacity());
|
||||
assertNotNull(layer.getHeatmapOpacity().getFunction());
|
||||
assertEquals(CameraFunction.class, layer.getHeatmapOpacity().getFunction().getClass());
|
||||
assertEquals(ExponentialStops.class, layer.getHeatmapOpacity().getFunction().getStops().getClass());
|
||||
assertEquals(0.5f, ((ExponentialStops) layer.getHeatmapOpacity().getFunction().getStops()).getBase(), 0.001);
|
||||
assertEquals(1, ((ExponentialStops) layer.getHeatmapOpacity().getFunction().getStops()).size());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -789,6 +789,17 @@
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value=".activity.FeatureOverviewActivity"/>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activity.style.HeatmapLayerActivity"
|
||||
android:description="@string/description_heatmaplayer"
|
||||
android:label="@string/activity_heatmaplayer">
|
||||
<meta-data
|
||||
android:name="@string/category"
|
||||
android:value="@string/category_style"/>
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value=".activity.FeatureOverviewActivity"/>
|
||||
</activity>
|
||||
|
||||
<!-- For Instrumentation tests -->
|
||||
<activity
|
||||
|
||||
@@ -0,0 +1,216 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.style;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
|
||||
import com.mapbox.mapboxsdk.maps.MapView;
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap;
|
||||
import com.mapbox.mapboxsdk.style.layers.CircleLayer;
|
||||
import com.mapbox.mapboxsdk.style.layers.HeatmapLayer;
|
||||
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
import timber.log.Timber;
|
||||
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.get;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.interpolate;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.linear;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.literal;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.rgb;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.rgba;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.stop;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.zoom;
|
||||
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.circleColor;
|
||||
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.circleOpacity;
|
||||
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.circleRadius;
|
||||
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.circleStrokeColor;
|
||||
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.circleStrokeWidth;
|
||||
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.heatmapIntensity;
|
||||
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.heatmapOpacity;
|
||||
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.heatmapRadius;
|
||||
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.heatmapWeight;
|
||||
|
||||
/**
|
||||
* Test activity showcasing the heatmap layer api.
|
||||
*/
|
||||
public class HeatmapLayerActivity extends AppCompatActivity {
|
||||
|
||||
private static final String EARTHQUAKE_SOURCE_URL = "https://www.mapbox.com/mapbox-gl-js/assets/earthquakes.geojson";
|
||||
private static final String EARTHQUAKE_SOURCE_ID = "earthquakes";
|
||||
private static final String HEATMAP_LAYER_ID = "earthquakes-heat";
|
||||
private static final String HEATMAP_LAYER_SOURCE = "earthquakes";
|
||||
private static final String CIRCLE_LAYER_ID = "earthquakes-circle";
|
||||
|
||||
private MapView mapView;
|
||||
private MapboxMap mapboxMap;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_heatmaplayer);
|
||||
|
||||
mapView = (MapView) findViewById(R.id.mapView);
|
||||
mapView.onCreate(savedInstanceState);
|
||||
mapView.getMapAsync(map -> {
|
||||
mapboxMap = map;
|
||||
addEarthquakeSource();
|
||||
addHeatmapLayer();
|
||||
addCircleLayer();
|
||||
});
|
||||
}
|
||||
|
||||
private void addEarthquakeSource() {
|
||||
try {
|
||||
mapboxMap.addSource(new GeoJsonSource(EARTHQUAKE_SOURCE_ID, new URL(EARTHQUAKE_SOURCE_URL)));
|
||||
} catch (MalformedURLException malformedUrlException) {
|
||||
Timber.e(malformedUrlException, "That's not an url... ");
|
||||
}
|
||||
}
|
||||
|
||||
private void addHeatmapLayer() {
|
||||
HeatmapLayer layer = new HeatmapLayer(HEATMAP_LAYER_ID, EARTHQUAKE_SOURCE_ID);
|
||||
layer.setMaxZoom(9);
|
||||
layer.setSourceLayer(HEATMAP_LAYER_SOURCE);
|
||||
layer.setProperties(
|
||||
|
||||
// TODO add heatmap color https://github.com/mapbox/mapbox-gl-native/issues/11172
|
||||
// Color ramp for heatmap. Domain is 0 (low) to 1 (high).
|
||||
// Begin color ramp at 0-stop with a 0-transparancy color
|
||||
// to create a blur-like effect.
|
||||
//heatmapColor(),
|
||||
|
||||
// Increase the heatmap weight based on frequency and property magnitude
|
||||
heatmapWeight(
|
||||
interpolate(
|
||||
linear(), get("mag"),
|
||||
stop(0, 0),
|
||||
stop(6, 1)
|
||||
)
|
||||
),
|
||||
|
||||
// Increase the heatmap color weight weight by zoom level
|
||||
// heatmap-intensity is a multiplier on top of heatmap-weight
|
||||
heatmapIntensity(
|
||||
interpolate(
|
||||
linear(), zoom(),
|
||||
stop(0, 1),
|
||||
stop(9, 3)
|
||||
)
|
||||
),
|
||||
|
||||
// Adjust the heatmap radius by zoom level
|
||||
heatmapRadius(
|
||||
interpolate(
|
||||
linear(), zoom(),
|
||||
stop(0, 2),
|
||||
stop(9, 20)
|
||||
)
|
||||
),
|
||||
|
||||
// Transition from heatmap to circle layer by zoom level
|
||||
heatmapOpacity(
|
||||
interpolate(
|
||||
linear(), zoom(),
|
||||
stop(7, 1),
|
||||
stop(9, 0)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
mapboxMap.addLayerAbove(layer, "waterway-label");
|
||||
}
|
||||
|
||||
private void addCircleLayer() {
|
||||
CircleLayer circleLayer = new CircleLayer(CIRCLE_LAYER_ID, EARTHQUAKE_SOURCE_ID);
|
||||
circleLayer.setProperties(
|
||||
|
||||
// Size circle radius by earthquake magnitude and zoom level
|
||||
circleRadius(
|
||||
interpolate(
|
||||
linear(), zoom(),
|
||||
literal(7), interpolate(
|
||||
linear(), get("mag"),
|
||||
stop(1, 1),
|
||||
stop(6, 4)
|
||||
),
|
||||
literal(16), interpolate(
|
||||
linear(), get("mag"),
|
||||
stop(1, 5),
|
||||
stop(6, 50)
|
||||
)
|
||||
)
|
||||
),
|
||||
|
||||
// Color circle by earthquake magnitude
|
||||
circleColor(
|
||||
interpolate(
|
||||
linear(), get("mag"),
|
||||
literal(1), rgba(33, 102, 172, 0),
|
||||
literal(2), rgb(103, 169, 207),
|
||||
literal(3), rgb(209, 229, 240),
|
||||
literal(4), rgb(253, 219, 199),
|
||||
literal(5), rgb(239, 138, 98),
|
||||
literal(6), rgb(178, 24, 43)
|
||||
)
|
||||
),
|
||||
|
||||
// Transition from heatmap to circle layer by zoom level
|
||||
circleOpacity(
|
||||
interpolate(
|
||||
linear(), zoom(),
|
||||
stop(7, 0),
|
||||
stop(8, 1)
|
||||
)
|
||||
),
|
||||
circleStrokeColor("white"),
|
||||
circleStrokeWidth(1.0f)
|
||||
);
|
||||
|
||||
mapboxMap.addLayerBelow(circleLayer, HEATMAP_LAYER_ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
mapView.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mapView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
mapView.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
mapView.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
mapView.onLowMemory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
mapView.onDestroy();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.mapbox.mapboxsdk.maps.MapView
|
||||
android:id="@id/mapView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:mapbox_styleUrl="@string/mapbox_style_dark"/>
|
||||
|
||||
</RelativeLayout>
|
||||
@@ -70,4 +70,5 @@
|
||||
<string name="description_grid_source">Example Custom Geometry Source</string>
|
||||
<string name="description_local_glyph">Suzhou using Droid Sans for Chinese glyphs</string>
|
||||
<string name="description_hillshade">Example raster-dem source and hillshade layer</string>
|
||||
<string name="description_heatmaplayer">Use HeatmapLayer to visualise earthquakes</string>
|
||||
</resources>
|
||||
|
||||
@@ -70,4 +70,5 @@
|
||||
<string name="activity_grid_source">Grid Source</string>
|
||||
<string name="activity_local_glyph">Local CJK glyph generation</string>
|
||||
<string name="activity_hillshade">Hillshade</string>
|
||||
<string name="activity_heatmaplayer">Heatmap layer</string>
|
||||
</resources>
|
||||
@@ -158,6 +158,8 @@ add_library(mbgl-android STATIC
|
||||
platform/android/src/style/layers/fill_extrusion_layer.hpp
|
||||
platform/android/src/style/layers/fill_layer.cpp
|
||||
platform/android/src/style/layers/fill_layer.hpp
|
||||
platform/android/src/style/layers/heatmap_layer.cpp
|
||||
platform/android/src/style/layers/heatmap_layer.hpp
|
||||
platform/android/src/style/layers/hillshade_layer.cpp
|
||||
platform/android/src/style/layers/hillshade_layer.hpp
|
||||
platform/android/src/style/layers/layer.cpp
|
||||
|
||||
@@ -28,6 +28,9 @@ var layers = Object.keys(spec.layer.type.values).map((type) => {
|
||||
}, []);
|
||||
|
||||
const paintProperties = Object.keys(spec[`paint_${type}`]).reduce((memo, name) => {
|
||||
// disabled for now, see https://github.com/mapbox/mapbox-gl-native/issues/11172
|
||||
if (name === 'heatmap-color') return memo;
|
||||
|
||||
spec[`paint_${type}`][name].name = name;
|
||||
memo.push(spec[`paint_${type}`][name]);
|
||||
return memo;
|
||||
|
||||
134
platform/android/src/style/layers/heatmap_layer.cpp
Normal file
134
platform/android/src/style/layers/heatmap_layer.cpp
Normal file
@@ -0,0 +1,134 @@
|
||||
// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`.
|
||||
|
||||
#include "heatmap_layer.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "../conversion/property_value.hpp"
|
||||
#include "../conversion/transition_options.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
/**
|
||||
* Creates an owning peer object (for layers not attached to the map) from the JVM side
|
||||
*/
|
||||
HeatmapLayer::HeatmapLayer(jni::JNIEnv& env, jni::String layerId, jni::String sourceId)
|
||||
: Layer(env, std::make_unique<mbgl::style::HeatmapLayer>(jni::Make<std::string>(env, layerId), jni::Make<std::string>(env, sourceId))) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a non-owning peer object (for layers currently attached to the map)
|
||||
*/
|
||||
HeatmapLayer::HeatmapLayer(mbgl::Map& map, mbgl::style::HeatmapLayer& coreLayer)
|
||||
: Layer(map, coreLayer) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an owning peer object (for layers not attached to the map)
|
||||
*/
|
||||
HeatmapLayer::HeatmapLayer(mbgl::Map& map, std::unique_ptr<mbgl::style::HeatmapLayer> coreLayer)
|
||||
: Layer(map, std::move(coreLayer)) {
|
||||
}
|
||||
|
||||
HeatmapLayer::~HeatmapLayer() = default;
|
||||
|
||||
// Property getters
|
||||
|
||||
jni::Object<jni::ObjectTag> HeatmapLayer::getHeatmapRadius(jni::JNIEnv& env) {
|
||||
using namespace mbgl::android::conversion;
|
||||
Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::HeatmapLayer>()->HeatmapLayer::getHeatmapRadius());
|
||||
return jni::Object<jni::ObjectTag>(*converted);
|
||||
}
|
||||
|
||||
jni::Object<TransitionOptions> HeatmapLayer::getHeatmapRadiusTransition(jni::JNIEnv& env) {
|
||||
using namespace mbgl::android::conversion;
|
||||
mbgl::style::TransitionOptions options = layer.as<mbgl::style::HeatmapLayer>()->HeatmapLayer::getHeatmapRadiusTransition();
|
||||
return *convert<jni::Object<TransitionOptions>>(env, options);
|
||||
}
|
||||
|
||||
void HeatmapLayer::setHeatmapRadiusTransition(jni::JNIEnv&, jlong duration, jlong delay) {
|
||||
mbgl::style::TransitionOptions options;
|
||||
options.duration.emplace(mbgl::Milliseconds(duration));
|
||||
options.delay.emplace(mbgl::Milliseconds(delay));
|
||||
layer.as<mbgl::style::HeatmapLayer>()->HeatmapLayer::setHeatmapRadiusTransition(options);
|
||||
}
|
||||
|
||||
jni::Object<jni::ObjectTag> HeatmapLayer::getHeatmapWeight(jni::JNIEnv& env) {
|
||||
using namespace mbgl::android::conversion;
|
||||
Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::HeatmapLayer>()->HeatmapLayer::getHeatmapWeight());
|
||||
return jni::Object<jni::ObjectTag>(*converted);
|
||||
}
|
||||
|
||||
jni::Object<jni::ObjectTag> HeatmapLayer::getHeatmapIntensity(jni::JNIEnv& env) {
|
||||
using namespace mbgl::android::conversion;
|
||||
Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::HeatmapLayer>()->HeatmapLayer::getHeatmapIntensity());
|
||||
return jni::Object<jni::ObjectTag>(*converted);
|
||||
}
|
||||
|
||||
jni::Object<TransitionOptions> HeatmapLayer::getHeatmapIntensityTransition(jni::JNIEnv& env) {
|
||||
using namespace mbgl::android::conversion;
|
||||
mbgl::style::TransitionOptions options = layer.as<mbgl::style::HeatmapLayer>()->HeatmapLayer::getHeatmapIntensityTransition();
|
||||
return *convert<jni::Object<TransitionOptions>>(env, options);
|
||||
}
|
||||
|
||||
void HeatmapLayer::setHeatmapIntensityTransition(jni::JNIEnv&, jlong duration, jlong delay) {
|
||||
mbgl::style::TransitionOptions options;
|
||||
options.duration.emplace(mbgl::Milliseconds(duration));
|
||||
options.delay.emplace(mbgl::Milliseconds(delay));
|
||||
layer.as<mbgl::style::HeatmapLayer>()->HeatmapLayer::setHeatmapIntensityTransition(options);
|
||||
}
|
||||
|
||||
jni::Object<jni::ObjectTag> HeatmapLayer::getHeatmapOpacity(jni::JNIEnv& env) {
|
||||
using namespace mbgl::android::conversion;
|
||||
Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::HeatmapLayer>()->HeatmapLayer::getHeatmapOpacity());
|
||||
return jni::Object<jni::ObjectTag>(*converted);
|
||||
}
|
||||
|
||||
jni::Object<TransitionOptions> HeatmapLayer::getHeatmapOpacityTransition(jni::JNIEnv& env) {
|
||||
using namespace mbgl::android::conversion;
|
||||
mbgl::style::TransitionOptions options = layer.as<mbgl::style::HeatmapLayer>()->HeatmapLayer::getHeatmapOpacityTransition();
|
||||
return *convert<jni::Object<TransitionOptions>>(env, options);
|
||||
}
|
||||
|
||||
void HeatmapLayer::setHeatmapOpacityTransition(jni::JNIEnv&, jlong duration, jlong delay) {
|
||||
mbgl::style::TransitionOptions options;
|
||||
options.duration.emplace(mbgl::Milliseconds(duration));
|
||||
options.delay.emplace(mbgl::Milliseconds(delay));
|
||||
layer.as<mbgl::style::HeatmapLayer>()->HeatmapLayer::setHeatmapOpacityTransition(options);
|
||||
}
|
||||
|
||||
|
||||
jni::Class<HeatmapLayer> HeatmapLayer::javaClass;
|
||||
|
||||
jni::jobject* HeatmapLayer::createJavaPeer(jni::JNIEnv& env) {
|
||||
static auto constructor = HeatmapLayer::javaClass.template GetConstructor<jni::jlong>(env);
|
||||
return HeatmapLayer::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this));
|
||||
}
|
||||
|
||||
void HeatmapLayer::registerNative(jni::JNIEnv& env) {
|
||||
// Lookup the class
|
||||
HeatmapLayer::javaClass = *jni::Class<HeatmapLayer>::Find(env).NewGlobalRef(env).release();
|
||||
|
||||
#define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name)
|
||||
|
||||
// Register the peer
|
||||
jni::RegisterNativePeer<HeatmapLayer>(
|
||||
env, HeatmapLayer::javaClass, "nativePtr",
|
||||
std::make_unique<HeatmapLayer, JNIEnv&, jni::String, jni::String>,
|
||||
"initialize",
|
||||
"finalize",
|
||||
METHOD(&HeatmapLayer::getHeatmapRadiusTransition, "nativeGetHeatmapRadiusTransition"),
|
||||
METHOD(&HeatmapLayer::setHeatmapRadiusTransition, "nativeSetHeatmapRadiusTransition"),
|
||||
METHOD(&HeatmapLayer::getHeatmapRadius, "nativeGetHeatmapRadius"),
|
||||
METHOD(&HeatmapLayer::getHeatmapWeight, "nativeGetHeatmapWeight"),
|
||||
METHOD(&HeatmapLayer::getHeatmapIntensityTransition, "nativeGetHeatmapIntensityTransition"),
|
||||
METHOD(&HeatmapLayer::setHeatmapIntensityTransition, "nativeSetHeatmapIntensityTransition"),
|
||||
METHOD(&HeatmapLayer::getHeatmapIntensity, "nativeGetHeatmapIntensity"),
|
||||
METHOD(&HeatmapLayer::getHeatmapOpacityTransition, "nativeGetHeatmapOpacityTransition"),
|
||||
METHOD(&HeatmapLayer::setHeatmapOpacityTransition, "nativeSetHeatmapOpacityTransition"),
|
||||
METHOD(&HeatmapLayer::getHeatmapOpacity, "nativeGetHeatmapOpacity"));
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
50
platform/android/src/style/layers/heatmap_layer.hpp
Normal file
50
platform/android/src/style/layers/heatmap_layer.hpp
Normal file
@@ -0,0 +1,50 @@
|
||||
// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "layer.hpp"
|
||||
#include "../transition_options.hpp"
|
||||
#include <mbgl/style/layers/heatmap_layer.hpp>
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class HeatmapLayer : public Layer {
|
||||
public:
|
||||
|
||||
static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/HeatmapLayer"; };
|
||||
|
||||
static jni::Class<HeatmapLayer> javaClass;
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
|
||||
HeatmapLayer(jni::JNIEnv&, jni::String, jni::String);
|
||||
|
||||
HeatmapLayer(mbgl::Map&, mbgl::style::HeatmapLayer&);
|
||||
|
||||
HeatmapLayer(mbgl::Map&, std::unique_ptr<mbgl::style::HeatmapLayer>);
|
||||
|
||||
~HeatmapLayer();
|
||||
|
||||
// Properties
|
||||
|
||||
jni::Object<jni::ObjectTag> getHeatmapRadius(jni::JNIEnv&);
|
||||
void setHeatmapRadiusTransition(jni::JNIEnv&, jlong duration, jlong delay);
|
||||
jni::Object<TransitionOptions> getHeatmapRadiusTransition(jni::JNIEnv&);
|
||||
|
||||
jni::Object<jni::ObjectTag> getHeatmapWeight(jni::JNIEnv&);
|
||||
|
||||
jni::Object<jni::ObjectTag> getHeatmapIntensity(jni::JNIEnv&);
|
||||
void setHeatmapIntensityTransition(jni::JNIEnv&, jlong duration, jlong delay);
|
||||
jni::Object<TransitionOptions> getHeatmapIntensityTransition(jni::JNIEnv&);
|
||||
|
||||
jni::Object<jni::ObjectTag> getHeatmapOpacity(jni::JNIEnv&);
|
||||
void setHeatmapOpacityTransition(jni::JNIEnv&, jlong duration, jlong delay);
|
||||
jni::Object<TransitionOptions> getHeatmapOpacityTransition(jni::JNIEnv&);
|
||||
jni::jobject* createJavaPeer(jni::JNIEnv&);
|
||||
|
||||
}; // class HeatmapLayer
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -10,6 +10,7 @@
|
||||
#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/heatmap_layer.hpp>
|
||||
#include <mbgl/style/layers/hillshade_layer.hpp>
|
||||
#include <mbgl/style/layers/line_layer.hpp>
|
||||
#include <mbgl/style/layers/raster_layer.hpp>
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <mbgl/style/layers/circle_layer.hpp>
|
||||
#include <mbgl/style/layers/fill_extrusion_layer.hpp>
|
||||
#include <mbgl/style/layers/fill_layer.hpp>
|
||||
#include <mbgl/style/layers/heatmap_layer.hpp>
|
||||
#include <mbgl/style/layers/hillshade_layer.hpp>
|
||||
#include <mbgl/style/layers/line_layer.hpp>
|
||||
#include <mbgl/style/layers/raster_layer.hpp>
|
||||
@@ -16,6 +17,7 @@
|
||||
#include "custom_layer.hpp"
|
||||
#include "fill_extrusion_layer.hpp"
|
||||
#include "fill_layer.hpp"
|
||||
#include "heatmap_layer.hpp"
|
||||
#include "hillshade_layer.hpp"
|
||||
#include "line_layer.hpp"
|
||||
#include "raster_layer.hpp"
|
||||
@@ -32,6 +34,7 @@ template <> struct PeerType<style::BackgroundLayer> { using Type = android::Back
|
||||
template <> struct PeerType<style::CircleLayer> { using Type = android::CircleLayer; };
|
||||
template <> struct PeerType<style::FillExtrusionLayer> { using Type = android::FillExtrusionLayer; };
|
||||
template <> struct PeerType<style::FillLayer> { using Type = android::FillLayer; };
|
||||
template <> struct PeerType<style::HeatmapLayer> { using Type = android::HeatmapLayer; };
|
||||
template <> struct PeerType<style::HillshadeLayer> { using Type = android::HillshadeLayer; };
|
||||
template <> struct PeerType<style::LineLayer> { using Type = android::LineLayer; };
|
||||
template <> struct PeerType<style::RasterLayer> { using Type = android::RasterLayer; };
|
||||
@@ -95,6 +98,7 @@ void registerNativeLayers(jni::JNIEnv& env) {
|
||||
CustomLayer::registerNative(env);
|
||||
FillExtrusionLayer::registerNative(env);
|
||||
FillLayer::registerNative(env);
|
||||
HeatmapLayer::registerNative(env);
|
||||
HillshadeLayer::registerNative(env);
|
||||
LineLayer::registerNative(env);
|
||||
RasterLayer::registerNative(env);
|
||||
|
||||
@@ -308,14 +308,15 @@ global.propertyDoc = function (propertyName, property, layerType, kind) {
|
||||
doc += '* Predefined functions, including mathematical and string operators\n' +
|
||||
'* Conditional expressions\n' +
|
||||
'* Variable assignments and references to assigned variables\n';
|
||||
const inputVariable = property.name === 'heatmap-color' ? '$heatmapDensity' : '$zoomLevel';
|
||||
if (property["property-function"]) {
|
||||
doc += '* Interpolation and step functions applied to the `$zoomLevel` variable and/or feature attributes\n';
|
||||
doc += `* Interpolation and step functions applied to the \`${inputVariable}\` variable and/or feature attributes\n`;
|
||||
} else if (property.function === "interpolated") {
|
||||
doc += '* Interpolation and step functions applied to the `$zoomLevel` variable\n\n' +
|
||||
doc += `* Interpolation and step functions applied to the \`${inputVariable}\` variable\n\n` +
|
||||
'This property does not support applying interpolation or step functions to feature attributes.';
|
||||
} else {
|
||||
doc += '* Step functions applied to the `$zoomLevel` variable\n\n' +
|
||||
'This property does not support applying interpolation functions to the `$zoomLevel` variable or applying interpolation or step functions to feature attributes.';
|
||||
doc += `* Step functions applied to the \`${inputVariable}\` variable\n\n` +
|
||||
`This property does not support applying interpolation functions to the \`${inputVariable}\` variable or applying interpolation or step functions to feature attributes.`;
|
||||
}
|
||||
}
|
||||
return doc;
|
||||
@@ -387,7 +388,7 @@ global.describeValue = function (value, property, layerType) {
|
||||
throw new Error(`No description available for ${value[0]} expression in ${property.name} of ${layerType}.`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
switch (property.type) {
|
||||
case 'boolean':
|
||||
return value ? '`YES`' : '`NO`';
|
||||
|
||||
@@ -23,6 +23,9 @@
|
||||
"circle": {
|
||||
"doc": "An `MGLCircleStyleLayer` is a style layer that renders one or more filled circles on the map.\n\nUse a circle style layer to configure the visual appearance of point or point collection features in vector tiles loaded by an `MGLVectorSource` object or `MGLPointAnnotation`, `MGLPointFeature`, `MGLPointCollection`, or `MGLPointCollectionFeature` instances in an `MGLShapeSource` object.\n\nA circle style layer renders circles whose radii are measured in screen units. To display circles on the map whose radii correspond to real-world distances, use many-sided regular polygons and configure their appearance using an `MGLFillStyleLayer` object."
|
||||
},
|
||||
"heatmap": {
|
||||
"doc": "An `MGLHeatmapStyleLayer` is a style layer that renders a <a href=\"https://en.wikipedia.org/wiki/Heat_map\">heatmap</a>.\n\nA heatmap visualizes the spatial distribution of a large, dense set of point data, using color to avoid cluttering the map with individual points at low zoom levels. The points are weighted by an attribute you specify. Use a heatmap style layer in conjunction with point or point collection features in vector tiles loaded by an `MGLVectorSource` object or `MGLPointAnnotation`, `MGLPointFeature`, `MGLPointCollection`, or `MGLPointCollectionFeature` instances in an `MGLShapeSource` object.\n\nConsider accompanying a heatmap style layer with an `MGLCircleStyleLayer` or `MGLSymbolStyleLayer` at high zoom levels. If you are unsure whether the point data in an `MGLShapeSource` is dense enough to warrant a heatmap, you can alternatively cluster the source using the `MGLShapeSourceOptionClustered` option and render the data using an `MGLCircleStyleLayer` or `MGLSymbolStyleLayer`."
|
||||
},
|
||||
"raster": {
|
||||
"doc": "An `MGLRasterStyleLayer` is a style layer that renders georeferenced raster imagery on the map, especially raster tiles.\n\nUse a raster style layer to configure the color parameters of raster tiles loaded by an `MGLRasterSource` object or raster images loaded by an `MGLImageSource` object. For example, you could use a raster style layer to render <a href=\"https://www.mapbox.com/satellite/\">Mapbox Satellite</a> imagery, a <a href=\"https://www.mapbox.com/help/define-tileset/#raster-tilesets\">raster tile set</a> uploaded to Mapbox Studio, or a raster map authored in <a href=\"https://tilemill-project.github.io/tilemill/\">TileMill</a>, the classic Mapbox Editor, or Mapbox Studio Classic.\n\nRaster images may also be used as icons or patterns in a style layer. To register an image for use as an icon or pattern, use the `-[MGLStyle setImage:forName:]` method. To configure a point annotation’s image, use the `MGLAnnotationImage` class."
|
||||
},
|
||||
@@ -79,6 +82,11 @@
|
||||
"doc": "The base color of this layer. The extrusion's surfaces will be shaded differently based on this color in combination with the `light` settings. If this color is specified with an alpha component, the alpha component will be ignored; use `fill-extrusion-opacity` to set layer opacityco."
|
||||
}
|
||||
},
|
||||
"paint_heatmap": {
|
||||
"heatmap-color": {
|
||||
"doc": "Defines the color of each pixel based on its density value in a heatmap. Should be an expression that uses `$heatmapDensity` as input."
|
||||
}
|
||||
},
|
||||
"paint_line": {
|
||||
"line-pattern": {
|
||||
"doc": "Name of image in style images to use for drawing image lines. For seamless patterns, image width must be a factor of two (2, 4, 8, ..., 512)."
|
||||
@@ -114,4 +122,4 @@
|
||||
"doc": "Distance that the text's anchor is moved from its original placement."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
189
platform/darwin/src/MGLHeatmapStyleLayer.h
Normal file
189
platform/darwin/src/MGLHeatmapStyleLayer.h
Normal file
@@ -0,0 +1,189 @@
|
||||
// This file is generated.
|
||||
// Edit platform/darwin/scripts/generate-style-code.js, then run `make darwin-style-code`.
|
||||
|
||||
#import "MGLFoundation.h"
|
||||
#import "MGLVectorStyleLayer.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
An `MGLHeatmapStyleLayer` is a style layer that renders a <a
|
||||
href="https://en.wikipedia.org/wiki/Heat_map">heatmap</a>.
|
||||
|
||||
A heatmap visualizes the spatial distribution of a large, dense set of point
|
||||
data, using color to avoid cluttering the map with individual points at low
|
||||
zoom levels. The points are weighted by an attribute you specify. Use a heatmap
|
||||
style layer in conjunction with point or point collection features in vector
|
||||
tiles loaded by an `MGLVectorSource` object or `MGLPointAnnotation`,
|
||||
`MGLPointFeature`, `MGLPointCollection`, or `MGLPointCollectionFeature`
|
||||
instances in an `MGLShapeSource` object.
|
||||
|
||||
Consider accompanying a heatmap style layer with an `MGLCircleStyleLayer` or
|
||||
`MGLSymbolStyleLayer` at high zoom levels. If you are unsure whether the point
|
||||
data in an `MGLShapeSource` is dense enough to warrant a heatmap, you can
|
||||
alternatively cluster the source using the `MGLShapeSourceOptionClustered`
|
||||
option and render the data using an `MGLCircleStyleLayer` or
|
||||
`MGLSymbolStyleLayer`.
|
||||
|
||||
You can access an existing heatmap style layer using the
|
||||
`-[MGLStyle layerWithIdentifier:]` method if you know its identifier;
|
||||
otherwise, find it using the `MGLStyle.layers` property. You can also create a
|
||||
new heatmap style layer and add it to the style using a method such as
|
||||
`-[MGLStyle addLayer:]`.
|
||||
|
||||
### Example
|
||||
|
||||
```swift
|
||||
let layer = MGLHeatmapStyleLayer(identifier: "earthquake-heat", source: earthquakes)
|
||||
layer.heatmapWeight = NSExpression(format: "FUNCTION(magnitude, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)",
|
||||
[0: 0,
|
||||
6: 1])
|
||||
layer.heatmapIntensity = NSExpression(format: "FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)",
|
||||
[0: 1,
|
||||
9: 3])
|
||||
mapView.style?.addLayer(layer)
|
||||
```
|
||||
*/
|
||||
MGL_EXPORT
|
||||
@interface MGLHeatmapStyleLayer : MGLVectorStyleLayer
|
||||
|
||||
/**
|
||||
Returns a heatmap style layer initialized with an identifier and source.
|
||||
|
||||
After initializing and configuring the style layer, add it to a map view’s
|
||||
style using the `-[MGLStyle addLayer:]` or
|
||||
`-[MGLStyle insertLayer:belowLayer:]` method.
|
||||
|
||||
@param identifier A string that uniquely identifies the source in the style to
|
||||
which it is added.
|
||||
@param source The source from which to obtain the data to style. If the source
|
||||
has not yet been added to the current style, the behavior is undefined.
|
||||
@return An initialized foreground style layer.
|
||||
*/
|
||||
- (instancetype)initWithIdentifier:(NSString *)identifier source:(MGLSource *)source;
|
||||
|
||||
#pragma mark - Accessing the Paint Attributes
|
||||
|
||||
/**
|
||||
Defines the color of each point based on its density value in a heatmap. Should
|
||||
be an expression that uses `$heatmapDensity` as input.
|
||||
|
||||
The default value of this property is an expression that evaluates to a rainbow
|
||||
color scale from blue to red. Set this property to `nil` to reset it to the
|
||||
default value.
|
||||
|
||||
You can set this property to an expression containing any of the following:
|
||||
|
||||
* Constant `UIColor` values
|
||||
* Predefined functions, including mathematical and string operators
|
||||
* Conditional expressions
|
||||
* Variable assignments and references to assigned variables
|
||||
* Interpolation and step functions applied to the `$heatmapDensity` variable
|
||||
|
||||
This property does not support applying interpolation or step functions to
|
||||
feature attributes.
|
||||
*/
|
||||
@property (nonatomic, null_resettable) NSExpression *heatmapColor;
|
||||
|
||||
/**
|
||||
Similar to `heatmapWeight` but controls the intensity of the heatmap globally.
|
||||
Primarily used for adjusting the heatmap based on zoom level.
|
||||
|
||||
The default value of this property is an expression that evaluates to the float
|
||||
`1`. Set this property to `nil` to reset it to the default value.
|
||||
|
||||
You can set this property to an expression containing any of the following:
|
||||
|
||||
* Constant numeric values
|
||||
* Predefined functions, including mathematical and string operators
|
||||
* Conditional expressions
|
||||
* Variable assignments and references to assigned variables
|
||||
* Interpolation and step functions applied to the `$zoomLevel` variable
|
||||
|
||||
This property does not support applying interpolation or step functions to
|
||||
feature attributes.
|
||||
*/
|
||||
@property (nonatomic, null_resettable) NSExpression *heatmapIntensity;
|
||||
|
||||
/**
|
||||
The transition affecting any changes to this layer’s `heatmapIntensity` property.
|
||||
|
||||
This property corresponds to the `heatmap-intensity-transition` property in the style JSON file format.
|
||||
*/
|
||||
@property (nonatomic) MGLTransition heatmapIntensityTransition;
|
||||
|
||||
/**
|
||||
The global opacity at which the heatmap layer will be drawn.
|
||||
|
||||
The default value of this property is an expression that evaluates to the float
|
||||
`1`. Set this property to `nil` to reset it to the default value.
|
||||
|
||||
You can set this property to an expression containing any of the following:
|
||||
|
||||
* Constant numeric values
|
||||
* Predefined functions, including mathematical and string operators
|
||||
* Conditional expressions
|
||||
* Variable assignments and references to assigned variables
|
||||
* Interpolation and step functions applied to the `$zoomLevel` variable
|
||||
|
||||
This property does not support applying interpolation or step functions to
|
||||
feature attributes.
|
||||
*/
|
||||
@property (nonatomic, null_resettable) NSExpression *heatmapOpacity;
|
||||
|
||||
/**
|
||||
The transition affecting any changes to this layer’s `heatmapOpacity` property.
|
||||
|
||||
This property corresponds to the `heatmap-opacity-transition` property in the style JSON file format.
|
||||
*/
|
||||
@property (nonatomic) MGLTransition heatmapOpacityTransition;
|
||||
|
||||
/**
|
||||
Radius of influence of one heatmap point in points. Increasing the value makes
|
||||
the heatmap smoother, but less detailed.
|
||||
|
||||
This property is measured in points.
|
||||
|
||||
The default value of this property is an expression that evaluates to the float
|
||||
`30`. Set this property to `nil` to reset it to the default value.
|
||||
|
||||
You can set this property to an expression containing any of the following:
|
||||
|
||||
* Constant numeric values
|
||||
* Predefined functions, including mathematical and string operators
|
||||
* Conditional expressions
|
||||
* Variable assignments and references to assigned variables
|
||||
* Interpolation and step functions applied to the `$zoomLevel` variable and/or
|
||||
feature attributes
|
||||
*/
|
||||
@property (nonatomic, null_resettable) NSExpression *heatmapRadius;
|
||||
|
||||
/**
|
||||
The transition affecting any changes to this layer’s `heatmapRadius` property.
|
||||
|
||||
This property corresponds to the `heatmap-radius-transition` property in the style JSON file format.
|
||||
*/
|
||||
@property (nonatomic) MGLTransition heatmapRadiusTransition;
|
||||
|
||||
/**
|
||||
A measure of how much an individual point contributes to the heatmap. A value
|
||||
of 10 would be equivalent to having 10 points of weight 1 in the same spot.
|
||||
Especially useful when combined with clustering.
|
||||
|
||||
The default value of this property is an expression that evaluates to the float
|
||||
`1`. Set this property to `nil` to reset it to the default value.
|
||||
|
||||
You can set this property to an expression containing any of the following:
|
||||
|
||||
* Constant numeric values
|
||||
* Predefined functions, including mathematical and string operators
|
||||
* Conditional expressions
|
||||
* Variable assignments and references to assigned variables
|
||||
* Interpolation and step functions applied to the `$zoomLevel` variable and/or
|
||||
feature attributes
|
||||
*/
|
||||
@property (nonatomic, null_resettable) NSExpression *heatmapWeight;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
210
platform/darwin/src/MGLHeatmapStyleLayer.mm
Normal file
210
platform/darwin/src/MGLHeatmapStyleLayer.mm
Normal file
@@ -0,0 +1,210 @@
|
||||
// This file is generated.
|
||||
// Edit platform/darwin/scripts/generate-style-code.js, then run `make darwin-style-code`.
|
||||
|
||||
#import "MGLSource.h"
|
||||
#import "NSPredicate+MGLAdditions.h"
|
||||
#import "NSDate+MGLAdditions.h"
|
||||
#import "MGLStyleLayer_Private.h"
|
||||
#import "MGLStyleValue_Private.h"
|
||||
#import "MGLHeatmapStyleLayer.h"
|
||||
|
||||
#include <mbgl/style/transition_options.hpp>
|
||||
#include <mbgl/style/layers/heatmap_layer.hpp>
|
||||
|
||||
@interface MGLHeatmapStyleLayer ()
|
||||
|
||||
@property (nonatomic, readonly) mbgl::style::HeatmapLayer *rawLayer;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MGLHeatmapStyleLayer
|
||||
|
||||
- (instancetype)initWithIdentifier:(NSString *)identifier source:(MGLSource *)source
|
||||
{
|
||||
auto layer = std::make_unique<mbgl::style::HeatmapLayer>(identifier.UTF8String, source.identifier.UTF8String);
|
||||
return self = [super initWithPendingLayer:std::move(layer)];
|
||||
}
|
||||
|
||||
- (mbgl::style::HeatmapLayer *)rawLayer
|
||||
{
|
||||
return (mbgl::style::HeatmapLayer *)super.rawLayer;
|
||||
}
|
||||
|
||||
- (NSString *)sourceIdentifier
|
||||
{
|
||||
MGLAssertStyleLayerIsValid();
|
||||
|
||||
return @(self.rawLayer->getSourceID().c_str());
|
||||
}
|
||||
|
||||
- (NSString *)sourceLayerIdentifier
|
||||
{
|
||||
MGLAssertStyleLayerIsValid();
|
||||
|
||||
auto layerID = self.rawLayer->getSourceLayer();
|
||||
return layerID.empty() ? nil : @(layerID.c_str());
|
||||
}
|
||||
|
||||
- (void)setSourceLayerIdentifier:(NSString *)sourceLayerIdentifier
|
||||
{
|
||||
MGLAssertStyleLayerIsValid();
|
||||
|
||||
self.rawLayer->setSourceLayer(sourceLayerIdentifier.UTF8String ?: "");
|
||||
}
|
||||
|
||||
- (void)setPredicate:(NSPredicate *)predicate
|
||||
{
|
||||
MGLAssertStyleLayerIsValid();
|
||||
|
||||
self.rawLayer->setFilter(predicate ? predicate.mgl_filter : mbgl::style::NullFilter());
|
||||
}
|
||||
|
||||
- (NSPredicate *)predicate
|
||||
{
|
||||
MGLAssertStyleLayerIsValid();
|
||||
|
||||
return [NSPredicate mgl_predicateWithFilter:self.rawLayer->getFilter()];
|
||||
}
|
||||
|
||||
#pragma mark - Accessing the Paint Attributes
|
||||
|
||||
- (void)setHeatmapColor:(NSExpression *)heatmapColor {
|
||||
MGLAssertStyleLayerIsValid();
|
||||
|
||||
auto mbglValue = MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toPropertyValue<mbgl::style::HeatmapColorPropertyValue>(heatmapColor);
|
||||
self.rawLayer->setHeatmapColor(mbglValue);
|
||||
}
|
||||
|
||||
- (NSExpression *)heatmapColor {
|
||||
MGLAssertStyleLayerIsValid();
|
||||
|
||||
auto propertyValue = self.rawLayer->getHeatmapColor();
|
||||
if (propertyValue.isUndefined()) {
|
||||
propertyValue = self.rawLayer->getDefaultHeatmapColor();
|
||||
}
|
||||
return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toExpression(propertyValue);
|
||||
}
|
||||
|
||||
- (void)setHeatmapIntensity:(NSExpression *)heatmapIntensity {
|
||||
MGLAssertStyleLayerIsValid();
|
||||
|
||||
auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue<mbgl::style::PropertyValue<float>>(heatmapIntensity);
|
||||
self.rawLayer->setHeatmapIntensity(mbglValue);
|
||||
}
|
||||
|
||||
- (NSExpression *)heatmapIntensity {
|
||||
MGLAssertStyleLayerIsValid();
|
||||
|
||||
auto propertyValue = self.rawLayer->getHeatmapIntensity();
|
||||
if (propertyValue.isUndefined()) {
|
||||
propertyValue = self.rawLayer->getDefaultHeatmapIntensity();
|
||||
}
|
||||
return MGLStyleValueTransformer<float, NSNumber *>().toExpression(propertyValue);
|
||||
}
|
||||
|
||||
- (void)setHeatmapIntensityTransition:(MGLTransition )transition {
|
||||
MGLAssertStyleLayerIsValid();
|
||||
|
||||
mbgl::style::TransitionOptions options { { MGLDurationFromTimeInterval(transition.duration) }, { MGLDurationFromTimeInterval(transition.delay) } };
|
||||
self.rawLayer->setHeatmapIntensityTransition(options);
|
||||
}
|
||||
|
||||
- (MGLTransition)heatmapIntensityTransition {
|
||||
MGLAssertStyleLayerIsValid();
|
||||
|
||||
mbgl::style::TransitionOptions transitionOptions = self.rawLayer->getHeatmapIntensityTransition();
|
||||
MGLTransition transition;
|
||||
transition.duration = MGLTimeIntervalFromDuration(transitionOptions.duration.value_or(mbgl::Duration::zero()));
|
||||
transition.delay = MGLTimeIntervalFromDuration(transitionOptions.delay.value_or(mbgl::Duration::zero()));
|
||||
|
||||
return transition;
|
||||
}
|
||||
|
||||
- (void)setHeatmapOpacity:(NSExpression *)heatmapOpacity {
|
||||
MGLAssertStyleLayerIsValid();
|
||||
|
||||
auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue<mbgl::style::PropertyValue<float>>(heatmapOpacity);
|
||||
self.rawLayer->setHeatmapOpacity(mbglValue);
|
||||
}
|
||||
|
||||
- (NSExpression *)heatmapOpacity {
|
||||
MGLAssertStyleLayerIsValid();
|
||||
|
||||
auto propertyValue = self.rawLayer->getHeatmapOpacity();
|
||||
if (propertyValue.isUndefined()) {
|
||||
propertyValue = self.rawLayer->getDefaultHeatmapOpacity();
|
||||
}
|
||||
return MGLStyleValueTransformer<float, NSNumber *>().toExpression(propertyValue);
|
||||
}
|
||||
|
||||
- (void)setHeatmapOpacityTransition:(MGLTransition )transition {
|
||||
MGLAssertStyleLayerIsValid();
|
||||
|
||||
mbgl::style::TransitionOptions options { { MGLDurationFromTimeInterval(transition.duration) }, { MGLDurationFromTimeInterval(transition.delay) } };
|
||||
self.rawLayer->setHeatmapOpacityTransition(options);
|
||||
}
|
||||
|
||||
- (MGLTransition)heatmapOpacityTransition {
|
||||
MGLAssertStyleLayerIsValid();
|
||||
|
||||
mbgl::style::TransitionOptions transitionOptions = self.rawLayer->getHeatmapOpacityTransition();
|
||||
MGLTransition transition;
|
||||
transition.duration = MGLTimeIntervalFromDuration(transitionOptions.duration.value_or(mbgl::Duration::zero()));
|
||||
transition.delay = MGLTimeIntervalFromDuration(transitionOptions.delay.value_or(mbgl::Duration::zero()));
|
||||
|
||||
return transition;
|
||||
}
|
||||
|
||||
- (void)setHeatmapRadius:(NSExpression *)heatmapRadius {
|
||||
MGLAssertStyleLayerIsValid();
|
||||
|
||||
auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue<mbgl::style::DataDrivenPropertyValue<float>>(heatmapRadius);
|
||||
self.rawLayer->setHeatmapRadius(mbglValue);
|
||||
}
|
||||
|
||||
- (NSExpression *)heatmapRadius {
|
||||
MGLAssertStyleLayerIsValid();
|
||||
|
||||
auto propertyValue = self.rawLayer->getHeatmapRadius();
|
||||
if (propertyValue.isUndefined()) {
|
||||
propertyValue = self.rawLayer->getDefaultHeatmapRadius();
|
||||
}
|
||||
return MGLStyleValueTransformer<float, NSNumber *>().toExpression(propertyValue);
|
||||
}
|
||||
|
||||
- (void)setHeatmapRadiusTransition:(MGLTransition )transition {
|
||||
MGLAssertStyleLayerIsValid();
|
||||
|
||||
mbgl::style::TransitionOptions options { { MGLDurationFromTimeInterval(transition.duration) }, { MGLDurationFromTimeInterval(transition.delay) } };
|
||||
self.rawLayer->setHeatmapRadiusTransition(options);
|
||||
}
|
||||
|
||||
- (MGLTransition)heatmapRadiusTransition {
|
||||
MGLAssertStyleLayerIsValid();
|
||||
|
||||
mbgl::style::TransitionOptions transitionOptions = self.rawLayer->getHeatmapRadiusTransition();
|
||||
MGLTransition transition;
|
||||
transition.duration = MGLTimeIntervalFromDuration(transitionOptions.duration.value_or(mbgl::Duration::zero()));
|
||||
transition.delay = MGLTimeIntervalFromDuration(transitionOptions.delay.value_or(mbgl::Duration::zero()));
|
||||
|
||||
return transition;
|
||||
}
|
||||
|
||||
- (void)setHeatmapWeight:(NSExpression *)heatmapWeight {
|
||||
MGLAssertStyleLayerIsValid();
|
||||
|
||||
auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue<mbgl::style::DataDrivenPropertyValue<float>>(heatmapWeight);
|
||||
self.rawLayer->setHeatmapWeight(mbglValue);
|
||||
}
|
||||
|
||||
- (NSExpression *)heatmapWeight {
|
||||
MGLAssertStyleLayerIsValid();
|
||||
|
||||
auto propertyValue = self.rawLayer->getHeatmapWeight();
|
||||
if (propertyValue.isUndefined()) {
|
||||
propertyValue = self.rawLayer->getDefaultHeatmapWeight();
|
||||
}
|
||||
return MGLStyleValueTransformer<float, NSNumber *>().toExpression(propertyValue);
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -8,6 +8,7 @@
|
||||
#import "MGLLineStyleLayer.h"
|
||||
#import "MGLCircleStyleLayer.h"
|
||||
#import "MGLSymbolStyleLayer.h"
|
||||
#import "MGLHeatmapStyleLayer.h"
|
||||
#import "MGLHillshadeStyleLayer.h"
|
||||
#import "MGLRasterStyleLayer.h"
|
||||
#import "MGLBackgroundStyleLayer.h"
|
||||
@@ -36,6 +37,7 @@
|
||||
#include <mbgl/style/layers/line_layer.hpp>
|
||||
#include <mbgl/style/layers/symbol_layer.hpp>
|
||||
#include <mbgl/style/layers/raster_layer.hpp>
|
||||
#include <mbgl/style/layers/heatmap_layer.hpp>
|
||||
#include <mbgl/style/layers/hillshade_layer.hpp>
|
||||
#include <mbgl/style/layers/circle_layer.hpp>
|
||||
#include <mbgl/style/layers/background_layer.hpp>
|
||||
@@ -401,6 +403,8 @@ static NSURL *MGLStyleURL_trafficNight;
|
||||
return [[MGLSymbolStyleLayer alloc] initWithRawLayer:symbolLayer];
|
||||
} else if (auto rasterLayer = rawLayer->as<mbgl::style::RasterLayer>()) {
|
||||
return [[MGLRasterStyleLayer alloc] initWithRawLayer:rasterLayer];
|
||||
} else if (auto heatmapLayer = rawLayer->as<mbgl::style::HeatmapLayer>()) {
|
||||
return [[MGLHeatmapStyleLayer alloc] initWithRawLayer:heatmapLayer];
|
||||
} else if (auto hillshadeLayer = rawLayer->as<mbgl::style::HillshadeLayer>()) {
|
||||
return [[MGLHillshadeStyleLayer alloc] initWithRawLayer:hillshadeLayer];
|
||||
} else if (auto circleLayer = rawLayer->as<mbgl::style::CircleLayer>()) {
|
||||
|
||||
@@ -157,7 +157,9 @@ namespace mbgl {
|
||||
- (void)set<%- camelize(property.name) %>:(NSExpression *)<%- objCName(property) %> {
|
||||
MGLAssertStyleLayerIsValid();
|
||||
|
||||
<% if (property["property-function"]) { -%>
|
||||
<% if (property.name === 'heatmap-color') { -%>
|
||||
auto mbglValue = MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toPropertyValue<mbgl::style::HeatmapColorPropertyValue>(heatmapColor);
|
||||
<% } else if (property["property-function"]) { -%>
|
||||
auto mbglValue = MGLStyleValueTransformer<<%- valueTransformerArguments(property).join(', ') %>>().toPropertyValue<mbgl::style::DataDrivenPropertyValue<<%- valueTransformerArguments(property)[0] %>>>(<%- objCName(property) %>);
|
||||
<% } else { -%>
|
||||
auto mbglValue = MGLStyleValueTransformer<<%- valueTransformerArguments(property).join(', ') %>>().toPropertyValue<mbgl::style::PropertyValue<<%- valueTransformerArguments(property)[0] %>>>(<%- objCName(property) %>);
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#import "MGLConversion.h"
|
||||
#include <mbgl/style/conversion/property_value.hpp>
|
||||
#include <mbgl/style/conversion/data_driven_property_value.hpp>
|
||||
#include <mbgl/style/conversion/heatmap_color_property_value.hpp>
|
||||
#include <mbgl/style/conversion/position.hpp>
|
||||
#import <mbgl/style/types.hpp>
|
||||
|
||||
@@ -52,11 +53,20 @@ public:
|
||||
return mbglValue.evaluate(evaluator);
|
||||
}
|
||||
|
||||
// Convert an mbgl heatmap color property value into an mgl style value
|
||||
NSExpression *toExpression(const mbgl::style::HeatmapColorPropertyValue &mbglValue) {
|
||||
if (mbglValue.isUndefined()) {
|
||||
return nil;
|
||||
}
|
||||
return [NSExpression mgl_expressionWithJSONObject:MGLJSONObjectFromMBGLExpression(mbglValue.getExpression())];
|
||||
}
|
||||
|
||||
/**
|
||||
Converts an NSExpression to an mbgl property value.
|
||||
*/
|
||||
template <typename MBGLValue>
|
||||
MBGLValue toPropertyValue(NSExpression *expression) {
|
||||
typename std::enable_if_t<!std::is_same<MBGLValue, mbgl::style::HeatmapColorPropertyValue>::value,
|
||||
MBGLValue> toPropertyValue(NSExpression *expression) {
|
||||
if (!expression) {
|
||||
return {};
|
||||
}
|
||||
@@ -85,6 +95,30 @@ public:
|
||||
|
||||
return *value;
|
||||
}
|
||||
|
||||
/**
|
||||
Converts an NSExpression to an mbgl property value.
|
||||
*/
|
||||
template <typename MBGLValue>
|
||||
typename std::enable_if_t<std::is_same<MBGLValue, mbgl::style::HeatmapColorPropertyValue>::value,
|
||||
MBGLValue> toPropertyValue(NSExpression *expression) {
|
||||
if (!expression) {
|
||||
return {};
|
||||
}
|
||||
|
||||
NSArray *jsonExpression = expression.mgl_jsonExpressionObject;
|
||||
|
||||
mbgl::style::conversion::Error valueError;
|
||||
auto value = mbgl::style::conversion::convert<mbgl::style::HeatmapColorPropertyValue>(
|
||||
mbgl::style::conversion::makeConvertible(jsonExpression), valueError);
|
||||
if (!value) {
|
||||
[NSException raise:NSInvalidArgumentException
|
||||
format:@"Invalid property value: %@", @(valueError.message.c_str())];
|
||||
return {};
|
||||
}
|
||||
|
||||
return *value;
|
||||
}
|
||||
|
||||
private: // Private utilities for converting from mgl to mbgl values
|
||||
|
||||
|
||||
@@ -10,10 +10,10 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
is defined by an `MGLShapeSource` or `MGLVectorSource` object.
|
||||
|
||||
Create instances of `MGLCircleStyleLayer`, `MGLFillStyleLayer`,
|
||||
`MGLFillExtrusionStyleLayer`, `MGLLineStyleLayer`, and `MGLSymbolStyleLayer` in
|
||||
order to use `MGLVectorStyleLayer`'s properties and methods. Do not create
|
||||
instances of `MGLVectorStyleLayer` directly, and do not create your own
|
||||
subclasses of this class.
|
||||
`MGLFillExtrusionStyleLayer`, `MGLHeatmapStyleLayer`, `MGLLineStyleLayer`, and
|
||||
`MGLSymbolStyleLayer` in order to use `MGLVectorStyleLayer`'s properties and
|
||||
methods. Do not create instances of `MGLVectorStyleLayer` directly, and do not
|
||||
create your own subclasses of this class.
|
||||
*/
|
||||
MGL_EXPORT
|
||||
@interface MGLVectorStyleLayer : MGLForegroundStyleLayer
|
||||
|
||||
@@ -230,6 +230,24 @@ class MGLDocumentationExampleTests: XCTestCase, MGLMapViewDelegate {
|
||||
|
||||
XCTAssertNotNil(mapView.style?.layer(withIdentifier: "buildings"))
|
||||
}
|
||||
|
||||
func testMGLHeatmapStyleLayer() {
|
||||
let earthquakes = MGLShapeSource(identifier: "earthquakes", url: URL(string: "https://example.com/earthquakes.json")!, options: [:])
|
||||
mapView.style?.addSource(earthquakes)
|
||||
|
||||
//#-example-code
|
||||
let layer = MGLHeatmapStyleLayer(identifier: "earthquake-heat", source: earthquakes)
|
||||
layer.heatmapWeight = NSExpression(format: "FUNCTION(magnitude, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)",
|
||||
[0: 0,
|
||||
6: 1])
|
||||
layer.heatmapIntensity = NSExpression(format: "FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)",
|
||||
[0: 1,
|
||||
9: 3])
|
||||
mapView.style?.addLayer(layer)
|
||||
//#-end-example-code
|
||||
|
||||
XCTAssertNotNil(mapView.style?.layer(withIdentifier: "earthquake-heat"))
|
||||
}
|
||||
|
||||
func testMGLSymbolStyleLayer() {
|
||||
let pois = MGLVectorSource(identifier: "pois", configurationURL: URL(string: "https://example.com/style.json")!)
|
||||
|
||||
61
platform/darwin/test/MGLHeatmapColorTests.mm
Normal file
61
platform/darwin/test/MGLHeatmapColorTests.mm
Normal file
@@ -0,0 +1,61 @@
|
||||
#import <Mapbox/Mapbox.h>
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#import "MGLStyleLayer_Private.h"
|
||||
|
||||
#include <mbgl/style/layers/heatmap_layer.hpp>
|
||||
|
||||
@interface MGLHeatmapColorTests : XCTestCase <MGLMapViewDelegate>
|
||||
@end
|
||||
|
||||
@implementation MGLHeatmapColorTests
|
||||
|
||||
- (void)testProperties {
|
||||
MGLPointFeature *feature = [[MGLPointFeature alloc] init];
|
||||
MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"sourceID" shape:feature options:nil];
|
||||
MGLHeatmapStyleLayer *layer = [[MGLHeatmapStyleLayer alloc] initWithIdentifier:@"layerID" source:source];
|
||||
|
||||
auto rawLayer = layer.rawLayer->as<mbgl::style::HeatmapLayer>();
|
||||
|
||||
XCTAssertTrue(rawLayer->getHeatmapColor().isUndefined(),
|
||||
@"heatmap-color should be unset initially.");
|
||||
NSExpression *defaultExpression = layer.heatmapColor;
|
||||
|
||||
NSExpression *constantExpression = [NSExpression expressionWithFormat:@"%@", [MGLColor redColor]];
|
||||
layer.heatmapColor = constantExpression;
|
||||
|
||||
|
||||
mbgl::style::PropertyValue<float> propertyValue = { 0xff };
|
||||
XCTAssertEqual(rawLayer->getHeatmapColor().evaluate(0.0), mbgl::Color::red(),
|
||||
@"Setting heatmapColor to a constant value expression should update heatmap-color.");
|
||||
XCTAssertEqualObjects(layer.heatmapColor, constantExpression,
|
||||
@"heatmapColor should round-trip constant value expressions.");
|
||||
|
||||
constantExpression = [NSExpression expressionWithFormat:@"%@", [MGLColor redColor]];
|
||||
NSExpression *constantExpression2 = [NSExpression expressionWithFormat:@"%@", [MGLColor blueColor]];
|
||||
NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($heatmapDensity, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@12: constantExpression2}];
|
||||
layer.heatmapColor = functionExpression;
|
||||
|
||||
XCTAssertEqual(rawLayer->getHeatmapColor().evaluate(11.0), mbgl::Color::red(),
|
||||
@"Setting heatmapColor to an expression depending on $heatmapDensity should update heatmap-color.");
|
||||
XCTAssertEqual(rawLayer->getHeatmapColor().evaluate(12.0), mbgl::Color::blue(),
|
||||
@"Setting heatmapColor to an expression depending on $heatmapDensity should update heatmap-color.");
|
||||
XCTAssertEqualObjects(layer.heatmapColor, functionExpression,
|
||||
@"heatmapColor should round-trip expressions depending on $heatmapDensity.");
|
||||
|
||||
layer.heatmapColor = nil;
|
||||
XCTAssertTrue(rawLayer->getHeatmapColor().isUndefined(),
|
||||
@"Unsetting heatmapColor should return heatmap-color to the default value.");
|
||||
XCTAssertEqualObjects(layer.heatmapColor, defaultExpression,
|
||||
@"heatmapColor should return the default value after being unset.");
|
||||
|
||||
functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
|
||||
XCTAssertThrowsSpecificNamed(layer.heatmapColor = functionExpression, NSException, NSInvalidArgumentException, @"MGLHeatmapLayer should raise an exception if a camera expression is applied to heatmapColor.");
|
||||
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
|
||||
XCTAssertThrowsSpecificNamed(layer.heatmapColor = functionExpression, NSException, NSInvalidArgumentException, @"MGLHeatmapLayer should raise an exception if a data expression is applied to heatmapColor.");
|
||||
functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
|
||||
functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
|
||||
XCTAssertThrowsSpecificNamed(layer.heatmapColor = functionExpression, NSException, NSInvalidArgumentException, @"MGLHeatmapLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
|
||||
}
|
||||
|
||||
@end
|
||||
296
platform/darwin/test/MGLHeatmapStyleLayerTests.mm
Normal file
296
platform/darwin/test/MGLHeatmapStyleLayerTests.mm
Normal file
@@ -0,0 +1,296 @@
|
||||
// This file is generated.
|
||||
// Edit platform/darwin/scripts/generate-style-code.js, then run `make darwin-style-code`.
|
||||
|
||||
#import "MGLStyleLayerTests.h"
|
||||
#import "../../darwin/src/NSDate+MGLAdditions.h"
|
||||
|
||||
#import "MGLStyleLayer_Private.h"
|
||||
|
||||
#include <mbgl/style/layers/heatmap_layer.hpp>
|
||||
#include <mbgl/style/transition_options.hpp>
|
||||
|
||||
@interface MGLHeatmapLayerTests : MGLStyleLayerTests
|
||||
@end
|
||||
|
||||
@implementation MGLHeatmapLayerTests
|
||||
|
||||
+ (NSString *)layerType {
|
||||
return @"heatmap";
|
||||
}
|
||||
|
||||
- (void)testPredicates {
|
||||
MGLPointFeature *feature = [[MGLPointFeature alloc] init];
|
||||
MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"sourceID" shape:feature options:nil];
|
||||
MGLHeatmapStyleLayer *layer = [[MGLHeatmapStyleLayer alloc] initWithIdentifier:@"layerID" source:source];
|
||||
|
||||
XCTAssertNil(layer.sourceLayerIdentifier);
|
||||
layer.sourceLayerIdentifier = @"layerID";
|
||||
XCTAssertEqualObjects(layer.sourceLayerIdentifier, @"layerID");
|
||||
layer.sourceLayerIdentifier = nil;
|
||||
XCTAssertNil(layer.sourceLayerIdentifier);
|
||||
|
||||
XCTAssertNil(layer.predicate);
|
||||
layer.predicate = [NSPredicate predicateWithValue:NO];
|
||||
XCTAssertEqualObjects(layer.predicate, [NSPredicate predicateWithValue:NO]);
|
||||
layer.predicate = nil;
|
||||
XCTAssertNil(layer.predicate);
|
||||
}
|
||||
|
||||
- (void)testProperties {
|
||||
MGLPointFeature *feature = [[MGLPointFeature alloc] init];
|
||||
MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"sourceID" shape:feature options:nil];
|
||||
|
||||
MGLHeatmapStyleLayer *layer = [[MGLHeatmapStyleLayer alloc] initWithIdentifier:@"layerID" source:source];
|
||||
XCTAssertNotEqual(layer.rawLayer, nullptr);
|
||||
XCTAssertTrue(layer.rawLayer->is<mbgl::style::HeatmapLayer>());
|
||||
auto rawLayer = layer.rawLayer->as<mbgl::style::HeatmapLayer>();
|
||||
|
||||
MGLTransition transitionTest = MGLTransitionMake(5, 4);
|
||||
|
||||
|
||||
// heatmap-intensity
|
||||
{
|
||||
XCTAssertTrue(rawLayer->getHeatmapIntensity().isUndefined(),
|
||||
@"heatmap-intensity should be unset initially.");
|
||||
NSExpression *defaultExpression = layer.heatmapIntensity;
|
||||
|
||||
NSExpression *constantExpression = [NSExpression expressionWithFormat:@"0xff"];
|
||||
layer.heatmapIntensity = constantExpression;
|
||||
mbgl::style::PropertyValue<float> propertyValue = { 0xff };
|
||||
XCTAssertEqual(rawLayer->getHeatmapIntensity(), propertyValue,
|
||||
@"Setting heatmapIntensity to a constant value expression should update heatmap-intensity.");
|
||||
XCTAssertEqualObjects(layer.heatmapIntensity, constantExpression,
|
||||
@"heatmapIntensity should round-trip constant value expressions.");
|
||||
|
||||
constantExpression = [NSExpression expressionWithFormat:@"0xff"];
|
||||
NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
|
||||
layer.heatmapIntensity = functionExpression;
|
||||
|
||||
mbgl::style::IntervalStops<float> intervalStops = {{
|
||||
{ -INFINITY, 0xff },
|
||||
{ 18, 0xff },
|
||||
}};
|
||||
propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
|
||||
|
||||
XCTAssertEqual(rawLayer->getHeatmapIntensity(), propertyValue,
|
||||
@"Setting heatmapIntensity to a camera expression should update heatmap-intensity.");
|
||||
XCTAssertEqualObjects(layer.heatmapIntensity, functionExpression,
|
||||
@"heatmapIntensity should round-trip camera expressions.");
|
||||
|
||||
|
||||
|
||||
layer.heatmapIntensity = nil;
|
||||
XCTAssertTrue(rawLayer->getHeatmapIntensity().isUndefined(),
|
||||
@"Unsetting heatmapIntensity should return heatmap-intensity to the default value.");
|
||||
XCTAssertEqualObjects(layer.heatmapIntensity, defaultExpression,
|
||||
@"heatmapIntensity should return the default value after being unset.");
|
||||
|
||||
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
|
||||
XCTAssertThrowsSpecificNamed(layer.heatmapIntensity = functionExpression, NSException, NSInvalidArgumentException, @"MGLHeatmapLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
|
||||
functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
|
||||
functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
|
||||
XCTAssertThrowsSpecificNamed(layer.heatmapIntensity = functionExpression, NSException, NSInvalidArgumentException, @"MGLHeatmapLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
|
||||
// Transition property test
|
||||
layer.heatmapIntensityTransition = transitionTest;
|
||||
auto toptions = rawLayer->getHeatmapIntensityTransition();
|
||||
XCTAssert(toptions.delay && MGLTimeIntervalFromDuration(*toptions.delay) == transitionTest.delay);
|
||||
XCTAssert(toptions.duration && MGLTimeIntervalFromDuration(*toptions.duration) == transitionTest.duration);
|
||||
|
||||
MGLTransition heatmapIntensityTransition = layer.heatmapIntensityTransition;
|
||||
XCTAssertEqual(heatmapIntensityTransition.delay, transitionTest.delay);
|
||||
XCTAssertEqual(heatmapIntensityTransition.duration, transitionTest.duration);
|
||||
}
|
||||
|
||||
// heatmap-opacity
|
||||
{
|
||||
XCTAssertTrue(rawLayer->getHeatmapOpacity().isUndefined(),
|
||||
@"heatmap-opacity should be unset initially.");
|
||||
NSExpression *defaultExpression = layer.heatmapOpacity;
|
||||
|
||||
NSExpression *constantExpression = [NSExpression expressionWithFormat:@"0xff"];
|
||||
layer.heatmapOpacity = constantExpression;
|
||||
mbgl::style::PropertyValue<float> propertyValue = { 0xff };
|
||||
XCTAssertEqual(rawLayer->getHeatmapOpacity(), propertyValue,
|
||||
@"Setting heatmapOpacity to a constant value expression should update heatmap-opacity.");
|
||||
XCTAssertEqualObjects(layer.heatmapOpacity, constantExpression,
|
||||
@"heatmapOpacity should round-trip constant value expressions.");
|
||||
|
||||
constantExpression = [NSExpression expressionWithFormat:@"0xff"];
|
||||
NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
|
||||
layer.heatmapOpacity = functionExpression;
|
||||
|
||||
mbgl::style::IntervalStops<float> intervalStops = {{
|
||||
{ -INFINITY, 0xff },
|
||||
{ 18, 0xff },
|
||||
}};
|
||||
propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
|
||||
|
||||
XCTAssertEqual(rawLayer->getHeatmapOpacity(), propertyValue,
|
||||
@"Setting heatmapOpacity to a camera expression should update heatmap-opacity.");
|
||||
XCTAssertEqualObjects(layer.heatmapOpacity, functionExpression,
|
||||
@"heatmapOpacity should round-trip camera expressions.");
|
||||
|
||||
|
||||
|
||||
layer.heatmapOpacity = nil;
|
||||
XCTAssertTrue(rawLayer->getHeatmapOpacity().isUndefined(),
|
||||
@"Unsetting heatmapOpacity should return heatmap-opacity to the default value.");
|
||||
XCTAssertEqualObjects(layer.heatmapOpacity, defaultExpression,
|
||||
@"heatmapOpacity should return the default value after being unset.");
|
||||
|
||||
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
|
||||
XCTAssertThrowsSpecificNamed(layer.heatmapOpacity = functionExpression, NSException, NSInvalidArgumentException, @"MGLHeatmapLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
|
||||
functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
|
||||
functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
|
||||
XCTAssertThrowsSpecificNamed(layer.heatmapOpacity = functionExpression, NSException, NSInvalidArgumentException, @"MGLHeatmapLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
|
||||
// Transition property test
|
||||
layer.heatmapOpacityTransition = transitionTest;
|
||||
auto toptions = rawLayer->getHeatmapOpacityTransition();
|
||||
XCTAssert(toptions.delay && MGLTimeIntervalFromDuration(*toptions.delay) == transitionTest.delay);
|
||||
XCTAssert(toptions.duration && MGLTimeIntervalFromDuration(*toptions.duration) == transitionTest.duration);
|
||||
|
||||
MGLTransition heatmapOpacityTransition = layer.heatmapOpacityTransition;
|
||||
XCTAssertEqual(heatmapOpacityTransition.delay, transitionTest.delay);
|
||||
XCTAssertEqual(heatmapOpacityTransition.duration, transitionTest.duration);
|
||||
}
|
||||
|
||||
// heatmap-radius
|
||||
{
|
||||
XCTAssertTrue(rawLayer->getHeatmapRadius().isUndefined(),
|
||||
@"heatmap-radius should be unset initially.");
|
||||
NSExpression *defaultExpression = layer.heatmapRadius;
|
||||
|
||||
NSExpression *constantExpression = [NSExpression expressionWithFormat:@"0xff"];
|
||||
layer.heatmapRadius = constantExpression;
|
||||
mbgl::style::DataDrivenPropertyValue<float> propertyValue = { 0xff };
|
||||
XCTAssertEqual(rawLayer->getHeatmapRadius(), propertyValue,
|
||||
@"Setting heatmapRadius to a constant value expression should update heatmap-radius.");
|
||||
XCTAssertEqualObjects(layer.heatmapRadius, constantExpression,
|
||||
@"heatmapRadius should round-trip constant value expressions.");
|
||||
|
||||
constantExpression = [NSExpression expressionWithFormat:@"0xff"];
|
||||
NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
|
||||
layer.heatmapRadius = functionExpression;
|
||||
|
||||
mbgl::style::IntervalStops<float> intervalStops = {{
|
||||
{ -INFINITY, 0xff },
|
||||
{ 18, 0xff },
|
||||
}};
|
||||
propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
|
||||
|
||||
XCTAssertEqual(rawLayer->getHeatmapRadius(), propertyValue,
|
||||
@"Setting heatmapRadius to a camera expression should update heatmap-radius.");
|
||||
XCTAssertEqualObjects(layer.heatmapRadius, functionExpression,
|
||||
@"heatmapRadius should round-trip camera expressions.");
|
||||
|
||||
functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(keyName, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@18: constantExpression}];
|
||||
layer.heatmapRadius = functionExpression;
|
||||
|
||||
mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
|
||||
propertyValue = mbgl::style::SourceFunction<float> { "keyName", exponentialStops };
|
||||
|
||||
XCTAssertEqual(rawLayer->getHeatmapRadius(), propertyValue,
|
||||
@"Setting heatmapRadius to a data expression should update heatmap-radius.");
|
||||
XCTAssertEqualObjects(layer.heatmapRadius, functionExpression,
|
||||
@"heatmapRadius should round-trip data expressions.");
|
||||
|
||||
functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
|
||||
layer.heatmapRadius = functionExpression;
|
||||
|
||||
std::map<float, float> innerStops { {18, 0xff} };
|
||||
mbgl::style::CompositeExponentialStops<float> compositeStops { { {10.0, innerStops} }, 1.0 };
|
||||
|
||||
propertyValue = mbgl::style::CompositeFunction<float> { "keyName", compositeStops };
|
||||
|
||||
XCTAssertEqual(rawLayer->getHeatmapRadius(), propertyValue,
|
||||
@"Setting heatmapRadius to a camera-data expression should update heatmap-radius.");
|
||||
XCTAssertEqualObjects(layer.heatmapRadius, functionExpression,
|
||||
@"heatmapRadius should round-trip camera-data expressions.");
|
||||
|
||||
|
||||
layer.heatmapRadius = nil;
|
||||
XCTAssertTrue(rawLayer->getHeatmapRadius().isUndefined(),
|
||||
@"Unsetting heatmapRadius should return heatmap-radius to the default value.");
|
||||
XCTAssertEqualObjects(layer.heatmapRadius, defaultExpression,
|
||||
@"heatmapRadius should return the default value after being unset.");
|
||||
// Transition property test
|
||||
layer.heatmapRadiusTransition = transitionTest;
|
||||
auto toptions = rawLayer->getHeatmapRadiusTransition();
|
||||
XCTAssert(toptions.delay && MGLTimeIntervalFromDuration(*toptions.delay) == transitionTest.delay);
|
||||
XCTAssert(toptions.duration && MGLTimeIntervalFromDuration(*toptions.duration) == transitionTest.duration);
|
||||
|
||||
MGLTransition heatmapRadiusTransition = layer.heatmapRadiusTransition;
|
||||
XCTAssertEqual(heatmapRadiusTransition.delay, transitionTest.delay);
|
||||
XCTAssertEqual(heatmapRadiusTransition.duration, transitionTest.duration);
|
||||
}
|
||||
|
||||
// heatmap-weight
|
||||
{
|
||||
XCTAssertTrue(rawLayer->getHeatmapWeight().isUndefined(),
|
||||
@"heatmap-weight should be unset initially.");
|
||||
NSExpression *defaultExpression = layer.heatmapWeight;
|
||||
|
||||
NSExpression *constantExpression = [NSExpression expressionWithFormat:@"0xff"];
|
||||
layer.heatmapWeight = constantExpression;
|
||||
mbgl::style::DataDrivenPropertyValue<float> propertyValue = { 0xff };
|
||||
XCTAssertEqual(rawLayer->getHeatmapWeight(), propertyValue,
|
||||
@"Setting heatmapWeight to a constant value expression should update heatmap-weight.");
|
||||
XCTAssertEqualObjects(layer.heatmapWeight, constantExpression,
|
||||
@"heatmapWeight should round-trip constant value expressions.");
|
||||
|
||||
constantExpression = [NSExpression expressionWithFormat:@"0xff"];
|
||||
NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
|
||||
layer.heatmapWeight = functionExpression;
|
||||
|
||||
mbgl::style::IntervalStops<float> intervalStops = {{
|
||||
{ -INFINITY, 0xff },
|
||||
{ 18, 0xff },
|
||||
}};
|
||||
propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
|
||||
|
||||
XCTAssertEqual(rawLayer->getHeatmapWeight(), propertyValue,
|
||||
@"Setting heatmapWeight to a camera expression should update heatmap-weight.");
|
||||
XCTAssertEqualObjects(layer.heatmapWeight, functionExpression,
|
||||
@"heatmapWeight should round-trip camera expressions.");
|
||||
|
||||
functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(keyName, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@18: constantExpression}];
|
||||
layer.heatmapWeight = functionExpression;
|
||||
|
||||
mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
|
||||
propertyValue = mbgl::style::SourceFunction<float> { "keyName", exponentialStops };
|
||||
|
||||
XCTAssertEqual(rawLayer->getHeatmapWeight(), propertyValue,
|
||||
@"Setting heatmapWeight to a data expression should update heatmap-weight.");
|
||||
XCTAssertEqualObjects(layer.heatmapWeight, functionExpression,
|
||||
@"heatmapWeight should round-trip data expressions.");
|
||||
|
||||
functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
|
||||
layer.heatmapWeight = functionExpression;
|
||||
|
||||
std::map<float, float> innerStops { {18, 0xff} };
|
||||
mbgl::style::CompositeExponentialStops<float> compositeStops { { {10.0, innerStops} }, 1.0 };
|
||||
|
||||
propertyValue = mbgl::style::CompositeFunction<float> { "keyName", compositeStops };
|
||||
|
||||
XCTAssertEqual(rawLayer->getHeatmapWeight(), propertyValue,
|
||||
@"Setting heatmapWeight to a camera-data expression should update heatmap-weight.");
|
||||
XCTAssertEqualObjects(layer.heatmapWeight, functionExpression,
|
||||
@"heatmapWeight should round-trip camera-data expressions.");
|
||||
|
||||
|
||||
layer.heatmapWeight = nil;
|
||||
XCTAssertTrue(rawLayer->getHeatmapWeight().isUndefined(),
|
||||
@"Unsetting heatmapWeight should return heatmap-weight to the default value.");
|
||||
XCTAssertEqualObjects(layer.heatmapWeight, defaultExpression,
|
||||
@"heatmapWeight should return the default value after being unset.");
|
||||
}
|
||||
}
|
||||
|
||||
- (void)testPropertyNames {
|
||||
[self testPropertyName:@"heatmap-intensity" isBoolean:NO];
|
||||
[self testPropertyName:@"heatmap-opacity" isBoolean:NO];
|
||||
[self testPropertyName:@"heatmap-radius" isBoolean:NO];
|
||||
[self testPropertyName:@"heatmap-weight" isBoolean:NO];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -59,6 +59,7 @@
|
||||
MGLTransition transitionTest = MGLTransitionMake(5, 4);
|
||||
|
||||
<% for (const property of properties) { -%>
|
||||
<% if (property.name === 'heatmap-color') continue; -%>
|
||||
|
||||
// <%- originalPropertyName(property) %>
|
||||
{
|
||||
@@ -151,6 +152,7 @@
|
||||
|
||||
- (void)testPropertyNames {
|
||||
<% for (const property of properties) { -%>
|
||||
<% if (property.name === 'heatmap-color') continue; -%>
|
||||
[self testPropertyName:@"<%- property.getter || property.name %>" isBoolean:<%- property.type === 'boolean' ? 'YES' : 'NO' %>];
|
||||
<% } -%>
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT
|
||||
|
||||
### Styles and rendering
|
||||
|
||||
* Added support for a new layer type: `MGLHeatmapStyleLayer`, a powerful way to visualize point data distributions using heatmaps, fully customizable through runtime styling. [#11046](https://github.com/mapbox/mapbox-gl-native/pull/11046)
|
||||
* The layout and paint properties on subclasses of `MGLStyleLayer` are now of type `NSExpression` instead of `MGLStyleValue`. A new “Predicates and Expressions” guide provides an overview of the supported operators. ([#10726](https://github.com/mapbox/mapbox-gl-native/pull/10726))
|
||||
* Added an `MGLComputedShapeSource` class that allows applications to supply vector data to a style layer on a per-tile basis. ([#9983](https://github.com/mapbox/mapbox-gl-native/pull/9983))
|
||||
* A style can now display smooth hillshading and customize its appearance at runtime using the `MGLHillshadeStyleLayer` class. Hillshading is based on a rasterized digital elevation model supplied by the `MGLRasterDEMSource` class. ([#10642](https://github.com/mapbox/mapbox-gl-native/pull/10642))
|
||||
|
||||
@@ -192,6 +192,7 @@ In style JSON | In the SDK
|
||||
`circle` | `MGLCircleStyleLayer`
|
||||
`fill` | `MGLFillStyleLayer`
|
||||
`fill-extrusion` | `MGLFillExtrusionStyleLayer`
|
||||
`heatmap` | `MGLHeatmapStyleLayer`
|
||||
`hillshade` | `MGLHillshadeStyleLayer`
|
||||
`line` | `MGLLineStyleLayer`
|
||||
`raster` | `MGLRasterStyleLayer`
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
16376B471FFDB92B0000563E /* one-liner.json in Resources */ = {isa = PBXBuildFile; fileRef = DA35D0871E1A6309007DED41 /* one-liner.json */; };
|
||||
16376B491FFEED010000563E /* MGLMapViewLayoutTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 16376B481FFEED010000563E /* MGLMapViewLayoutTests.m */; };
|
||||
165D0CE720005419009A3C66 /* Mapbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA8847D21CBAF91600AB86E3 /* Mapbox.framework */; };
|
||||
170C437C2029D96F00863DF0 /* MGLHeatmapColorTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 170C43782028D49800863DF0 /* MGLHeatmapColorTests.mm */; };
|
||||
170C437D2029D97900863DF0 /* MGLHeatmapStyleLayerTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 170C43792028D49800863DF0 /* MGLHeatmapStyleLayerTests.mm */; };
|
||||
1753ED421E53CE6F00A9FD90 /* MGLConversion.h in Headers */ = {isa = PBXBuildFile; fileRef = 1753ED411E53CE6F00A9FD90 /* MGLConversion.h */; };
|
||||
1753ED431E53CE6F00A9FD90 /* MGLConversion.h in Headers */ = {isa = PBXBuildFile; fileRef = 1753ED411E53CE6F00A9FD90 /* MGLConversion.h */; };
|
||||
1F06668A1EC64F8E001C16D7 /* MGLLight.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F0666881EC64F8E001C16D7 /* MGLLight.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
@@ -226,6 +228,10 @@
|
||||
55E2AD131E5B125400E8C587 /* MGLOfflineStorageTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 55E2AD121E5B125400E8C587 /* MGLOfflineStorageTests.mm */; };
|
||||
632281DF1E6F855900D75A5D /* MBXEmbeddedMapViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 632281DE1E6F855900D75A5D /* MBXEmbeddedMapViewController.m */; };
|
||||
6407D6701E0085FD00F6A9C3 /* MGLDocumentationExampleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6407D66F1E0085FD00F6A9C3 /* MGLDocumentationExampleTests.swift */; };
|
||||
8989B17C201A48EB0081CF59 /* MGLHeatmapStyleLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 8989B17A201A48EA0081CF59 /* MGLHeatmapStyleLayer.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
8989B17D201A48EB0081CF59 /* MGLHeatmapStyleLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 8989B17A201A48EA0081CF59 /* MGLHeatmapStyleLayer.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
8989B17E201A48EB0081CF59 /* MGLHeatmapStyleLayer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8989B17B201A48EA0081CF59 /* MGLHeatmapStyleLayer.mm */; };
|
||||
8989B17F201A48EB0081CF59 /* MGLHeatmapStyleLayer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8989B17B201A48EA0081CF59 /* MGLHeatmapStyleLayer.mm */; };
|
||||
920A3E5D1E6F995200C16EFC /* MGLSourceQueryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 920A3E5C1E6F995200C16EFC /* MGLSourceQueryTests.m */; };
|
||||
927FBCFC1F4DAA8300F8BF1F /* MBXSnapshotsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 927FBCFB1F4DAA8300F8BF1F /* MBXSnapshotsViewController.m */; };
|
||||
927FBCFF1F4DB05500F8BF1F /* MGLMapSnapshotter.h in Headers */ = {isa = PBXBuildFile; fileRef = 927FBCFD1F4DB05500F8BF1F /* MGLMapSnapshotter.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
@@ -670,6 +676,8 @@
|
||||
16376B3F1FFDB4B40000563E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
16376B401FFDB4B40000563E /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
|
||||
16376B481FFEED010000563E /* MGLMapViewLayoutTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MGLMapViewLayoutTests.m; sourceTree = "<group>"; };
|
||||
170C43782028D49800863DF0 /* MGLHeatmapColorTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLHeatmapColorTests.mm; path = ../../darwin/test/MGLHeatmapColorTests.mm; sourceTree = "<group>"; };
|
||||
170C43792028D49800863DF0 /* MGLHeatmapStyleLayerTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLHeatmapStyleLayerTests.mm; path = ../../darwin/test/MGLHeatmapStyleLayerTests.mm; sourceTree = "<group>"; };
|
||||
1753ED411E53CE6F00A9FD90 /* MGLConversion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLConversion.h; sourceTree = "<group>"; };
|
||||
1F0666881EC64F8E001C16D7 /* MGLLight.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLLight.h; sourceTree = "<group>"; };
|
||||
1F0666891EC64F8E001C16D7 /* MGLLight.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLLight.mm; sourceTree = "<group>"; };
|
||||
@@ -801,6 +809,8 @@
|
||||
632281DD1E6F855900D75A5D /* MBXEmbeddedMapViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MBXEmbeddedMapViewController.h; sourceTree = "<group>"; };
|
||||
632281DE1E6F855900D75A5D /* MBXEmbeddedMapViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MBXEmbeddedMapViewController.m; sourceTree = "<group>"; };
|
||||
6407D66F1E0085FD00F6A9C3 /* MGLDocumentationExampleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MGLDocumentationExampleTests.swift; path = ../../darwin/test/MGLDocumentationExampleTests.swift; sourceTree = "<group>"; };
|
||||
8989B17A201A48EA0081CF59 /* MGLHeatmapStyleLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLHeatmapStyleLayer.h; sourceTree = "<group>"; };
|
||||
8989B17B201A48EA0081CF59 /* MGLHeatmapStyleLayer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLHeatmapStyleLayer.mm; sourceTree = "<group>"; };
|
||||
920A3E5C1E6F995200C16EFC /* MGLSourceQueryTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MGLSourceQueryTests.m; path = ../../darwin/test/MGLSourceQueryTests.m; sourceTree = "<group>"; };
|
||||
927FBCFA1F4DAA8300F8BF1F /* MBXSnapshotsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MBXSnapshotsViewController.h; sourceTree = "<group>"; };
|
||||
927FBCFB1F4DAA8300F8BF1F /* MBXSnapshotsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MBXSnapshotsViewController.m; sourceTree = "<group>"; };
|
||||
@@ -1236,6 +1246,8 @@
|
||||
FA68F1481E9D656600F9F6C2 /* MGLFillExtrusionStyleLayer.h */,
|
||||
FA68F1491E9D656600F9F6C2 /* MGLFillExtrusionStyleLayer.mm */,
|
||||
35D13AC11D3D19DD00AFB4E0 /* MGLFillStyleLayer.h */,
|
||||
8989B17A201A48EA0081CF59 /* MGLHeatmapStyleLayer.h */,
|
||||
8989B17B201A48EA0081CF59 /* MGLHeatmapStyleLayer.mm */,
|
||||
35D13AC21D3D19DD00AFB4E0 /* MGLFillStyleLayer.mm */,
|
||||
3538AA1B1D542239008EC33D /* MGLForegroundStyleLayer.h */,
|
||||
3538AA1C1D542239008EC33D /* MGLForegroundStyleLayer.mm */,
|
||||
@@ -1306,6 +1318,8 @@
|
||||
3575798F1D513EF1000B822E /* Layers */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
170C43782028D49800863DF0 /* MGLHeatmapColorTests.mm */,
|
||||
170C43792028D49800863DF0 /* MGLHeatmapStyleLayerTests.mm */,
|
||||
DA2DBBCC1D51E80400D38FF9 /* MGLStyleLayerTests.h */,
|
||||
DA2DBBCD1D51E80400D38FF9 /* MGLStyleLayerTests.m */,
|
||||
DA3C6FF21E2859E700F962BE /* test-Bridging-Header.h */,
|
||||
@@ -1967,6 +1981,7 @@
|
||||
DA8847F91CBAFA5100AB86E3 /* MGLPolygon.h in Headers */,
|
||||
4049C2AC1DB6E05500B3F799 /* MGLPointCollection_Private.h in Headers */,
|
||||
DA8847F81CBAFA5100AB86E3 /* MGLPointAnnotation.h in Headers */,
|
||||
8989B17C201A48EB0081CF59 /* MGLHeatmapStyleLayer.h in Headers */,
|
||||
353933F21D3FB753003F57D7 /* MGLCircleStyleLayer.h in Headers */,
|
||||
DA8847F31CBAFA5100AB86E3 /* MGLMultiPoint.h in Headers */,
|
||||
30E578171DAA85520050F07E /* UIImage+MGLAdditions.h in Headers */,
|
||||
@@ -2104,6 +2119,7 @@
|
||||
DABFB8631CBE99E500D62B32 /* MGLOfflineRegion.h in Headers */,
|
||||
DA35A2B21CCA141D00E826B2 /* MGLCompassDirectionFormatter.h in Headers */,
|
||||
DAF0D8141DFE0EC500B28378 /* MGLVectorSource_Private.h in Headers */,
|
||||
8989B17D201A48EB0081CF59 /* MGLHeatmapStyleLayer.h in Headers */,
|
||||
DABFB8731CBE9A9900D62B32 /* Mapbox.h in Headers */,
|
||||
357FE2DE1E02D2B20068B753 /* NSCoder+MGLAdditions.h in Headers */,
|
||||
1753ED431E53CE6F00A9FD90 /* MGLConversion.h in Headers */,
|
||||
@@ -2548,6 +2564,8 @@
|
||||
409F43FD1E9E781C0048729D /* MGLMapViewDelegateIntegrationTests.swift in Sources */,
|
||||
DA2E88651CC0382C00F24E7B /* MGLStyleTests.mm in Sources */,
|
||||
DA2E88611CC0382C00F24E7B /* MGLGeometryTests.mm in Sources */,
|
||||
170C437D2029D97900863DF0 /* MGLHeatmapStyleLayerTests.mm in Sources */,
|
||||
170C437C2029D96F00863DF0 /* MGLHeatmapColorTests.mm in Sources */,
|
||||
357579801D501E09000B822E /* MGLFillStyleLayerTests.mm in Sources */,
|
||||
35D9DDE21DA25EEC00DAAD69 /* MGLCodingTests.m in Sources */,
|
||||
DA1F8F3D1EBD287B00367E42 /* MGLDocumentationGuideTests.swift in Sources */,
|
||||
@@ -2660,6 +2678,7 @@
|
||||
35B82BFA1D6C5F8400B1B721 /* NSPredicate+MGLAdditions.mm in Sources */,
|
||||
DA8848521CBAFB9800AB86E3 /* MGLAPIClient.m in Sources */,
|
||||
966FCF4E1F3A5C9200F2B6DE /* MGLUserLocationHeadingBeamLayer.m in Sources */,
|
||||
8989B17E201A48EB0081CF59 /* MGLHeatmapStyleLayer.mm in Sources */,
|
||||
DA8848301CBAFA6200AB86E3 /* NSProcessInfo+MGLAdditions.m in Sources */,
|
||||
353AFA161D65AB17005A69F4 /* NSDate+MGLAdditions.mm in Sources */,
|
||||
35D13AC51D3D19DD00AFB4E0 /* MGLFillStyleLayer.mm in Sources */,
|
||||
@@ -2752,6 +2771,7 @@
|
||||
DAA4E4311CBB730400178DFB /* MGLMapboxEvents.m in Sources */,
|
||||
966FCF4F1F3A5C9200F2B6DE /* MGLUserLocationHeadingBeamLayer.m in Sources */,
|
||||
DAA4E4231CBB730400178DFB /* MGLPolygon.mm in Sources */,
|
||||
8989B17F201A48EB0081CF59 /* MGLHeatmapStyleLayer.mm in Sources */,
|
||||
353AFA171D65AB17005A69F4 /* NSDate+MGLAdditions.mm in Sources */,
|
||||
35D13AC61D3D19DD00AFB4E0 /* MGLFillStyleLayer.mm in Sources */,
|
||||
DAA4E42A1CBB730400178DFB /* NSProcessInfo+MGLAdditions.m in Sources */,
|
||||
|
||||
@@ -95,6 +95,7 @@ custom_categories:
|
||||
- MGLCircleStyleLayer
|
||||
- MGLFillStyleLayer
|
||||
- MGLFillExtrusionStyleLayer
|
||||
- MGLHeatmapStyleLayer
|
||||
- MGLHillshadeStyleLayer
|
||||
- MGLLineStyleLayer
|
||||
- MGLSymbolStyleLayer
|
||||
|
||||
@@ -45,6 +45,7 @@ FOUNDATION_EXPORT MGL_EXPORT const unsigned char MapboxVersionString[];
|
||||
#import "MGLSymbolStyleLayer.h"
|
||||
#import "MGLRasterStyleLayer.h"
|
||||
#import "MGLCircleStyleLayer.h"
|
||||
#import "MGLHeatmapStyleLayer.h"
|
||||
#import "MGLHillshadeStyleLayer.h"
|
||||
#import "MGLBackgroundStyleLayer.h"
|
||||
#import "MGLOpenGLStyleLayer.h"
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
### Styles and rendering
|
||||
|
||||
* Added support for a new layer type: `MGLHeatmapStyleLayer`, a powerful way to visualize point data distributions using heatmaps, fully customizable through runtime styling. [#11046](https://github.com/mapbox/mapbox-gl-native/pull/11046)
|
||||
* The layout and paint properties on subclasses of `MGLStyleLayer` are now of type `NSExpression` instead of `MGLStyleValue`. A new “Predicates and Expressions” guide provides an overview of the supported operators. ([#10726](https://github.com/mapbox/mapbox-gl-native/pull/10726))
|
||||
* Added an `MGLComputedShapeSource` class that allows applications to supply vector data to a style layer on a per-tile basis. ([#9983](https://github.com/mapbox/mapbox-gl-native/pull/9983))
|
||||
* A style can now display smooth hillshading and customize its appearance at runtime using the `MGLHillshadeStyleLayer` class. Hillshading is based on a rasterized digital elevation model supplied by the `MGLRasterDEMSource` class. ([#10642](https://github.com/mapbox/mapbox-gl-native/pull/10642))
|
||||
|
||||
16
platform/macos/app/Assets.xcassets/Layers/heatmap.imageset/Contents.json
vendored
Normal file
16
platform/macos/app/Assets.xcassets/Layers/heatmap.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "heatmap.pdf",
|
||||
"language-direction" : "left-to-right"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
},
|
||||
"properties" : {
|
||||
"template-rendering-intent" : "template"
|
||||
}
|
||||
}
|
||||
BIN
platform/macos/app/Assets.xcassets/Layers/heatmap.imageset/heatmap.pdf
vendored
Normal file
BIN
platform/macos/app/Assets.xcassets/Layers/heatmap.imageset/heatmap.pdf
vendored
Normal file
Binary file not shown.
@@ -31,6 +31,9 @@
|
||||
if ([layer isKindOfClass:[MGLSymbolStyleLayer class]]) {
|
||||
return [NSImage imageNamed:@"symbol"];
|
||||
}
|
||||
if ([layer isKindOfClass:[MGLHeatmapStyleLayer class]]) {
|
||||
return [NSImage imageNamed:@"heatmap"];
|
||||
}
|
||||
if ([layer isKindOfClass:[MGLHillshadeStyleLayer class]]) {
|
||||
return [NSImage imageNamed:@"hillshade"];
|
||||
}
|
||||
|
||||
809
platform/macos/app/heatmap.json
Normal file
809
platform/macos/app/heatmap.json
Normal file
@@ -0,0 +1,809 @@
|
||||
{
|
||||
"version": 8,
|
||||
"name": "Basic Heatmap",
|
||||
"center": [
|
||||
30.49860107152665,
|
||||
50.459868549177486
|
||||
],
|
||||
"zoom": 14.033276876197775,
|
||||
"bearing": 0,
|
||||
"pitch": 0,
|
||||
"sources": {
|
||||
"mapbox": {
|
||||
"url": "mapbox://mapbox.mapbox-streets-v7",
|
||||
"type": "vector"
|
||||
}
|
||||
},
|
||||
"sprite": "mapbox://sprites/mourner/cjcgg2bl16cf42snvcbbaf09z",
|
||||
"glyphs": "mapbox://fonts/mourner/{fontstack}/{range}.pbf",
|
||||
"layers": [
|
||||
{
|
||||
"id": "background",
|
||||
"type": "background",
|
||||
"paint": {
|
||||
"background-color": "#dedede"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "landuse_overlay_national_park",
|
||||
"type": "fill",
|
||||
"source": "mapbox",
|
||||
"source-layer": "landuse_overlay",
|
||||
"filter": [
|
||||
"==",
|
||||
"class",
|
||||
"national_park"
|
||||
],
|
||||
"paint": {
|
||||
"fill-color": "#d2edae",
|
||||
"fill-opacity": 0.75
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "landuse_park",
|
||||
"type": "fill",
|
||||
"source": "mapbox",
|
||||
"source-layer": "landuse",
|
||||
"filter": [
|
||||
"==",
|
||||
"class",
|
||||
"park"
|
||||
],
|
||||
"paint": {
|
||||
"fill-color": "#d2edae"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "waterway",
|
||||
"type": "line",
|
||||
"source": "mapbox",
|
||||
"source-layer": "waterway",
|
||||
"filter": [
|
||||
"all",
|
||||
[
|
||||
"==",
|
||||
"$type",
|
||||
"LineString"
|
||||
],
|
||||
[
|
||||
"in",
|
||||
"class",
|
||||
"canal",
|
||||
"river"
|
||||
]
|
||||
],
|
||||
"paint": {
|
||||
"line-color": "#a0cfdf",
|
||||
"line-width": {
|
||||
"base": 1.4,
|
||||
"stops": [
|
||||
[
|
||||
8,
|
||||
0.5
|
||||
],
|
||||
[
|
||||
20,
|
||||
15
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "water",
|
||||
"type": "fill",
|
||||
"source": "mapbox",
|
||||
"source-layer": "water",
|
||||
"paint": {
|
||||
"fill-color": "#a0cfdf"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "building",
|
||||
"type": "fill",
|
||||
"source": "mapbox",
|
||||
"source-layer": "building",
|
||||
"paint": {
|
||||
"fill-color": "#d6d6d6"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "tunnel_minor",
|
||||
"type": "line",
|
||||
"source": "mapbox",
|
||||
"source-layer": "road",
|
||||
"filter": [
|
||||
"all",
|
||||
[
|
||||
"==",
|
||||
"$type",
|
||||
"LineString"
|
||||
],
|
||||
[
|
||||
"all",
|
||||
[
|
||||
"==",
|
||||
"structure",
|
||||
"tunnel"
|
||||
],
|
||||
[
|
||||
"in",
|
||||
"class",
|
||||
"link",
|
||||
"motorway_link",
|
||||
"path",
|
||||
"pedestrian",
|
||||
"service",
|
||||
"street",
|
||||
"street_limited",
|
||||
"track"
|
||||
]
|
||||
]
|
||||
],
|
||||
"layout": {
|
||||
"line-cap": "butt",
|
||||
"line-join": "miter"
|
||||
},
|
||||
"paint": {
|
||||
"line-color": "#efefef",
|
||||
"line-width": {
|
||||
"base": 1.55,
|
||||
"stops": [
|
||||
[
|
||||
4,
|
||||
0.25
|
||||
],
|
||||
[
|
||||
20,
|
||||
30
|
||||
]
|
||||
]
|
||||
},
|
||||
"line-dasharray": [
|
||||
0.36,
|
||||
0.18
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "tunnel_major",
|
||||
"type": "line",
|
||||
"source": "mapbox",
|
||||
"source-layer": "road",
|
||||
"filter": [
|
||||
"all",
|
||||
[
|
||||
"==",
|
||||
"$type",
|
||||
"LineString"
|
||||
],
|
||||
[
|
||||
"all",
|
||||
[
|
||||
"==",
|
||||
"structure",
|
||||
"tunnel"
|
||||
],
|
||||
[
|
||||
"in",
|
||||
"class",
|
||||
"motorway",
|
||||
"primary",
|
||||
"secondary",
|
||||
"tertiary",
|
||||
"trunk"
|
||||
]
|
||||
]
|
||||
],
|
||||
"layout": {
|
||||
"line-cap": "butt",
|
||||
"line-join": "miter"
|
||||
},
|
||||
"paint": {
|
||||
"line-color": "#fff",
|
||||
"line-width": {
|
||||
"base": 1.4,
|
||||
"stops": [
|
||||
[
|
||||
6,
|
||||
0.5
|
||||
],
|
||||
[
|
||||
20,
|
||||
30
|
||||
]
|
||||
]
|
||||
},
|
||||
"line-dasharray": [
|
||||
0.28,
|
||||
0.14
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "road_minor",
|
||||
"type": "line",
|
||||
"source": "mapbox",
|
||||
"source-layer": "road",
|
||||
"filter": [
|
||||
"all",
|
||||
[
|
||||
"==",
|
||||
"$type",
|
||||
"LineString"
|
||||
],
|
||||
[
|
||||
"all",
|
||||
[
|
||||
"in",
|
||||
"class",
|
||||
"link",
|
||||
"motorway_link",
|
||||
"path",
|
||||
"pedestrian",
|
||||
"service",
|
||||
"street",
|
||||
"street_limited",
|
||||
"track"
|
||||
],
|
||||
[
|
||||
"in",
|
||||
"structure",
|
||||
"ford",
|
||||
"none"
|
||||
]
|
||||
]
|
||||
],
|
||||
"layout": {
|
||||
"line-cap": "round",
|
||||
"line-join": "round"
|
||||
},
|
||||
"paint": {
|
||||
"line-color": "#efefef",
|
||||
"line-width": {
|
||||
"base": 1.55,
|
||||
"stops": [
|
||||
[
|
||||
4,
|
||||
0.25
|
||||
],
|
||||
[
|
||||
20,
|
||||
30
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "road_major",
|
||||
"type": "line",
|
||||
"source": "mapbox",
|
||||
"source-layer": "road",
|
||||
"filter": [
|
||||
"all",
|
||||
[
|
||||
"==",
|
||||
"$type",
|
||||
"LineString"
|
||||
],
|
||||
[
|
||||
"all",
|
||||
[
|
||||
"in",
|
||||
"class",
|
||||
"motorway",
|
||||
"primary",
|
||||
"secondary",
|
||||
"tertiary",
|
||||
"trunk"
|
||||
],
|
||||
[
|
||||
"in",
|
||||
"structure",
|
||||
"ford",
|
||||
"none"
|
||||
]
|
||||
]
|
||||
],
|
||||
"layout": {
|
||||
"line-cap": "round",
|
||||
"line-join": "round"
|
||||
},
|
||||
"paint": {
|
||||
"line-color": "#fff",
|
||||
"line-width": {
|
||||
"base": 1.4,
|
||||
"stops": [
|
||||
[
|
||||
6,
|
||||
0.5
|
||||
],
|
||||
[
|
||||
20,
|
||||
30
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "bridge_minor case",
|
||||
"type": "line",
|
||||
"source": "mapbox",
|
||||
"source-layer": "road",
|
||||
"filter": [
|
||||
"all",
|
||||
[
|
||||
"==",
|
||||
"$type",
|
||||
"LineString"
|
||||
],
|
||||
[
|
||||
"all",
|
||||
[
|
||||
"==",
|
||||
"structure",
|
||||
"bridge"
|
||||
],
|
||||
[
|
||||
"in",
|
||||
"class",
|
||||
"link",
|
||||
"motorway_link",
|
||||
"path",
|
||||
"pedestrian",
|
||||
"service",
|
||||
"street",
|
||||
"street_limited",
|
||||
"track"
|
||||
]
|
||||
]
|
||||
],
|
||||
"layout": {
|
||||
"line-cap": "butt",
|
||||
"line-join": "miter"
|
||||
},
|
||||
"paint": {
|
||||
"line-color": "#dedede",
|
||||
"line-width": {
|
||||
"base": 1.6,
|
||||
"stops": [
|
||||
[
|
||||
12,
|
||||
0.5
|
||||
],
|
||||
[
|
||||
20,
|
||||
10
|
||||
]
|
||||
]
|
||||
},
|
||||
"line-gap-width": {
|
||||
"base": 1.55,
|
||||
"stops": [
|
||||
[
|
||||
4,
|
||||
0.25
|
||||
],
|
||||
[
|
||||
20,
|
||||
30
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "bridge_major case",
|
||||
"type": "line",
|
||||
"source": "mapbox",
|
||||
"source-layer": "road",
|
||||
"filter": [
|
||||
"all",
|
||||
[
|
||||
"==",
|
||||
"$type",
|
||||
"LineString"
|
||||
],
|
||||
[
|
||||
"all",
|
||||
[
|
||||
"==",
|
||||
"structure",
|
||||
"bridge"
|
||||
],
|
||||
[
|
||||
"in",
|
||||
"class",
|
||||
"motorway",
|
||||
"primary",
|
||||
"secondary",
|
||||
"tertiary",
|
||||
"trunk"
|
||||
]
|
||||
]
|
||||
],
|
||||
"layout": {
|
||||
"line-cap": "butt",
|
||||
"line-join": "miter"
|
||||
},
|
||||
"paint": {
|
||||
"line-color": "#dedede",
|
||||
"line-width": {
|
||||
"base": 1.6,
|
||||
"stops": [
|
||||
[
|
||||
12,
|
||||
0.5
|
||||
],
|
||||
[
|
||||
20,
|
||||
10
|
||||
]
|
||||
]
|
||||
},
|
||||
"line-gap-width": {
|
||||
"base": 1.55,
|
||||
"stops": [
|
||||
[
|
||||
4,
|
||||
0.25
|
||||
],
|
||||
[
|
||||
20,
|
||||
30
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "bridge_minor",
|
||||
"type": "line",
|
||||
"source": "mapbox",
|
||||
"source-layer": "road",
|
||||
"filter": [
|
||||
"all",
|
||||
[
|
||||
"==",
|
||||
"$type",
|
||||
"LineString"
|
||||
],
|
||||
[
|
||||
"all",
|
||||
[
|
||||
"==",
|
||||
"structure",
|
||||
"bridge"
|
||||
],
|
||||
[
|
||||
"in",
|
||||
"class",
|
||||
"link",
|
||||
"motorway_link",
|
||||
"path",
|
||||
"pedestrian",
|
||||
"service",
|
||||
"street",
|
||||
"street_limited",
|
||||
"track"
|
||||
]
|
||||
]
|
||||
],
|
||||
"layout": {
|
||||
"line-cap": "round",
|
||||
"line-join": "round"
|
||||
},
|
||||
"paint": {
|
||||
"line-color": "#efefef",
|
||||
"line-width": {
|
||||
"base": 1.55,
|
||||
"stops": [
|
||||
[
|
||||
4,
|
||||
0.25
|
||||
],
|
||||
[
|
||||
20,
|
||||
30
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "bridge_major",
|
||||
"type": "line",
|
||||
"source": "mapbox",
|
||||
"source-layer": "road",
|
||||
"filter": [
|
||||
"all",
|
||||
[
|
||||
"==",
|
||||
"$type",
|
||||
"LineString"
|
||||
],
|
||||
[
|
||||
"all",
|
||||
[
|
||||
"==",
|
||||
"structure",
|
||||
"bridge"
|
||||
],
|
||||
[
|
||||
"in",
|
||||
"class",
|
||||
"motorway",
|
||||
"primary",
|
||||
"secondary",
|
||||
"tertiary",
|
||||
"trunk"
|
||||
]
|
||||
]
|
||||
],
|
||||
"layout": {
|
||||
"line-cap": "round",
|
||||
"line-join": "round"
|
||||
},
|
||||
"paint": {
|
||||
"line-color": "#fff",
|
||||
"line-width": {
|
||||
"base": 1.4,
|
||||
"stops": [
|
||||
[
|
||||
6,
|
||||
0.5
|
||||
],
|
||||
[
|
||||
20,
|
||||
30
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "admin_country",
|
||||
"type": "line",
|
||||
"source": "mapbox",
|
||||
"source-layer": "admin",
|
||||
"filter": [
|
||||
"all",
|
||||
[
|
||||
"==",
|
||||
"$type",
|
||||
"LineString"
|
||||
],
|
||||
[
|
||||
"all",
|
||||
[
|
||||
"<=",
|
||||
"admin_level",
|
||||
2
|
||||
],
|
||||
[
|
||||
"==",
|
||||
"maritime",
|
||||
0
|
||||
]
|
||||
]
|
||||
],
|
||||
"layout": {
|
||||
"line-cap": "round",
|
||||
"line-join": "round"
|
||||
},
|
||||
"paint": {
|
||||
"line-color": "#8b8a8a",
|
||||
"line-width": {
|
||||
"base": 1.3,
|
||||
"stops": [
|
||||
[
|
||||
3,
|
||||
0.5
|
||||
],
|
||||
[
|
||||
22,
|
||||
15
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "road_major_label",
|
||||
"type": "symbol",
|
||||
"source": "mapbox",
|
||||
"source-layer": "road_label",
|
||||
"filter": [
|
||||
"all",
|
||||
[
|
||||
"==",
|
||||
"$type",
|
||||
"LineString"
|
||||
],
|
||||
[
|
||||
"in",
|
||||
"class",
|
||||
"motorway",
|
||||
"primary",
|
||||
"secondary",
|
||||
"tertiary",
|
||||
"trunk"
|
||||
]
|
||||
],
|
||||
"layout": {
|
||||
"symbol-placement": "line",
|
||||
"text-field": "{name_en}",
|
||||
"text-font": [
|
||||
"Open Sans Semibold",
|
||||
"Arial Unicode MS Bold"
|
||||
],
|
||||
"text-transform": "uppercase",
|
||||
"text-letter-spacing": 0.1,
|
||||
"text-size": {
|
||||
"base": 1.4,
|
||||
"stops": [
|
||||
[
|
||||
10,
|
||||
8
|
||||
],
|
||||
[
|
||||
20,
|
||||
14
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"paint": {
|
||||
"text-color": "#666",
|
||||
"text-halo-color": "rgba(255,255,255,0.75)",
|
||||
"text-halo-width": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "place_label_other",
|
||||
"type": "symbol",
|
||||
"source": "mapbox",
|
||||
"source-layer": "place_label",
|
||||
"minzoom": 8,
|
||||
"filter": [
|
||||
"all",
|
||||
[
|
||||
"==",
|
||||
"$type",
|
||||
"Point"
|
||||
],
|
||||
[
|
||||
"in",
|
||||
"type",
|
||||
"hamlet",
|
||||
"island",
|
||||
"neighbourhood",
|
||||
"suburb",
|
||||
"town",
|
||||
"village"
|
||||
]
|
||||
],
|
||||
"layout": {
|
||||
"text-field": "{name_en}",
|
||||
"text-font": [
|
||||
"Open Sans Semibold",
|
||||
"Arial Unicode MS Bold"
|
||||
],
|
||||
"text-max-width": 6,
|
||||
"text-size": {
|
||||
"stops": [
|
||||
[
|
||||
6,
|
||||
12
|
||||
],
|
||||
[
|
||||
12,
|
||||
16
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"paint": {
|
||||
"text-color": "#666",
|
||||
"text-halo-color": "rgba(255,255,255,0.75)",
|
||||
"text-halo-width": 1,
|
||||
"text-halo-blur": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "place_label_city",
|
||||
"type": "symbol",
|
||||
"source": "mapbox",
|
||||
"source-layer": "place_label",
|
||||
"maxzoom": 16,
|
||||
"filter": [
|
||||
"all",
|
||||
[
|
||||
"==",
|
||||
"$type",
|
||||
"Point"
|
||||
],
|
||||
[
|
||||
"==",
|
||||
"type",
|
||||
"city"
|
||||
]
|
||||
],
|
||||
"layout": {
|
||||
"text-field": "{name_en}",
|
||||
"text-font": [
|
||||
"Open Sans Bold",
|
||||
"Arial Unicode MS Bold"
|
||||
],
|
||||
"text-max-width": 10,
|
||||
"text-size": {
|
||||
"stops": [
|
||||
[
|
||||
3,
|
||||
12
|
||||
],
|
||||
[
|
||||
8,
|
||||
16
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"paint": {
|
||||
"text-color": "#666",
|
||||
"text-halo-color": "rgba(255,255,255,0.75)",
|
||||
"text-halo-width": 1,
|
||||
"text-halo-blur": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "country_label",
|
||||
"type": "symbol",
|
||||
"source": "mapbox",
|
||||
"source-layer": "country_label",
|
||||
"maxzoom": 12,
|
||||
"filter": [
|
||||
"==",
|
||||
"$type",
|
||||
"Point"
|
||||
],
|
||||
"layout": {
|
||||
"text-field": "{name_en}",
|
||||
"text-font": [
|
||||
"Open Sans Regular",
|
||||
"Arial Unicode MS Regular"
|
||||
],
|
||||
"text-max-width": 10,
|
||||
"text-size": {
|
||||
"stops": [
|
||||
[
|
||||
3,
|
||||
14
|
||||
],
|
||||
[
|
||||
8,
|
||||
22
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"paint": {
|
||||
"text-color": "#666",
|
||||
"text-halo-color": "rgba(255,255,255,0.75)",
|
||||
"text-halo-width": 1,
|
||||
"text-halo-blur": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "road-heatmap",
|
||||
"type": "heatmap",
|
||||
"source": "mapbox",
|
||||
"source-layer": "road",
|
||||
"paint": {
|
||||
"heatmap-intensity": 1
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
72
platform/macos/app/resources/heatmap.svg
Normal file
72
platform/macos/app/resources/heatmap.svg
Normal file
@@ -0,0 +1,72 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
id="svg4148"
|
||||
version="1.1"
|
||||
inkscape:version="0.92.2 5c3e80d, 2017-08-06"
|
||||
sodipodi:docname="heatmap.svg"
|
||||
inkscape:export-filename="/Users/mxn/Desktop/symbol.png"
|
||||
inkscape:export-xdpi="90.000244"
|
||||
inkscape:export-ydpi="90.000244">
|
||||
<defs
|
||||
id="defs4150" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="23.25"
|
||||
inkscape:cx="4.7741936"
|
||||
inkscape:cy="7.6812068"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
units="px"
|
||||
inkscape:window-width="1280"
|
||||
inkscape:window-height="755"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="1"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:snap-bbox="true" />
|
||||
<metadata
|
||||
id="metadata4153">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-1036.3622)">
|
||||
<path
|
||||
style="opacity:1;fill:#ffffff;fill-opacity:0;fill-rule:evenodd;stroke:#000000;stroke-width:0.99369001;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 11.237265,1036.8591 a 4.2655011,4.1972104 0 0 0 -4.2658922,4.1979 4.2655011,4.1972104 0 0 0 0.025231,0.427 5.3408028,5.2552965 0 0 0 -1.1586611,-0.1299 5.3408028,5.2552965 0 0 0 -5.34109749,5.2556 5.3408028,5.2552965 0 0 0 5.34109749,5.2557 5.3408028,5.2552965 0 0 0 5.3410983,-5.2557 5.3408028,5.2552965 0 0 0 -0.186318,-1.3664 4.2655011,4.1972104 0 0 0 0.244542,0.012 4.2655011,4.1972104 0 0 0 4.26589,-4.198 4.2655011,4.1972104 0 0 0 -4.26589,-4.1979 z"
|
||||
id="path818"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="opacity:1;fill:#000000;fill-opacity:0.15686275;fill-rule:evenodd;stroke:none;stroke-width:0.99369001;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 11.005859,1038.875 c -4.8895767,1.3679 0.321278,7.2823 2.416016,2.7578 0.450567,-1.4666 -0.923376,-2.9624 -2.416016,-2.7578 z m -5.5078121,4.5 c -5.49629855,0.4756 -2.1892763,9.0394 2.2363281,5.9121 2.667642,-1.8963 1.5392118,-6.8607 -2.2363281,-5.9121 z"
|
||||
id="path836"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.0 KiB |
@@ -179,6 +179,7 @@ In style JSON | In the SDK
|
||||
`circle` | `MGLCircleStyleLayer`
|
||||
`fill` | `MGLFillStyleLayer`
|
||||
`fill-extrusion` | `MGLFillExtrusionStyleLayer`
|
||||
`heatmap` | `MGLHeatmapStyleLayer`
|
||||
`hillshade` | `MGLHillshadeStyleLayer`
|
||||
`line` | `MGLLineStyleLayer`
|
||||
`raster` | `MGLRasterStyleLayer`
|
||||
|
||||
@@ -80,6 +80,7 @@ custom_categories:
|
||||
- MGLCircleStyleLayer
|
||||
- MGLFillStyleLayer
|
||||
- MGLFillExtrusionStyleLayer
|
||||
- MGLHeatmapStyleLayer
|
||||
- MGLHillshadeStyleLayer
|
||||
- MGLLineStyleLayer
|
||||
- MGLSymbolStyleLayer
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
07D9474D1F67441B00E37934 /* MGLAbstractShapeSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 07D947471F6741F500E37934 /* MGLAbstractShapeSource_Private.h */; };
|
||||
07F8E2F71F674C8800F794BB /* MGLComputedShapeSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 07F8E2F41F674C8000F794BB /* MGLComputedShapeSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
07F8E2F81F674C9000F794BB /* MGLComputedShapeSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = 07F8E2F51F674C8000F794BB /* MGLComputedShapeSource.mm */; };
|
||||
170A82BF201BDD1B00943087 /* MGLHeatmapStyleLayerTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 170A82BE201BDD1B00943087 /* MGLHeatmapStyleLayerTests.mm */; };
|
||||
170A82C4201FB6EC00943087 /* MGLHeatmapColorTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 170A82C2201FAFF800943087 /* MGLHeatmapColorTests.mm */; };
|
||||
1753ED401E53CE6100A9FD90 /* MGLConversion.h in Headers */ = {isa = PBXBuildFile; fileRef = 1753ED3F1E53CE5200A9FD90 /* MGLConversion.h */; };
|
||||
1F7454A31ECFB00300021D39 /* MGLLight_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F7454A01ECFB00300021D39 /* MGLLight_Private.h */; };
|
||||
1F7454A41ECFB00300021D39 /* MGLLight.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F7454A11ECFB00300021D39 /* MGLLight.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
@@ -85,6 +87,9 @@
|
||||
55D120A31F7906E6004B6D81 /* libmbgl-filesource.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 55D120A41F7906E6004B6D81 /* libmbgl-filesource.a */; };
|
||||
55D120A51F790A0C004B6D81 /* libmbgl-filesource.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 55D120A41F7906E6004B6D81 /* libmbgl-filesource.a */; };
|
||||
55E2AD111E5B0A6900E8C587 /* MGLOfflineStorageTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 55E2AD101E5B0A6900E8C587 /* MGLOfflineStorageTests.mm */; };
|
||||
89462399200D199100DA8EF2 /* heatmap.json in Resources */ = {isa = PBXBuildFile; fileRef = 89462398200D199100DA8EF2 /* heatmap.json */; };
|
||||
8946239D200E744800DA8EF2 /* MGLHeatmapStyleLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 8946239A200E73CA00DA8EF2 /* MGLHeatmapStyleLayer.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
894623A0200E748000DA8EF2 /* MGLHeatmapStyleLayer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8946239B200E73CA00DA8EF2 /* MGLHeatmapStyleLayer.mm */; };
|
||||
92092EF01F5EB10E00AF5130 /* MGLMapSnapshotter.h in Headers */ = {isa = PBXBuildFile; fileRef = 92092EEE1F5EB10E00AF5130 /* MGLMapSnapshotter.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
92092EF11F5EB10E00AF5130 /* MGLMapSnapshotter.mm in Sources */ = {isa = PBXBuildFile; fileRef = 92092EEF1F5EB10E00AF5130 /* MGLMapSnapshotter.mm */; };
|
||||
920A3E591E6F859D00C16EFC /* MGLSourceQueryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 920A3E581E6F859D00C16EFC /* MGLSourceQueryTests.m */; };
|
||||
@@ -298,6 +303,8 @@
|
||||
07D947491F6741F500E37934 /* MGLAbstractShapeSource.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLAbstractShapeSource.mm; sourceTree = "<group>"; };
|
||||
07F8E2F41F674C8000F794BB /* MGLComputedShapeSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLComputedShapeSource.h; sourceTree = "<group>"; };
|
||||
07F8E2F51F674C8000F794BB /* MGLComputedShapeSource.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLComputedShapeSource.mm; sourceTree = "<group>"; };
|
||||
170A82BE201BDD1B00943087 /* MGLHeatmapStyleLayerTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLHeatmapStyleLayerTests.mm; sourceTree = "<group>"; };
|
||||
170A82C2201FAFF800943087 /* MGLHeatmapColorTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLHeatmapColorTests.mm; sourceTree = "<group>"; };
|
||||
1753ED3F1E53CE5200A9FD90 /* MGLConversion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLConversion.h; sourceTree = "<group>"; };
|
||||
1F7454A01ECFB00300021D39 /* MGLLight_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLLight_Private.h; sourceTree = "<group>"; };
|
||||
1F7454A11ECFB00300021D39 /* MGLLight.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLLight.h; sourceTree = "<group>"; };
|
||||
@@ -369,6 +376,9 @@
|
||||
55D9B4B01D005D3900C1CCE2 /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; };
|
||||
55E2AD101E5B0A6900E8C587 /* MGLOfflineStorageTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLOfflineStorageTests.mm; path = ../../darwin/test/MGLOfflineStorageTests.mm; sourceTree = "<group>"; };
|
||||
55FE0E8D1D100A0900FD240B /* config.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = config.xcconfig; path = ../../build/macos/config.xcconfig; sourceTree = "<group>"; };
|
||||
89462398200D199100DA8EF2 /* heatmap.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = heatmap.json; sourceTree = "<group>"; };
|
||||
8946239A200E73CA00DA8EF2 /* MGLHeatmapStyleLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLHeatmapStyleLayer.h; sourceTree = "<group>"; };
|
||||
8946239B200E73CA00DA8EF2 /* MGLHeatmapStyleLayer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLHeatmapStyleLayer.mm; sourceTree = "<group>"; };
|
||||
92092EEE1F5EB10E00AF5130 /* MGLMapSnapshotter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLMapSnapshotter.h; sourceTree = "<group>"; };
|
||||
92092EEF1F5EB10E00AF5130 /* MGLMapSnapshotter.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLMapSnapshotter.mm; sourceTree = "<group>"; };
|
||||
920A3E581E6F859D00C16EFC /* MGLSourceQueryTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGLSourceQueryTests.m; sourceTree = "<group>"; };
|
||||
@@ -672,6 +682,8 @@
|
||||
35602BF91D3EA99F0050646F /* MGLFillStyleLayer.mm */,
|
||||
35602BFD1D3EA9B40050646F /* MGLForegroundStyleLayer.h */,
|
||||
35602BFE1D3EA9B40050646F /* MGLForegroundStyleLayer.mm */,
|
||||
8946239A200E73CA00DA8EF2 /* MGLHeatmapStyleLayer.h */,
|
||||
8946239B200E73CA00DA8EF2 /* MGLHeatmapStyleLayer.mm */,
|
||||
DAF25714201901C200367EF5 /* MGLHillshadeStyleLayer.h */,
|
||||
DAF25713201901C100367EF5 /* MGLHillshadeStyleLayer.mm */,
|
||||
DA8F25891D51CA540010E6B5 /* MGLLineStyleLayer.h */,
|
||||
@@ -825,6 +837,7 @@
|
||||
DA839EA61CC2E3400062CAFB /* Info.plist */,
|
||||
96E027331E57C9A7004B8E66 /* Localizable.strings */,
|
||||
DA839E981CC2E3400062CAFB /* Supporting Files */,
|
||||
89462398200D199100DA8EF2 /* heatmap.json */,
|
||||
);
|
||||
name = "Demo App";
|
||||
path = app;
|
||||
@@ -875,6 +888,8 @@
|
||||
DA8F257C1D51C5F40010E6B5 /* Layers */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
170A82C2201FAFF800943087 /* MGLHeatmapColorTests.mm */,
|
||||
170A82BE201BDD1B00943087 /* MGLHeatmapStyleLayerTests.mm */,
|
||||
40E1601A1DF216E6005EA6D9 /* MGLStyleLayerTests.h */,
|
||||
40E1601B1DF216E6005EA6D9 /* MGLStyleLayerTests.m */,
|
||||
DA2207BA1DC076930002F84D /* test-Bridging-Header.h */,
|
||||
@@ -1232,6 +1247,7 @@
|
||||
359819591E02F611008FC139 /* NSCoder+MGLAdditions.h in Headers */,
|
||||
DAE6C38E1CC31E2A00DB3429 /* MGLOfflineStorage_Private.h in Headers */,
|
||||
DA87A9A01DC9DC6200810D09 /* MGLValueEvaluator.h in Headers */,
|
||||
8946239D200E744800DA8EF2 /* MGLHeatmapStyleLayer.h in Headers */,
|
||||
DAE6C3601CC31E0400DB3429 /* MGLOfflineRegion.h in Headers */,
|
||||
DAE6C3681CC31E0400DB3429 /* MGLTilePyramidOfflineRegion.h in Headers */,
|
||||
DA35A2CF1CCAAED300E826B2 /* NSValue+MGLAdditions.h in Headers */,
|
||||
@@ -1422,6 +1438,7 @@
|
||||
DA839EA01CC2E3400062CAFB /* MapDocument.xib in Resources */,
|
||||
353BAEF81D6463B8009A8DA9 /* amsterdam.geojson in Resources */,
|
||||
96E027311E57C9A7004B8E66 /* Localizable.strings in Resources */,
|
||||
89462399200D199100DA8EF2 /* heatmap.json in Resources */,
|
||||
DA839EA51CC2E3400062CAFB /* MainMenu.xib in Resources */,
|
||||
DA5589771D320C41006B7F64 /* wms.json in Resources */,
|
||||
DAE6C2E21CC304F900DB3429 /* Credits.rtf in Resources */,
|
||||
@@ -1503,6 +1520,7 @@
|
||||
07D9474B1F6743F000E37934 /* MGLAbstractShapeSource.mm in Sources */,
|
||||
DAE6C3941CC31E2A00DB3429 /* MGLStyle.mm in Sources */,
|
||||
DAE6C3871CC31E2A00DB3429 /* MGLGeometry.mm in Sources */,
|
||||
894623A0200E748000DA8EF2 /* MGLHeatmapStyleLayer.mm in Sources */,
|
||||
3527428E1D4C24AB00A1ECE6 /* MGLCircleStyleLayer.mm in Sources */,
|
||||
35602C011D3EA9B40050646F /* MGLForegroundStyleLayer.mm in Sources */,
|
||||
408AA86A1DAEEE5D00022900 /* NSDictionary+MGLAdditions.mm in Sources */,
|
||||
@@ -1565,11 +1583,13 @@
|
||||
DAE6C3D21CC34C9900DB3429 /* MGLGeometryTests.mm in Sources */,
|
||||
DA87A9A41DCACC5000810D09 /* MGLSymbolStyleLayerTests.mm in Sources */,
|
||||
40E1601D1DF217D6005EA6D9 /* MGLStyleLayerTests.m in Sources */,
|
||||
170A82BF201BDD1B00943087 /* MGLHeatmapStyleLayerTests.mm in Sources */,
|
||||
1F95931B1E6DE2B600D5B294 /* MGLNSDateAdditionsTests.mm in Sources */,
|
||||
DAF25721201902C100367EF5 /* MGLHillshadeStyleLayerTests.mm in Sources */,
|
||||
DA87A9A61DCACC5000810D09 /* MGLCircleStyleLayerTests.mm in Sources */,
|
||||
DA87A99E1DC9DC2100810D09 /* MGLPredicateTests.mm in Sources */,
|
||||
DD58A4C91D822C6700E1F038 /* MGLExpressionTests.mm in Sources */,
|
||||
170A82C4201FB6EC00943087 /* MGLHeatmapColorTests.mm in Sources */,
|
||||
4031ACFC1E9EB3C100A3EA26 /* MGLMapViewDelegateIntegrationTests.swift in Sources */,
|
||||
4031AD031E9FD6AA00A3EA26 /* MGLSDKTestHelpers.swift in Sources */,
|
||||
DA87A9A71DCACC5000810D09 /* MGLBackgroundStyleLayerTests.mm in Sources */,
|
||||
|
||||
@@ -44,6 +44,7 @@ FOUNDATION_EXPORT MGL_EXPORT const unsigned char MapboxVersionString[];
|
||||
#import "MGLRasterStyleLayer.h"
|
||||
#import "MGLCircleStyleLayer.h"
|
||||
#import "MGLBackgroundStyleLayer.h"
|
||||
#import "MGLHeatmapStyleLayer.h"
|
||||
#import "MGLHillshadeStyleLayer.h"
|
||||
#import "MGLOpenGLStyleLayer.h"
|
||||
#import "MGLSource.h"
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#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/heatmap_layer.hpp>
|
||||
#include <mbgl/style/layers/hillshade_layer.hpp>
|
||||
#include <mbgl/style/layers/line_layer.hpp>
|
||||
#include <mbgl/style/layers/raster_layer.hpp>
|
||||
|
||||
@@ -23,24 +23,6 @@
|
||||
"render-tests/fill-extrusion-pattern/opacity": "https://github.com/mapbox/mapbox-gl-js/issues/3327",
|
||||
"render-tests/geojson/inline-linestring-fill": "current behavior is arbitrary",
|
||||
"render-tests/geojson/inline-polygon-symbol": "behavior needs reconciliation with gl-js",
|
||||
"render-tests/heatmap-color/default": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
|
||||
"render-tests/heatmap-color/expression": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
|
||||
"render-tests/heatmap-color/function": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
|
||||
"render-tests/heatmap-intensity/default": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
|
||||
"render-tests/heatmap-intensity/function": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
|
||||
"render-tests/heatmap-intensity/literal": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
|
||||
"render-tests/heatmap-opacity/default": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
|
||||
"render-tests/heatmap-opacity/function": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
|
||||
"render-tests/heatmap-opacity/literal": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
|
||||
"render-tests/heatmap-radius/antimeridian": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
|
||||
"render-tests/heatmap-radius/data-expression": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
|
||||
"render-tests/heatmap-radius/default": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
|
||||
"render-tests/heatmap-radius/function": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
|
||||
"render-tests/heatmap-radius/literal": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
|
||||
"render-tests/heatmap-radius/pitch30": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
|
||||
"render-tests/heatmap-weight/default": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
|
||||
"render-tests/heatmap-weight/identity-property-function": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
|
||||
"render-tests/heatmap-weight/literal": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
|
||||
"render-tests/mixed-zoom/z10-z11": "https://github.com/mapbox/mapbox-gl-native/issues/10397",
|
||||
"render-tests/raster-masking/overlapping-zoom": "https://github.com/mapbox/mapbox-gl-native/issues/10195",
|
||||
"render-tests/regressions/mapbox-gl-js#2305": "https://github.com/mapbox/mapbox-gl-native/issues/6927",
|
||||
|
||||
@@ -7,9 +7,6 @@ const outputPath = 'src/mbgl/shaders';
|
||||
|
||||
var shaders = require('../mapbox-gl-js/src/shaders');
|
||||
|
||||
delete shaders.heatmap;
|
||||
delete shaders.heatmapTexture;
|
||||
|
||||
require('./style-code');
|
||||
|
||||
writeIfModified(path.join(outputPath, 'preludes.hpp'), `// NOTE: DO NOT CHANGE THIS FILE. IT IS AUTOMATICALLY GENERATED.
|
||||
|
||||
@@ -97,6 +97,8 @@ global.paintPropertyType = function (property, type) {
|
||||
global.propertyValueType = function (property) {
|
||||
if (isDataDriven(property)) {
|
||||
return `DataDrivenPropertyValue<${evaluatedType(property)}>`;
|
||||
} else if (property.name === 'heatmap-color') {
|
||||
return `HeatmapColorPropertyValue`;
|
||||
} else {
|
||||
return `PropertyValue<${evaluatedType(property)}>`;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
var spec = module.exports = require('../mapbox-gl-js/src/style-spec/reference/v8');
|
||||
|
||||
// Make temporary modifications here when Native doesn't have all features that JS has.
|
||||
|
||||
delete spec.layer.type.values.heatmap;
|
||||
|
||||
@@ -85,6 +85,10 @@ public:
|
||||
static ColorMode alphaBlended() {
|
||||
return ColorMode { Add { One, OneMinusSrcAlpha }, {}, { true, true, true, true } };
|
||||
}
|
||||
|
||||
static ColorMode additive() {
|
||||
return ColorMode { Add { One, One }, {}, { true, true, true, true } };
|
||||
}
|
||||
};
|
||||
|
||||
constexpr bool operator!=(const ColorMode::Mask& a, const ColorMode::Mask& b) {
|
||||
|
||||
@@ -60,6 +60,16 @@ static_assert(std::is_same<std::underlying_type_t<TextureFormat>, GLenum>::value
|
||||
static_assert(underlying_type(TextureFormat::RGBA) == GL_RGBA, "OpenGL type mismatch");
|
||||
static_assert(underlying_type(TextureFormat::Alpha) == GL_ALPHA, "OpenGL type mismatch");
|
||||
|
||||
static_assert(std::is_same<std::underlying_type_t<TextureType>, GLenum>::value, "OpenGL type mismatch");
|
||||
static_assert(underlying_type(TextureType::UnsignedByte) == GL_UNSIGNED_BYTE, "OpenGL type mismatch");
|
||||
|
||||
#if MBGL_USE_GLES2 && GL_HALF_FLOAT_OES
|
||||
static_assert(underlying_type(TextureType::HalfFloat) == GL_HALF_FLOAT_OES, "OpenGL type mismatch");
|
||||
#endif
|
||||
#if !MBGL_USE_GLES2 && GL_HALF_FLOAT_ARB
|
||||
static_assert(underlying_type(TextureType::HalfFloat) == GL_HALF_FLOAT_ARB, "OpenGL type mismatch");
|
||||
#endif
|
||||
|
||||
static_assert(underlying_type(UniformDataType::Float) == GL_FLOAT, "OpenGL type mismatch");
|
||||
static_assert(underlying_type(UniformDataType::FloatVec2) == GL_FLOAT_VEC2, "OpenGL type mismatch");
|
||||
static_assert(underlying_type(UniformDataType::FloatVec3) == GL_FLOAT_VEC3, "OpenGL type mismatch");
|
||||
@@ -116,6 +126,19 @@ void Context::initializeExtensions(const std::function<gl::ProcAddress(const cha
|
||||
programBinary = std::make_unique<extension::ProgramBinary>(fn);
|
||||
#endif
|
||||
|
||||
#if MBGL_USE_GLES2
|
||||
constexpr const char* halfFloatExtensionName = "OES_texture_half_float";
|
||||
constexpr const char* halfFloatColorBufferExtensionName = "EXT_color_buffer_half_float";
|
||||
#else
|
||||
constexpr const char* halfFloatExtensionName = "ARB_half_float_pixel";
|
||||
constexpr const char* halfFloatColorBufferExtensionName = "ARB_color_buffer_float";
|
||||
#endif
|
||||
if (strstr(extensions, halfFloatExtensionName) != nullptr &&
|
||||
strstr(extensions, halfFloatColorBufferExtensionName) != nullptr) {
|
||||
|
||||
supportsHalfFloatTextures = true;
|
||||
}
|
||||
|
||||
if (!supportsVertexArrays()) {
|
||||
Log::Warning(Event::OpenGL, "Not using Vertex Array Objects");
|
||||
}
|
||||
@@ -491,10 +514,10 @@ Context::createFramebuffer(const Texture& color,
|
||||
}
|
||||
|
||||
UniqueTexture
|
||||
Context::createTexture(const Size size, const void* data, TextureFormat format, TextureUnit unit) {
|
||||
Context::createTexture(const Size size, const void* data, TextureFormat format, TextureUnit unit, TextureType type) {
|
||||
auto obj = createTexture();
|
||||
pixelStoreUnpack = { 1 };
|
||||
updateTexture(obj, size, data, format, unit);
|
||||
updateTexture(obj, size, data, format, unit, type);
|
||||
// We are using clamp to edge here since OpenGL ES doesn't allow GL_REPEAT on NPOT textures.
|
||||
// We use those when the pixelRatio isn't a power of two, e.g. on iPhone 6 Plus.
|
||||
MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
|
||||
@@ -505,11 +528,11 @@ Context::createTexture(const Size size, const void* data, TextureFormat format,
|
||||
}
|
||||
|
||||
void Context::updateTexture(
|
||||
TextureID id, const Size size, const void* data, TextureFormat format, TextureUnit unit) {
|
||||
TextureID id, const Size size, const void* data, TextureFormat format, TextureUnit unit, TextureType type) {
|
||||
activeTextureUnit = unit;
|
||||
texture[unit] = id;
|
||||
MBGL_CHECK_ERROR(glTexImage2D(GL_TEXTURE_2D, 0, static_cast<GLenum>(format), size.width,
|
||||
size.height, 0, static_cast<GLenum>(format), GL_UNSIGNED_BYTE,
|
||||
size.height, 0, static_cast<GLenum>(format), static_cast<GLenum>(type),
|
||||
data));
|
||||
}
|
||||
|
||||
|
||||
@@ -125,23 +125,29 @@ public:
|
||||
|
||||
// Create a texture from an image with data.
|
||||
template <typename Image>
|
||||
Texture createTexture(const Image& image, TextureUnit unit = 0) {
|
||||
Texture createTexture(const Image& image,
|
||||
TextureUnit unit = 0,
|
||||
TextureType type = TextureType::UnsignedByte) {
|
||||
auto format = image.channels == 4 ? TextureFormat::RGBA : TextureFormat::Alpha;
|
||||
return { image.size, createTexture(image.size, image.data.get(), format, unit) };
|
||||
return { image.size, createTexture(image.size, image.data.get(), format, unit, type) };
|
||||
}
|
||||
|
||||
template <typename Image>
|
||||
void updateTexture(Texture& obj, const Image& image, TextureUnit unit = 0) {
|
||||
void updateTexture(Texture& obj,
|
||||
const Image& image,
|
||||
TextureUnit unit = 0,
|
||||
TextureType type = TextureType::UnsignedByte) {
|
||||
auto format = image.channels == 4 ? TextureFormat::RGBA : TextureFormat::Alpha;
|
||||
updateTexture(obj.texture.get(), image.size, image.data.get(), format, unit);
|
||||
updateTexture(obj.texture.get(), image.size, image.data.get(), format, unit, type);
|
||||
obj.size = image.size;
|
||||
}
|
||||
|
||||
// Creates an empty texture with the specified dimensions.
|
||||
Texture createTexture(const Size size,
|
||||
TextureFormat format = TextureFormat::RGBA,
|
||||
TextureUnit unit = 0) {
|
||||
return { size, createTexture(size, nullptr, format, unit) };
|
||||
TextureUnit unit = 0,
|
||||
TextureType type = TextureType::UnsignedByte) {
|
||||
return { size, createTexture(size, nullptr, format, unit, type) };
|
||||
}
|
||||
|
||||
void bindTexture(Texture&,
|
||||
@@ -232,6 +238,8 @@ public:
|
||||
State<value::PixelTransferStencil> pixelTransferStencil;
|
||||
#endif // MBGL_USE_GLES2
|
||||
|
||||
bool supportsHalfFloatTextures = false;
|
||||
|
||||
private:
|
||||
State<value::StencilFunc> stencilFunc;
|
||||
State<value::StencilMask> stencilMask;
|
||||
@@ -259,8 +267,8 @@ private:
|
||||
void updateVertexBuffer(UniqueBuffer& buffer, const void* data, std::size_t size);
|
||||
UniqueBuffer createIndexBuffer(const void* data, std::size_t size, const BufferUsage usage);
|
||||
void updateIndexBuffer(UniqueBuffer& buffer, const void* data, std::size_t size);
|
||||
UniqueTexture createTexture(Size size, const void* data, TextureFormat, TextureUnit);
|
||||
void updateTexture(TextureID, Size size, const void* data, TextureFormat, TextureUnit);
|
||||
UniqueTexture createTexture(Size size, const void* data, TextureFormat, TextureUnit, TextureType);
|
||||
void updateTexture(TextureID, Size size, const void* data, TextureFormat, TextureUnit, TextureType);
|
||||
UniqueFramebuffer createFramebuffer();
|
||||
UniqueRenderbuffer createRenderbuffer(RenderbufferType, Size size);
|
||||
std::unique_ptr<uint8_t[]> readFramebuffer(Size, TextureFormat, bool flip);
|
||||
|
||||
@@ -64,6 +64,15 @@ enum class TextureFormat : uint32_t {
|
||||
#endif // MBGL_USE_GLES2
|
||||
};
|
||||
|
||||
enum class TextureType : uint32_t {
|
||||
UnsignedByte = 0x1401,
|
||||
#if MBGL_USE_GLES2
|
||||
HalfFloat = 0x8D61,
|
||||
#else
|
||||
HalfFloat = 0x140B,
|
||||
#endif // MBGL_USE_GLES2
|
||||
};
|
||||
|
||||
enum class PrimitiveType {
|
||||
Points = 0x0000,
|
||||
Lines = 0x0001,
|
||||
|
||||
@@ -30,7 +30,7 @@ MBGL_DEFINE_ATTRIBUTE(int16_t, 2, a_anchor_pos);
|
||||
MBGL_DEFINE_ATTRIBUTE(uint16_t, 2, a_texture_pos);
|
||||
MBGL_DEFINE_ATTRIBUTE(int16_t, 4, a_normal_ed);
|
||||
MBGL_DEFINE_ATTRIBUTE(uint8_t, 1, a_fade_opacity);
|
||||
MBGL_DEFINE_ATTRIBUTE(uint8_t, 2, a_placed);
|
||||
MBGL_DEFINE_ATTRIBUTE(uint8_t, 2, a_placed);
|
||||
|
||||
template <typename T, std::size_t N>
|
||||
struct a_data {
|
||||
@@ -142,6 +142,11 @@ struct a_halo_blur {
|
||||
using Type = gl::Attribute<float, 1>;
|
||||
};
|
||||
|
||||
struct a_weight {
|
||||
static auto name() { return "a_weight"; }
|
||||
using Type = gl::Attribute<float, 1>;
|
||||
};
|
||||
|
||||
} // namespace attributes
|
||||
|
||||
struct PositionOnlyLayoutAttributes : gl::Attributes<
|
||||
|
||||
7
src/mbgl/programs/heatmap_program.cpp
Normal file
7
src/mbgl/programs/heatmap_program.cpp
Normal file
@@ -0,0 +1,7 @@
|
||||
#include <mbgl/programs/heatmap_program.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
static_assert(sizeof(HeatmapLayoutVertex) == 4, "expected HeatmapLayoutVertex size");
|
||||
|
||||
} // namespace mbgl
|
||||
49
src/mbgl/programs/heatmap_program.hpp
Normal file
49
src/mbgl/programs/heatmap_program.hpp
Normal file
@@ -0,0 +1,49 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/programs/program.hpp>
|
||||
#include <mbgl/programs/attributes.hpp>
|
||||
#include <mbgl/programs/uniforms.hpp>
|
||||
#include <mbgl/shaders/heatmap.hpp>
|
||||
#include <mbgl/util/geometry.hpp>
|
||||
#include <mbgl/style/layers/heatmap_layer_properties.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
namespace uniforms {
|
||||
MBGL_DEFINE_UNIFORM_SCALAR(float, u_intensity);
|
||||
} // namespace uniforms
|
||||
|
||||
class HeatmapProgram : public Program<
|
||||
shaders::heatmap,
|
||||
gl::Triangle,
|
||||
gl::Attributes<
|
||||
attributes::a_pos>,
|
||||
gl::Uniforms<
|
||||
uniforms::u_intensity,
|
||||
uniforms::u_matrix,
|
||||
uniforms::heatmap::u_extrude_scale>,
|
||||
style::HeatmapPaintProperties>
|
||||
{
|
||||
public:
|
||||
using Program::Program;
|
||||
|
||||
/*
|
||||
* @param {number} x vertex position
|
||||
* @param {number} y vertex position
|
||||
* @param {number} ex extrude normal
|
||||
* @param {number} ey extrude normal
|
||||
*/
|
||||
static LayoutVertex vertex(Point<int16_t> p, float ex, float ey) {
|
||||
return LayoutVertex {
|
||||
{{
|
||||
static_cast<int16_t>((p.x * 2) + ((ex + 1) / 2)),
|
||||
static_cast<int16_t>((p.y * 2) + ((ey + 1) / 2))
|
||||
}}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
using HeatmapLayoutVertex = HeatmapProgram::LayoutVertex;
|
||||
using HeatmapAttributes = HeatmapProgram::Attributes;
|
||||
|
||||
} // namespace mbgl
|
||||
7
src/mbgl/programs/heatmap_texture_program.cpp
Normal file
7
src/mbgl/programs/heatmap_texture_program.cpp
Normal file
@@ -0,0 +1,7 @@
|
||||
#include <mbgl/programs/heatmap_texture_program.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
static_assert(sizeof(HeatmapTextureLayoutVertex) == 4, "expected HeatmapTextureLayoutVertex size");
|
||||
|
||||
} // namespace mbgl
|
||||
43
src/mbgl/programs/heatmap_texture_program.hpp
Normal file
43
src/mbgl/programs/heatmap_texture_program.hpp
Normal file
@@ -0,0 +1,43 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/programs/program.hpp>
|
||||
#include <mbgl/programs/attributes.hpp>
|
||||
#include <mbgl/programs/uniforms.hpp>
|
||||
#include <mbgl/shaders/heatmap_texture.hpp>
|
||||
#include <mbgl/style/properties.hpp>
|
||||
#include <mbgl/util/geometry.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
namespace uniforms {
|
||||
MBGL_DEFINE_UNIFORM_SCALAR(gl::TextureUnit, u_color_ramp);
|
||||
} // namespace uniforms
|
||||
|
||||
class HeatmapTextureProgram : public Program<
|
||||
shaders::heatmap_texture,
|
||||
gl::Triangle,
|
||||
gl::Attributes<attributes::a_pos>,
|
||||
gl::Uniforms<
|
||||
uniforms::u_matrix,
|
||||
uniforms::u_world,
|
||||
uniforms::u_image,
|
||||
uniforms::u_color_ramp,
|
||||
uniforms::u_opacity>,
|
||||
style::Properties<>> {
|
||||
public:
|
||||
using Program::Program;
|
||||
|
||||
static LayoutVertex layoutVertex(Point<int16_t> p) {
|
||||
return LayoutVertex{
|
||||
{{
|
||||
p.x,
|
||||
p.y
|
||||
}}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
using HeatmapTextureLayoutVertex = HeatmapTextureProgram::LayoutVertex;
|
||||
using HeatmapTextureAttributes = HeatmapTextureProgram::Attributes;
|
||||
|
||||
} // namespace mbgl
|
||||
@@ -6,6 +6,8 @@
|
||||
#include <mbgl/programs/extrusion_texture_program.hpp>
|
||||
#include <mbgl/programs/fill_program.hpp>
|
||||
#include <mbgl/programs/fill_extrusion_program.hpp>
|
||||
#include <mbgl/programs/heatmap_program.hpp>
|
||||
#include <mbgl/programs/heatmap_texture_program.hpp>
|
||||
#include <mbgl/programs/hillshade_program.hpp>
|
||||
#include <mbgl/programs/hillshade_prepare_program.hpp>
|
||||
#include <mbgl/programs/line_program.hpp>
|
||||
@@ -30,6 +32,8 @@ public:
|
||||
fillPattern(context, programParameters),
|
||||
fillOutline(context, programParameters),
|
||||
fillOutlinePattern(context, programParameters),
|
||||
heatmap(context, programParameters),
|
||||
heatmapTexture(context, programParameters),
|
||||
hillshade(context, programParameters),
|
||||
hillshadePrepare(context, programParameters),
|
||||
line(context, programParameters),
|
||||
@@ -55,6 +59,8 @@ public:
|
||||
ProgramMap<FillPatternProgram> fillPattern;
|
||||
ProgramMap<FillOutlineProgram> fillOutline;
|
||||
ProgramMap<FillOutlinePatternProgram> fillOutlinePattern;
|
||||
ProgramMap<HeatmapProgram> heatmap;
|
||||
HeatmapTextureProgram heatmapTexture;
|
||||
HillshadeProgram hillshade;
|
||||
HillshadePrepareProgram hillshadePrepare;
|
||||
ProgramMap<LineProgram> line;
|
||||
|
||||
@@ -37,9 +37,14 @@ MBGL_DEFINE_UNIFORM_SCALAR(Size, u_texsize);
|
||||
MBGL_DEFINE_UNIFORM_SCALAR(bool, u_pitch_with_map);
|
||||
MBGL_DEFINE_UNIFORM_SCALAR(float, u_camera_to_center_distance);
|
||||
MBGL_DEFINE_UNIFORM_SCALAR(float, u_fade_change);
|
||||
MBGL_DEFINE_UNIFORM_SCALAR(float, u_weight);
|
||||
|
||||
MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_extrude_scale);
|
||||
|
||||
namespace heatmap {
|
||||
MBGL_DEFINE_UNIFORM_SCALAR(float, u_extrude_scale);
|
||||
} // namespace heatmap
|
||||
|
||||
MBGL_DEFINE_UNIFORM_VECTOR(uint16_t, 2, u_pattern_tl_a);
|
||||
MBGL_DEFINE_UNIFORM_VECTOR(uint16_t, 2, u_pattern_br_a);
|
||||
MBGL_DEFINE_UNIFORM_VECTOR(uint16_t, 2, u_pattern_tl_b);
|
||||
|
||||
98
src/mbgl/renderer/buckets/heatmap_bucket.cpp
Normal file
98
src/mbgl/renderer/buckets/heatmap_bucket.cpp
Normal file
@@ -0,0 +1,98 @@
|
||||
#include <mbgl/renderer/buckets/heatmap_bucket.hpp>
|
||||
#include <mbgl/renderer/bucket_parameters.hpp>
|
||||
#include <mbgl/programs/heatmap_program.hpp>
|
||||
#include <mbgl/style/layers/heatmap_layer_impl.hpp>
|
||||
#include <mbgl/renderer/layers/render_heatmap_layer.hpp>
|
||||
#include <mbgl/util/constants.hpp>
|
||||
#include <mbgl/util/math.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
using namespace style;
|
||||
|
||||
HeatmapBucket::HeatmapBucket(const BucketParameters& parameters, const std::vector<const RenderLayer*>& layers)
|
||||
: mode(parameters.mode) {
|
||||
for (const auto& layer : layers) {
|
||||
paintPropertyBinders.emplace(
|
||||
std::piecewise_construct,
|
||||
std::forward_as_tuple(layer->getID()),
|
||||
std::forward_as_tuple(
|
||||
layer->as<RenderHeatmapLayer>()->evaluated,
|
||||
parameters.tileID.overscaledZ));
|
||||
}
|
||||
}
|
||||
|
||||
void HeatmapBucket::upload(gl::Context& context) {
|
||||
vertexBuffer = context.createVertexBuffer(std::move(vertices));
|
||||
indexBuffer = context.createIndexBuffer(std::move(triangles));
|
||||
|
||||
for (auto& pair : paintPropertyBinders) {
|
||||
pair.second.upload(context);
|
||||
}
|
||||
|
||||
uploaded = true;
|
||||
}
|
||||
|
||||
bool HeatmapBucket::hasData() const {
|
||||
return !segments.empty();
|
||||
}
|
||||
|
||||
void HeatmapBucket::addFeature(const GeometryTileFeature& feature,
|
||||
const GeometryCollection& geometry) {
|
||||
constexpr const uint16_t vertexLength = 4;
|
||||
|
||||
for (auto& points : geometry) {
|
||||
for(auto& point : points) {
|
||||
auto x = point.x;
|
||||
auto y = point.y;
|
||||
|
||||
// Do not include points that are outside the tile boundaries.
|
||||
// Include all points in Still mode. You need to include points from
|
||||
// neighbouring tiles so that they are not clipped at tile boundaries.
|
||||
if ((mode == MapMode::Continuous) &&
|
||||
(x < 0 || x >= util::EXTENT || y < 0 || y >= util::EXTENT)) continue;
|
||||
|
||||
if (segments.empty() || segments.back().vertexLength + vertexLength > std::numeric_limits<uint16_t>::max()) {
|
||||
// Move to a new segments because the old one can't hold the geometry.
|
||||
segments.emplace_back(vertices.vertexSize(), triangles.indexSize());
|
||||
}
|
||||
|
||||
// this geometry will be of the Point type, and we'll derive
|
||||
// two triangles from it.
|
||||
//
|
||||
// ┌─────────┐
|
||||
// │ 4 3 │
|
||||
// │ │
|
||||
// │ 1 2 │
|
||||
// └─────────┘
|
||||
//
|
||||
vertices.emplace_back(HeatmapProgram::vertex(point, -1, -1)); // 1
|
||||
vertices.emplace_back(HeatmapProgram::vertex(point, 1, -1)); // 2
|
||||
vertices.emplace_back(HeatmapProgram::vertex(point, 1, 1)); // 3
|
||||
vertices.emplace_back(HeatmapProgram::vertex(point, -1, 1)); // 4
|
||||
|
||||
auto& segment = segments.back();
|
||||
assert(segment.vertexLength <= std::numeric_limits<uint16_t>::max());
|
||||
uint16_t index = segment.vertexLength;
|
||||
|
||||
// 1, 2, 3
|
||||
// 1, 4, 3
|
||||
triangles.emplace_back(index, index + 1, index + 2);
|
||||
triangles.emplace_back(index, index + 3, index + 2);
|
||||
|
||||
segment.vertexLength += vertexLength;
|
||||
segment.indexLength += 6;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& pair : paintPropertyBinders) {
|
||||
pair.second.populateVertexVectors(feature, vertices.vertexSize());
|
||||
}
|
||||
}
|
||||
|
||||
float HeatmapBucket::getQueryRadius(const RenderLayer& layer) const {
|
||||
(void)layer;
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
40
src/mbgl/renderer/buckets/heatmap_bucket.hpp
Normal file
40
src/mbgl/renderer/buckets/heatmap_bucket.hpp
Normal file
@@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/renderer/bucket.hpp>
|
||||
#include <mbgl/map/mode.hpp>
|
||||
#include <mbgl/tile/geometry_tile_data.hpp>
|
||||
#include <mbgl/gl/vertex_buffer.hpp>
|
||||
#include <mbgl/gl/index_buffer.hpp>
|
||||
#include <mbgl/programs/segment.hpp>
|
||||
#include <mbgl/programs/heatmap_program.hpp>
|
||||
#include <mbgl/style/layers/heatmap_layer_properties.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
class BucketParameters;
|
||||
|
||||
class HeatmapBucket : public Bucket {
|
||||
public:
|
||||
HeatmapBucket(const BucketParameters&, const std::vector<const RenderLayer*>&);
|
||||
|
||||
void addFeature(const GeometryTileFeature&,
|
||||
const GeometryCollection&) override;
|
||||
bool hasData() const override;
|
||||
|
||||
void upload(gl::Context&) override;
|
||||
|
||||
float getQueryRadius(const RenderLayer&) const override;
|
||||
|
||||
gl::VertexVector<HeatmapLayoutVertex> vertices;
|
||||
gl::IndexVector<gl::Triangles> triangles;
|
||||
SegmentVector<HeatmapAttributes> segments;
|
||||
|
||||
optional<gl::VertexBuffer<HeatmapLayoutVertex>> vertexBuffer;
|
||||
optional<gl::IndexBuffer<gl::Triangles>> indexBuffer;
|
||||
|
||||
std::map<std::string, HeatmapProgram::PaintPropertyBinders> paintPropertyBinders;
|
||||
|
||||
const MapMode mode;
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
178
src/mbgl/renderer/layers/render_heatmap_layer.cpp
Normal file
178
src/mbgl/renderer/layers/render_heatmap_layer.cpp
Normal file
@@ -0,0 +1,178 @@
|
||||
#include <mbgl/renderer/layers/render_heatmap_layer.hpp>
|
||||
#include <mbgl/renderer/buckets/heatmap_bucket.hpp>
|
||||
#include <mbgl/renderer/render_tile.hpp>
|
||||
#include <mbgl/renderer/paint_parameters.hpp>
|
||||
#include <mbgl/renderer/render_static_data.hpp>
|
||||
#include <mbgl/programs/programs.hpp>
|
||||
#include <mbgl/programs/heatmap_program.hpp>
|
||||
#include <mbgl/tile/tile.hpp>
|
||||
#include <mbgl/style/layers/heatmap_layer.hpp>
|
||||
#include <mbgl/style/layers/heatmap_layer_impl.hpp>
|
||||
#include <mbgl/geometry/feature_index.hpp>
|
||||
#include <mbgl/util/math.hpp>
|
||||
#include <mbgl/util/intersection_tests.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
using namespace style;
|
||||
|
||||
RenderHeatmapLayer::RenderHeatmapLayer(Immutable<style::HeatmapLayer::Impl> _impl)
|
||||
: RenderLayer(style::LayerType::Heatmap, _impl),
|
||||
unevaluated(impl().paint.untransitioned()), colorRamp({256, 1}) {
|
||||
}
|
||||
|
||||
const style::HeatmapLayer::Impl& RenderHeatmapLayer::impl() const {
|
||||
return static_cast<const style::HeatmapLayer::Impl&>(*baseImpl);
|
||||
}
|
||||
|
||||
std::unique_ptr<Bucket> RenderHeatmapLayer::createBucket(const BucketParameters& parameters, const std::vector<const RenderLayer*>& layers) const {
|
||||
return std::make_unique<HeatmapBucket>(parameters, layers);
|
||||
}
|
||||
|
||||
void RenderHeatmapLayer::transition(const TransitionParameters& parameters) {
|
||||
unevaluated = impl().paint.transitioned(parameters, std::move(unevaluated));
|
||||
}
|
||||
|
||||
void RenderHeatmapLayer::evaluate(const PropertyEvaluationParameters& parameters) {
|
||||
evaluated = unevaluated.evaluate(parameters);
|
||||
|
||||
passes = (evaluated.get<style::HeatmapOpacity>() > 0)
|
||||
? (RenderPass::Translucent | RenderPass::Pass3D)
|
||||
: RenderPass::None;
|
||||
}
|
||||
|
||||
bool RenderHeatmapLayer::hasTransition() const {
|
||||
return unevaluated.hasTransition();
|
||||
}
|
||||
|
||||
void RenderHeatmapLayer::render(PaintParameters& parameters, RenderSource*) {
|
||||
if (parameters.pass == RenderPass::Opaque) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (parameters.pass == RenderPass::Pass3D) {
|
||||
const auto& viewportSize = parameters.staticData.backendSize;
|
||||
const auto size = Size{viewportSize.width / 4, viewportSize.height / 4};
|
||||
|
||||
if (!renderTexture || renderTexture->getSize() != size) {
|
||||
if (parameters.context.supportsHalfFloatTextures) {
|
||||
renderTexture = OffscreenTexture(parameters.context, size, gl::TextureType::HalfFloat);
|
||||
|
||||
try {
|
||||
renderTexture->bind();
|
||||
} catch (const std::runtime_error& ex) {
|
||||
// can't render to a half-float texture; falling back to unsigned byte one
|
||||
renderTexture = nullopt;
|
||||
parameters.context.supportsHalfFloatTextures = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!renderTexture) {
|
||||
renderTexture = OffscreenTexture(parameters.context, size, gl::TextureType::UnsignedByte);
|
||||
renderTexture->bind();
|
||||
}
|
||||
|
||||
} else {
|
||||
renderTexture->bind();
|
||||
}
|
||||
|
||||
if (!colorRampTexture) {
|
||||
colorRampTexture = parameters.context.createTexture(colorRamp, 1, gl::TextureType::UnsignedByte);
|
||||
}
|
||||
|
||||
parameters.context.clear(Color{ 0.0f, 0.0f, 0.0f, 1.0f }, {}, {});
|
||||
|
||||
for (const RenderTile& tile : renderTiles) {
|
||||
assert(dynamic_cast<HeatmapBucket*>(tile.tile.getBucket(*baseImpl)));
|
||||
HeatmapBucket& bucket = *reinterpret_cast<HeatmapBucket*>(tile.tile.getBucket(*baseImpl));
|
||||
|
||||
const auto extrudeScale = tile.id.pixelsToTileUnits(1, parameters.state.getZoom());
|
||||
|
||||
const auto stencilMode = parameters.mapMode != MapMode::Continuous
|
||||
? parameters.stencilModeForClipping(tile.clip)
|
||||
: gl::StencilMode::disabled();
|
||||
|
||||
parameters.programs.heatmap.get(evaluated).draw(
|
||||
parameters.context,
|
||||
gl::Triangles(),
|
||||
parameters.depthModeForSublayer(0, gl::DepthMode::ReadOnly),
|
||||
stencilMode,
|
||||
gl::ColorMode::additive(),
|
||||
HeatmapProgram::UniformValues {
|
||||
uniforms::u_intensity::Value{evaluated.get<style::HeatmapIntensity>()},
|
||||
uniforms::u_matrix::Value{tile.matrix},
|
||||
uniforms::heatmap::u_extrude_scale::Value{extrudeScale}
|
||||
},
|
||||
*bucket.vertexBuffer,
|
||||
*bucket.indexBuffer,
|
||||
bucket.segments,
|
||||
bucket.paintPropertyBinders.at(getID()),
|
||||
evaluated,
|
||||
parameters.state.getZoom(),
|
||||
getID()
|
||||
);
|
||||
}
|
||||
|
||||
} else if (parameters.pass == RenderPass::Translucent) {
|
||||
parameters.context.bindTexture(renderTexture->getTexture(), 0, gl::TextureFilter::Linear);
|
||||
parameters.context.bindTexture(*colorRampTexture, 1, gl::TextureFilter::Linear);
|
||||
|
||||
const auto& size = parameters.staticData.backendSize;
|
||||
|
||||
mat4 viewportMat;
|
||||
matrix::ortho(viewportMat, 0, size.width, size.height, 0, 0, 1);
|
||||
|
||||
const Properties<>::PossiblyEvaluated properties;
|
||||
|
||||
parameters.programs.heatmapTexture.draw(
|
||||
parameters.context, gl::Triangles(), gl::DepthMode::disabled(),
|
||||
gl::StencilMode::disabled(), parameters.colorModeForRenderPass(),
|
||||
HeatmapTextureProgram::UniformValues{
|
||||
uniforms::u_matrix::Value{ viewportMat }, uniforms::u_world::Value{ size },
|
||||
uniforms::u_image::Value{ 0 },
|
||||
uniforms::u_color_ramp::Value{ 1 },
|
||||
uniforms::u_opacity::Value{ evaluated.get<HeatmapOpacity>() } },
|
||||
parameters.staticData.extrusionTextureVertexBuffer,
|
||||
parameters.staticData.quadTriangleIndexBuffer,
|
||||
parameters.staticData.extrusionTextureSegments,
|
||||
HeatmapTextureProgram::PaintPropertyBinders{ properties, 0 }, properties,
|
||||
parameters.state.getZoom(), getID());
|
||||
}
|
||||
}
|
||||
|
||||
void RenderHeatmapLayer::updateColorRamp() {
|
||||
auto colorValue = unevaluated.get<HeatmapColor>().getValue();
|
||||
if (colorValue.isUndefined()) {
|
||||
colorValue = HeatmapLayer::getDefaultHeatmapColor();
|
||||
}
|
||||
|
||||
const auto length = colorRamp.bytes();
|
||||
|
||||
for (uint32_t i = 0; i < length; i += 4) {
|
||||
const auto color = colorValue.evaluate(static_cast<double>(i) / length);
|
||||
colorRamp.data[i + 0] = std::floor(color.r * 255);
|
||||
colorRamp.data[i + 1] = std::floor(color.g * 255);
|
||||
colorRamp.data[i + 2] = std::floor(color.b * 255);
|
||||
colorRamp.data[i + 3] = std::floor(color.a * 255);
|
||||
}
|
||||
|
||||
if (colorRampTexture) {
|
||||
colorRampTexture = nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
bool RenderHeatmapLayer::queryIntersectsFeature(
|
||||
const GeometryCoordinates& queryGeometry,
|
||||
const GeometryTileFeature& feature,
|
||||
const float zoom,
|
||||
const float bearing,
|
||||
const float pixelsToTileUnits) const {
|
||||
(void) queryGeometry;
|
||||
(void) feature;
|
||||
(void) zoom;
|
||||
(void) bearing;
|
||||
(void) pixelsToTileUnits;
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
48
src/mbgl/renderer/layers/render_heatmap_layer.hpp
Normal file
48
src/mbgl/renderer/layers/render_heatmap_layer.hpp
Normal file
@@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/renderer/render_layer.hpp>
|
||||
#include <mbgl/style/layers/heatmap_layer_impl.hpp>
|
||||
#include <mbgl/style/layers/heatmap_layer_properties.hpp>
|
||||
#include <mbgl/util/optional.hpp>
|
||||
#include <mbgl/util/offscreen_texture.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
class RenderHeatmapLayer: public RenderLayer {
|
||||
public:
|
||||
RenderHeatmapLayer(Immutable<style::HeatmapLayer::Impl>);
|
||||
~RenderHeatmapLayer() final = default;
|
||||
|
||||
void transition(const TransitionParameters&) override;
|
||||
void evaluate(const PropertyEvaluationParameters&) override;
|
||||
bool hasTransition() const override;
|
||||
void render(PaintParameters&, RenderSource*) override;
|
||||
|
||||
bool queryIntersectsFeature(
|
||||
const GeometryCoordinates&,
|
||||
const GeometryTileFeature&,
|
||||
const float,
|
||||
const float,
|
||||
const float) const override;
|
||||
|
||||
void updateColorRamp();
|
||||
|
||||
std::unique_ptr<Bucket> createBucket(const BucketParameters&, const std::vector<const RenderLayer*>&) const override;
|
||||
|
||||
// Paint properties
|
||||
style::HeatmapPaintProperties::Unevaluated unevaluated;
|
||||
style::HeatmapPaintProperties::PossiblyEvaluated evaluated;
|
||||
|
||||
const style::HeatmapLayer::Impl& impl() const;
|
||||
|
||||
PremultipliedImage colorRamp;
|
||||
optional<OffscreenTexture> renderTexture;
|
||||
optional<gl::Texture> colorRampTexture;
|
||||
};
|
||||
|
||||
template <>
|
||||
inline bool RenderLayer::is<RenderHeatmapLayer>() const {
|
||||
return type == style::LayerType::Heatmap;
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <mbgl/renderer/layers/render_line_layer.hpp>
|
||||
#include <mbgl/renderer/layers/render_raster_layer.hpp>
|
||||
#include <mbgl/renderer/layers/render_symbol_layer.hpp>
|
||||
#include <mbgl/renderer/layers/render_heatmap_layer.hpp>
|
||||
#include <mbgl/style/types.hpp>
|
||||
#include <mbgl/renderer/render_tile.hpp>
|
||||
|
||||
@@ -35,6 +36,8 @@ std::unique_ptr<RenderLayer> RenderLayer::create(Immutable<Layer::Impl> impl) {
|
||||
return std::make_unique<RenderCustomLayer>(staticImmutableCast<CustomLayer::Impl>(impl));
|
||||
case LayerType::FillExtrusion:
|
||||
return std::make_unique<RenderFillExtrusionLayer>(staticImmutableCast<FillExtrusionLayer::Impl>(impl));
|
||||
case LayerType::Heatmap:
|
||||
return std::make_unique<RenderHeatmapLayer>(staticImmutableCast<HeatmapLayer::Impl>(impl));
|
||||
}
|
||||
|
||||
// Not reachable, but placate GCC.
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <mbgl/renderer/layers/render_background_layer.hpp>
|
||||
#include <mbgl/renderer/layers/render_custom_layer.hpp>
|
||||
#include <mbgl/renderer/layers/render_fill_extrusion_layer.hpp>
|
||||
#include <mbgl/renderer/layers/render_heatmap_layer.hpp>
|
||||
#include <mbgl/renderer/layers/render_hillshade_layer.hpp>
|
||||
#include <mbgl/renderer/style_diff.hpp>
|
||||
#include <mbgl/renderer/query.hpp>
|
||||
@@ -185,6 +186,10 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) {
|
||||
|
||||
if (layerAdded || layerChanged) {
|
||||
layer.transition(transitionParameters);
|
||||
|
||||
if (layer.is<RenderHeatmapLayer>()) {
|
||||
layer.as<RenderHeatmapLayer>()->updateColorRamp();
|
||||
}
|
||||
}
|
||||
|
||||
if (layerAdded || layerChanged || zoomChanged || layer.hasTransition()) {
|
||||
@@ -290,7 +295,11 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) {
|
||||
RenderLayer* layer = getRenderLayer(layerImpl->id);
|
||||
assert(layer);
|
||||
|
||||
if (!parameters.staticData.has3D && (layer->is<RenderFillExtrusionLayer>() || layer->is<RenderHillshadeLayer>())) {
|
||||
if (!parameters.staticData.has3D && (
|
||||
layer->is<RenderFillExtrusionLayer>() ||
|
||||
layer->is<RenderHillshadeLayer>() ||
|
||||
layer->is<RenderHeatmapLayer>())) {
|
||||
|
||||
parameters.staticData.has3D = true;
|
||||
}
|
||||
|
||||
|
||||
128
src/mbgl/shaders/heatmap.cpp
Normal file
128
src/mbgl/shaders/heatmap.cpp
Normal file
@@ -0,0 +1,128 @@
|
||||
// NOTE: DO NOT CHANGE THIS FILE. IT IS AUTOMATICALLY GENERATED.
|
||||
|
||||
#include <mbgl/shaders/heatmap.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace shaders {
|
||||
|
||||
const char* heatmap::name = "heatmap";
|
||||
const char* heatmap::vertexSource = R"MBGL_SHADER(
|
||||
|
||||
#ifndef HAS_UNIFORM_u_weight
|
||||
uniform lowp float a_weight_t;
|
||||
attribute highp vec2 a_weight;
|
||||
varying highp float weight;
|
||||
#else
|
||||
uniform highp float u_weight;
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef HAS_UNIFORM_u_radius
|
||||
uniform lowp float a_radius_t;
|
||||
attribute mediump vec2 a_radius;
|
||||
#else
|
||||
uniform mediump float u_radius;
|
||||
#endif
|
||||
|
||||
|
||||
uniform mat4 u_matrix;
|
||||
uniform float u_extrude_scale;
|
||||
uniform float u_opacity;
|
||||
uniform float u_intensity;
|
||||
|
||||
attribute vec2 a_pos;
|
||||
|
||||
varying vec2 v_extrude;
|
||||
|
||||
// Effective "0" in the kernel density texture to adjust the kernel size to;
|
||||
// this empirically chosen number minimizes artifacts on overlapping kernels
|
||||
// for typical heatmap cases (assuming clustered source)
|
||||
const highp float ZERO = 1.0 / 255.0 / 16.0;
|
||||
|
||||
// Gaussian kernel coefficient: 1 / sqrt(2 * PI)
|
||||
#define GAUSS_COEF 0.3989422804014327
|
||||
|
||||
void main(void) {
|
||||
|
||||
#ifndef HAS_UNIFORM_u_weight
|
||||
weight = unpack_mix_vec2(a_weight, a_weight_t);
|
||||
#else
|
||||
highp float weight = u_weight;
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef HAS_UNIFORM_u_radius
|
||||
mediump float radius = unpack_mix_vec2(a_radius, a_radius_t);
|
||||
#else
|
||||
mediump float radius = u_radius;
|
||||
#endif
|
||||
|
||||
|
||||
// unencode the extrusion vector that we snuck into the a_pos vector
|
||||
vec2 unscaled_extrude = vec2(mod(a_pos, 2.0) * 2.0 - 1.0);
|
||||
|
||||
// This 'extrude' comes in ranging from [-1, -1], to [1, 1]. We'll use
|
||||
// it to produce the vertices of a square mesh framing the point feature
|
||||
// we're adding to the kernel density texture. We'll also pass it as
|
||||
// a varying, so that the fragment shader can determine the distance of
|
||||
// each fragment from the point feature.
|
||||
// Before we do so, we need to scale it up sufficiently so that the
|
||||
// kernel falls effectively to zero at the edge of the mesh.
|
||||
// That is, we want to know S such that
|
||||
// weight * u_intensity * GAUSS_COEF * exp(-0.5 * 3.0^2 * S^2) == ZERO
|
||||
// Which solves to:
|
||||
// S = sqrt(-2.0 * log(ZERO / (weight * u_intensity * GAUSS_COEF))) / 3.0
|
||||
float S = sqrt(-2.0 * log(ZERO / weight / u_intensity / GAUSS_COEF)) / 3.0;
|
||||
|
||||
// Pass the varying in units of radius
|
||||
v_extrude = S * unscaled_extrude;
|
||||
|
||||
// Scale by radius and the zoom-based scale factor to produce actual
|
||||
// mesh position
|
||||
vec2 extrude = v_extrude * radius * u_extrude_scale;
|
||||
|
||||
// multiply a_pos by 0.5, since we had it * 2 in order to sneak
|
||||
// in extrusion data
|
||||
vec4 pos = vec4(floor(a_pos * 0.5) + extrude, 0, 1);
|
||||
|
||||
gl_Position = u_matrix * pos;
|
||||
}
|
||||
|
||||
)MBGL_SHADER";
|
||||
const char* heatmap::fragmentSource = R"MBGL_SHADER(
|
||||
|
||||
#ifndef HAS_UNIFORM_u_weight
|
||||
varying highp float weight;
|
||||
#else
|
||||
uniform highp float u_weight;
|
||||
#endif
|
||||
|
||||
|
||||
uniform highp float u_intensity;
|
||||
varying vec2 v_extrude;
|
||||
|
||||
// Gaussian kernel coefficient: 1 / sqrt(2 * PI)
|
||||
#define GAUSS_COEF 0.3989422804014327
|
||||
|
||||
void main() {
|
||||
|
||||
#ifdef HAS_UNIFORM_u_weight
|
||||
highp float weight = u_weight;
|
||||
#endif
|
||||
|
||||
|
||||
// Kernel density estimation with a Gaussian kernel of size 5x5
|
||||
float d = -0.5 * 3.0 * 3.0 * dot(v_extrude, v_extrude);
|
||||
float val = weight * u_intensity * GAUSS_COEF * exp(d);
|
||||
|
||||
gl_FragColor = vec4(val, 1.0, 1.0, 1.0);
|
||||
|
||||
#ifdef OVERDRAW_INSPECTOR
|
||||
gl_FragColor = vec4(1.0);
|
||||
#endif
|
||||
}
|
||||
|
||||
)MBGL_SHADER";
|
||||
|
||||
} // namespace shaders
|
||||
} // namespace mbgl
|
||||
16
src/mbgl/shaders/heatmap.hpp
Normal file
16
src/mbgl/shaders/heatmap.hpp
Normal file
@@ -0,0 +1,16 @@
|
||||
// NOTE: DO NOT CHANGE THIS FILE. IT IS AUTOMATICALLY GENERATED.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace mbgl {
|
||||
namespace shaders {
|
||||
|
||||
class heatmap {
|
||||
public:
|
||||
static const char* name;
|
||||
static const char* vertexSource;
|
||||
static const char* fragmentSource;
|
||||
};
|
||||
|
||||
} // namespace shaders
|
||||
} // namespace mbgl
|
||||
42
src/mbgl/shaders/heatmap_texture.cpp
Normal file
42
src/mbgl/shaders/heatmap_texture.cpp
Normal file
@@ -0,0 +1,42 @@
|
||||
// NOTE: DO NOT CHANGE THIS FILE. IT IS AUTOMATICALLY GENERATED.
|
||||
|
||||
#include <mbgl/shaders/heatmap_texture.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace shaders {
|
||||
|
||||
const char* heatmap_texture::name = "heatmap_texture";
|
||||
const char* heatmap_texture::vertexSource = R"MBGL_SHADER(
|
||||
uniform mat4 u_matrix;
|
||||
uniform vec2 u_world;
|
||||
attribute vec2 a_pos;
|
||||
varying vec2 v_pos;
|
||||
|
||||
void main() {
|
||||
gl_Position = u_matrix * vec4(a_pos * u_world, 0, 1);
|
||||
|
||||
v_pos.x = a_pos.x;
|
||||
v_pos.y = 1.0 - a_pos.y;
|
||||
}
|
||||
|
||||
)MBGL_SHADER";
|
||||
const char* heatmap_texture::fragmentSource = R"MBGL_SHADER(
|
||||
uniform sampler2D u_image;
|
||||
uniform sampler2D u_color_ramp;
|
||||
uniform float u_opacity;
|
||||
varying vec2 v_pos;
|
||||
|
||||
void main() {
|
||||
float t = texture2D(u_image, v_pos).r;
|
||||
vec4 color = texture2D(u_color_ramp, vec2(t, 0.5));
|
||||
gl_FragColor = color * u_opacity;
|
||||
|
||||
#ifdef OVERDRAW_INSPECTOR
|
||||
gl_FragColor = vec4(0.0);
|
||||
#endif
|
||||
}
|
||||
|
||||
)MBGL_SHADER";
|
||||
|
||||
} // namespace shaders
|
||||
} // namespace mbgl
|
||||
16
src/mbgl/shaders/heatmap_texture.hpp
Normal file
16
src/mbgl/shaders/heatmap_texture.hpp
Normal file
@@ -0,0 +1,16 @@
|
||||
// NOTE: DO NOT CHANGE THIS FILE. IT IS AUTOMATICALLY GENERATED.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace mbgl {
|
||||
namespace shaders {
|
||||
|
||||
class heatmap_texture {
|
||||
public:
|
||||
static const char* name;
|
||||
static const char* vertexSource;
|
||||
static const char* fragmentSource;
|
||||
};
|
||||
|
||||
} // namespace shaders
|
||||
} // namespace mbgl
|
||||
@@ -6,6 +6,7 @@
|
||||
#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/heatmap_layer.hpp>
|
||||
#include <mbgl/style/layers/hillshade_layer.hpp>
|
||||
#include <mbgl/style/layers/line_layer.hpp>
|
||||
#include <mbgl/style/layers/raster_layer.hpp>
|
||||
@@ -165,6 +166,8 @@ optional<std::unique_ptr<Layer>> Converter<std::unique_ptr<Layer>>::operator()(c
|
||||
converted = convertVectorLayer<SymbolLayer>(*id, value, error);
|
||||
} else if (*type == "raster") {
|
||||
converted = convertRasterLayer(*id, value, error);
|
||||
} else if (*type == "heatmap") {
|
||||
converted = convertVectorLayer<HeatmapLayer>(*id, value, error);
|
||||
} else if (*type == "hillshade") {
|
||||
converted = convertHillshadeLayer(*id, value, error);
|
||||
} else if (*type == "background") {
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <mbgl/style/layers/line_layer.hpp>
|
||||
#include <mbgl/style/layers/symbol_layer.hpp>
|
||||
#include <mbgl/style/layers/circle_layer.hpp>
|
||||
#include <mbgl/style/layers/heatmap_layer.hpp>
|
||||
#include <mbgl/style/layers/fill_extrusion_layer.hpp>
|
||||
#include <mbgl/style/layers/raster_layer.hpp>
|
||||
#include <mbgl/style/layers/hillshade_layer.hpp>
|
||||
@@ -72,6 +73,7 @@ inline auto makeLayoutPropertySetters() {
|
||||
|
||||
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -166,6 +168,17 @@ inline auto makePaintPropertySetters() {
|
||||
result["circle-stroke-opacity"] = &setProperty<CircleLayer, DataDrivenPropertyValue<float>, &CircleLayer::setCircleStrokeOpacity>;
|
||||
result["circle-stroke-opacity-transition"] = &setTransition<CircleLayer, &CircleLayer::setCircleStrokeOpacityTransition>;
|
||||
|
||||
result["heatmap-radius"] = &setProperty<HeatmapLayer, DataDrivenPropertyValue<float>, &HeatmapLayer::setHeatmapRadius>;
|
||||
result["heatmap-radius-transition"] = &setTransition<HeatmapLayer, &HeatmapLayer::setHeatmapRadiusTransition>;
|
||||
result["heatmap-weight"] = &setProperty<HeatmapLayer, DataDrivenPropertyValue<float>, &HeatmapLayer::setHeatmapWeight>;
|
||||
result["heatmap-weight-transition"] = &setTransition<HeatmapLayer, &HeatmapLayer::setHeatmapWeightTransition>;
|
||||
result["heatmap-intensity"] = &setProperty<HeatmapLayer, PropertyValue<float>, &HeatmapLayer::setHeatmapIntensity>;
|
||||
result["heatmap-intensity-transition"] = &setTransition<HeatmapLayer, &HeatmapLayer::setHeatmapIntensityTransition>;
|
||||
result["heatmap-color"] = &setProperty<HeatmapLayer, HeatmapColorPropertyValue, &HeatmapLayer::setHeatmapColor>;
|
||||
result["heatmap-color-transition"] = &setTransition<HeatmapLayer, &HeatmapLayer::setHeatmapColorTransition>;
|
||||
result["heatmap-opacity"] = &setProperty<HeatmapLayer, PropertyValue<float>, &HeatmapLayer::setHeatmapOpacity>;
|
||||
result["heatmap-opacity-transition"] = &setTransition<HeatmapLayer, &HeatmapLayer::setHeatmapOpacityTransition>;
|
||||
|
||||
result["fill-extrusion-opacity"] = &setProperty<FillExtrusionLayer, PropertyValue<float>, &FillExtrusionLayer::setFillExtrusionOpacity>;
|
||||
result["fill-extrusion-opacity-transition"] = &setTransition<FillExtrusionLayer, &FillExtrusionLayer::setFillExtrusionOpacityTransition>;
|
||||
result["fill-extrusion-color"] = &setProperty<FillExtrusionLayer, DataDrivenPropertyValue<Color>, &FillExtrusionLayer::setFillExtrusionColor>;
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <mbgl/style/conversion/constant.hpp>
|
||||
#include <mbgl/style/conversion/property_value.hpp>
|
||||
#include <mbgl/style/conversion/data_driven_property_value.hpp>
|
||||
#include <mbgl/style/conversion/heatmap_color_property_value.hpp>
|
||||
#include <mbgl/style/conversion/transition_options.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
239
src/mbgl/style/layers/heatmap_layer.cpp
Normal file
239
src/mbgl/style/layers/heatmap_layer.cpp
Normal file
@@ -0,0 +1,239 @@
|
||||
// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`.
|
||||
|
||||
#include <mbgl/style/layers/heatmap_layer.hpp>
|
||||
#include <mbgl/style/layers/heatmap_layer_impl.hpp>
|
||||
#include <mbgl/style/layer_observer.hpp>
|
||||
// for constructing default heatmap-color ramp expression from style JSON
|
||||
#include <mbgl/style/conversion.hpp>
|
||||
#include <mbgl/style/conversion/json.hpp>
|
||||
#include <mbgl/style/conversion/heatmap_color_property_value.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace style {
|
||||
|
||||
HeatmapLayer::HeatmapLayer(const std::string& layerID, const std::string& sourceID)
|
||||
: Layer(makeMutable<Impl>(LayerType::Heatmap, layerID, sourceID)) {
|
||||
}
|
||||
|
||||
HeatmapLayer::HeatmapLayer(Immutable<Impl> impl_)
|
||||
: Layer(std::move(impl_)) {
|
||||
}
|
||||
|
||||
HeatmapLayer::~HeatmapLayer() = default;
|
||||
|
||||
const HeatmapLayer::Impl& HeatmapLayer::impl() const {
|
||||
return static_cast<const Impl&>(*baseImpl);
|
||||
}
|
||||
|
||||
Mutable<HeatmapLayer::Impl> HeatmapLayer::mutableImpl() const {
|
||||
return makeMutable<Impl>(impl());
|
||||
}
|
||||
|
||||
std::unique_ptr<Layer> HeatmapLayer::cloneRef(const std::string& id_) const {
|
||||
auto impl_ = mutableImpl();
|
||||
impl_->id = id_;
|
||||
impl_->paint = HeatmapPaintProperties::Transitionable();
|
||||
return std::make_unique<HeatmapLayer>(std::move(impl_));
|
||||
}
|
||||
|
||||
void HeatmapLayer::Impl::stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>&) const {
|
||||
}
|
||||
|
||||
// Source
|
||||
|
||||
const std::string& HeatmapLayer::getSourceID() const {
|
||||
return impl().source;
|
||||
}
|
||||
|
||||
void HeatmapLayer::setSourceLayer(const std::string& sourceLayer) {
|
||||
auto impl_ = mutableImpl();
|
||||
impl_->sourceLayer = sourceLayer;
|
||||
baseImpl = std::move(impl_);
|
||||
}
|
||||
|
||||
const std::string& HeatmapLayer::getSourceLayer() const {
|
||||
return impl().sourceLayer;
|
||||
}
|
||||
|
||||
// Filter
|
||||
|
||||
void HeatmapLayer::setFilter(const Filter& filter) {
|
||||
auto impl_ = mutableImpl();
|
||||
impl_->filter = filter;
|
||||
baseImpl = std::move(impl_);
|
||||
observer->onLayerChanged(*this);
|
||||
}
|
||||
|
||||
const Filter& HeatmapLayer::getFilter() const {
|
||||
return impl().filter;
|
||||
}
|
||||
|
||||
// Visibility
|
||||
|
||||
void HeatmapLayer::setVisibility(VisibilityType value) {
|
||||
if (value == getVisibility())
|
||||
return;
|
||||
auto impl_ = mutableImpl();
|
||||
impl_->visibility = value;
|
||||
baseImpl = std::move(impl_);
|
||||
observer->onLayerChanged(*this);
|
||||
}
|
||||
|
||||
// Zoom range
|
||||
|
||||
void HeatmapLayer::setMinZoom(float minZoom) {
|
||||
auto impl_ = mutableImpl();
|
||||
impl_->minZoom = minZoom;
|
||||
baseImpl = std::move(impl_);
|
||||
}
|
||||
|
||||
void HeatmapLayer::setMaxZoom(float maxZoom) {
|
||||
auto impl_ = mutableImpl();
|
||||
impl_->maxZoom = maxZoom;
|
||||
baseImpl = std::move(impl_);
|
||||
}
|
||||
|
||||
// Layout properties
|
||||
|
||||
|
||||
// Paint properties
|
||||
|
||||
DataDrivenPropertyValue<float> HeatmapLayer::getDefaultHeatmapRadius() {
|
||||
return { 30 };
|
||||
}
|
||||
|
||||
DataDrivenPropertyValue<float> HeatmapLayer::getHeatmapRadius() const {
|
||||
return impl().paint.template get<HeatmapRadius>().value;
|
||||
}
|
||||
|
||||
void HeatmapLayer::setHeatmapRadius(DataDrivenPropertyValue<float> value) {
|
||||
if (value == getHeatmapRadius())
|
||||
return;
|
||||
auto impl_ = mutableImpl();
|
||||
impl_->paint.template get<HeatmapRadius>().value = value;
|
||||
baseImpl = std::move(impl_);
|
||||
observer->onLayerChanged(*this);
|
||||
}
|
||||
|
||||
void HeatmapLayer::setHeatmapRadiusTransition(const TransitionOptions& options) {
|
||||
auto impl_ = mutableImpl();
|
||||
impl_->paint.template get<HeatmapRadius>().options = options;
|
||||
baseImpl = std::move(impl_);
|
||||
}
|
||||
|
||||
TransitionOptions HeatmapLayer::getHeatmapRadiusTransition() const {
|
||||
return impl().paint.template get<HeatmapRadius>().options;
|
||||
}
|
||||
|
||||
DataDrivenPropertyValue<float> HeatmapLayer::getDefaultHeatmapWeight() {
|
||||
return { 1 };
|
||||
}
|
||||
|
||||
DataDrivenPropertyValue<float> HeatmapLayer::getHeatmapWeight() const {
|
||||
return impl().paint.template get<HeatmapWeight>().value;
|
||||
}
|
||||
|
||||
void HeatmapLayer::setHeatmapWeight(DataDrivenPropertyValue<float> value) {
|
||||
if (value == getHeatmapWeight())
|
||||
return;
|
||||
auto impl_ = mutableImpl();
|
||||
impl_->paint.template get<HeatmapWeight>().value = value;
|
||||
baseImpl = std::move(impl_);
|
||||
observer->onLayerChanged(*this);
|
||||
}
|
||||
|
||||
void HeatmapLayer::setHeatmapWeightTransition(const TransitionOptions& options) {
|
||||
auto impl_ = mutableImpl();
|
||||
impl_->paint.template get<HeatmapWeight>().options = options;
|
||||
baseImpl = std::move(impl_);
|
||||
}
|
||||
|
||||
TransitionOptions HeatmapLayer::getHeatmapWeightTransition() const {
|
||||
return impl().paint.template get<HeatmapWeight>().options;
|
||||
}
|
||||
|
||||
PropertyValue<float> HeatmapLayer::getDefaultHeatmapIntensity() {
|
||||
return { 1 };
|
||||
}
|
||||
|
||||
PropertyValue<float> HeatmapLayer::getHeatmapIntensity() const {
|
||||
return impl().paint.template get<HeatmapIntensity>().value;
|
||||
}
|
||||
|
||||
void HeatmapLayer::setHeatmapIntensity(PropertyValue<float> value) {
|
||||
if (value == getHeatmapIntensity())
|
||||
return;
|
||||
auto impl_ = mutableImpl();
|
||||
impl_->paint.template get<HeatmapIntensity>().value = value;
|
||||
baseImpl = std::move(impl_);
|
||||
observer->onLayerChanged(*this);
|
||||
}
|
||||
|
||||
void HeatmapLayer::setHeatmapIntensityTransition(const TransitionOptions& options) {
|
||||
auto impl_ = mutableImpl();
|
||||
impl_->paint.template get<HeatmapIntensity>().options = options;
|
||||
baseImpl = std::move(impl_);
|
||||
}
|
||||
|
||||
TransitionOptions HeatmapLayer::getHeatmapIntensityTransition() const {
|
||||
return impl().paint.template get<HeatmapIntensity>().options;
|
||||
}
|
||||
|
||||
HeatmapColorPropertyValue HeatmapLayer::getDefaultHeatmapColor() {
|
||||
conversion::Error error;
|
||||
std::string rawValue = R"JSON(["interpolate",["linear"],["heatmap-density"],0,"rgba(0, 0, 255, 0)",0.1,"royalblue",0.3,"cyan",0.5,"lime",0.7,"yellow",1,"red"])JSON";
|
||||
return *conversion::convertJSON<HeatmapColorPropertyValue>(rawValue, error);
|
||||
}
|
||||
|
||||
HeatmapColorPropertyValue HeatmapLayer::getHeatmapColor() const {
|
||||
return impl().paint.template get<HeatmapColor>().value;
|
||||
}
|
||||
|
||||
void HeatmapLayer::setHeatmapColor(HeatmapColorPropertyValue value) {
|
||||
if (value == getHeatmapColor())
|
||||
return;
|
||||
auto impl_ = mutableImpl();
|
||||
impl_->paint.template get<HeatmapColor>().value = value;
|
||||
baseImpl = std::move(impl_);
|
||||
observer->onLayerChanged(*this);
|
||||
}
|
||||
|
||||
void HeatmapLayer::setHeatmapColorTransition(const TransitionOptions& options) {
|
||||
auto impl_ = mutableImpl();
|
||||
impl_->paint.template get<HeatmapColor>().options = options;
|
||||
baseImpl = std::move(impl_);
|
||||
}
|
||||
|
||||
TransitionOptions HeatmapLayer::getHeatmapColorTransition() const {
|
||||
return impl().paint.template get<HeatmapColor>().options;
|
||||
}
|
||||
|
||||
PropertyValue<float> HeatmapLayer::getDefaultHeatmapOpacity() {
|
||||
return { 1 };
|
||||
}
|
||||
|
||||
PropertyValue<float> HeatmapLayer::getHeatmapOpacity() const {
|
||||
return impl().paint.template get<HeatmapOpacity>().value;
|
||||
}
|
||||
|
||||
void HeatmapLayer::setHeatmapOpacity(PropertyValue<float> value) {
|
||||
if (value == getHeatmapOpacity())
|
||||
return;
|
||||
auto impl_ = mutableImpl();
|
||||
impl_->paint.template get<HeatmapOpacity>().value = value;
|
||||
baseImpl = std::move(impl_);
|
||||
observer->onLayerChanged(*this);
|
||||
}
|
||||
|
||||
void HeatmapLayer::setHeatmapOpacityTransition(const TransitionOptions& options) {
|
||||
auto impl_ = mutableImpl();
|
||||
impl_->paint.template get<HeatmapOpacity>().options = options;
|
||||
baseImpl = std::move(impl_);
|
||||
}
|
||||
|
||||
TransitionOptions HeatmapLayer::getHeatmapOpacityTransition() const {
|
||||
return impl().paint.template get<HeatmapOpacity>().options;
|
||||
}
|
||||
|
||||
} // namespace style
|
||||
} // namespace mbgl
|
||||
15
src/mbgl/style/layers/heatmap_layer_impl.cpp
Normal file
15
src/mbgl/style/layers/heatmap_layer_impl.cpp
Normal file
@@ -0,0 +1,15 @@
|
||||
#include <mbgl/style/layers/heatmap_layer_impl.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace style {
|
||||
|
||||
bool HeatmapLayer::Impl::hasLayoutDifference(const Layer::Impl& other) const {
|
||||
assert(dynamic_cast<const HeatmapLayer::Impl*>(&other));
|
||||
const auto& impl = static_cast<const style::HeatmapLayer::Impl&>(other);
|
||||
return filter != impl.filter ||
|
||||
visibility != impl.visibility ||
|
||||
paint.hasDataDrivenPropertyDifference(impl.paint);
|
||||
}
|
||||
|
||||
} // namespace style
|
||||
} // namespace mbgl
|
||||
21
src/mbgl/style/layers/heatmap_layer_impl.hpp
Normal file
21
src/mbgl/style/layers/heatmap_layer_impl.hpp
Normal file
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/style/layer_impl.hpp>
|
||||
#include <mbgl/style/layers/heatmap_layer.hpp>
|
||||
#include <mbgl/style/layers/heatmap_layer_properties.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace style {
|
||||
|
||||
class HeatmapLayer::Impl : public Layer::Impl {
|
||||
public:
|
||||
using Layer::Impl::Impl;
|
||||
|
||||
bool hasLayoutDifference(const Layer::Impl&) const override;
|
||||
void stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>&) const override;
|
||||
|
||||
HeatmapPaintProperties::Transitionable paint;
|
||||
};
|
||||
|
||||
} // namespace style
|
||||
} // namespace mbgl
|
||||
9
src/mbgl/style/layers/heatmap_layer_properties.cpp
Normal file
9
src/mbgl/style/layers/heatmap_layer_properties.cpp
Normal file
@@ -0,0 +1,9 @@
|
||||
// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`.
|
||||
|
||||
#include <mbgl/style/layers/heatmap_layer_properties.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace style {
|
||||
|
||||
} // namespace style
|
||||
} // namespace mbgl
|
||||
40
src/mbgl/style/layers/heatmap_layer_properties.hpp
Normal file
40
src/mbgl/style/layers/heatmap_layer_properties.hpp
Normal file
@@ -0,0 +1,40 @@
|
||||
// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/style/types.hpp>
|
||||
#include <mbgl/style/layout_property.hpp>
|
||||
#include <mbgl/style/paint_property.hpp>
|
||||
#include <mbgl/style/properties.hpp>
|
||||
#include <mbgl/programs/attributes.hpp>
|
||||
#include <mbgl/programs/uniforms.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace style {
|
||||
|
||||
struct HeatmapRadius : DataDrivenPaintProperty<float, attributes::a_radius, uniforms::u_radius> {
|
||||
static float defaultValue() { return 30; }
|
||||
};
|
||||
|
||||
struct HeatmapWeight : DataDrivenPaintProperty<float, attributes::a_weight, uniforms::u_weight> {
|
||||
static float defaultValue() { return 1; }
|
||||
};
|
||||
|
||||
struct HeatmapIntensity : PaintProperty<float> {
|
||||
static float defaultValue() { return 1; }
|
||||
};
|
||||
|
||||
struct HeatmapOpacity : PaintProperty<float> {
|
||||
static float defaultValue() { return 1; }
|
||||
};
|
||||
|
||||
class HeatmapPaintProperties : public Properties<
|
||||
HeatmapRadius,
|
||||
HeatmapWeight,
|
||||
HeatmapIntensity,
|
||||
HeatmapColor,
|
||||
HeatmapOpacity
|
||||
> {};
|
||||
|
||||
} // namespace style
|
||||
} // namespace mbgl
|
||||
@@ -8,6 +8,12 @@
|
||||
#include <mbgl/style/layers/<%- type.replace('-', '_') %>_layer.hpp>
|
||||
#include <mbgl/style/layers/<%- type.replace('-', '_') %>_layer_impl.hpp>
|
||||
#include <mbgl/style/layer_observer.hpp>
|
||||
<% if (type === 'heatmap') { -%>
|
||||
// for constructing default heatmap-color ramp expression from style JSON
|
||||
#include <mbgl/style/conversion.hpp>
|
||||
#include <mbgl/style/conversion/json.hpp>
|
||||
#include <mbgl/style/conversion/heatmap_color_property_value.hpp>
|
||||
<% } -%>
|
||||
|
||||
namespace mbgl {
|
||||
namespace style {
|
||||
@@ -134,7 +140,13 @@ void <%- camelize(type) %>Layer::set<%- camelize(property.name) %>(<%- propertyV
|
||||
// Paint properties
|
||||
<% for (const property of paintProperties) { %>
|
||||
<%- propertyValueType(property) %> <%- camelize(type) %>Layer::getDefault<%- camelize(property.name) %>() {
|
||||
<% if (property.name === 'heatmap-color') { -%>
|
||||
conversion::Error error;
|
||||
std::string rawValue = R"JSON(<%- JSON.stringify(property.default) %>)JSON";
|
||||
return *conversion::convertJSON<<%- propertyValueType(property)%>>(rawValue, error);
|
||||
<% } else { -%>
|
||||
return { <%- defaultValue(property) %> };
|
||||
<% } -%>
|
||||
}
|
||||
|
||||
<%- propertyValueType(property) %> <%- camelize(type) %>Layer::get<%- camelize(property.name) %>() const {
|
||||
|
||||
@@ -25,6 +25,7 @@ struct <%- camelize(property.name) %> : <%- layoutPropertyType(property, type) %
|
||||
|
||||
<% } -%>
|
||||
<% for (const property of paintProperties) { -%>
|
||||
<% if (property.name === 'heatmap-color') continue; -%>
|
||||
struct <%- camelize(property.name) %> : <%- paintPropertyType(property, type) %> {
|
||||
static <%- evaluatedType(property) %> defaultValue() { return <%- defaultValue(property) %>; }
|
||||
};
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <mbgl/style/properties.hpp>
|
||||
#include <mbgl/style/property_value.hpp>
|
||||
#include <mbgl/style/heatmap_color_property_value.hpp>
|
||||
#include <mbgl/style/data_driven_property_value.hpp>
|
||||
#include <mbgl/renderer/property_evaluator.hpp>
|
||||
#include <mbgl/renderer/cross_faded_property_evaluator.hpp>
|
||||
@@ -48,5 +49,27 @@ public:
|
||||
static constexpr bool IsDataDriven = false;
|
||||
};
|
||||
|
||||
/*
|
||||
* Special-case paint property traits for heatmap-color, needed because
|
||||
* heatmap-color values do not fit into the
|
||||
* Undefined | Value | {Camera,Source,Composite}Function taxonomy that applies
|
||||
* to all other paint properties.
|
||||
*
|
||||
* These traits are provided here--despite the fact that heatmap-color
|
||||
* is not used like other paint properties--to allow the parameter-pack-based
|
||||
* batch evaluation of paint properties to compile properly.
|
||||
*/
|
||||
class HeatmapColor {
|
||||
public:
|
||||
using TransitionableType = Transitionable<HeatmapColorPropertyValue>;
|
||||
using UnevaluatedType = Transitioning<HeatmapColorPropertyValue>;
|
||||
using EvaluatorType = PropertyEvaluator<Color>;
|
||||
using PossiblyEvaluatedType = Color;
|
||||
using Type = Color;
|
||||
static constexpr bool IsDataDriven = false;
|
||||
|
||||
static Color defaultValue() { return {}; }
|
||||
};
|
||||
|
||||
} // namespace style
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <mbgl/style/layers/background_layer.hpp>
|
||||
#include <mbgl/style/layers/fill_layer.hpp>
|
||||
#include <mbgl/style/layers/fill_extrusion_layer.hpp>
|
||||
#include <mbgl/style/layers/heatmap_layer.hpp>
|
||||
#include <mbgl/style/layers/line_layer.hpp>
|
||||
#include <mbgl/style/layers/circle_layer.hpp>
|
||||
#include <mbgl/style/layers/raster_layer.hpp>
|
||||
|
||||
@@ -11,20 +11,21 @@ OffscreenTexture& OffscreenTexture::operator=(OffscreenTexture&&) = default;
|
||||
|
||||
class OffscreenTexture::Impl {
|
||||
public:
|
||||
Impl(gl::Context& context_, const Size size_)
|
||||
: context(context_), size(std::move(size_)) {
|
||||
Impl(gl::Context& context_, const Size size_, const gl::TextureType type_)
|
||||
: context(context_), size(std::move(size_)), type(type_) {
|
||||
assert(!size.isEmpty());
|
||||
}
|
||||
Impl(gl::Context& context_,
|
||||
const Size size_,
|
||||
gl::Renderbuffer<gl::RenderbufferType::DepthComponent>& depth_)
|
||||
: context(context_), size(std::move(size_)), depth(&depth_) {
|
||||
gl::Renderbuffer<gl::RenderbufferType::DepthComponent>& depth_,
|
||||
const gl::TextureType type_)
|
||||
: context(context_), size(std::move(size_)), depth(&depth_), type(type_) {
|
||||
assert(!size.isEmpty());
|
||||
}
|
||||
|
||||
void bind() {
|
||||
if (!framebuffer) {
|
||||
texture = context.createTexture(size, gl::TextureFormat::RGBA);
|
||||
texture = context.createTexture(size, gl::TextureFormat::RGBA, 0, type);
|
||||
if (depth) {
|
||||
framebuffer = context.createFramebuffer(*texture, *depth);
|
||||
} else {
|
||||
@@ -58,18 +59,21 @@ private:
|
||||
optional<gl::Framebuffer> framebuffer;
|
||||
optional<gl::Texture> texture;
|
||||
gl::Renderbuffer<gl::RenderbufferType::DepthComponent>* depth = nullptr;
|
||||
const gl::TextureType type;
|
||||
};
|
||||
|
||||
OffscreenTexture::OffscreenTexture(gl::Context& context,
|
||||
const Size size)
|
||||
: impl(std::make_unique<Impl>(context, std::move(size))) {
|
||||
const Size size,
|
||||
const gl::TextureType type)
|
||||
: impl(std::make_unique<Impl>(context, std::move(size), type)) {
|
||||
assert(!size.isEmpty());
|
||||
}
|
||||
|
||||
OffscreenTexture::OffscreenTexture(gl::Context& context,
|
||||
const Size size,
|
||||
gl::Renderbuffer<gl::RenderbufferType::DepthComponent>& renderbuffer)
|
||||
: impl(std::make_unique<Impl>(context, std::move(size), renderbuffer)) {
|
||||
gl::Renderbuffer<gl::RenderbufferType::DepthComponent>& renderbuffer,
|
||||
const gl::TextureType type)
|
||||
: impl(std::make_unique<Impl>(context, std::move(size), renderbuffer, type)) {
|
||||
assert(!size.isEmpty());
|
||||
}
|
||||
|
||||
|
||||
@@ -12,10 +12,12 @@ class Texture;
|
||||
class OffscreenTexture {
|
||||
public:
|
||||
OffscreenTexture(gl::Context&,
|
||||
Size size = { 256, 256 });
|
||||
Size size = { 256, 256 },
|
||||
gl::TextureType type = gl::TextureType::UnsignedByte);
|
||||
OffscreenTexture(gl::Context&,
|
||||
Size size,
|
||||
gl::Renderbuffer<gl::RenderbufferType::DepthComponent>&);
|
||||
gl::Renderbuffer<gl::RenderbufferType::DepthComponent>&,
|
||||
gl::TextureType type = gl::TextureType::UnsignedByte);
|
||||
~OffscreenTexture();
|
||||
OffscreenTexture(OffscreenTexture&&);
|
||||
OffscreenTexture& operator=(OffscreenTexture&&);
|
||||
|
||||
Reference in New Issue
Block a user