Merge branch 'master' into release-boba
# Conflicts: # platform/android/CHANGELOG.md # platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/Mapbox.java # platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/CompassView.java # platform/android/scripts/exclude-activity-gen.json # platform/ios/CHANGELOG.md # platform/ios/Mapbox-iOS-SDK-nightly-dynamic.podspec # platform/ios/Mapbox-iOS-SDK-symbols.podspec # platform/ios/Mapbox-iOS-SDK.podspec # platform/macos/CHANGELOG.md
This commit is contained in:
58
INSTALL.md
58
INSTALL.md
@@ -7,50 +7,38 @@ that you can download instantly and get started with fast](https://www.mapbox.co
|
||||
Still with us? These are the instructions you'll need to build Mapbox GL Native
|
||||
from source on a variety of platforms and set up a development environment.
|
||||
|
||||
Your journey will start with getting the source code, then installing the
|
||||
dependencies, and then setting up a development environment, which varies
|
||||
depending on your operating system and what platform you want to develop for.
|
||||
Your journey will start with installing dependencies, then getting the source code, and
|
||||
then setting up a development environment, which varies depending on your
|
||||
operating system and what platform you want to develop for.
|
||||
|
||||
## 1: Getting the source
|
||||
## 1: Installing dependencies
|
||||
|
||||
Clone the git repository:
|
||||
### macOS
|
||||
|
||||
git clone https://github.com/mapbox/mapbox-gl-native.git
|
||||
cd mapbox-gl-native
|
||||
1. Install [Xcode](https://developer.apple.com/xcode/)
|
||||
2. Launch Xcode and install any updates
|
||||
3. Install [Homebrew](http://brew.sh)
|
||||
4. Install [Node.js](https://nodejs.org/), [CMake](https://cmake.org/), and [ccache](https://ccache.samba.org) with `brew install nodejs cmake ccache`
|
||||
5. Install [xcpretty](https://github.com/supermarin/xcpretty) with `[sudo] gem install xcpretty` (optional, used for prettifying command line builds)
|
||||
|
||||
## 2: Installing dependencies
|
||||
### Linux
|
||||
|
||||
These dependencies are required for all operating systems and all platform
|
||||
targets.
|
||||
|
||||
- Modern C++ compiler that supports `-std=c++14`\*
|
||||
- clang++ 3.5 or later _or_
|
||||
- g++-4.9 or later
|
||||
- [CMake](https://cmake.org/) 3.1 or later (for build only)
|
||||
- [cURL](https://curl.haxx.se) (for build only)
|
||||
- [Node.js](https://nodejs.org/) 4.2.1 or later (for build only)
|
||||
- [`pkg-config`](https://wiki.freedesktop.org/www/Software/pkg-config/) (for build only)
|
||||
|
||||
**Note**: We partially support C++14 because GCC 4.9 does not fully implement the
|
||||
final draft of the C++14 standard. More information in [DEVELOPING.md](DEVELOPING.md).
|
||||
|
||||
Depending on your operating system and target, you'll need additional
|
||||
dependencies:
|
||||
|
||||
### Additional dependencies for Linux
|
||||
Install the following:
|
||||
|
||||
- `clang++` 3.5 or later or `g++` 4.9 or later
|
||||
- [git](https://git-scm.com/)
|
||||
- [CMake](https://cmake.org/) 3.1 or later
|
||||
- [cURL](https://curl.haxx.se)
|
||||
- [Node.js](https://nodejs.org/) 4.2.1 or later
|
||||
- [`libcurl`](http://curl.haxx.se/libcurl/) (depends on OpenSSL)
|
||||
- [ccache](https://ccache.samba.org) (optional, improves recompilation performance)
|
||||
|
||||
### Additional dependencies for macOS
|
||||
## 2: Getting the source
|
||||
|
||||
- Apple Command Line Tools (available at [Apple Developer](https://developer.apple.com/download/more/))
|
||||
- [Homebrew](http://brew.sh)
|
||||
- [Cask](http://caskroom.io/) (if building for Android)
|
||||
- [xcpretty](https://github.com/supermarin/xcpretty) (`gem install xcpretty`)
|
||||
Clone the git repository:
|
||||
|
||||
### Optional dependencies
|
||||
|
||||
- [ccache](https://ccache.samba.org) (for build only; improves recompilation performance)
|
||||
git clone https://github.com/mapbox/mapbox-gl-native.git
|
||||
cd mapbox-gl-native
|
||||
|
||||
## 3: Setting up a development environment & building
|
||||
|
||||
@@ -58,7 +46,7 @@ See the relevant SDK documentation for next steps:
|
||||
|
||||
* [Maps SDK for Android](platform/android/)
|
||||
* [Maps SDK for iOS](platform/ios/)
|
||||
* [Maps SDK for iOS](platform/macos/)
|
||||
* [Maps SDK for macOS](platform/macos/)
|
||||
* [Mapbox Qt SDK](platform/qt/)
|
||||
* [Mapbox GL Native on Linux](platform/linux/)
|
||||
* [node-mapbox-gl-native](platform/node/)
|
||||
|
||||
@@ -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
|
||||
@@ -170,6 +174,7 @@ set(MBGL_CORE_FILES
|
||||
include/mbgl/renderer/renderer.hpp
|
||||
include/mbgl/renderer/renderer_backend.hpp
|
||||
include/mbgl/renderer/renderer_frontend.hpp
|
||||
include/mbgl/renderer/renderer_observer.hpp
|
||||
src/mbgl/renderer/backend_scope.cpp
|
||||
src/mbgl/renderer/bucket.hpp
|
||||
src/mbgl/renderer/bucket_parameters.cpp
|
||||
@@ -206,7 +211,6 @@ set(MBGL_CORE_FILES
|
||||
src/mbgl/renderer/renderer_backend.cpp
|
||||
src/mbgl/renderer/renderer_impl.cpp
|
||||
src/mbgl/renderer/renderer_impl.hpp
|
||||
src/mbgl/renderer/renderer_observer.hpp
|
||||
src/mbgl/renderer/style_diff.cpp
|
||||
src/mbgl/renderer/style_diff.hpp
|
||||
src/mbgl/renderer/tile_mask.hpp
|
||||
@@ -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
|
||||
|
||||
@@ -48,7 +48,7 @@ public:
|
||||
void dumpDebugLogs();
|
||||
|
||||
// Memory
|
||||
void onLowMemory();
|
||||
void reduceMemoryUse();
|
||||
|
||||
private:
|
||||
class Impl;
|
||||
|
||||
@@ -54,6 +54,26 @@ struct Converter<CustomGeometrySource::Options> {
|
||||
}
|
||||
}
|
||||
|
||||
const auto wrapValue = objectMember(value, "wrap");
|
||||
if (wrapValue) {
|
||||
if (toBool(*wrapValue)) {
|
||||
options.tileOptions.wrap = static_cast<bool>(*toBool(*wrapValue));
|
||||
} else {
|
||||
error = { "CustomGeometrySource TileOptions wrap value must be a boolean" };
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
const auto clipValue = objectMember(value, "clip");
|
||||
if (clipValue) {
|
||||
if (toBool(*clipValue)) {
|
||||
options.tileOptions.clip = static_cast<double>(*toBool(*clipValue));
|
||||
} else {
|
||||
error = { "CustomGeometrySource TileOptiosn clip value must be a boolean" };
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
return { options };
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -25,6 +25,8 @@ public:
|
||||
double tolerance = 0.375;
|
||||
uint16_t tileSize = util::tileSize;
|
||||
uint16_t buffer = 128;
|
||||
bool clip = false;
|
||||
bool wrap = false;
|
||||
};
|
||||
|
||||
struct Options {
|
||||
|
||||
@@ -14,22 +14,28 @@ namespace mbgl {
|
||||
class Tileset {
|
||||
public:
|
||||
enum class Scheme : bool { XYZ, TMS };
|
||||
enum class DEMEncoding : bool { Mapbox, Terrarium };
|
||||
|
||||
std::vector<std::string> tiles;
|
||||
Range<uint8_t> zoomRange;
|
||||
std::string attribution;
|
||||
Scheme scheme;
|
||||
// DEMEncoding is not supported by the TileJSON spec
|
||||
DEMEncoding encoding;
|
||||
optional<LatLngBounds> bounds;
|
||||
|
||||
|
||||
Tileset(std::vector<std::string> tiles_ = std::vector<std::string>(),
|
||||
Range<uint8_t> zoomRange_ = { 0, util::DEFAULT_MAX_ZOOM },
|
||||
std::string attribution_ = {},
|
||||
Scheme scheme_ = Scheme::XYZ)
|
||||
Scheme scheme_ = Scheme::XYZ,
|
||||
DEMEncoding encoding_ = DEMEncoding::Mapbox)
|
||||
: tiles(std::move(tiles_)),
|
||||
zoomRange(std::move(zoomRange_)),
|
||||
attribution(std::move(attribution_)),
|
||||
scheme(scheme_),
|
||||
bounds() {}
|
||||
encoding(encoding_),
|
||||
bounds() {};
|
||||
|
||||
// TileJSON also includes center and zoom but they are not used by mbgl.
|
||||
|
||||
|
||||
Submodule mapbox-gl-js updated: de365184e1...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)
|
||||
@@ -22,7 +26,7 @@ Mapbox welcomes participation and contributions from everyone. If you'd like to
|
||||
## 5.4.0 - January 30, 2018
|
||||
- Blacklist Adreno 2xx GPU for VAO support [#11047](https://github.com/mapbox/mapbox-gl-native/pull/11047)
|
||||
- Bearing tracking mode GPS_NORTH_FACING [#11095](https://github.com/mapbox/mapbox-gl-native/pull/11095)
|
||||
- Disable logging missing location permissons [#11084](https://github.com/mapbox/mapbox-gl-native/pull/11084)
|
||||
- Disable logging for missing location permissions when location is disabled [#11084](https://github.com/mapbox/mapbox-gl-native/pull/11084)
|
||||
- Create offline handler using the main thread looper [#11021](https://github.com/mapbox/mapbox-gl-native/pull/11021)
|
||||
|
||||
## 6.0.0-beta.1 - January 26, 2018
|
||||
|
||||
@@ -13,7 +13,7 @@ BUILDTYPE=Debug or BUILDTYPE=Release
|
||||
##### Creating an Android Archive file that supports all ABIs
|
||||
|
||||
```sh
|
||||
BUILDTYPE=RELEASE make apackage
|
||||
BUILDTYPE=Release make apackage
|
||||
```
|
||||
|
||||
This will build native libraries to support following ABIs:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
GROUP=com.mapbox.mapboxsdk
|
||||
VERSION_NAME=6.0.0-SNAPSHOT
|
||||
VERSION_NAME=7.0.0-SNAPSHOT
|
||||
|
||||
POM_DESCRIPTION=Mapbox GL Android SDK
|
||||
POM_URL=https://github.com/mapbox/mapbox-gl-native
|
||||
|
||||
@@ -12,4 +12,7 @@
|
||||
# config for okhttp 3.8.0, https://github.com/square/okhttp/pull/3354
|
||||
-dontwarn okio.**
|
||||
-dontwarn javax.annotation.Nullable
|
||||
-dontwarn javax.annotation.ParametersAreNonnullByDefault
|
||||
-dontwarn javax.annotation.ParametersAreNonnullByDefault
|
||||
|
||||
# config for optional location provider https://github.com/mapbox/mapbox-gl-native/issues/10960
|
||||
-dontwarn com.mapzen.android.lost.api**
|
||||
@@ -42,6 +42,8 @@ import com.mapbox.mapboxsdk.maps.widgets.MyLocationViewSettings;
|
||||
import com.mapbox.mapboxsdk.net.ConnectivityReceiver;
|
||||
import com.mapbox.mapboxsdk.storage.FileSource;
|
||||
|
||||
import javax.microedition.khronos.egl.EGLConfig;
|
||||
import javax.microedition.khronos.opengles.GL10;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.ref.WeakReference;
|
||||
@@ -50,9 +52,6 @@ import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import javax.microedition.khronos.egl.EGLConfig;
|
||||
import javax.microedition.khronos.opengles.GL10;
|
||||
|
||||
import timber.log.Timber;
|
||||
|
||||
import static com.mapbox.mapboxsdk.maps.widgets.CompassView.TIME_MAP_NORTH_ANIMATION;
|
||||
|
||||
@@ -7,10 +7,10 @@ import android.support.annotation.NonNull;
|
||||
import android.support.v4.view.ViewCompat;
|
||||
import android.support.v4.view.ViewPropertyAnimatorCompat;
|
||||
import android.support.v4.view.ViewPropertyAnimatorListenerAdapter;
|
||||
import android.support.v7.widget.AppCompatImageView;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap;
|
||||
|
||||
@@ -24,7 +24,7 @@ import com.mapbox.mapboxsdk.maps.MapboxMap;
|
||||
* </p>
|
||||
*/
|
||||
@SuppressLint("AppCompatCustomView")
|
||||
public final class CompassView extends ImageView implements Runnable {
|
||||
public final class CompassView extends AppCompatImageView implements Runnable {
|
||||
|
||||
public static final long TIME_WAIT_IDLE = 500;
|
||||
public static final long TIME_MAP_NORTH_ANIMATION = 150;
|
||||
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -11,7 +11,7 @@ import static com.mapbox.mapboxsdk.utils.ColorUtils.rgbaToColor;
|
||||
import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
|
||||
|
||||
/**
|
||||
* Client-side hillshading visualization based on DEM data. Currently, the implementation only supports Mapbox Terrain RGB tiles
|
||||
* Client-side hillshading visualization based on DEM data. Currently, the implementation only supports Mapbox Terrain RGB and Mapzen Terrarium tiles.
|
||||
*
|
||||
* @see <a href="https://www.mapbox.com/mapbox-gl-style-spec/#layers-hillshade">The online documentation</a>
|
||||
*/
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -37,18 +37,18 @@ public class CustomGeometrySource extends Source {
|
||||
* @param provider The tile provider that returns geometry data for this source.
|
||||
*/
|
||||
public CustomGeometrySource(String id, GeometryTileProvider provider) {
|
||||
this(id, provider, new GeoJsonOptions());
|
||||
this(id, provider, new CustomGeometrySourceOptions());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a CustomGeometrySource with non-default GeoJsonOptions.
|
||||
* Create a CustomGeometrySource with non-default CustomGeometrySourceOptions.
|
||||
* <p>Supported options are minZoom, maxZoom, buffer, and tolerance.</p>
|
||||
*
|
||||
* @param id The source id.
|
||||
* @param provider The tile provider that returns geometry data for this source.
|
||||
* @param options GeoJsonOptions.
|
||||
* @param options CustomGeometrySourceOptions.
|
||||
*/
|
||||
public CustomGeometrySource(String id, GeometryTileProvider provider, GeoJsonOptions options) {
|
||||
public CustomGeometrySource(String id, GeometryTileProvider provider, CustomGeometrySourceOptions options) {
|
||||
this.provider = provider;
|
||||
executor = Executors.newFixedThreadPool(4);
|
||||
initialize(id, options);
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.mapbox.mapboxsdk.style.sources;
|
||||
|
||||
/**
|
||||
* Builder class for composing CustomGeometrySource objects.
|
||||
*/
|
||||
public class CustomGeometrySourceOptions extends GeoJsonOptions {
|
||||
|
||||
/**
|
||||
* If the data includes wrapped coordinates, setting this to true unwraps the coordinates.
|
||||
*
|
||||
* @param wrap defaults to false
|
||||
* @return the current instance for chaining
|
||||
*/
|
||||
public CustomGeometrySourceOptions withWrap(boolean wrap) {
|
||||
this.put("wrap", wrap);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the data includes geometry outside the tile boundaries, setting this to true clips the geometry
|
||||
* to the tile boundaries.
|
||||
*
|
||||
* @param clip defaults to false
|
||||
* @return the current instance for chaining
|
||||
*/
|
||||
public CustomGeometrySourceOptions withClip(boolean clip) {
|
||||
this.put("clip", clip);
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -800,6 +800,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>
|
||||
@@ -71,4 +71,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>
|
||||
|
||||
@@ -71,4 +71,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
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
"QueryRenderedFeaturesBoxHighlightActivity",
|
||||
"MultiMapActivity",
|
||||
"MapInDialogActivity",
|
||||
"SimpleMapActivity",
|
||||
"ManualZoomActivity",
|
||||
"MaxMinZoomActivity",
|
||||
"ScrollByActivity",
|
||||
@@ -34,4 +35,4 @@
|
||||
"SymbolGeneratorActivity",
|
||||
"TextureViewTransparentBackgroundActivity",
|
||||
"SimpleMapActivity"
|
||||
]
|
||||
]
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -77,8 +77,8 @@ void AndroidRendererFrontend::update(std::shared_ptr<UpdateParameters> params) {
|
||||
mapRenderer.requestRender();
|
||||
}
|
||||
|
||||
void AndroidRendererFrontend::onLowMemory() {
|
||||
mapRenderer.actor().invoke(&Renderer::onLowMemory);
|
||||
void AndroidRendererFrontend::reduceMemoryUse() {
|
||||
mapRenderer.actor().invoke(&Renderer::reduceMemoryUse);
|
||||
}
|
||||
|
||||
std::vector<Feature> AndroidRendererFrontend::querySourceFeatures(const std::string& sourceID,
|
||||
|
||||
@@ -39,7 +39,7 @@ public:
|
||||
AnnotationIDs queryShapeAnnotations(const ScreenBox& box) const;
|
||||
|
||||
// Memory
|
||||
void onLowMemory();
|
||||
void reduceMemoryUse();
|
||||
|
||||
private:
|
||||
MapRenderer& mapRenderer;
|
||||
|
||||
@@ -96,7 +96,7 @@ void nativeContextLost(void */*context*/) {
|
||||
mbgl::Log::Info(mbgl::Event::General, "nativeContextLost");
|
||||
}
|
||||
|
||||
void nativeDenitialize(void *context) {
|
||||
void nativeDeinitialize(void *context) {
|
||||
mbgl::Log::Info(mbgl::Event::General, "nativeDeinitialize");
|
||||
delete reinterpret_cast<ExampleCustomLayer*>(context);
|
||||
}
|
||||
@@ -132,7 +132,7 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) {
|
||||
|
||||
env->SetStaticLongField(customLayerClass,
|
||||
env->GetStaticFieldID(customLayerClass, "DeinitializeFunction", "J"),
|
||||
reinterpret_cast<jlong>(nativeDenitialize));
|
||||
reinterpret_cast<jlong>(nativeDeinitialize));
|
||||
|
||||
return JNI_VERSION_1_6;
|
||||
}
|
||||
|
||||
@@ -450,7 +450,7 @@ jni::Array<jni::jlong> NativeMapView::addMarkers(jni::JNIEnv& env, jni::Array<jn
|
||||
}
|
||||
|
||||
void NativeMapView::onLowMemory(JNIEnv&) {
|
||||
rendererFrontend->onLowMemory();
|
||||
rendererFrontend->reduceMemoryUse();
|
||||
}
|
||||
|
||||
using DebugOptions = mbgl::MapDebugOptions;
|
||||
|
||||
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);
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
// This conversion is expected not to fail because it's used only in contexts where
|
||||
// the value was originally a GeoJsonOptions object on the Java side. If it fails
|
||||
// the value was originally a CustomGeometrySourceOptions object on the Java side. If it fails
|
||||
// to convert, it's a bug in our serialization or Java-side static typing.
|
||||
static style::CustomGeometrySource::Options convertCustomGeometrySourceOptions(jni::JNIEnv& env,
|
||||
jni::Object<> options,
|
||||
|
||||
@@ -160,6 +160,7 @@ the following terms for concepts defined in the style specification:
|
||||
|
||||
In the style specification | In the SDK
|
||||
---------------------------|---------
|
||||
bounds | coordinate bounds
|
||||
filter | predicate
|
||||
function type | interpolation mode
|
||||
id | identifier
|
||||
@@ -200,6 +201,7 @@ In style JSON | In TileJSON | In the SDK
|
||||
`tiles` | `tiles` | `tileURLTemplates` parameter in `-[MGLTileSource initWithIdentifier:tileURLTemplates:options:]`
|
||||
`minzoom` | `minzoom` | `MGLTileSourceOptionMinimumZoomLevel`
|
||||
`maxzoom` | `maxzoom` | `MGLTileSourceOptionMaximumZoomLevel`
|
||||
`bounds` | `bounds` | `MGLTileSourceOptionCoordinateBounds`
|
||||
`tileSize` | — | `MGLTileSourceOptionTileSize`
|
||||
`attribution` | `attribution` | `MGLTileSourceOptionAttributionHTMLString` (but consider specifying `MGLTileSourceOptionAttributionInfos` instead for improved security)
|
||||
`scheme` | `scheme` | `MGLTileSourceOptionTileCoordinateSystem`
|
||||
|
||||
@@ -318,14 +318,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;
|
||||
@@ -397,7 +398,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."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,6 +81,31 @@ extern MGL_EXPORT const MGLShapeSourceOption MGLShapeSourceOptionBuffer;
|
||||
*/
|
||||
extern MGL_EXPORT const MGLShapeSourceOption MGLShapeSourceOptionSimplificationTolerance;
|
||||
|
||||
/**
|
||||
An `NSNumber` object containing a Boolean value; specifies whether the shape of
|
||||
an `MGLComputedShapeSource` should be wrapped to accomodate coordinates with
|
||||
longitudes beyond −180 and 180. The default value is `NO`.
|
||||
|
||||
Setting this option to `YES` affects rendering performance.
|
||||
|
||||
This option is ignored when creating an instance of a class besides
|
||||
`MGLComputedShapeSource`.
|
||||
*/
|
||||
extern MGL_EXPORT const MGLShapeSourceOption MGLShapeSourceOptionWrapsCoordinates;
|
||||
|
||||
/**
|
||||
An `NSNumber` object containing a Boolean value; specifies whether the shape of
|
||||
an `MGLComputedShapeSource` should be clipped at the edge of each tile. The
|
||||
default value is `NO`.
|
||||
|
||||
Setting this option to `YES` affects rendering performance. Use this option to
|
||||
clip `MGLPolyline`s and `MGLPolygon`s at tile boundaries without artifacts.
|
||||
|
||||
This option is ignored when creating an instance of a class besides
|
||||
`MGLComputedShapeSource`.
|
||||
*/
|
||||
extern MGL_EXPORT const MGLShapeSourceOption MGLShapeSourceOptionClipsCoordinates;
|
||||
|
||||
/**
|
||||
`MGLAbstractShapeSource` is an abstract base class for map content sources that
|
||||
supply vector shapes to be shown on the map. A shape source is added to an
|
||||
|
||||
@@ -8,6 +8,8 @@ const MGLShapeSourceOption MGLShapeSourceOptionMaximumZoomLevel = @"MGLShapeSour
|
||||
const MGLShapeSourceOption MGLShapeSourceOptionMaximumZoomLevelForClustering = @"MGLShapeSourceOptionMaximumZoomLevelForClustering";
|
||||
const MGLShapeSourceOption MGLShapeSourceOptionMinimumZoomLevel = @"MGLShapeSourceOptionMinimumZoomLevel";
|
||||
const MGLShapeSourceOption MGLShapeSourceOptionSimplificationTolerance = @"MGLShapeSourceOptionSimplificationTolerance";
|
||||
const MGLShapeSourceOption MGLShapeSourceOptionWrapsCoordinates = @"MGLShapeSourceOptionWrapsCoordinates";
|
||||
const MGLShapeSourceOption MGLShapeSourceOptionClipsCoordinates = @"MGLShapeSourceOptionClipsCoordinates";
|
||||
|
||||
@interface MGLAbstractShapeSource ()
|
||||
|
||||
@@ -113,5 +115,22 @@ mbgl::style::CustomGeometrySource::Options MBGLCustomGeometrySourceOptionsFromDi
|
||||
}
|
||||
sourceOptions.tileOptions.tolerance = value.doubleValue;
|
||||
}
|
||||
|
||||
if (NSNumber *value = options[MGLShapeSourceOptionWrapsCoordinates]) {
|
||||
if (![value isKindOfClass:[NSNumber class]]) {
|
||||
[NSException raise:NSInvalidArgumentException
|
||||
format:@"MGLShapeSourceOptionWrapsCoordinates must be an NSNumber."];
|
||||
}
|
||||
sourceOptions.tileOptions.wrap = value.boolValue;
|
||||
}
|
||||
|
||||
if (NSNumber *value = options[MGLShapeSourceOptionClipsCoordinates]) {
|
||||
if (![value isKindOfClass:[NSNumber class]]) {
|
||||
[NSException raise:NSInvalidArgumentException
|
||||
format:@"MGLShapeSourceOptionClipsCoordinates must be an NSNumber."];
|
||||
}
|
||||
sourceOptions.tileOptions.clip = value.boolValue;
|
||||
}
|
||||
|
||||
return sourceOptions;
|
||||
}
|
||||
|
||||
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
|
||||
@@ -81,7 +81,7 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64;
|
||||
@end
|
||||
|
||||
@interface MGLMapSnapshotter()
|
||||
|
||||
@property (nonatomic) BOOL loading;
|
||||
@end
|
||||
|
||||
@implementation MGLMapSnapshotter {
|
||||
@@ -90,6 +90,7 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64;
|
||||
std::unique_ptr<mbgl::MapSnapshotter> _mbglMapSnapshotter;
|
||||
std::unique_ptr<mbgl::Actor<mbgl::MapSnapshotter::Callback>> _snapshotCallback;
|
||||
NS_ARRAY_OF(MGLAttributionInfo *) *_attributionInfo;
|
||||
|
||||
}
|
||||
|
||||
- (instancetype)initWithOptions:(MGLMapSnapshotOptions *)options
|
||||
@@ -115,182 +116,192 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64;
|
||||
format:@"Already started this snapshotter."];
|
||||
}
|
||||
|
||||
_loading = true;
|
||||
self.loading = true;
|
||||
|
||||
dispatch_async(queue, ^{
|
||||
_snapshotCallback = std::make_unique<mbgl::Actor<mbgl::MapSnapshotter::Callback>>(*mbgl::Scheduler::GetCurrent(), [=](std::exception_ptr mbglError, mbgl::PremultipliedImage image, mbgl::MapSnapshotter::Attributions attributions, mbgl::MapSnapshotter::PointForFn pointForFn) {
|
||||
_loading = false;
|
||||
__weak __typeof__(self) weakSelf = self;
|
||||
_snapshotCallback = std::make_unique<mbgl::Actor<mbgl::MapSnapshotter::Callback>>(*mbgl::Scheduler::GetCurrent(), [=](std::exception_ptr mbglError, mbgl::PremultipliedImage image, mbgl::MapSnapshotter::Attributions attributions, mbgl::MapSnapshotter::PointForFn pointForFn) {
|
||||
__typeof__(self) strongSelf = weakSelf;
|
||||
strongSelf.loading = false;
|
||||
|
||||
|
||||
if (mbglError) {
|
||||
NSString *description = @(mbgl::util::toString(mbglError).c_str());
|
||||
NSDictionary *userInfo = @{NSLocalizedDescriptionKey: description};
|
||||
NSError *error = [NSError errorWithDomain:MGLErrorDomain code:MGLErrorCodeSnapshotFailed userInfo:userInfo];
|
||||
|
||||
NSMutableArray *infos = [NSMutableArray array];
|
||||
|
||||
// Dispatch result to origin queue
|
||||
dispatch_async(queue, ^{
|
||||
completion(nil, error);
|
||||
});
|
||||
} else {
|
||||
#if TARGET_OS_IPHONE
|
||||
CGFloat fontSize = [UIFont smallSystemFontSize];
|
||||
UIColor *attributeFontColor = [UIColor blackColor];
|
||||
MGLImage *mglImage = [[MGLImage alloc] initWithMGLPremultipliedImage:std::move(image) scale:strongSelf.options.scale];
|
||||
#else
|
||||
CGFloat fontSize = [NSFont systemFontSizeForControlSize:NSMiniControlSize];
|
||||
NSColor *attributeFontColor = [NSColor blackColor];
|
||||
MGLImage *mglImage = [[MGLImage alloc] initWithMGLPremultipliedImage:std::move(image)];
|
||||
mglImage.size = NSMakeSize(mglImage.size.width / strongSelf.options.scale,
|
||||
mglImage.size.height / strongSelf.options.scale);
|
||||
#endif
|
||||
for (auto attribution = attributions.begin(); attribution != attributions.end(); ++attribution) {
|
||||
NSString *attributionHTMLString = @(attribution->c_str());
|
||||
NSArray *tileSetInfos = [MGLAttributionInfo attributionInfosFromHTMLString:attributionHTMLString
|
||||
fontSize:fontSize
|
||||
linkColor:attributeFontColor];
|
||||
[infos growArrayByAddingAttributionInfosFromArray:tileSetInfos];
|
||||
}
|
||||
|
||||
_attributionInfo = infos;
|
||||
|
||||
if (mbglError) {
|
||||
NSString *description = @(mbgl::util::toString(mbglError).c_str());
|
||||
NSDictionary *userInfo = @{NSLocalizedDescriptionKey: description};
|
||||
NSError *error = [NSError errorWithDomain:MGLErrorDomain code:MGLErrorCodeSnapshotFailed userInfo:userInfo];
|
||||
|
||||
// Dispatch result to origin queue
|
||||
dispatch_async(queue, ^{
|
||||
completion(nil, error);
|
||||
});
|
||||
} else {
|
||||
#if TARGET_OS_IPHONE
|
||||
MGLImage *mglImage = [[MGLImage alloc] initWithMGLPremultipliedImage:std::move(image) scale:self.options.scale];
|
||||
#else
|
||||
MGLImage *mglImage = [[MGLImage alloc] initWithMGLPremultipliedImage:std::move(image)];
|
||||
mglImage.size = NSMakeSize(mglImage.size.width / self.options.scale,
|
||||
mglImage.size.height / self.options.scale);
|
||||
#endif
|
||||
|
||||
// Process image watermark in a work queue
|
||||
dispatch_queue_t workQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
|
||||
dispatch_async(workQueue, ^{
|
||||
#if TARGET_OS_IPHONE
|
||||
MGLAttributionInfoStyle attributionInfoStyle = MGLAttributionInfoStyleLong;
|
||||
for (NSUInteger styleValue = MGLAttributionInfoStyleLong; styleValue >= MGLAttributionInfoStyleShort; styleValue--) {
|
||||
attributionInfoStyle = (MGLAttributionInfoStyle)styleValue;
|
||||
CGSize attributionSize = [self attributionSizeWithLogoStyle:attributionInfoStyle sourceAttributionStyle:attributionInfoStyle];
|
||||
if (attributionSize.width <= mglImage.size.width) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
UIImage *logoImage = [self logoImageWithStyle:attributionInfoStyle];
|
||||
CGSize attributionBackgroundSize = [self attributionTextSizeWithStyle:attributionInfoStyle];
|
||||
|
||||
CGRect logoImageRect = CGRectMake(MGLLogoImagePosition.x, mglImage.size.height - (MGLLogoImagePosition.y + logoImage.size.height), logoImage.size.width, logoImage.size.height);
|
||||
CGPoint attributionOrigin = CGPointMake(mglImage.size.width - 10 - attributionBackgroundSize.width,
|
||||
logoImageRect.origin.y + (logoImageRect.size.height / 2) - (attributionBackgroundSize.height / 2) + 1);
|
||||
if (!logoImage) {
|
||||
CGSize defaultLogoSize = [self mapboxLongStyleLogo].size;
|
||||
logoImageRect = CGRectMake(0, mglImage.size.height - (MGLLogoImagePosition.y + defaultLogoSize.height), 0, defaultLogoSize.height);
|
||||
attributionOrigin = CGPointMake(10, logoImageRect.origin.y + (logoImageRect.size.height / 2) - (attributionBackgroundSize.height / 2) + 1);
|
||||
}
|
||||
|
||||
CGRect attributionBackgroundFrame = CGRectMake(attributionOrigin.x,
|
||||
attributionOrigin.y,
|
||||
attributionBackgroundSize.width,
|
||||
attributionBackgroundSize.height);
|
||||
CGPoint attributionTextPosition = CGPointMake(attributionBackgroundFrame.origin.x + 10,
|
||||
attributionBackgroundFrame.origin.y - 1);
|
||||
|
||||
CGRect cropRect = CGRectMake(attributionBackgroundFrame.origin.x * mglImage.scale,
|
||||
attributionBackgroundFrame.origin.y * mglImage.scale,
|
||||
attributionBackgroundSize.width * mglImage.scale,
|
||||
attributionBackgroundSize.height * mglImage.scale);
|
||||
|
||||
|
||||
UIGraphicsBeginImageContextWithOptions(mglImage.size, NO, self.options.scale);
|
||||
|
||||
[mglImage drawInRect:CGRectMake(0, 0, mglImage.size.width, mglImage.size.height)];
|
||||
|
||||
[logoImage drawInRect:logoImageRect];
|
||||
|
||||
UIImage *currentImage = UIGraphicsGetImageFromCurrentImageContext();
|
||||
CGImageRef attributionImageRef = CGImageCreateWithImageInRect([currentImage CGImage], cropRect);
|
||||
UIImage *attributionImage = [UIImage imageWithCGImage:attributionImageRef];
|
||||
CGImageRelease(attributionImageRef);
|
||||
|
||||
CIImage *ciAttributionImage = [[CIImage alloc] initWithCGImage:attributionImage.CGImage];
|
||||
|
||||
UIImage *blurredAttributionBackground = [self blurredAttributionBackground:ciAttributionImage];
|
||||
|
||||
[blurredAttributionBackground drawInRect:attributionBackgroundFrame];
|
||||
|
||||
[self drawAttributionTextWithStyle:attributionInfoStyle origin:attributionTextPosition];
|
||||
|
||||
UIImage *compositedImage = UIGraphicsGetImageFromCurrentImageContext();
|
||||
|
||||
UIGraphicsEndImageContext();
|
||||
#else
|
||||
NSSize targetSize = NSMakeSize(self.options.size.width, self.options.size.height);
|
||||
NSRect targetFrame = NSMakeRect(0, 0, targetSize.width, targetSize.height);
|
||||
|
||||
MGLAttributionInfoStyle attributionInfoStyle = MGLAttributionInfoStyleLong;
|
||||
for (NSUInteger styleValue = MGLAttributionInfoStyleLong; styleValue >= MGLAttributionInfoStyleShort; styleValue--) {
|
||||
attributionInfoStyle = (MGLAttributionInfoStyle)styleValue;
|
||||
CGSize attributionSize = [self attributionSizeWithLogoStyle:attributionInfoStyle sourceAttributionStyle:attributionInfoStyle];
|
||||
if (attributionSize.width <= mglImage.size.width) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
NSImage *logoImage = [self logoImageWithStyle:attributionInfoStyle];
|
||||
CGSize attributionBackgroundSize = [self attributionTextSizeWithStyle:attributionInfoStyle];
|
||||
NSImage *sourceImage = mglImage;
|
||||
|
||||
CGRect logoImageRect = CGRectMake(MGLLogoImagePosition.x, MGLLogoImagePosition.y, logoImage.size.width, logoImage.size.height);
|
||||
CGPoint attributionOrigin = CGPointMake(targetFrame.size.width - 10 - attributionBackgroundSize.width,
|
||||
MGLLogoImagePosition.y + 1);
|
||||
if (!logoImage) {
|
||||
CGSize defaultLogoSize = [self mapboxLongStyleLogo].size;
|
||||
logoImageRect = CGRectMake(0, MGLLogoImagePosition.y, 0, defaultLogoSize.height);
|
||||
attributionOrigin = CGPointMake(10, attributionOrigin.y);
|
||||
}
|
||||
|
||||
CGRect attributionBackgroundFrame = CGRectMake(attributionOrigin.x,
|
||||
attributionOrigin.y,
|
||||
attributionBackgroundSize.width,
|
||||
attributionBackgroundSize.height);
|
||||
CGPoint attributionTextPosition = CGPointMake(attributionBackgroundFrame.origin.x + 10,
|
||||
logoImageRect.origin.y + (logoImageRect.size.height / 2) - (attributionBackgroundSize.height / 2));
|
||||
|
||||
|
||||
NSImage *compositedImage = nil;
|
||||
NSImageRep *sourceImageRep = [sourceImage bestRepresentationForRect:targetFrame
|
||||
context:nil
|
||||
hints:nil];
|
||||
compositedImage = [[NSImage alloc] initWithSize:targetSize];
|
||||
|
||||
[compositedImage lockFocus];
|
||||
|
||||
[sourceImageRep drawInRect: targetFrame];
|
||||
|
||||
if (logoImage) {
|
||||
[logoImage drawInRect:logoImageRect];
|
||||
}
|
||||
|
||||
NSBitmapImageRep *attributionBackground = [[NSBitmapImageRep alloc] initWithFocusedViewRect:attributionBackgroundFrame];
|
||||
|
||||
CIImage *attributionBackgroundImage = [[CIImage alloc] initWithCGImage:[attributionBackground CGImage]];
|
||||
|
||||
NSImage *blurredAttributionBackground = [self blurredAttributionBackground:attributionBackgroundImage];
|
||||
|
||||
[blurredAttributionBackground drawInRect:attributionBackgroundFrame];
|
||||
|
||||
[self drawAttributionTextWithStyle:attributionInfoStyle origin:attributionTextPosition];
|
||||
|
||||
[compositedImage unlockFocus];
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
// Dispatch result to origin queue
|
||||
dispatch_async(queue, ^{
|
||||
MGLMapSnapshot* snapshot = [[MGLMapSnapshot alloc] initWithImage:compositedImage scale:self.options.scale pointForFn:pointForFn];
|
||||
completion(snapshot, nil);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
_mbglMapSnapshotter->snapshot(_snapshotCallback->self());
|
||||
[strongSelf drawAttributedSnapshot:attributions snapshotImage:mglImage pointForFn:pointForFn queue:queue completionHandler:completion];
|
||||
}
|
||||
_snapshotCallback = NULL;
|
||||
});
|
||||
dispatch_async(queue, ^{
|
||||
_mbglMapSnapshotter->snapshot(_snapshotCallback->self());
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
- (MGLImage *)drawAttributedSnapshot:(mbgl::MapSnapshotter::Attributions)attributions snapshotImage:(MGLImage *)mglImage pointForFn:(mbgl::MapSnapshotter::PointForFn)pointForFn queue:(dispatch_queue_t)queue completionHandler:(MGLMapSnapshotCompletionHandler)completion {
|
||||
|
||||
NSMutableArray *infos = [NSMutableArray array];
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
CGFloat fontSize = [UIFont smallSystemFontSize];
|
||||
UIColor *attributeFontColor = [UIColor blackColor];
|
||||
#else
|
||||
CGFloat fontSize = [NSFont systemFontSizeForControlSize:NSMiniControlSize];
|
||||
NSColor *attributeFontColor = [NSColor blackColor];
|
||||
#endif
|
||||
for (auto attribution = attributions.begin(); attribution != attributions.end(); ++attribution) {
|
||||
NSString *attributionHTMLString = @(attribution->c_str());
|
||||
NSArray *tileSetInfos = [MGLAttributionInfo attributionInfosFromHTMLString:attributionHTMLString
|
||||
fontSize:fontSize
|
||||
linkColor:attributeFontColor];
|
||||
[infos growArrayByAddingAttributionInfosFromArray:tileSetInfos];
|
||||
}
|
||||
|
||||
_attributionInfo = infos;
|
||||
|
||||
// Process image watermark in a work queue
|
||||
dispatch_queue_t workQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
|
||||
dispatch_async(workQueue, ^{
|
||||
#if TARGET_OS_IPHONE
|
||||
MGLAttributionInfoStyle attributionInfoStyle = MGLAttributionInfoStyleLong;
|
||||
for (NSUInteger styleValue = MGLAttributionInfoStyleLong; styleValue >= MGLAttributionInfoStyleShort; styleValue--) {
|
||||
attributionInfoStyle = (MGLAttributionInfoStyle)styleValue;
|
||||
CGSize attributionSize = [self attributionSizeWithLogoStyle:attributionInfoStyle sourceAttributionStyle:attributionInfoStyle];
|
||||
if (attributionSize.width <= mglImage.size.width) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
UIImage *logoImage = [self logoImageWithStyle:attributionInfoStyle];
|
||||
CGSize attributionBackgroundSize = [self attributionTextSizeWithStyle:attributionInfoStyle];
|
||||
|
||||
CGRect logoImageRect = CGRectMake(MGLLogoImagePosition.x, mglImage.size.height - (MGLLogoImagePosition.y + logoImage.size.height), logoImage.size.width, logoImage.size.height);
|
||||
CGPoint attributionOrigin = CGPointMake(mglImage.size.width - 10 - attributionBackgroundSize.width,
|
||||
logoImageRect.origin.y + (logoImageRect.size.height / 2) - (attributionBackgroundSize.height / 2) + 1);
|
||||
if (!logoImage) {
|
||||
CGSize defaultLogoSize = [self mapboxLongStyleLogo].size;
|
||||
logoImageRect = CGRectMake(0, mglImage.size.height - (MGLLogoImagePosition.y + defaultLogoSize.height), 0, defaultLogoSize.height);
|
||||
attributionOrigin = CGPointMake(10, logoImageRect.origin.y + (logoImageRect.size.height / 2) - (attributionBackgroundSize.height / 2) + 1);
|
||||
}
|
||||
|
||||
CGRect attributionBackgroundFrame = CGRectMake(attributionOrigin.x,
|
||||
attributionOrigin.y,
|
||||
attributionBackgroundSize.width,
|
||||
attributionBackgroundSize.height);
|
||||
CGPoint attributionTextPosition = CGPointMake(attributionBackgroundFrame.origin.x + 10,
|
||||
attributionBackgroundFrame.origin.y - 1);
|
||||
|
||||
CGRect cropRect = CGRectMake(attributionBackgroundFrame.origin.x * mglImage.scale,
|
||||
attributionBackgroundFrame.origin.y * mglImage.scale,
|
||||
attributionBackgroundSize.width * mglImage.scale,
|
||||
attributionBackgroundSize.height * mglImage.scale);
|
||||
|
||||
|
||||
UIGraphicsBeginImageContextWithOptions(mglImage.size, NO, self.options.scale);
|
||||
|
||||
[mglImage drawInRect:CGRectMake(0, 0, mglImage.size.width, mglImage.size.height)];
|
||||
|
||||
[logoImage drawInRect:logoImageRect];
|
||||
|
||||
UIImage *currentImage = UIGraphicsGetImageFromCurrentImageContext();
|
||||
CGImageRef attributionImageRef = CGImageCreateWithImageInRect([currentImage CGImage], cropRect);
|
||||
UIImage *attributionImage = [UIImage imageWithCGImage:attributionImageRef];
|
||||
CGImageRelease(attributionImageRef);
|
||||
|
||||
CIImage *ciAttributionImage = [[CIImage alloc] initWithCGImage:attributionImage.CGImage];
|
||||
|
||||
UIImage *blurredAttributionBackground = [self blurredAttributionBackground:ciAttributionImage];
|
||||
|
||||
[blurredAttributionBackground drawInRect:attributionBackgroundFrame];
|
||||
|
||||
[self drawAttributionTextWithStyle:attributionInfoStyle origin:attributionTextPosition];
|
||||
|
||||
UIImage *compositedImage = UIGraphicsGetImageFromCurrentImageContext();
|
||||
|
||||
UIGraphicsEndImageContext();
|
||||
#else
|
||||
NSSize targetSize = NSMakeSize(self.options.size.width, self.options.size.height);
|
||||
NSRect targetFrame = NSMakeRect(0, 0, targetSize.width, targetSize.height);
|
||||
|
||||
MGLAttributionInfoStyle attributionInfoStyle = MGLAttributionInfoStyleLong;
|
||||
for (NSUInteger styleValue = MGLAttributionInfoStyleLong; styleValue >= MGLAttributionInfoStyleShort; styleValue--) {
|
||||
attributionInfoStyle = (MGLAttributionInfoStyle)styleValue;
|
||||
CGSize attributionSize = [self attributionSizeWithLogoStyle:attributionInfoStyle sourceAttributionStyle:attributionInfoStyle];
|
||||
if (attributionSize.width <= mglImage.size.width) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
NSImage *logoImage = [self logoImageWithStyle:attributionInfoStyle];
|
||||
CGSize attributionBackgroundSize = [self attributionTextSizeWithStyle:attributionInfoStyle];
|
||||
NSImage *sourceImage = mglImage;
|
||||
|
||||
CGRect logoImageRect = CGRectMake(MGLLogoImagePosition.x, MGLLogoImagePosition.y, logoImage.size.width, logoImage.size.height);
|
||||
CGPoint attributionOrigin = CGPointMake(targetFrame.size.width - 10 - attributionBackgroundSize.width,
|
||||
MGLLogoImagePosition.y + 1);
|
||||
if (!logoImage) {
|
||||
CGSize defaultLogoSize = [self mapboxLongStyleLogo].size;
|
||||
logoImageRect = CGRectMake(0, MGLLogoImagePosition.y, 0, defaultLogoSize.height);
|
||||
attributionOrigin = CGPointMake(10, attributionOrigin.y);
|
||||
}
|
||||
|
||||
CGRect attributionBackgroundFrame = CGRectMake(attributionOrigin.x,
|
||||
attributionOrigin.y,
|
||||
attributionBackgroundSize.width,
|
||||
attributionBackgroundSize.height);
|
||||
CGPoint attributionTextPosition = CGPointMake(attributionBackgroundFrame.origin.x + 10,
|
||||
logoImageRect.origin.y + (logoImageRect.size.height / 2) - (attributionBackgroundSize.height / 2));
|
||||
|
||||
|
||||
NSImage *compositedImage = nil;
|
||||
NSImageRep *sourceImageRep = [sourceImage bestRepresentationForRect:targetFrame
|
||||
context:nil
|
||||
hints:nil];
|
||||
compositedImage = [[NSImage alloc] initWithSize:targetSize];
|
||||
|
||||
[compositedImage lockFocus];
|
||||
|
||||
[sourceImageRep drawInRect: targetFrame];
|
||||
|
||||
if (logoImage) {
|
||||
[logoImage drawInRect:logoImageRect];
|
||||
}
|
||||
|
||||
NSBitmapImageRep *attributionBackground = [[NSBitmapImageRep alloc] initWithFocusedViewRect:attributionBackgroundFrame];
|
||||
|
||||
CIImage *attributionBackgroundImage = [[CIImage alloc] initWithCGImage:[attributionBackground CGImage]];
|
||||
|
||||
NSImage *blurredAttributionBackground = [self blurredAttributionBackground:attributionBackgroundImage];
|
||||
|
||||
[blurredAttributionBackground drawInRect:attributionBackgroundFrame];
|
||||
|
||||
[self drawAttributionTextWithStyle:attributionInfoStyle origin:attributionTextPosition];
|
||||
|
||||
[compositedImage unlockFocus];
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
// Dispatch result to origin queue
|
||||
dispatch_async(queue, ^{
|
||||
MGLMapSnapshot* snapshot = [[MGLMapSnapshot alloc] initWithImage:compositedImage scale:self.options.scale pointForFn:pointForFn];
|
||||
completion(snapshot, nil);
|
||||
});
|
||||
});
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)drawAttributionTextWithStyle:(MGLAttributionInfoStyle)attributionInfoStyle origin:(CGPoint)origin
|
||||
|
||||
@@ -56,9 +56,9 @@ public:
|
||||
return renderer.get();
|
||||
}
|
||||
|
||||
void onLowMemory() {
|
||||
void reduceMemoryUse() {
|
||||
if (!renderer) return;
|
||||
renderer->onLowMemory();
|
||||
renderer->reduceMemoryUse();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -41,6 +41,20 @@ extern MGL_EXPORT const MGLTileSourceOption MGLTileSourceOptionMinimumZoomLevel;
|
||||
*/
|
||||
extern MGL_EXPORT const MGLTileSourceOption MGLTileSourceOptionMaximumZoomLevel;
|
||||
|
||||
/**
|
||||
An `NSValue` object containing an `MGLCoordinateBounds` struct that specifies
|
||||
the geographic extent of the source.
|
||||
|
||||
If this option is specified, the SDK avoids requesting any tile that falls
|
||||
outside of the coordinate bounds. Otherwise, the SDK requests any tile needed
|
||||
to cover the viewport, as it does by default.
|
||||
|
||||
This option corresponds to the `bounds` key in the
|
||||
<a href="https://github.com/mapbox/tilejson-spec/tree/master/2.1.0">TileJSON</a>
|
||||
specification.
|
||||
*/
|
||||
extern MGL_EXPORT const MGLTileSourceOption MGLTileSourceOptionCoordinateBounds;
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
/**
|
||||
An HTML string defining the buttons to be displayed in an action sheet when the
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
#import "MGLTileSource_Private.h"
|
||||
|
||||
#import "MGLAttributionInfo_Private.h"
|
||||
#import "MGLGeometry_Private.h"
|
||||
#import "NSString+MGLAdditions.h"
|
||||
#import "NSValue+MGLAdditions.h"
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
#import <UIKit/UIKit.h>
|
||||
@@ -13,6 +15,7 @@
|
||||
|
||||
const MGLTileSourceOption MGLTileSourceOptionMinimumZoomLevel = @"MGLTileSourceOptionMinimumZoomLevel";
|
||||
const MGLTileSourceOption MGLTileSourceOptionMaximumZoomLevel = @"MGLTileSourceOptionMaximumZoomLevel";
|
||||
const MGLTileSourceOption MGLTileSourceOptionCoordinateBounds = @"MGLTileSourceOptionCoordinateBounds";
|
||||
const MGLTileSourceOption MGLTileSourceOptionAttributionHTMLString = @"MGLTileSourceOptionAttributionHTMLString";
|
||||
const MGLTileSourceOption MGLTileSourceOptionAttributionInfos = @"MGLTileSourceOptionAttributionInfos";
|
||||
const MGLTileSourceOption MGLTileSourceOptionTileCoordinateSystem = @"MGLTileSourceOptionTileCoordinateSystem";
|
||||
@@ -70,6 +73,15 @@ mbgl::Tileset MGLTileSetFromTileURLTemplates(NS_ARRAY_OF(NSString *) *tileURLTem
|
||||
[NSException raise:NSInvalidArgumentException
|
||||
format:@"MGLTileSourceOptionMinimumZoomLevel must be less than MGLTileSourceOptionMaximumZoomLevel."];
|
||||
}
|
||||
|
||||
if (NSValue *coordinateBounds = options[MGLTileSourceOptionCoordinateBounds]) {
|
||||
if (![coordinateBounds isKindOfClass:[NSValue class]]
|
||||
&& strcmp(coordinateBounds.objCType, @encode(MGLCoordinateBounds)) == 0) {
|
||||
[NSException raise:NSInvalidArgumentException
|
||||
format:@"MGLTileSourceOptionCoordinateBounds must be set to an NSValue containing an MGLCoordinateBounds."];
|
||||
}
|
||||
tileSet.bounds = MGLLatLngBoundsFromCoordinateBounds(coordinateBounds.MGLCoordinateBoundsValue);
|
||||
}
|
||||
|
||||
if (NSString *attribution = options[MGLTileSourceOptionAttributionHTMLString]) {
|
||||
if (![attribution isKindOfClass:[NSString class]]) {
|
||||
|
||||
@@ -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' %>];
|
||||
<% } -%>
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#import <Mapbox/Mapbox.h>
|
||||
#import "MGLTileSource_Private.h"
|
||||
#import "MGLGeometry_Private.h"
|
||||
|
||||
#include <mbgl/util/tileset.hpp>
|
||||
|
||||
@@ -40,6 +41,19 @@
|
||||
XCTAssertEqual(tileSet.zoomRange.min, 1);
|
||||
XCTAssertEqual(tileSet.zoomRange.max, 2);
|
||||
|
||||
// when the tile set has a bounds set
|
||||
MGLCoordinateBounds bounds = MGLCoordinateBoundsMake(CLLocationCoordinate2DMake(12, 34), CLLocationCoordinate2DMake(56, 78));
|
||||
tileSet = MGLTileSetFromTileURLTemplates(@[@"tile.1"], @{
|
||||
MGLTileSourceOptionCoordinateBounds: @(bounds),
|
||||
});
|
||||
|
||||
// the mbgl object reflects the set values for the bounds
|
||||
XCTAssert(!!tileSet.bounds, @"The bounds are set after setting the bounds");
|
||||
if (tileSet.bounds) {
|
||||
MGLCoordinateBounds actual = MGLCoordinateBoundsFromLatLngBounds(*tileSet.bounds);
|
||||
XCTAssert(MGLCoordinateBoundsEqualToCoordinateBounds(bounds, actual), @"The bounds round-trip");
|
||||
}
|
||||
|
||||
// when the tile set has an attribution
|
||||
NSString *attribution = @"my tileset © ©️🎈";
|
||||
tileSet = MGLTileSetFromTileURLTemplates(tileURLTemplates, @{
|
||||
|
||||
@@ -10,6 +10,12 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
namespace {
|
||||
|
||||
const std::string assetProtocol = "asset://";
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
class AssetFileSource::Impl {
|
||||
@@ -19,18 +25,17 @@ public:
|
||||
}
|
||||
|
||||
void request(const std::string& url, ActorRef<FileSourceRequest> req) {
|
||||
std::string path;
|
||||
|
||||
if (url.size() <= 8 || url[8] == '/') {
|
||||
// This is an empty or absolute path.
|
||||
path = mbgl::util::percentDecode(url.substr(8));
|
||||
} else {
|
||||
// This is a relative path. Prefix with the application root.
|
||||
path = root + "/" + mbgl::util::percentDecode(url.substr(8));
|
||||
}
|
||||
|
||||
Response response;
|
||||
|
||||
if (!acceptsURL(url)) {
|
||||
response.error = std::make_unique<Response::Error>(Response::Error::Reason::Other,
|
||||
"Invalid asset URL");
|
||||
req.invoke(&FileSourceRequest::setResponse, response);
|
||||
return;
|
||||
}
|
||||
|
||||
// Cut off the protocol and prefix with path.
|
||||
const auto path = root + "/" + mbgl::util::percentDecode(url.substr(assetProtocol.size()));
|
||||
struct stat buf;
|
||||
int result = stat(path.c_str(), &buf);
|
||||
|
||||
@@ -69,4 +74,8 @@ std::unique_ptr<AsyncRequest> AssetFileSource::request(const Resource& resource,
|
||||
return std::move(req);
|
||||
}
|
||||
|
||||
bool AssetFileSource::acceptsURL(const std::string& url) {
|
||||
return std::equal(assetProtocol.begin(), assetProtocol.end(), url.begin());
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -14,16 +14,6 @@
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace {
|
||||
|
||||
const std::string assetProtocol = "asset://";
|
||||
|
||||
bool isAssetURL(const std::string& url) {
|
||||
return std::equal(assetProtocol.begin(), assetProtocol.end(), url.begin());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
class DefaultFileSource::Impl {
|
||||
@@ -118,7 +108,7 @@ public:
|
||||
ref.invoke(&FileSourceRequest::setResponse, res);
|
||||
};
|
||||
|
||||
if (isAssetURL(resource.url)) {
|
||||
if (AssetFileSource::acceptsURL(resource.url)) {
|
||||
//Asset request
|
||||
tasks[req] = assetFileSource->request(resource, callback);
|
||||
} else if (LocalFileSource::acceptsURL(resource.url)) {
|
||||
|
||||
@@ -16,8 +16,7 @@
|
||||
|
||||
namespace {
|
||||
|
||||
const char* protocol = "file://";
|
||||
const std::size_t protocolLength = 7;
|
||||
const std::string fileProtocol = "file://";
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -28,11 +27,17 @@ public:
|
||||
Impl(ActorRef<Impl>) {}
|
||||
|
||||
void request(const std::string& url, ActorRef<FileSourceRequest> req) {
|
||||
// Cut off the protocol
|
||||
std::string path = mbgl::util::percentDecode(url.substr(protocolLength));
|
||||
|
||||
Response response;
|
||||
|
||||
if (!acceptsURL(url)) {
|
||||
response.error = std::make_unique<Response::Error>(Response::Error::Reason::Other,
|
||||
"Invalid file URL");
|
||||
req.invoke(&FileSourceRequest::setResponse, response);
|
||||
return;
|
||||
}
|
||||
|
||||
// Cut off the protocol and prefix with path.
|
||||
const auto path = mbgl::util::percentDecode(url.substr(fileProtocol.size()));
|
||||
struct stat buf;
|
||||
int result = stat(path.c_str(), &buf);
|
||||
|
||||
@@ -70,7 +75,7 @@ std::unique_ptr<AsyncRequest> LocalFileSource::request(const Resource& resource,
|
||||
}
|
||||
|
||||
bool LocalFileSource::acceptsURL(const std::string& url) {
|
||||
return url.compare(0, protocolLength, protocol) == 0;
|
||||
return std::equal(fileProtocol.begin(), fileProtocol.end(), url.begin());
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -11,6 +11,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))
|
||||
@@ -34,15 +35,19 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT
|
||||
### Map snapshots
|
||||
|
||||
* Fixed a memory leak that occurred when creating a map snapshot. ([#10585](https://github.com/mapbox/mapbox-gl-native/pull/10585))
|
||||
* Fixed an issue that caused `MGLMapSnapshotter.pointForCoordinate` to return an incorrect value. ([#11035](https://github.com/mapbox/mapbox-gl-native/pull/11035))
|
||||
|
||||
### Other changes
|
||||
## Other changes
|
||||
|
||||
* Feature querying results now account for the `MGLSymbolStyleLayer.circleStrokeWidth` property. ([#10897](https://github.com/mapbox/mapbox-gl-native/pull/10897))
|
||||
* Fixed an issue preventing labels from being transliterated when VoiceOver was enabled on iOS 10._x_ and below. ([#10881](https://github.com/mapbox/mapbox-gl-native/pull/10881))
|
||||
* Labels are now transliterated from more languages when VoiceOver is enabled. ([#10881](https://github.com/mapbox/mapbox-gl-native/pull/10881))
|
||||
* Long-pressing the attribution button causes the SDK’s version number to be displayed in the action sheet that appears. ([#10650](https://github.com/mapbox/mapbox-gl-native/pull/10650))
|
||||
|
||||
## 3.7.4 - February 12, 2018
|
||||
|
||||
* Added the `MGLTileSourceOptionTileCoordinateBounds` option to create an `MGLTileSource` that only supplies tiles within a specific geographic bounding box. ([#11141](https://github.com/mapbox/mapbox-gl-native/pull/11141))
|
||||
* Fixed an issue that caused `-[MGLMapSnapshotter pointForCoordinate:]` to return the wrong point. ([#11035](https://github.com/mapbox/mapbox-gl-native/pull/11035))
|
||||
|
||||
## 3.7.3 - January 10, 2018
|
||||
|
||||
* Fixed a crash while zooming while annotations are present on the map. ([#10791](https://github.com/mapbox/mapbox-gl-native/pull/10791))
|
||||
|
||||
@@ -50,12 +50,13 @@
|
||||
options.zoomLevel = 10;
|
||||
|
||||
// Create and start the snapshotter
|
||||
__weak UIImageView *weakImageView = imageView;
|
||||
MGLMapSnapshotter* snapshotter = [[MGLMapSnapshotter alloc] initWithOptions:options];
|
||||
[snapshotter startWithCompletionHandler: ^(MGLMapSnapshot* snapshot, NSError *error) {
|
||||
if (error) {
|
||||
NSLog(@"Could not load snapshot: %@", [error localizedDescription]);
|
||||
} else {
|
||||
imageView.image = snapshot.image;
|
||||
weakImageView.image = snapshot.image;
|
||||
}
|
||||
}];
|
||||
|
||||
|
||||
@@ -1280,6 +1280,7 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
|
||||
- (void)styleDynamicPointCollection
|
||||
{
|
||||
[self.mapView setCenterCoordinate:CLLocationCoordinate2DMake(36.9979, -109.0441) zoomLevel:14 animated:NO];
|
||||
|
||||
CLLocationCoordinate2D coordinates[] = {
|
||||
{37.00145594210082, -109.04960632324219},
|
||||
{37.00173012609867, -109.0404224395752},
|
||||
@@ -1889,7 +1890,8 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
|
||||
[self updateHUD];
|
||||
}
|
||||
|
||||
- (void)mapView:(MGLMapView *)mapView regionDidChangeAnimated:(BOOL)animated {
|
||||
- (void)mapView:(MGLMapView *)mapView regionDidChangeWithReason:(MGLCameraChangeReason)reason animated:(BOOL)animated
|
||||
{
|
||||
[self updateHUD];
|
||||
}
|
||||
|
||||
|
||||
@@ -109,6 +109,7 @@ the following terms for concepts defined in the style specification:
|
||||
|
||||
In the style specification | In the SDK
|
||||
---------------------------|---------
|
||||
bounds | coordinate bounds
|
||||
filter | predicate
|
||||
function type | interpolation mode
|
||||
id | identifier
|
||||
@@ -149,6 +150,7 @@ In style JSON | In TileJSON | In the SDK
|
||||
`tiles` | `tiles` | `tileURLTemplates` parameter in `-[MGLTileSource initWithIdentifier:tileURLTemplates:options:]`
|
||||
`minzoom` | `minzoom` | `MGLTileSourceOptionMinimumZoomLevel`
|
||||
`maxzoom` | `maxzoom` | `MGLTileSourceOptionMaximumZoomLevel`
|
||||
`bounds` | `bounds` | `MGLTileSourceOptionCoordinateBounds`
|
||||
`tileSize` | — | `MGLTileSourceOptionTileSize`
|
||||
`attribution` | `attribution` | `MGLTileSourceOptionAttributionHTMLString` (but consider specifying `MGLTileSourceOptionAttributionInfos` instead for improved security)
|
||||
`scheme` | `scheme` | `MGLTileSourceOptionTileCoordinateSystem`
|
||||
@@ -190,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, ); }; };
|
||||
@@ -297,6 +303,12 @@
|
||||
96E5170320005A6800A02306 /* FABKitProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8848811CBB033F00AB86E3 /* FABKitProtocol.h */; };
|
||||
96E5170420005A6B00A02306 /* SMCalloutView.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8848891CBB037E00AB86E3 /* SMCalloutView.h */; };
|
||||
96F3F73C1F57124B003E2D2C /* MGLUserLocationHeadingIndicator.h in Headers */ = {isa = PBXBuildFile; fileRef = 96F3F73B1F5711F1003E2D2C /* MGLUserLocationHeadingIndicator.h */; };
|
||||
AC518DFF201BB55A00EBC820 /* MGLTelemetryConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = AC518DFD201BB55A00EBC820 /* MGLTelemetryConfig.h */; };
|
||||
AC518E00201BB55A00EBC820 /* MGLTelemetryConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = AC518DFD201BB55A00EBC820 /* MGLTelemetryConfig.h */; };
|
||||
AC518E03201BB56000EBC820 /* MGLTelemetryConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = AC518DFE201BB55A00EBC820 /* MGLTelemetryConfig.m */; };
|
||||
AC518E04201BB56100EBC820 /* MGLTelemetryConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = AC518DFE201BB55A00EBC820 /* MGLTelemetryConfig.m */; };
|
||||
CA55CD41202C16AA00CE7095 /* MGLCameraChangeReason.h in Headers */ = {isa = PBXBuildFile; fileRef = CA55CD3E202C16AA00CE7095 /* MGLCameraChangeReason.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
CA55CD42202C16AA00CE7095 /* MGLCameraChangeReason.h in Headers */ = {isa = PBXBuildFile; fileRef = CA55CD3E202C16AA00CE7095 /* MGLCameraChangeReason.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
DA00FC8E1D5EEB0D009AABC8 /* MGLAttributionInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = DA00FC8C1D5EEB0D009AABC8 /* MGLAttributionInfo.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
DA00FC8F1D5EEB0D009AABC8 /* MGLAttributionInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = DA00FC8C1D5EEB0D009AABC8 /* MGLAttributionInfo.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
DA00FC901D5EEB0D009AABC8 /* MGLAttributionInfo.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA00FC8D1D5EEB0D009AABC8 /* MGLAttributionInfo.mm */; };
|
||||
@@ -666,6 +678,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>"; };
|
||||
@@ -797,6 +811,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>"; };
|
||||
@@ -831,6 +847,9 @@
|
||||
96E0272D1E57C7E6004B8E66 /* vi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = vi; path = vi.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
96E0272E1E57C7E7004B8E66 /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-BR"; path = "pt-BR.lproj/Localizable.strings"; sourceTree = "<group>"; };
|
||||
96F3F73B1F5711F1003E2D2C /* MGLUserLocationHeadingIndicator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGLUserLocationHeadingIndicator.h; sourceTree = "<group>"; };
|
||||
AC518DFD201BB55A00EBC820 /* MGLTelemetryConfig.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGLTelemetryConfig.h; sourceTree = "<group>"; };
|
||||
AC518DFE201BB55A00EBC820 /* MGLTelemetryConfig.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MGLTelemetryConfig.m; sourceTree = "<group>"; };
|
||||
CA55CD3E202C16AA00CE7095 /* MGLCameraChangeReason.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLCameraChangeReason.h; sourceTree = "<group>"; };
|
||||
DA00FC8C1D5EEB0D009AABC8 /* MGLAttributionInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLAttributionInfo.h; sourceTree = "<group>"; };
|
||||
DA00FC8D1D5EEB0D009AABC8 /* MGLAttributionInfo.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLAttributionInfo.mm; sourceTree = "<group>"; };
|
||||
DA0CD58F1CF56F6A00A5F5A5 /* MGLFeatureTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLFeatureTests.mm; path = ../../darwin/test/MGLFeatureTests.mm; sourceTree = "<group>"; };
|
||||
@@ -1236,6 +1255,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 +1327,8 @@
|
||||
3575798F1D513EF1000B822E /* Layers */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
170C43782028D49800863DF0 /* MGLHeatmapColorTests.mm */,
|
||||
170C43792028D49800863DF0 /* MGLHeatmapStyleLayerTests.mm */,
|
||||
DA2DBBCC1D51E80400D38FF9 /* MGLStyleLayerTests.h */,
|
||||
DA2DBBCD1D51E80400D38FF9 /* MGLStyleLayerTests.m */,
|
||||
DA3C6FF21E2859E700F962BE /* test-Bridging-Header.h */,
|
||||
@@ -1587,19 +1610,20 @@
|
||||
DA8848331CBAFB2A00AB86E3 /* Kit */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
355ADFF91E9281C300F3939D /* Views */,
|
||||
35CE617F1D4165C2004F2359 /* Categories */,
|
||||
DAD165841CF4D06B001FF4B9 /* Annotations */,
|
||||
DAD165851CF4D08B001FF4B9 /* Telemetry */,
|
||||
DA704CC01F65A475004B3F28 /* MGLMapAccessibilityElement.h */,
|
||||
DA704CC11F65A475004B3F28 /* MGLMapAccessibilityElement.mm */,
|
||||
DA8848361CBAFB8500AB86E3 /* MGLMapView.h */,
|
||||
DA17BE2F1CC4BAC300402C41 /* MGLMapView_Private.h */,
|
||||
DA8848371CBAFB8500AB86E3 /* MGLMapView+IBAdditions.h */,
|
||||
DA737EE01D056A4E005BDA16 /* MGLMapViewDelegate.h */,
|
||||
DA88484A1CBAFB9800AB86E3 /* MGLMapView.mm */,
|
||||
35CE617F1D4165C2004F2359 /* Categories */,
|
||||
DA88487F1CBB033F00AB86E3 /* Fabric */,
|
||||
DA8848881CBB036000AB86E3 /* SMCalloutView */,
|
||||
DAD165851CF4D08B001FF4B9 /* Telemetry */,
|
||||
355ADFF91E9281C300F3939D /* Views */,
|
||||
CA55CD3E202C16AA00CE7095 /* MGLCameraChangeReason.h */,
|
||||
DA704CC01F65A475004B3F28 /* MGLMapAccessibilityElement.h */,
|
||||
DA704CC11F65A475004B3F28 /* MGLMapAccessibilityElement.mm */,
|
||||
DA17BE2F1CC4BAC300402C41 /* MGLMapView_Private.h */,
|
||||
DA8848361CBAFB8500AB86E3 /* MGLMapView.h */,
|
||||
DA88484A1CBAFB9800AB86E3 /* MGLMapView.mm */,
|
||||
DA8848371CBAFB8500AB86E3 /* MGLMapView+IBAdditions.h */,
|
||||
DA737EE01D056A4E005BDA16 /* MGLMapViewDelegate.h */,
|
||||
);
|
||||
name = Kit;
|
||||
path = src;
|
||||
@@ -1858,6 +1882,8 @@
|
||||
DA8848491CBAFB9800AB86E3 /* MGLMapboxEvents.m */,
|
||||
9620BB361E69FE1700705A1D /* MGLSDKUpdateChecker.h */,
|
||||
9620BB371E69FE1700705A1D /* MGLSDKUpdateChecker.mm */,
|
||||
AC518DFD201BB55A00EBC820 /* MGLTelemetryConfig.h */,
|
||||
AC518DFE201BB55A00EBC820 /* MGLTelemetryConfig.m */,
|
||||
);
|
||||
name = Telemetry;
|
||||
sourceTree = "<group>";
|
||||
@@ -1891,6 +1917,8 @@
|
||||
350098DC1D484E60004B2AF0 /* NSValue+MGLStyleAttributeAdditions.h in Headers */,
|
||||
DA8848231CBAFA6200AB86E3 /* MGLOfflineStorage_Private.h in Headers */,
|
||||
404326891D5B9B27007111BD /* MGLAnnotationContainerView_Private.h in Headers */,
|
||||
CA55CD41202C16AA00CE7095 /* MGLCameraChangeReason.h in Headers */,
|
||||
1FB7DAAF1F2A4DBD00410606 /* MGLVectorSource+MGLAdditions.h in Headers */,
|
||||
DA88483B1CBAFB8500AB86E3 /* MGLCalloutView.h in Headers */,
|
||||
35E0CFE61D3E501500188327 /* MGLStyle_Private.h in Headers */,
|
||||
3510FFF01D6D9D8C00F413B2 /* NSExpression+MGLAdditions.h in Headers */,
|
||||
@@ -1963,6 +1991,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 */,
|
||||
@@ -1978,6 +2007,7 @@
|
||||
DA8847F51CBAFA5100AB86E3 /* MGLOfflineRegion.h in Headers */,
|
||||
DA737EE11D056A4E005BDA16 /* MGLMapViewDelegate.h in Headers */,
|
||||
DA8848851CBB033F00AB86E3 /* FABKitProtocol.h in Headers */,
|
||||
AC518DFF201BB55A00EBC820 /* MGLTelemetryConfig.h in Headers */,
|
||||
DA88481B1CBAFA6200AB86E3 /* MGLGeometry_Private.h in Headers */,
|
||||
3510FFF91D6DCC4700F413B2 /* NSCompoundPredicate+MGLAdditions.h in Headers */,
|
||||
3557F7B01E1D27D300CCA5E6 /* MGLDistanceFormatter.h in Headers */,
|
||||
@@ -2038,6 +2068,7 @@
|
||||
96E516EF2000594F00A02306 /* NSArray+MGLAdditions.h in Headers */,
|
||||
96E516F12000596800A02306 /* NSString+MGLAdditions.h in Headers */,
|
||||
35E0CFE71D3E501500188327 /* MGLStyle_Private.h in Headers */,
|
||||
CA55CD42202C16AA00CE7095 /* MGLCameraChangeReason.h in Headers */,
|
||||
DABFB86D1CBE9A0F00D62B32 /* MGLAnnotationImage.h in Headers */,
|
||||
DABFB8721CBE9A0F00D62B32 /* MGLUserLocation.h in Headers */,
|
||||
927FBD001F4DB05500F8BF1F /* MGLMapSnapshotter.h in Headers */,
|
||||
@@ -2068,6 +2099,7 @@
|
||||
96E516FB20005A4000A02306 /* MGLUserLocationHeadingBeamLayer.h in Headers */,
|
||||
96E516DC2000547000A02306 /* MGLPolyline_Private.h in Headers */,
|
||||
353AFA151D65AB17005A69F4 /* NSDate+MGLAdditions.h in Headers */,
|
||||
AC518E00201BB55A00EBC820 /* MGLTelemetryConfig.h in Headers */,
|
||||
3510FFFA1D6DCC4700F413B2 /* NSCompoundPredicate+MGLAdditions.h in Headers */,
|
||||
DA72620C1DEEE3480043BB89 /* MGLOpenGLStyleLayer.h in Headers */,
|
||||
35CE61831D4165D9004F2359 /* UIColor+MGLAdditions.h in Headers */,
|
||||
@@ -2099,6 +2131,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 */,
|
||||
@@ -2544,6 +2577,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 */,
|
||||
@@ -2656,6 +2691,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 */,
|
||||
@@ -2667,6 +2703,7 @@
|
||||
DA72620D1DEEE3480043BB89 /* MGLOpenGLStyleLayer.mm in Sources */,
|
||||
DA88481A1CBAFA6200AB86E3 /* MGLAccountManager.m in Sources */,
|
||||
3510FFFB1D6DCC4700F413B2 /* NSCompoundPredicate+MGLAdditions.mm in Sources */,
|
||||
AC518E03201BB56000EBC820 /* MGLTelemetryConfig.m in Sources */,
|
||||
DA8848271CBAFA6200AB86E3 /* MGLPolyline.mm in Sources */,
|
||||
DA8848581CBAFB9800AB86E3 /* MGLMapboxEvents.m in Sources */,
|
||||
35CE61841D4165D9004F2359 /* UIColor+MGLAdditions.mm in Sources */,
|
||||
@@ -2747,6 +2784,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 */,
|
||||
@@ -2758,6 +2796,7 @@
|
||||
DA72620E1DEEE3480043BB89 /* MGLOpenGLStyleLayer.mm in Sources */,
|
||||
DAA4E42F1CBB730400178DFB /* MGLCompactCalloutView.m in Sources */,
|
||||
3510FFFC1D6DCC4700F413B2 /* NSCompoundPredicate+MGLAdditions.mm in Sources */,
|
||||
AC518E04201BB56100EBC820 /* MGLTelemetryConfig.m in Sources */,
|
||||
DAA4E4271CBB730400178DFB /* MGLTilePyramidOfflineRegion.mm in Sources */,
|
||||
DAA4E41C1CBB730400178DFB /* MGLAccountManager.m in Sources */,
|
||||
35CE61851D4165D9004F2359 /* UIColor+MGLAdditions.mm in Sources */,
|
||||
|
||||
@@ -95,6 +95,7 @@ custom_categories:
|
||||
- MGLCircleStyleLayer
|
||||
- MGLFillStyleLayer
|
||||
- MGLFillExtrusionStyleLayer
|
||||
- MGLHeatmapStyleLayer
|
||||
- MGLHillshadeStyleLayer
|
||||
- MGLLineStyleLayer
|
||||
- MGLSymbolStyleLayer
|
||||
|
||||
61
platform/ios/src/MGLCameraChangeReason.h
Normal file
61
platform/ios/src/MGLCameraChangeReason.h
Normal file
@@ -0,0 +1,61 @@
|
||||
#import "MGLFoundation.h"
|
||||
|
||||
/**
|
||||
:nodoc:
|
||||
Bitmask values that describe why a camera move occurred.
|
||||
|
||||
Values of this type are passed to the `MGLMapView`'s delegate in the following methods:
|
||||
|
||||
- `-mapView:shouldChangeFromCamera:toCamera:reason:`
|
||||
- `-mapView:regionWillChangeWithReason:animated:`
|
||||
- `-mapView:regionIsChangingWithReason:`
|
||||
- `-mapView:regionDidChangeWithReason:animated:`
|
||||
|
||||
It's important to note that it's almost impossible to perform a rotate without zooming (in or out),
|
||||
so if you'll often find `MGLCameraChangeReasonGesturePinch` set alongside `MGLCameraChangeReasonGestureRotate`.
|
||||
|
||||
Since there are several reasons why a zoom or rotation has occurred, it is worth considering
|
||||
creating a combined constant, for example:
|
||||
|
||||
```
|
||||
static const MGLCameraChangeReason anyZoom = MGLCameraChangeReasonGesturePinch |
|
||||
MGLCameraChangeReasonGestureZoomIn |
|
||||
MGLCameraChangeReasonGestureZoomOut |
|
||||
MGLCameraChangeReasonGestureOneFingerZoom;
|
||||
|
||||
static const MGLCameraChangeReason anyRotation = MGLCameraChangeReasonResetNorth | MGLCameraChangeReasonGestureRotate;
|
||||
```
|
||||
*/
|
||||
typedef NS_OPTIONS(NSUInteger, MGLCameraChangeReason)
|
||||
{
|
||||
/// :nodoc: The reason for the camera change has not be specified.
|
||||
MGLCameraChangeReasonNone = 0,
|
||||
|
||||
/// :nodoc: Set when a public API that moves the camera is called. This may be set for some gestures,
|
||||
/// for example MGLCameraChangeReasonResetNorth.
|
||||
MGLCameraChangeReasonProgrammatic = 1 << 0,
|
||||
|
||||
/// :nodoc: The user tapped the compass to reset the map orientation so North is up.
|
||||
MGLCameraChangeReasonResetNorth = 1 << 1,
|
||||
|
||||
/// :nodoc: The user panned the map.
|
||||
MGLCameraChangeReasonGesturePan = 1 << 2,
|
||||
|
||||
/// :nodoc: The user pinched to zoom in/out.
|
||||
MGLCameraChangeReasonGesturePinch = 1 << 3,
|
||||
|
||||
// :nodoc: The user rotated the map.
|
||||
MGLCameraChangeReasonGestureRotate = 1 << 4,
|
||||
|
||||
/// :nodoc: The user zoomed the map in (one finger double tap).
|
||||
MGLCameraChangeReasonGestureZoomIn = 1 << 5,
|
||||
|
||||
/// :nodoc: The user zoomed the map out (two finger single tap).
|
||||
MGLCameraChangeReasonGestureZoomOut = 1 << 6,
|
||||
|
||||
/// :nodoc: The user long pressed on the map for a quick zoom (single tap, then long press and drag up/down).
|
||||
MGLCameraChangeReasonGestureOneFingerZoom = 1 << 7,
|
||||
|
||||
// :nodoc: The user panned with two fingers to tilt the map (two finger drag).
|
||||
MGLCameraChangeReasonGestureTilt = 1 << 8
|
||||
};
|
||||
@@ -1,9 +1,9 @@
|
||||
#import "MGLLocationManager.h"
|
||||
#import "MGLTelemetryConfig.h"
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
static const NSTimeInterval MGLLocationManagerHibernationTimeout = 300.0;
|
||||
static const NSTimeInterval MGLLocationManagerHibernationPollInterval = 5.0;
|
||||
static const CLLocationDistance MGLLocationManagerHibernationRadius = 300.0;
|
||||
static const CLLocationDistance MGLLocationManagerDistanceFilter = 5.0;
|
||||
static NSString * const MGLLocationManagerRegionIdentifier = @"MGLLocationManagerRegionIdentifier.fence.center";
|
||||
|
||||
@@ -122,7 +122,7 @@ static NSString * const MGLLocationManagerRegionIdentifier = @"MGLLocationManage
|
||||
}
|
||||
|
||||
- (void)establishRegionMonitoringForLocation:(CLLocation *)location {
|
||||
CLCircularRegion *region = [[CLCircularRegion alloc] initWithCenter:location.coordinate radius:MGLLocationManagerHibernationRadius identifier:MGLLocationManagerRegionIdentifier];
|
||||
CLCircularRegion *region = [[CLCircularRegion alloc] initWithCenter:location.coordinate radius:MGLTelemetryConfig.sharedConfig.MGLLocationManagerHibernationRadius identifier:MGLLocationManagerRegionIdentifier];
|
||||
region.notifyOnEntry = NO;
|
||||
region.notifyOnExit = YES;
|
||||
[self.standardLocationManager startMonitoringForRegion:region];
|
||||
@@ -151,7 +151,7 @@ static NSString * const MGLLocationManagerRegionIdentifier = @"MGLLocationManage
|
||||
if (location.speed > 0.0) {
|
||||
[self startBackgroundTimeoutTimer];
|
||||
}
|
||||
if (self.standardLocationManager.monitoredRegions.count == 0 || location.horizontalAccuracy < MGLLocationManagerHibernationRadius) {
|
||||
if (self.standardLocationManager.monitoredRegions.count == 0 || location.horizontalAccuracy < MGLTelemetryConfig.sharedConfig.MGLLocationManagerHibernationRadius) {
|
||||
[self establishRegionMonitoringForLocation:location];
|
||||
}
|
||||
if ([self.delegate respondsToSelector:@selector(locationManager:didUpdateLocations:)]) {
|
||||
|
||||
@@ -210,6 +210,8 @@ public:
|
||||
@property (nonatomic) UILongPressGestureRecognizer *quickZoom;
|
||||
@property (nonatomic) UIPanGestureRecognizer *twoFingerDrag;
|
||||
|
||||
@property (nonatomic) MGLCameraChangeReason cameraChangeReasonBitmask;
|
||||
|
||||
/// Mapping from reusable identifiers to annotation images.
|
||||
@property (nonatomic) NS_MUTABLE_DICTIONARY_OF(NSString *, MGLAnnotationImage *) *annotationImagesByIdentifier;
|
||||
|
||||
@@ -506,10 +508,6 @@ public:
|
||||
_doubleTap.numberOfTapsRequired = 2;
|
||||
[self addGestureRecognizer:_doubleTap];
|
||||
|
||||
_singleTapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTapGesture:)];
|
||||
[_singleTapGestureRecognizer requireGestureRecognizerToFail:_doubleTap];
|
||||
_singleTapGestureRecognizer.delegate = self;
|
||||
[self addGestureRecognizer:_singleTapGestureRecognizer];
|
||||
|
||||
_twoFingerDrag = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleTwoFingerDragGesture:)];
|
||||
_twoFingerDrag.minimumNumberOfTouches = 2;
|
||||
@@ -534,16 +532,25 @@ public:
|
||||
[_quickZoom requireGestureRecognizerToFail:_doubleTap];
|
||||
[self addGestureRecognizer:_quickZoom];
|
||||
|
||||
_singleTapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTapGesture:)];
|
||||
[_singleTapGestureRecognizer requireGestureRecognizerToFail:_doubleTap];
|
||||
_singleTapGestureRecognizer.delegate = self;
|
||||
[_singleTapGestureRecognizer requireGestureRecognizerToFail:_quickZoom];
|
||||
[self addGestureRecognizer:_singleTapGestureRecognizer];
|
||||
|
||||
// observe app activity
|
||||
//
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(willTerminate) name:UIApplicationWillTerminateNotification object:nil];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sleepGL:) name:UIApplicationDidEnterBackgroundNotification object:nil];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(wakeGL:) name:UIApplicationWillEnterForegroundNotification object:nil];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sleepGL:) name:UIApplicationWillResignActiveNotification object:nil];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(wakeGL:) name:UIApplicationDidBecomeActiveNotification object:nil];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didReceiveMemoryWarning) name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(deviceOrientationDidChange:) name:UIDeviceOrientationDidChangeNotification object:nil];
|
||||
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
|
||||
|
||||
|
||||
// set initial position
|
||||
//
|
||||
mbgl::CameraOptions options;
|
||||
@@ -551,6 +558,9 @@ public:
|
||||
mbgl::EdgeInsets padding = MGLEdgeInsetsFromNSEdgeInsets(self.contentInset);
|
||||
options.padding = padding;
|
||||
options.zoom = 0;
|
||||
|
||||
_cameraChangeReasonBitmask = MGLCameraChangeReasonNone;
|
||||
|
||||
_mbglMap->jumpTo(options);
|
||||
_pendingLatitude = NAN;
|
||||
_pendingLongitude = NAN;
|
||||
@@ -706,7 +716,7 @@ public:
|
||||
{
|
||||
MGLAssertIsMainThread();
|
||||
|
||||
_rendererFrontend->onLowMemory();
|
||||
_rendererFrontend->reduceMemoryUse();
|
||||
}
|
||||
|
||||
#pragma mark - Layout -
|
||||
@@ -1148,6 +1158,13 @@ public:
|
||||
- (void)sleepGL:(__unused NSNotification *)notification
|
||||
{
|
||||
MGLAssertIsMainThread();
|
||||
|
||||
// Ideally we would wait until we actually received a memory warning but the bulk of the memory
|
||||
// we have to release is tied up in GL buffers that we can't touch once we're in the background.
|
||||
// Compromise position: release everything but currently rendering tiles
|
||||
// A possible improvement would be to store a copy of the GL buffers that we could use to rapidly
|
||||
// restart, but that we could also discard in response to a memory warning.
|
||||
_rendererFrontend->reduceMemoryUse();
|
||||
|
||||
if ( ! self.dormant)
|
||||
{
|
||||
@@ -1237,6 +1254,8 @@ public:
|
||||
|
||||
- (void)handleCompassTapGesture:(__unused id)sender
|
||||
{
|
||||
self.cameraChangeReasonBitmask |= MGLCameraChangeReasonResetNorth;
|
||||
|
||||
[self resetNorthAnimated:YES];
|
||||
|
||||
if (self.userTrackingMode == MGLUserTrackingModeFollowWithHeading ||
|
||||
@@ -1259,6 +1278,7 @@ public:
|
||||
|
||||
- (void)notifyGestureDidBegin {
|
||||
BOOL animated = NO;
|
||||
|
||||
[self cameraWillChangeAnimated:animated];
|
||||
_mbglMap->setGestureInProgress(true);
|
||||
_changeDelimiterSuppressionDepth++;
|
||||
@@ -1282,6 +1302,23 @@ public:
|
||||
return _changeDelimiterSuppressionDepth > 0;
|
||||
}
|
||||
|
||||
- (BOOL)_shouldChangeFromCamera:(nonnull MGLMapCamera *)oldCamera toCamera:(nonnull MGLMapCamera *)newCamera
|
||||
{
|
||||
// Check delegates first
|
||||
if ([self.delegate respondsToSelector:@selector(mapView:shouldChangeFromCamera:toCamera:reason:)])
|
||||
{
|
||||
return [self.delegate mapView:self shouldChangeFromCamera:oldCamera toCamera:newCamera reason:self.cameraChangeReasonBitmask];
|
||||
}
|
||||
else if ([self.delegate respondsToSelector:@selector(mapView:shouldChangeFromCamera:toCamera:)])
|
||||
{
|
||||
return [self.delegate mapView:self shouldChangeFromCamera:oldCamera toCamera:newCamera];
|
||||
}
|
||||
else
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)handlePanGesture:(UIPanGestureRecognizer *)pan
|
||||
{
|
||||
if ( ! self.isScrollEnabled) return;
|
||||
@@ -1289,7 +1326,9 @@ public:
|
||||
_mbglMap->cancelTransitions();
|
||||
|
||||
MGLMapCamera *oldCamera = self.camera;
|
||||
|
||||
|
||||
self.cameraChangeReasonBitmask |= MGLCameraChangeReasonGesturePan;
|
||||
|
||||
if (pan.state == UIGestureRecognizerStateBegan)
|
||||
{
|
||||
[self trackGestureEvent:MGLEventGesturePanStart forRecognizer:pan];
|
||||
@@ -1303,9 +1342,8 @@ public:
|
||||
CGPoint delta = [pan translationInView:pan.view];
|
||||
|
||||
MGLMapCamera *toCamera = [self cameraByPanningWithTranslation:delta panGesture:pan];
|
||||
|
||||
if (![self.delegate respondsToSelector:@selector(mapView:shouldChangeFromCamera:toCamera:)] ||
|
||||
[self.delegate mapView:self shouldChangeFromCamera:oldCamera toCamera:toCamera])
|
||||
|
||||
if ([self _shouldChangeFromCamera:oldCamera toCamera:toCamera])
|
||||
{
|
||||
_mbglMap->moveBy({ delta.x, delta.y });
|
||||
[pan setTranslation:CGPointZero inView:pan.view];
|
||||
@@ -1327,9 +1365,8 @@ public:
|
||||
{
|
||||
CGPoint offset = CGPointMake(velocity.x * self.decelerationRate / 4, velocity.y * self.decelerationRate / 4);
|
||||
MGLMapCamera *toCamera = [self cameraByPanningWithTranslation:offset panGesture:pan];
|
||||
|
||||
if (![self.delegate respondsToSelector:@selector(mapView:shouldChangeFromCamera:toCamera:)] ||
|
||||
[self.delegate mapView:self shouldChangeFromCamera:oldCamera toCamera:toCamera])
|
||||
|
||||
if ([self _shouldChangeFromCamera:oldCamera toCamera:toCamera])
|
||||
{
|
||||
_mbglMap->moveBy({ offset.x, offset.y }, MGLDurationFromTimeInterval(self.decelerationRate));
|
||||
}
|
||||
@@ -1360,6 +1397,8 @@ public:
|
||||
CGPoint centerPoint = [self anchorPointForGesture:pinch];
|
||||
MGLMapCamera *oldCamera = self.camera;
|
||||
|
||||
self.cameraChangeReasonBitmask |= MGLCameraChangeReasonGesturePinch;
|
||||
|
||||
if (pinch.state == UIGestureRecognizerStateBegan)
|
||||
{
|
||||
[self trackGestureEvent:MGLEventGesturePinchStart forRecognizer:pinch];
|
||||
@@ -1376,9 +1415,8 @@ public:
|
||||
|
||||
// Calculates the final camera zoom, has no effect within current map camera.
|
||||
MGLMapCamera *toCamera = [self cameraByZoomingToZoomLevel:newZoom aroundAnchorPoint:centerPoint];
|
||||
|
||||
if (![self.delegate respondsToSelector:@selector(mapView:shouldChangeFromCamera:toCamera:)] ||
|
||||
[self.delegate mapView:self shouldChangeFromCamera:oldCamera toCamera:toCamera])
|
||||
|
||||
if ([self _shouldChangeFromCamera:oldCamera toCamera:toCamera])
|
||||
{
|
||||
_mbglMap->setZoom(newZoom, mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y });
|
||||
// The gesture recognizer only reports the gesture’s current center
|
||||
@@ -1430,9 +1468,8 @@ public:
|
||||
// Calculates the final camera zoom, this has no effect within current map camera.
|
||||
double zoom = log2(newScale);
|
||||
MGLMapCamera *toCamera = [self cameraByZoomingToZoomLevel:zoom aroundAnchorPoint:centerPoint];
|
||||
|
||||
if ([self.delegate respondsToSelector:@selector(mapView:shouldChangeFromCamera:toCamera:)]
|
||||
&& ![self.delegate mapView:self shouldChangeFromCamera:oldCamera toCamera:toCamera])
|
||||
|
||||
if ([self _shouldChangeFromCamera:oldCamera toCamera:toCamera])
|
||||
{
|
||||
drift = NO;
|
||||
} else {
|
||||
@@ -1458,7 +1495,9 @@ public:
|
||||
|
||||
CGPoint centerPoint = [self anchorPointForGesture:rotate];
|
||||
MGLMapCamera *oldCamera = self.camera;
|
||||
|
||||
|
||||
self.cameraChangeReasonBitmask |= MGLCameraChangeReasonGestureRotate;
|
||||
|
||||
if (rotate.state == UIGestureRecognizerStateBegan)
|
||||
{
|
||||
[self trackGestureEvent:MGLEventGestureRotateStart forRecognizer:rotate];
|
||||
@@ -1485,9 +1524,8 @@ public:
|
||||
}
|
||||
|
||||
MGLMapCamera *toCamera = [self cameraByRotatingToDirection:newDegrees aroundAnchorPoint:centerPoint];
|
||||
|
||||
if (![self.delegate respondsToSelector:@selector(mapView:shouldChangeFromCamera:toCamera:)] ||
|
||||
[self.delegate mapView:self shouldChangeFromCamera:oldCamera toCamera:toCamera])
|
||||
|
||||
if ([self _shouldChangeFromCamera:oldCamera toCamera:toCamera])
|
||||
{
|
||||
_mbglMap->setBearing(newDegrees, mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y });
|
||||
}
|
||||
@@ -1505,9 +1543,8 @@ public:
|
||||
CGFloat newDegrees = MGLDegreesFromRadians(newRadians) * -1;
|
||||
|
||||
MGLMapCamera *toCamera = [self cameraByRotatingToDirection:newDegrees aroundAnchorPoint:centerPoint];
|
||||
|
||||
if (![self.delegate respondsToSelector:@selector(mapView:shouldChangeFromCamera:toCamera:)] ||
|
||||
[self.delegate mapView:self shouldChangeFromCamera:oldCamera toCamera:toCamera])
|
||||
|
||||
if ([self _shouldChangeFromCamera:oldCamera toCamera:toCamera])
|
||||
{
|
||||
_mbglMap->setBearing(newDegrees, mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y }, MGLDurationFromTimeInterval(decelerationRate));
|
||||
|
||||
@@ -1552,6 +1589,7 @@ public:
|
||||
}
|
||||
[self deselectAnnotation:self.selectedAnnotation animated:YES];
|
||||
UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, nextElement);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1562,7 +1600,7 @@ public:
|
||||
CGRect positionRect = [self positioningRectForAnnotation:annotation defaultCalloutPoint:calloutPoint];
|
||||
[self selectAnnotation:annotation animated:YES calloutPositioningRect:positionRect];
|
||||
}
|
||||
else
|
||||
else if (self.selectedAnnotation)
|
||||
{
|
||||
[self deselectAnnotation:self.selectedAnnotation animated:YES];
|
||||
}
|
||||
@@ -1644,6 +1682,8 @@ public:
|
||||
|
||||
if (doubleTap.state == UIGestureRecognizerStateEnded)
|
||||
{
|
||||
self.cameraChangeReasonBitmask |= MGLCameraChangeReasonGestureZoomIn;
|
||||
|
||||
MGLMapCamera *oldCamera = self.camera;
|
||||
|
||||
double newZoom = round(self.zoomLevel) + 1.0;
|
||||
@@ -1651,9 +1691,8 @@ public:
|
||||
CGPoint gesturePoint = [self anchorPointForGesture:doubleTap];
|
||||
|
||||
MGLMapCamera *toCamera = [self cameraByZoomingToZoomLevel:newZoom aroundAnchorPoint:gesturePoint];
|
||||
|
||||
if (![self.delegate respondsToSelector:@selector(mapView:shouldChangeFromCamera:toCamera:)] ||
|
||||
[self.delegate mapView:self shouldChangeFromCamera:oldCamera toCamera:toCamera])
|
||||
|
||||
if ([self _shouldChangeFromCamera:oldCamera toCamera:toCamera])
|
||||
{
|
||||
[self trackGestureEvent:MGLEventGestureDoubleTap forRecognizer:doubleTap];
|
||||
|
||||
@@ -1680,9 +1719,13 @@ public:
|
||||
|
||||
_mbglMap->cancelTransitions();
|
||||
|
||||
self.cameraChangeReasonBitmask |= MGLCameraChangeReasonGestureZoomOut;
|
||||
|
||||
if (twoFingerTap.state == UIGestureRecognizerStateBegan)
|
||||
{
|
||||
[self trackGestureEvent:MGLEventGestureTwoFingerSingleTap forRecognizer:twoFingerTap];
|
||||
|
||||
[self notifyGestureDidBegin];
|
||||
}
|
||||
else if (twoFingerTap.state == UIGestureRecognizerStateEnded)
|
||||
{
|
||||
@@ -1693,9 +1736,8 @@ public:
|
||||
CGPoint gesturePoint = [self anchorPointForGesture:twoFingerTap];
|
||||
|
||||
MGLMapCamera *toCamera = [self cameraByZoomingToZoomLevel:newZoom aroundAnchorPoint:gesturePoint];
|
||||
|
||||
if (![self.delegate respondsToSelector:@selector(mapView:shouldChangeFromCamera:toCamera:)] ||
|
||||
[self.delegate mapView:self shouldChangeFromCamera:oldCamera toCamera:toCamera])
|
||||
|
||||
if ([self _shouldChangeFromCamera:oldCamera toCamera:toCamera])
|
||||
{
|
||||
mbgl::ScreenCoordinate center(gesturePoint.x, gesturePoint.y);
|
||||
_mbglMap->setZoom(newZoom, center, MGLDurationFromTimeInterval(MGLAnimationDuration));
|
||||
@@ -1715,7 +1757,9 @@ public:
|
||||
if ( ! self.isZoomEnabled) return;
|
||||
|
||||
_mbglMap->cancelTransitions();
|
||||
|
||||
|
||||
self.cameraChangeReasonBitmask |= MGLCameraChangeReasonGestureOneFingerZoom;
|
||||
|
||||
if (quickZoom.state == UIGestureRecognizerStateBegan)
|
||||
{
|
||||
[self trackGestureEvent:MGLEventGestureQuickZoom forRecognizer:quickZoom];
|
||||
@@ -1738,9 +1782,8 @@ public:
|
||||
|
||||
MGLMapCamera *oldCamera = self.camera;
|
||||
MGLMapCamera *toCamera = [self cameraByZoomingToZoomLevel:newZoom aroundAnchorPoint:centerPoint];
|
||||
|
||||
if (![self.delegate respondsToSelector:@selector(mapView:shouldChangeFromCamera:toCamera:)] ||
|
||||
[self.delegate mapView:self shouldChangeFromCamera:oldCamera toCamera:toCamera])
|
||||
|
||||
if ([self _shouldChangeFromCamera:oldCamera toCamera:toCamera])
|
||||
{
|
||||
_mbglMap->setZoom(newZoom, mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y });
|
||||
}
|
||||
@@ -1760,6 +1803,8 @@ public:
|
||||
|
||||
_mbglMap->cancelTransitions();
|
||||
|
||||
self.cameraChangeReasonBitmask |= MGLCameraChangeReasonGestureTilt;
|
||||
|
||||
if (twoFingerDrag.state == UIGestureRecognizerStateBegan)
|
||||
{
|
||||
[self trackGestureEvent:MGLEventGesturePitchStart forRecognizer:twoFingerDrag];
|
||||
@@ -1779,8 +1824,7 @@ public:
|
||||
MGLMapCamera *oldCamera = self.camera;
|
||||
MGLMapCamera *toCamera = [self cameraByTiltingToPitch:pitchNew];
|
||||
|
||||
if (![self.delegate respondsToSelector:@selector(mapView:shouldChangeFromCamera:toCamera:)] ||
|
||||
[self.delegate mapView:self shouldChangeFromCamera:oldCamera toCamera:toCamera])
|
||||
if ([self _shouldChangeFromCamera:oldCamera toCamera:toCamera])
|
||||
{
|
||||
_mbglMap->setPitch(pitchNew, mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y });
|
||||
}
|
||||
@@ -2278,7 +2322,7 @@ public:
|
||||
|
||||
- (void)emptyMemoryCache
|
||||
{
|
||||
_rendererFrontend->onLowMemory();
|
||||
_rendererFrontend->reduceMemoryUse();
|
||||
}
|
||||
|
||||
- (void)setZoomEnabled:(BOOL)zoomEnabled
|
||||
@@ -2871,6 +2915,8 @@ public:
|
||||
{
|
||||
self.userTrackingMode = MGLUserTrackingModeNone;
|
||||
|
||||
self.cameraChangeReasonBitmask |= MGLCameraChangeReasonProgrammatic;
|
||||
|
||||
[self _setCenterCoordinate:centerCoordinate edgePadding:self.contentInset zoomLevel:zoomLevel direction:direction duration:animated ? MGLAnimationDuration : 0 animationTimingFunction:nil completionHandler:completion];
|
||||
}
|
||||
|
||||
@@ -2920,6 +2966,9 @@ public:
|
||||
}
|
||||
|
||||
_mbglMap->cancelTransitions();
|
||||
|
||||
self.cameraChangeReasonBitmask |= MGLCameraChangeReasonProgrammatic;
|
||||
|
||||
_mbglMap->easeTo(cameraOptions, animationOptions);
|
||||
}
|
||||
|
||||
@@ -2943,6 +2992,8 @@ public:
|
||||
if (zoomLevel == self.zoomLevel) return;
|
||||
_mbglMap->cancelTransitions();
|
||||
|
||||
self.cameraChangeReasonBitmask |= MGLCameraChangeReasonProgrammatic;
|
||||
|
||||
CGFloat duration = animated ? MGLAnimationDuration : 0;
|
||||
|
||||
_mbglMap->setZoom(zoomLevel,
|
||||
@@ -3031,6 +3082,9 @@ public:
|
||||
- (void)setVisibleCoordinates:(const CLLocationCoordinate2D *)coordinates count:(NSUInteger)count edgePadding:(UIEdgeInsets)insets direction:(CLLocationDirection)direction duration:(NSTimeInterval)duration animationTimingFunction:(nullable CAMediaTimingFunction *)function completionHandler:(nullable void (^)(void))completion
|
||||
{
|
||||
self.userTrackingMode = MGLUserTrackingModeNone;
|
||||
|
||||
self.cameraChangeReasonBitmask |= MGLCameraChangeReasonProgrammatic;
|
||||
|
||||
[self _setVisibleCoordinates:coordinates count:count edgePadding:insets direction:direction duration:duration animationTimingFunction:function completionHandler:completion];
|
||||
}
|
||||
|
||||
@@ -3080,6 +3134,9 @@ public:
|
||||
|
||||
[self willChangeValueForKey:@"visibleCoordinateBounds"];
|
||||
_mbglMap->cancelTransitions();
|
||||
|
||||
self.cameraChangeReasonBitmask |= MGLCameraChangeReasonProgrammatic;
|
||||
|
||||
_mbglMap->easeTo(cameraOptions, animationOptions);
|
||||
[self didChangeValueForKey:@"visibleCoordinateBounds"];
|
||||
}
|
||||
@@ -3113,6 +3170,8 @@ public:
|
||||
|
||||
CGFloat duration = animated ? MGLAnimationDuration : 0;
|
||||
|
||||
self.cameraChangeReasonBitmask |= MGLCameraChangeReasonProgrammatic;
|
||||
|
||||
if (self.userTrackingMode == MGLUserTrackingModeNone)
|
||||
{
|
||||
_mbglMap->setBearing(direction,
|
||||
@@ -3197,6 +3256,9 @@ public:
|
||||
|
||||
[self willChangeValueForKey:@"camera"];
|
||||
_mbglMap->cancelTransitions();
|
||||
|
||||
self.cameraChangeReasonBitmask |= MGLCameraChangeReasonProgrammatic;
|
||||
|
||||
mbgl::CameraOptions cameraOptions = [self cameraOptionsObjectForAnimatingToCamera:camera edgePadding:edgePadding];
|
||||
_mbglMap->easeTo(cameraOptions, animationOptions);
|
||||
[self didChangeValueForKey:@"camera"];
|
||||
@@ -3253,6 +3315,9 @@ public:
|
||||
|
||||
[self willChangeValueForKey:@"camera"];
|
||||
_mbglMap->cancelTransitions();
|
||||
|
||||
self.cameraChangeReasonBitmask |= MGLCameraChangeReasonProgrammatic;
|
||||
|
||||
mbgl::CameraOptions cameraOptions = [self cameraOptionsObjectForAnimatingToCamera:camera edgePadding:insets];
|
||||
_mbglMap->flyTo(cameraOptions, animationOptions);
|
||||
[self didChangeValueForKey:@"camera"];
|
||||
@@ -3413,6 +3478,13 @@ public:
|
||||
return [self metersPerPointAtLatitude:latitude];
|
||||
}
|
||||
|
||||
#pragma mark - Camera Change Reason -
|
||||
|
||||
- (void)resetCameraChangeReason
|
||||
{
|
||||
self.cameraChangeReasonBitmask = MGLCameraChangeReasonNone;
|
||||
}
|
||||
|
||||
#pragma mark - Styling -
|
||||
|
||||
- (NS_ARRAY_OF(NSURL *) *)bundledStyleURLs
|
||||
@@ -5354,9 +5426,16 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! [self isSuppressingChangeDelimiters] && [self.delegate respondsToSelector:@selector(mapView:regionWillChangeAnimated:)])
|
||||
if ( ! [self isSuppressingChangeDelimiters] )
|
||||
{
|
||||
[self.delegate mapView:self regionWillChangeAnimated:animated];
|
||||
if ([self.delegate respondsToSelector:@selector(mapView:regionWillChangeWithReason:animated:)])
|
||||
{
|
||||
[self.delegate mapView:self regionWillChangeWithReason:self.cameraChangeReasonBitmask animated:animated];
|
||||
}
|
||||
else if ([self.delegate respondsToSelector:@selector(mapView:regionWillChangeAnimated:)])
|
||||
{
|
||||
[self.delegate mapView:self regionWillChangeAnimated:animated];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5370,8 +5449,12 @@ public:
|
||||
if (!self.scaleBar.hidden) {
|
||||
[(MGLScaleBar *)self.scaleBar setMetersPerPoint:[self metersPerPointAtLatitude:self.centerCoordinate.latitude]];
|
||||
}
|
||||
|
||||
if ([self.delegate respondsToSelector:@selector(mapViewRegionIsChanging:)])
|
||||
|
||||
if ([self.delegate respondsToSelector:@selector(mapView:regionIsChangingWithReason:)])
|
||||
{
|
||||
[self.delegate mapView:self regionIsChangingWithReason:self.cameraChangeReasonBitmask];
|
||||
}
|
||||
else if ([self.delegate respondsToSelector:@selector(mapViewRegionIsChanging:)])
|
||||
{
|
||||
[self.delegate mapViewRegionIsChanging:self];
|
||||
}
|
||||
@@ -5384,9 +5467,13 @@ public:
|
||||
|
||||
[self updateCompass];
|
||||
|
||||
if ( ! [self isSuppressingChangeDelimiters] && [self.delegate respondsToSelector:@selector(mapView:regionDidChangeAnimated:)])
|
||||
if ( ! [self isSuppressingChangeDelimiters])
|
||||
{
|
||||
if ([UIApplication sharedApplication].applicationState == UIApplicationStateActive)
|
||||
BOOL respondsToSelector = [self.delegate respondsToSelector:@selector(mapView:regionDidChangeAnimated:)];
|
||||
BOOL respondsToSelectorWithReason = [self.delegate respondsToSelector:@selector(mapView:regionDidChangeWithReason:animated:)];
|
||||
|
||||
if ((respondsToSelector || respondsToSelectorWithReason) &&
|
||||
([UIApplication sharedApplication].applicationState == UIApplicationStateActive))
|
||||
{
|
||||
_featureAccessibilityElements = nil;
|
||||
_visiblePlaceFeatures = nil;
|
||||
@@ -5398,7 +5485,17 @@ public:
|
||||
UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, nil);
|
||||
}
|
||||
}
|
||||
[self.delegate mapView:self regionDidChangeAnimated:animated];
|
||||
|
||||
if (respondsToSelectorWithReason)
|
||||
{
|
||||
[self.delegate mapView:self regionDidChangeWithReason:self.cameraChangeReasonBitmask animated:animated];
|
||||
}
|
||||
else if (respondsToSelector)
|
||||
{
|
||||
[self.delegate mapView:self regionDidChangeAnimated:animated];
|
||||
}
|
||||
|
||||
[self resetCameraChangeReason];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import "MGLTypes.h"
|
||||
#import "MGLCameraChangeReason.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@@ -21,17 +22,80 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
#pragma mark Responding to Map Position Changes
|
||||
|
||||
/**
|
||||
Asks the delegate whether the map view should be allowed to change from the
|
||||
existing camera to the new camera in response to a user gesture.
|
||||
|
||||
This method is called as soon as the user gesture is recognized. It is not
|
||||
called in response to a programmatic camera change, such as by setting the
|
||||
`centerCoordinate` property or calling `-flyToCamera:completionHandler:`.
|
||||
|
||||
This method is called many times during gesturing, so you should avoid performing
|
||||
complex or performance-intensive tasks in your implementation.
|
||||
|
||||
@param mapView The map view that the user is manipulating.
|
||||
@param oldCamera The camera representing the viewpoint at the moment the
|
||||
gesture is recognized. If this method returns `NO`, the map view’s camera
|
||||
continues to be this camera.
|
||||
@param newCamera The expected camera after the gesture completes. If this
|
||||
method returns `YES`, this camera becomes the map view’s camera.
|
||||
@return A Boolean value indicating whether the map view should stay at
|
||||
`oldCamera` or change to `newCamera`.
|
||||
*/
|
||||
- (BOOL)mapView:(MGLMapView *)mapView shouldChangeFromCamera:(MGLMapCamera *)oldCamera toCamera:(MGLMapCamera *)newCamera;
|
||||
|
||||
/**
|
||||
:nodoc:
|
||||
Asks the delegate whether the map view should be allowed to change from the
|
||||
existing camera to the new camera in response to a user gesture.
|
||||
|
||||
This method is called as soon as the user gesture is recognized. It is not
|
||||
called in response to a programmatic camera change, such as by setting the
|
||||
`centerCoordinate` property or calling `-flyToCamera:completionHandler:`.
|
||||
|
||||
This method is called many times during gesturing, so you should avoid performing
|
||||
complex or performance-intensive tasks in your implementation.
|
||||
|
||||
@param mapView The map view that the user is manipulating.
|
||||
@param oldCamera The camera representing the viewpoint at the moment the
|
||||
gesture is recognized. If this method returns `NO`, the map view’s camera
|
||||
continues to be this camera.
|
||||
@param newCamera The expected camera after the gesture completes. If this
|
||||
method returns `YES`, this camera becomes the map view’s camera.
|
||||
@param reason The reason for the camera change.
|
||||
@return A Boolean value indicating whether the map view should stay at
|
||||
`oldCamera` or change to `newCamera`.
|
||||
|
||||
@note If this method is implemented `-mapView:shouldChangeFromCamera:toCamera:` will not be called.
|
||||
*/
|
||||
- (BOOL)mapView:(MGLMapView *)mapView shouldChangeFromCamera:(MGLMapCamera *)oldCamera toCamera:(MGLMapCamera *)newCamera reason:(MGLCameraChangeReason)reason;
|
||||
|
||||
/**
|
||||
Tells the delegate that the viewpoint depicted by the map view is about to change.
|
||||
|
||||
This method is called whenever the currently displayed map camera will start
|
||||
changing for any reason.
|
||||
|
||||
|
||||
@param mapView The map view whose viewpoint will change.
|
||||
@param animated Whether the change will cause an animated effect on the map.
|
||||
*/
|
||||
- (void)mapView:(MGLMapView *)mapView regionWillChangeAnimated:(BOOL)animated;
|
||||
|
||||
/**
|
||||
:nodoc:
|
||||
Tells the delegate that the viewpoint depicted by the map view is about to change.
|
||||
|
||||
This method is called whenever the currently displayed map camera will start
|
||||
changing for any reason.
|
||||
|
||||
@param mapView The map view whose viewpoint will change.
|
||||
@param animated Whether the change will cause an animated effect on the map.
|
||||
@param reason The reason for the camera change.
|
||||
|
||||
@note If this method is implemented `-mapView:regionWillChangeAnimated:` will not be called.
|
||||
*/
|
||||
- (void)mapView:(MGLMapView *)mapView regionWillChangeWithReason:(MGLCameraChangeReason)reason animated:(BOOL)animated;
|
||||
|
||||
/**
|
||||
Tells the delegate that the viewpoint depicted by the map view is changing.
|
||||
|
||||
@@ -48,6 +112,26 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
*/
|
||||
- (void)mapViewRegionIsChanging:(MGLMapView *)mapView;
|
||||
|
||||
/**
|
||||
:nodoc:
|
||||
Tells the delegate that the viewpoint depicted by the map view is changing.
|
||||
|
||||
This method is called as the currently displayed map camera changes as part of
|
||||
an animation, whether due to a user gesture or due to a call to a method such
|
||||
as `-[MGLMapView setCamera:animated:]`. This method can be called before
|
||||
`-mapViewDidFinishLoadingMap:` is called.
|
||||
|
||||
During the animation, this method may be called many times to report updates to
|
||||
the viewpoint. Therefore, your implementation of this method should be as lightweight
|
||||
as possible to avoid affecting performance.
|
||||
|
||||
@param mapView The map view whose viewpoint is changing.
|
||||
@param reason The reason for the camera change.
|
||||
|
||||
@note If this method is implemented `-mapViewRegionIsChanging:` will not be called.
|
||||
*/
|
||||
- (void)mapView:(MGLMapView *)mapView regionIsChangingWithReason:(MGLCameraChangeReason)reason;
|
||||
|
||||
/**
|
||||
Tells the delegate that the viewpoint depicted by the map view has finished
|
||||
changing.
|
||||
@@ -62,26 +146,21 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
- (void)mapView:(MGLMapView *)mapView regionDidChangeAnimated:(BOOL)animated;
|
||||
|
||||
/**
|
||||
Asks the delegate whether the map view should be allowed to change from the
|
||||
existing camera to the new camera in response to a user gesture.
|
||||
|
||||
This method is called as soon as the user gesture is recognized. It is not
|
||||
called in response to a programmatic camera change, such as by setting the
|
||||
`centerCoordinate` property or calling `-flyToCamera:completionHandler:`.
|
||||
|
||||
This method is called many times during gesturing, so you should avoid performing
|
||||
complex or performance-intensive tasks in your implementation.
|
||||
|
||||
@param mapView The map view that the user is manipulating.
|
||||
@param oldCamera The camera representing the viewpoint at the moment the
|
||||
gesture is recognized. If this method returns `NO`, the map view’s camera
|
||||
continues to be this camera.
|
||||
@param newCamera The expected camera after the gesture completes. If this
|
||||
method returns `YES`, this camera becomes the map view’s camera.
|
||||
@return A Boolean value indicating whether the map view should stay at
|
||||
`oldCamera` or change to `newCamera`.
|
||||
:nodoc:
|
||||
Tells the delegate that the viewpoint depicted by the map view has finished
|
||||
changing.
|
||||
|
||||
This method is called whenever the currently displayed map camera has finished
|
||||
changing, after any calls to `-mapViewRegionIsChanging:` due to animation. Therefore,
|
||||
this method can be called before `-mapViewDidFinishLoadingMap:` is called.
|
||||
|
||||
@param mapView The map view whose viewpoint has changed.
|
||||
@param animated Whether the change caused an animated effect on the map.
|
||||
@param reason The reason for the camera change.
|
||||
|
||||
@note If this method is implemented `-mapView:regionDidChangeAnimated:` will not be called.
|
||||
*/
|
||||
- (BOOL)mapView:(MGLMapView *)mapView shouldChangeFromCamera:(MGLMapCamera *)oldCamera toCamera:(MGLMapCamera *)newCamera;
|
||||
- (void)mapView:(MGLMapView *)mapView regionDidChangeWithReason:(MGLCameraChangeReason)reason animated:(BOOL)animated;
|
||||
|
||||
#pragma mark Loading the Map
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#import "NSException+MGLAdditions.h"
|
||||
#import "MGLAPIClient.h"
|
||||
#import "MGLLocationManager.h"
|
||||
#import "MGLTelemetryConfig.h"
|
||||
|
||||
#include <mbgl/storage/reachability.h>
|
||||
#include <sys/sysctl.h>
|
||||
@@ -172,6 +173,8 @@ const NSTimeInterval MGLFlushInterval = 180;
|
||||
- (instancetype) init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
[MGLTelemetryConfig.sharedConfig configurationFromKey:[[NSUserDefaults standardUserDefaults] objectForKey:MGLMapboxMetricsProfile]];
|
||||
|
||||
_currentAccountTypeValue = @0;
|
||||
_currentMetricsEnabledValue = YES;
|
||||
|
||||
|
||||
18
platform/ios/src/MGLTelemetryConfig.h
Normal file
18
platform/ios/src/MGLTelemetryConfig.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <CoreLocation/CoreLocation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface MGLTelemetryConfig : NSObject
|
||||
|
||||
@property (nonatomic) CLLocationDistance MGLLocationManagerHibernationRadius;
|
||||
|
||||
extern NSString *const MGLMapboxMetricsProfile;
|
||||
|
||||
+ (nullable instancetype)sharedConfig;
|
||||
|
||||
- (void)configurationFromKey:(NSString *)key;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
35
platform/ios/src/MGLTelemetryConfig.m
Normal file
35
platform/ios/src/MGLTelemetryConfig.m
Normal file
@@ -0,0 +1,35 @@
|
||||
#import "MGLTelemetryConfig.h"
|
||||
|
||||
static const CLLocationDistance MGLConfigHibernationRadiusDefault = 300.0;
|
||||
static const CLLocationDistance MGLConfigHibernationRadiusWide = 600.0;
|
||||
|
||||
NSString *const MGLMapboxMetricsProfile = @"MGLMapboxMetricsProfile";
|
||||
|
||||
static NSString *const MGLConfigHibernationRadiusWideKey = @"WideGeoFence";
|
||||
|
||||
@implementation MGLTelemetryConfig
|
||||
|
||||
- (instancetype) init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_MGLLocationManagerHibernationRadius = MGLConfigHibernationRadiusDefault;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (nullable instancetype)sharedConfig {
|
||||
static dispatch_once_t onceToken;
|
||||
static MGLTelemetryConfig *_sharedConfig;
|
||||
dispatch_once(&onceToken, ^{
|
||||
_sharedConfig = [[self alloc] init];
|
||||
});
|
||||
return _sharedConfig;
|
||||
}
|
||||
|
||||
- (void)configurationFromKey:(NSString *)key {
|
||||
if ([key isEqualToString:MGLConfigHibernationRadiusWideKey]) {
|
||||
_MGLLocationManagerHibernationRadius = MGLConfigHibernationRadiusWide;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -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"
|
||||
|
||||
@@ -13,6 +13,10 @@ extension MGLMapViewDelegateIntegrationTests: MGLMapViewDelegate {
|
||||
|
||||
func mapViewRegionIsChanging(_ mapView: MGLMapView) {}
|
||||
|
||||
func mapViewRegionIsChanging(_ mapView: MGLMapView, reason: MGLCameraChangeReason) {}
|
||||
|
||||
func mapView(_ mapView: MGLMapView, regionIsChangingWith reason: MGLCameraChangeReason) {}
|
||||
|
||||
func mapView(_ mapView: MGLMapView, didChange mode: MGLUserTrackingMode, animated: Bool) {}
|
||||
|
||||
func mapViewDidFinishLoadingMap(_ mapView: MGLMapView) {}
|
||||
@@ -33,10 +37,16 @@ extension MGLMapViewDelegateIntegrationTests: MGLMapViewDelegate {
|
||||
|
||||
func mapView(_ mapView: MGLMapView, didDeselect annotation: MGLAnnotation) {}
|
||||
|
||||
func mapView(_ mapView: MGLMapView, didSingleTapAt coordinate: CLLocationCoordinate2D) {}
|
||||
|
||||
func mapView(_ mapView: MGLMapView, regionDidChangeAnimated animated: Bool) {}
|
||||
|
||||
func mapView(_ mapView: MGLMapView, regionDidChangeWith reason: MGLCameraChangeReason, animated: Bool) {}
|
||||
|
||||
func mapView(_ mapView: MGLMapView, regionWillChangeAnimated animated: Bool) {}
|
||||
|
||||
func mapView(_ mapView: MGLMapView, regionWillChangeWith reason: MGLCameraChangeReason, animated: Bool) {}
|
||||
|
||||
func mapViewDidFailLoadingMap(_ mapView: MGLMapView, withError error: Error) {}
|
||||
|
||||
func mapView(_ mapView: MGLMapView, didUpdate userLocation: MGLUserLocation?) {}
|
||||
@@ -79,4 +89,5 @@ extension MGLMapViewDelegateIntegrationTests: MGLMapViewDelegate {
|
||||
|
||||
func mapView(_ mapView: MGLMapView, shouldChangeFrom oldCamera: MGLMapCamera, to newCamera: MGLMapCamera) -> Bool { return false }
|
||||
|
||||
func mapView(_ mapView: MGLMapView, shouldChangeFrom oldCamera: MGLMapCamera, to newCamera: MGLMapCamera, reason: MGLCameraChangeReason) -> Bool { return false }
|
||||
}
|
||||
|
||||
@@ -538,10 +538,13 @@
|
||||
userInfo:@{ @"animated" : @(animated) }];
|
||||
}
|
||||
|
||||
- (void)mapView:(MGLMapView *)mapView regionDidChangeAnimated:(BOOL)animated {
|
||||
- (void)mapView:(MGLMapView *)mapView regionDidChangeWithReason:(MGLCameraChangeReason)reason animated:(BOOL)animated {
|
||||
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:@"regionDidChangeAnimated"
|
||||
object:mapView
|
||||
userInfo:@{ @"animated" : @(animated) }];
|
||||
userInfo:@{ @"animated" : @(animated),
|
||||
@"reason" : @(reason)
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)testDelegatesStartStopLocatingUser {
|
||||
|
||||
@@ -4,20 +4,24 @@
|
||||
|
||||
### 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))
|
||||
* The `MGLSymbolStyleLayer.textFontNames` property can now depend on a feature’s attributes. ([#10850](https://github.com/mapbox/mapbox-gl-native/pull/10850))
|
||||
* Properties such as `MGLSymbolStyleLayer.iconAllowsOverlap` and `MGLSymbolStyleLayer.iconIgnoresPlacement` now account for symbols in other sources. ([#10436](https://github.com/mapbox/mapbox-gl-native/pull/10436))
|
||||
|
||||
### Map rendering
|
||||
|
||||
* Improved the reliability of collision detection between symbols near the edges of tiles, as well as between symbols when the map is tilted. It is no longer necessary to enable `MGLSymbolStyleLayer.symbolAvoidsEdges` to prevent symbols in adjacent tiles from overlapping with each other. ([#10436](https://github.com/mapbox/mapbox-gl-native/pull/10436))
|
||||
* Symbols can fade in and out as the map pans, rotates, or tilts. ([#10436](https://github.com/mapbox/mapbox-gl-native/pull/10436))
|
||||
* Properties such as `MGLSymbolStyleLayer.iconAllowsOverlap` and `MGLSymbolStyleLayer.iconIgnoresPlacement` now account for symbols in other sources. ([#10436](https://github.com/mapbox/mapbox-gl-native/pull/10436))
|
||||
* Added the `MGLTileSourceOptionTileCoordinateBounds` option to create an `MGLTileSource` that only supplies tiles within a specific geographic bounding box. ([#11141](https://github.com/mapbox/mapbox-gl-native/pull/11141))
|
||||
* Fixed an issue preventing a dynamically-added `MGLRasterStyleLayer` from drawing until the map pans. ([#10270](https://github.com/mapbox/mapbox-gl-native/pull/10270))
|
||||
* Fixed an issue preventing `MGLImageSource`s from drawing on the map when the map is zoomed in and tilted. ([#10677](https://github.com/mapbox/mapbox-gl-native/pull/10677))
|
||||
* Improved the sharpness of raster tiles on Retina displays. ([#10984](https://github.com/mapbox/mapbox-gl-native/pull/10984))
|
||||
* Fixed a crash parsing a malformed style. ([#11001](https://github.com/mapbox/mapbox-gl-native/pull/11001))
|
||||
* Added the `MGLTileSourceOptionTileCoordinateBounds` option to create an `MGLTileSource` that only supplies tiles within a specific geographic bounding box. ([#11141](https://github.com/mapbox/mapbox-gl-native/pull/11141))
|
||||
|
||||
### Map snapshots
|
||||
|
||||
@@ -28,6 +32,7 @@
|
||||
|
||||
* Added Danish and Hebrew localizations. ([#10967](https://github.com/mapbox/mapbox-gl-native/pull/10967), [#11136](https://github.com/mapbox/mapbox-gl-native/pull/11134))
|
||||
* Feature querying results now account for the `MGLSymbolStyleLayer.circleStrokeWidth` property. ([#10897](https://github.com/mapbox/mapbox-gl-native/pull/10897))
|
||||
* Added a Hebrew localization. ([#10967](https://github.com/mapbox/mapbox-gl-native/pull/10967))
|
||||
|
||||
## v0.6.1 - January 16, 2018
|
||||
|
||||
|
||||
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.
@@ -726,8 +726,14 @@ NS_ARRAY_OF(id <MGLAnnotation>) *MBXFlattenedShapes(NS_ARRAY_OF(id <MGLAnnotatio
|
||||
[self.undoManager setActionName:@"Add Graticule"];
|
||||
}
|
||||
|
||||
NSDictionary *sourceOptions = @{
|
||||
MGLShapeSourceOptionMaximumZoomLevel:@14,
|
||||
MGLShapeSourceOptionWrapsCoordinates: @YES,
|
||||
MGLShapeSourceOptionClipsCoordinates: @YES,
|
||||
};
|
||||
MGLComputedShapeSource *source = [[MGLComputedShapeSource alloc] initWithIdentifier:@"graticule"
|
||||
options:@{MGLShapeSourceOptionMaximumZoomLevel:@14}];
|
||||
options:sourceOptions];
|
||||
|
||||
source.dataSource = self;
|
||||
[self.mapView.style addSource:source];
|
||||
MGLLineStyleLayer *lineLayer = [[MGLLineStyleLayer alloc] initWithIdentifier:@"graticule.lines"
|
||||
|
||||
@@ -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 |
@@ -96,6 +96,7 @@ the following terms for concepts defined in the style specification:
|
||||
|
||||
In the style specification | In the SDK
|
||||
---------------------------|---------
|
||||
bounds | coordinate bounds
|
||||
filter | predicate
|
||||
function type | interpolation mode
|
||||
id | identifier
|
||||
@@ -136,6 +137,7 @@ In style JSON | In TileJSON | In the SDK
|
||||
`tiles` | `tiles` | `tileURLTemplates` parameter in `-[MGLTileSource initWithIdentifier:tileURLTemplates:options:]`
|
||||
`minzoom` | `minzoom` | `MGLTileSourceOptionMinimumZoomLevel`
|
||||
`maxzoom` | `maxzoom` | `MGLTileSourceOptionMaximumZoomLevel`
|
||||
`bounds` | `bounds` | `MGLTileSourceOptionCoordinateBounds`
|
||||
`tileSize` | — | `MGLTileSourceOptionTileSize`
|
||||
`attribution` | `attribution` | `MGLTileSourceOptionAttributionHTMLString` (but consider specifying `MGLTileSourceOptionAttributionInfos` instead for improved security)
|
||||
`scheme` | `scheme` | `MGLTileSourceOptionTileCoordinateSystem`
|
||||
@@ -177,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>"; };
|
||||
@@ -676,6 +686,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 */,
|
||||
@@ -829,6 +841,7 @@
|
||||
DA839EA61CC2E3400062CAFB /* Info.plist */,
|
||||
96E027331E57C9A7004B8E66 /* Localizable.strings */,
|
||||
DA839E981CC2E3400062CAFB /* Supporting Files */,
|
||||
89462398200D199100DA8EF2 /* heatmap.json */,
|
||||
);
|
||||
name = "Demo App";
|
||||
path = app;
|
||||
@@ -879,6 +892,8 @@
|
||||
DA8F257C1D51C5F40010E6B5 /* Layers */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
170A82C2201FAFF800943087 /* MGLHeatmapColorTests.mm */,
|
||||
170A82BE201BDD1B00943087 /* MGLHeatmapStyleLayerTests.mm */,
|
||||
40E1601A1DF216E6005EA6D9 /* MGLStyleLayerTests.h */,
|
||||
40E1601B1DF216E6005EA6D9 /* MGLStyleLayerTests.m */,
|
||||
DA2207BA1DC076930002F84D /* test-Bridging-Header.h */,
|
||||
@@ -1236,6 +1251,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 */,
|
||||
@@ -1427,6 +1443,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 */,
|
||||
@@ -1508,6 +1525,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 */,
|
||||
@@ -1570,11 +1588,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>
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
"render-tests/background-color/transition": "https://github.com/mapbox/mapbox-gl-native/issues/10619",
|
||||
"render-tests/debug/collision": "https://github.com/mapbox/mapbox-gl-native/issues/3841",
|
||||
"render-tests/debug/collision-lines": "https://github.com/mapbox/mapbox-gl-native/issues/10412",
|
||||
"render-tests/debug/collision-lines-overscaled": "https://github.com/mapbox/mapbox-gl-native/issues/10412",
|
||||
"render-tests/debug/collision-lines-pitched": "https://github.com/mapbox/mapbox-gl-native/issues/10412",
|
||||
"render-tests/debug/collision-pitched-wrapped": "https://github.com/mapbox/mapbox-gl-native/issues/10412",
|
||||
"render-tests/debug/tile": "https://github.com/mapbox/mapbox-gl-native/issues/3841",
|
||||
@@ -22,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",
|
||||
@@ -84,6 +67,10 @@
|
||||
"render-tests/combinations/line-translucent--heatmap-translucent": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
|
||||
"render-tests/combinations/raster-translucent--heatmap-translucent": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
|
||||
"render-tests/combinations/symbol-translucent--heatmap-translucent": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
|
||||
"render-tests/combinations/background-opaque--hillshade-translucent": "https://github.com/mapbox/mapbox-gl-native/pull/10642",
|
||||
"render-tests/combinations/background-translucent--hillshade-translucent": "https://github.com/mapbox/mapbox-gl-native/pull/10642",
|
||||
"render-tests/combinations/circle-translucent--hillshade-translucent": "https://github.com/mapbox/mapbox-gl-native/pull/10642",
|
||||
"render-tests/combinations/fill-extrusion-translucent--hillshade-translucent": "https://github.com/mapbox/mapbox-gl-native/pull/10642",
|
||||
"render-tests/combinations/background-opaque--fill-extrusion-translucent": "needs investigation",
|
||||
"render-tests/combinations/background-translucent--fill-extrusion-translucent": "needs investigation",
|
||||
"render-tests/combinations/circle-translucent--fill-extrusion-translucent": "needs investigation",
|
||||
|
||||
@@ -442,10 +442,9 @@ void MapWindow::initializeGL()
|
||||
void MapWindow::paintGL()
|
||||
{
|
||||
m_frameDraws++;
|
||||
m_map->resize(size(), size() * pixelRatio());
|
||||
m_map->resize(size());
|
||||
#if QT_VERSION >= 0x050400
|
||||
// When we're using QOpenGLWidget, we need to tell Mapbox GL about the framebuffer we're using.
|
||||
m_map->setFramebufferObject(defaultFramebufferObject());
|
||||
m_map->setFramebufferObject(defaultFramebufferObject(), size() * pixelRatio());
|
||||
#endif
|
||||
m_map->render();
|
||||
}
|
||||
|
||||
@@ -26,6 +26,11 @@ public:
|
||||
SharedGLContext
|
||||
};
|
||||
|
||||
enum MapMode {
|
||||
Continuous = 0,
|
||||
Static
|
||||
};
|
||||
|
||||
enum ConstrainMode {
|
||||
NoConstrain = 0,
|
||||
ConstrainHeightOnly,
|
||||
@@ -40,6 +45,9 @@ public:
|
||||
GLContextMode contextMode() const;
|
||||
void setContextMode(GLContextMode);
|
||||
|
||||
MapMode mapMode() const;
|
||||
void setMapMode(MapMode);
|
||||
|
||||
ConstrainMode constrainMode() const;
|
||||
void setConstrainMode(ConstrainMode);
|
||||
|
||||
@@ -66,6 +74,7 @@ public:
|
||||
|
||||
private:
|
||||
GLContextMode m_contextMode;
|
||||
MapMode m_mapMode;
|
||||
ConstrainMode m_constrainMode;
|
||||
ViewportMode m_viewportMode;
|
||||
|
||||
@@ -191,8 +200,7 @@ public:
|
||||
void scaleBy(double scale, const QPointF ¢er = QPointF());
|
||||
void rotateBy(const QPointF &first, const QPointF &second);
|
||||
|
||||
void resize(const QSize &size, const QSize &framebufferSize);
|
||||
void setFramebufferObject(quint32 fbo);
|
||||
void resize(const QSize &size);
|
||||
|
||||
double metersPerPixelAtLatitude(double latitude, double zoom) const;
|
||||
QMapbox::ProjectedMeters projectedMetersForCoordinate(const QMapbox::Coordinate &) const;
|
||||
@@ -226,15 +234,27 @@ public:
|
||||
|
||||
void setFilter(const QString &layer, const QVariant &filter);
|
||||
|
||||
// When rendering on a different thread,
|
||||
// should be called on the render thread.
|
||||
void createRenderer();
|
||||
void destroyRenderer();
|
||||
void setFramebufferObject(quint32 fbo, const QSize &size);
|
||||
|
||||
public slots:
|
||||
void render();
|
||||
void connectionEstablished();
|
||||
|
||||
// Commit changes, load all the resources
|
||||
// and renders the map when completed.
|
||||
void startStaticRender();
|
||||
|
||||
signals:
|
||||
void needsRendering();
|
||||
void mapChanged(QMapboxGL::MapChange);
|
||||
void copyrightsChanged(const QString ©rightsHtml);
|
||||
|
||||
void staticRenderFinished(const QString &error);
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(QMapboxGL)
|
||||
|
||||
|
||||
@@ -61,8 +61,12 @@ add_library(qmapboxgl SHARED
|
||||
platform/qt/src/qmapbox.cpp
|
||||
platform/qt/src/qmapboxgl.cpp
|
||||
platform/qt/src/qmapboxgl_p.hpp
|
||||
platform/qt/src/qmapboxgl_renderer_frontend_p.hpp
|
||||
platform/qt/src/qmapboxgl_renderer_frontend_p.cpp
|
||||
platform/qt/src/qmapboxgl_map_observer.cpp
|
||||
platform/qt/src/qmapboxgl_map_observer.hpp
|
||||
platform/qt/src/qmapboxgl_map_renderer.cpp
|
||||
platform/qt/src/qmapboxgl_map_renderer.hpp
|
||||
platform/qt/src/qmapboxgl_renderer_backend.hpp
|
||||
platform/qt/src/qmapboxgl_renderer_backend.cpp
|
||||
platform/default/mbgl/util/default_styles.hpp
|
||||
)
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#include "qmapboxgl.hpp"
|
||||
#include "qmapboxgl_p.hpp"
|
||||
#include "qmapboxgl_renderer_frontend_p.hpp"
|
||||
|
||||
#include "qmapboxgl_map_observer.hpp"
|
||||
#include "qmapboxgl_renderer_observer.hpp"
|
||||
|
||||
#include "qt_conversion.hpp"
|
||||
#include "qt_geojson.hpp"
|
||||
@@ -43,11 +45,8 @@
|
||||
|
||||
#if QT_VERSION >= 0x050000
|
||||
#include <QGuiApplication>
|
||||
#include <QWindow>
|
||||
#include <QOpenGLContext>
|
||||
#else
|
||||
#include <QCoreApplication>
|
||||
#include <QGLContext>
|
||||
#endif
|
||||
|
||||
#include <QDebug>
|
||||
@@ -65,6 +64,10 @@ using namespace QMapbox;
|
||||
static_assert(mbgl::underlying_type(QMapboxGLSettings::UniqueGLContext) == mbgl::underlying_type(mbgl::GLContextMode::Unique), "error");
|
||||
static_assert(mbgl::underlying_type(QMapboxGLSettings::SharedGLContext) == mbgl::underlying_type(mbgl::GLContextMode::Shared), "error");
|
||||
|
||||
// mbgl::MapMode
|
||||
static_assert(mbgl::underlying_type(QMapboxGLSettings::Continuous) == mbgl::underlying_type(mbgl::MapMode::Continuous), "error");
|
||||
static_assert(mbgl::underlying_type(QMapboxGLSettings::Static) == mbgl::underlying_type(mbgl::MapMode::Static), "error");
|
||||
|
||||
// mbgl::ConstrainMode
|
||||
static_assert(mbgl::underlying_type(QMapboxGLSettings::NoConstrain) == mbgl::underlying_type(mbgl::ConstrainMode::None), "error");
|
||||
static_assert(mbgl::underlying_type(QMapboxGLSettings::ConstrainHeightOnly) == mbgl::underlying_type(mbgl::ConstrainMode::HeightOnly), "error");
|
||||
@@ -164,6 +167,27 @@ std::unique_ptr<mbgl::style::Image> toStyleImage(const QString &id, const QImage
|
||||
\sa contextMode()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\enum QMapboxGLSettings::MapMode
|
||||
|
||||
This enum sets the map rendering mode
|
||||
|
||||
\value Continuous The map will render as data arrives from the network and
|
||||
react immediately to state changes.
|
||||
|
||||
This is the default mode and the preferred when the map is intended to be
|
||||
interactive.
|
||||
|
||||
\value Static The map will no longer react to state changes and will only
|
||||
be rendered when QMapboxGL::startStaticRender is called. After all the
|
||||
resources are loaded, the QMapboxGL::staticRenderFinished signal is emitted.
|
||||
|
||||
This mode is useful for taking a snapshot of the finished rendering result
|
||||
of the map into a QImage.
|
||||
|
||||
\sa mapMode()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\enum QMapboxGLSettings::ConstrainMode
|
||||
|
||||
@@ -200,6 +224,7 @@ std::unique_ptr<mbgl::style::Image> toStyleImage(const QString &id, const QImage
|
||||
*/
|
||||
QMapboxGLSettings::QMapboxGLSettings()
|
||||
: m_contextMode(QMapboxGLSettings::SharedGLContext)
|
||||
, m_mapMode(QMapboxGLSettings::Continuous)
|
||||
, m_constrainMode(QMapboxGLSettings::ConstrainHeightOnly)
|
||||
, m_viewportMode(QMapboxGLSettings::DefaultViewport)
|
||||
, m_cacheMaximumSize(mbgl::util::DEFAULT_MAX_CACHE_SIZE)
|
||||
@@ -229,6 +254,31 @@ void QMapboxGLSettings::setContextMode(GLContextMode mode)
|
||||
m_contextMode = mode;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the map mode. Static mode will emit a signal for
|
||||
rendering a map only when the map is fully loaded.
|
||||
Animations like style transitions and labels fading won't
|
||||
be seen.
|
||||
|
||||
The Continuous mode will emit the signal for every new
|
||||
change on the map and it is usually what you expect for
|
||||
a interactive map.
|
||||
|
||||
By default, it is set to QMapboxGLSettings::Continuous.
|
||||
*/
|
||||
QMapboxGLSettings::MapMode QMapboxGLSettings::mapMode() const
|
||||
{
|
||||
return m_mapMode;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the map \a mode.
|
||||
*/
|
||||
void QMapboxGLSettings::setMapMode(MapMode mode)
|
||||
{
|
||||
m_mapMode = mode;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the constrain mode. This is used to limit the map to wrap
|
||||
around the globe horizontally.
|
||||
@@ -1048,32 +1098,17 @@ void QMapboxGL::rotateBy(const QPointF &first, const QPointF &second)
|
||||
}
|
||||
|
||||
/*!
|
||||
Resize the map to \a size and scale to fit at \a framebufferSize. For
|
||||
high DPI screens, the size will be smaller than the \a framebufferSize.
|
||||
|
||||
This fallowing example will double the pixel density of the map for
|
||||
a given \c size:
|
||||
|
||||
\code
|
||||
map->resize(size / 2, size);
|
||||
\endcode
|
||||
Resize the map to \a size_ and scale to fit at the framebuffer. For
|
||||
high DPI screens, the size will be smaller than the framebuffer.
|
||||
*/
|
||||
void QMapboxGL::resize(const QSize& size, const QSize& framebufferSize)
|
||||
void QMapboxGL::resize(const QSize& size_)
|
||||
{
|
||||
if (d_ptr->size == size && d_ptr->fbSize == framebufferSize) return;
|
||||
auto size = sanitizedSize(size_);
|
||||
|
||||
d_ptr->size = size;
|
||||
d_ptr->fbSize = framebufferSize;
|
||||
if (d_ptr->mapObj->getSize() == size)
|
||||
return;
|
||||
|
||||
d_ptr->mapObj->setSize(sanitizedSize(size));
|
||||
}
|
||||
|
||||
/*!
|
||||
If Mapbox GL needs to rebind the default \a fbo, it will use the
|
||||
ID supplied here.
|
||||
*/
|
||||
void QMapboxGL::setFramebufferObject(quint32 fbo) {
|
||||
d_ptr->fbObject = fbo;
|
||||
d_ptr->mapObj->setSize(size);
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -1467,6 +1502,51 @@ void QMapboxGL::setFilter(const QString& layer, const QVariant& filter)
|
||||
qWarning() << "Layer doesn't support filters";
|
||||
}
|
||||
|
||||
/*!
|
||||
Creates the infrastructure needed for rendering the map. It
|
||||
should be called before any call to render().
|
||||
|
||||
Must be called on the render thread.
|
||||
*/
|
||||
void QMapboxGL::createRenderer()
|
||||
{
|
||||
d_ptr->createRenderer();
|
||||
}
|
||||
|
||||
/*!
|
||||
Destroys the infrastructure needed for rendering the map,
|
||||
releasing resources.
|
||||
|
||||
Must be called on the render thread.
|
||||
*/
|
||||
void QMapboxGL::destroyRenderer()
|
||||
{
|
||||
d_ptr->destroyRenderer();
|
||||
}
|
||||
|
||||
/*!
|
||||
Start a static rendering of the current state of the map. This
|
||||
should only be called when the map is initialized in static mode.
|
||||
|
||||
\sa QMapboxGLSettings::MapMode
|
||||
*/
|
||||
void QMapboxGL::startStaticRender()
|
||||
{
|
||||
d_ptr->mapObj->renderStill([this](std::exception_ptr err) {
|
||||
QString what;
|
||||
|
||||
try {
|
||||
if (err) {
|
||||
std::rethrow_exception(err);
|
||||
}
|
||||
} catch(const std::exception& e) {
|
||||
what = e.what();
|
||||
}
|
||||
|
||||
emit staticRenderFinished(what);
|
||||
});
|
||||
}
|
||||
|
||||
/*!
|
||||
Renders the map using OpenGL draw calls. It will make sure to bind the
|
||||
framebuffer object before drawing; otherwise a valid OpenGL context is
|
||||
@@ -1475,28 +1555,33 @@ void QMapboxGL::setFilter(const QString& layer, const QVariant& filter)
|
||||
|
||||
This function should be called only after the signal needsRendering() is
|
||||
emitted at least once.
|
||||
|
||||
Must be called on the render thread.
|
||||
*/
|
||||
void QMapboxGL::render()
|
||||
{
|
||||
#if defined(__APPLE__) && QT_VERSION < 0x050000
|
||||
// FIXME Qt 4.x provides an incomplete FBO at start.
|
||||
// See https://bugreports.qt.io/browse/QTBUG-36802 for details.
|
||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
d_ptr->dirty = false;
|
||||
d_ptr->render();
|
||||
}
|
||||
|
||||
/*!
|
||||
If Mapbox GL needs to rebind the default \a fbo, it will use the
|
||||
ID supplied here. \a size is the size of the framebuffer, which
|
||||
on high DPI screens is usually bigger than the map size.
|
||||
|
||||
Must be called on the render thread.
|
||||
*/
|
||||
void QMapboxGL::setFramebufferObject(quint32 fbo, const QSize& size)
|
||||
{
|
||||
d_ptr->setFramebufferObject(fbo, size);
|
||||
}
|
||||
|
||||
/*!
|
||||
Informs the map that the network connection has been established, causing
|
||||
all network requests that previously timed out to be retried immediately.
|
||||
*/
|
||||
void QMapboxGL::connectionEstablished()
|
||||
{
|
||||
d_ptr->connectionEstablished();
|
||||
mbgl::NetworkStatus::Reachable();
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -1509,6 +1594,16 @@ void QMapboxGL::connectionEstablished()
|
||||
\sa render()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn void QMapboxGL::staticRenderFinished(const QString &error)
|
||||
|
||||
This signal is emitted when a static map is fully drawn. Usually the next
|
||||
step is to extract the map from a framebuffer into a container like a
|
||||
QImage. \a error is set to a message when an error occurs.
|
||||
|
||||
\sa startStaticRender()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn void QMapboxGL::mapChanged(QMapboxGL::MapChange change)
|
||||
|
||||
@@ -1526,186 +1621,140 @@ void QMapboxGL::connectionEstablished()
|
||||
\a copyrightsHtml is a string with a HTML snippet.
|
||||
*/
|
||||
|
||||
class QMapboxGLRendererFrontend;
|
||||
|
||||
QMapboxGLPrivate::QMapboxGLPrivate(QMapboxGL *q, const QMapboxGLSettings &settings, const QSize &size_, qreal pixelRatio)
|
||||
QMapboxGLPrivate::QMapboxGLPrivate(QMapboxGL *q, const QMapboxGLSettings &settings, const QSize &size, qreal pixelRatio_)
|
||||
: QObject(q)
|
||||
, size(size_)
|
||||
, q_ptr(q)
|
||||
, fileSourceObj(sharedDefaultFileSource(
|
||||
, m_fileSourceObj(sharedDefaultFileSource(
|
||||
settings.cacheDatabasePath().toStdString(),
|
||||
settings.assetPath().toStdString(),
|
||||
settings.cacheDatabaseMaximumSize()))
|
||||
, threadPool(mbgl::sharedThreadPool())
|
||||
, m_threadPool(mbgl::sharedThreadPool())
|
||||
, m_mode(settings.contextMode())
|
||||
, m_pixelRatio(pixelRatio_)
|
||||
{
|
||||
// Setup resource transform if needed
|
||||
// Setup the FileSource
|
||||
m_fileSourceObj->setAccessToken(settings.accessToken().toStdString());
|
||||
m_fileSourceObj->setAPIBaseURL(settings.apiBaseUrl().toStdString());
|
||||
|
||||
if (settings.resourceTransform()) {
|
||||
m_resourceTransform =
|
||||
std::make_unique< mbgl::Actor<mbgl::ResourceTransform> >( *mbgl::Scheduler::GetCurrent(),
|
||||
[callback = settings.resourceTransform()]
|
||||
(mbgl::Resource::Kind , const std::string&& url_) -> std::string {
|
||||
return callback(std::move(url_));
|
||||
}
|
||||
);
|
||||
fileSourceObj->setResourceTransform(m_resourceTransform->self());
|
||||
m_resourceTransform = std::make_unique<mbgl::Actor<mbgl::ResourceTransform>>(*mbgl::Scheduler::GetCurrent(),
|
||||
[callback = settings.resourceTransform()] (mbgl::Resource::Kind, const std::string &&url_) -> std::string {
|
||||
return callback(std::move(url_));
|
||||
});
|
||||
m_fileSourceObj->setResourceTransform(m_resourceTransform->self());
|
||||
}
|
||||
|
||||
// Setup and connect the renderer frontend
|
||||
frontend = std::make_unique<QMapboxGLRendererFrontend>(
|
||||
std::make_unique<mbgl::Renderer>(*this, pixelRatio, *fileSourceObj, *threadPool,
|
||||
static_cast<mbgl::GLContextMode>(settings.contextMode())),
|
||||
*this);
|
||||
connect(frontend.get(), SIGNAL(updated()), this, SLOT(invalidate()));
|
||||
|
||||
mapObj = std::make_unique<mbgl::Map>(
|
||||
*frontend,
|
||||
*this, sanitizedSize(size),
|
||||
pixelRatio, *fileSourceObj, *threadPool,
|
||||
mbgl::MapMode::Continuous,
|
||||
static_cast<mbgl::ConstrainMode>(settings.constrainMode()),
|
||||
static_cast<mbgl::ViewportMode>(settings.viewportMode()));
|
||||
// Setup MapObserver
|
||||
m_mapObserver = std::make_unique<QMapboxGLMapObserver>(this);
|
||||
|
||||
qRegisterMetaType<QMapboxGL::MapChange>("QMapboxGL::MapChange");
|
||||
|
||||
fileSourceObj->setAccessToken(settings.accessToken().toStdString());
|
||||
fileSourceObj->setAPIBaseURL(settings.apiBaseUrl().toStdString());
|
||||
connect(m_mapObserver.get(), SIGNAL(mapChanged(QMapboxGL::MapChange)), q, SIGNAL(mapChanged(QMapboxGL::MapChange)));
|
||||
connect(m_mapObserver.get(), SIGNAL(copyrightsChanged(QString)), q, SIGNAL(copyrightsChanged(QString)));
|
||||
|
||||
connect(this, SIGNAL(needsRendering()), q_ptr, SIGNAL(needsRendering()), Qt::QueuedConnection);
|
||||
connect(this, SIGNAL(mapChanged(QMapboxGL::MapChange)), q_ptr, SIGNAL(mapChanged(QMapboxGL::MapChange)), Qt::QueuedConnection);
|
||||
connect(this, SIGNAL(copyrightsChanged(QString)), q_ptr, SIGNAL(copyrightsChanged(QString)), Qt::QueuedConnection);
|
||||
// Setup the Map object
|
||||
mapObj = std::make_unique<mbgl::Map>(
|
||||
*this, // RendererFrontend
|
||||
*m_mapObserver,
|
||||
sanitizedSize(size),
|
||||
m_pixelRatio, *m_fileSourceObj, *m_threadPool,
|
||||
static_cast<mbgl::MapMode>(settings.mapMode()),
|
||||
static_cast<mbgl::ConstrainMode>(settings.constrainMode()),
|
||||
static_cast<mbgl::ViewportMode>(settings.viewportMode()));
|
||||
|
||||
// Needs to be Queued to give time to discard redundant draw calls via the `renderQueued` flag.
|
||||
connect(this, SIGNAL(needsRendering()), q, SIGNAL(needsRendering()), Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
QMapboxGLPrivate::~QMapboxGLPrivate()
|
||||
{
|
||||
}
|
||||
|
||||
mbgl::Size QMapboxGLPrivate::getFramebufferSize() const {
|
||||
return sanitizedSize(fbSize);
|
||||
}
|
||||
|
||||
void QMapboxGLPrivate::updateAssumedState() {
|
||||
assumeFramebufferBinding(fbObject);
|
||||
#if QT_VERSION >= 0x050600
|
||||
assumeViewport(0, 0, getFramebufferSize());
|
||||
#endif
|
||||
}
|
||||
|
||||
void QMapboxGLPrivate::bind() {
|
||||
setFramebufferBinding(fbObject);
|
||||
setViewport(0, 0, getFramebufferSize());
|
||||
}
|
||||
|
||||
void QMapboxGLPrivate::invalidate()
|
||||
void QMapboxGLPrivate::update(std::shared_ptr<mbgl::UpdateParameters> parameters)
|
||||
{
|
||||
if (!dirty) {
|
||||
emit needsRendering();
|
||||
dirty = true;
|
||||
std::lock_guard<std::recursive_mutex> lock(m_mapRendererMutex);
|
||||
|
||||
if (!m_mapRenderer) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_mapRenderer->updateParameters(std::move(parameters));
|
||||
|
||||
requestRendering();
|
||||
}
|
||||
|
||||
void QMapboxGLPrivate::setObserver(mbgl::RendererObserver &observer)
|
||||
{
|
||||
m_rendererObserver = std::make_shared<QMapboxGLRendererObserver>(
|
||||
*mbgl::util::RunLoop::Get(), observer);
|
||||
|
||||
std::lock_guard<std::recursive_mutex> lock(m_mapRendererMutex);
|
||||
|
||||
if (m_mapRenderer) {
|
||||
m_mapRenderer->setObserver(m_rendererObserver);
|
||||
}
|
||||
}
|
||||
|
||||
void QMapboxGLPrivate::createRenderer()
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(m_mapRendererMutex);
|
||||
|
||||
if (m_mapRenderer) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_mapRenderer = std::make_unique<QMapboxGLMapRenderer>(
|
||||
m_pixelRatio,
|
||||
*m_fileSourceObj,
|
||||
*m_threadPool,
|
||||
m_mode
|
||||
);
|
||||
|
||||
connect(m_mapRenderer.get(), SIGNAL(needsRendering()), this, SLOT(requestRendering()));
|
||||
|
||||
m_mapRenderer->setObserver(m_rendererObserver);
|
||||
}
|
||||
|
||||
void QMapboxGLPrivate::destroyRenderer()
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(m_mapRendererMutex);
|
||||
|
||||
m_mapRenderer.reset();
|
||||
}
|
||||
|
||||
void QMapboxGLPrivate::render()
|
||||
{
|
||||
frontend->render();
|
||||
}
|
||||
std::lock_guard<std::recursive_mutex> lock(m_mapRendererMutex);
|
||||
|
||||
void QMapboxGLPrivate::onCameraWillChange(mbgl::MapObserver::CameraChangeMode mode)
|
||||
{
|
||||
if (mode == mbgl::MapObserver::CameraChangeMode::Immediate) {
|
||||
emit mapChanged(QMapboxGL::MapChangeRegionWillChange);
|
||||
} else {
|
||||
emit mapChanged(QMapboxGL::MapChangeRegionWillChangeAnimated);
|
||||
if (!m_mapRenderer) {
|
||||
createRenderer();
|
||||
}
|
||||
}
|
||||
|
||||
void QMapboxGLPrivate::onCameraIsChanging()
|
||||
{
|
||||
emit mapChanged(QMapboxGL::MapChangeRegionIsChanging);
|
||||
}
|
||||
|
||||
void QMapboxGLPrivate::onCameraDidChange(mbgl::MapObserver::CameraChangeMode mode)
|
||||
{
|
||||
if (mode == mbgl::MapObserver::CameraChangeMode::Immediate) {
|
||||
emit mapChanged(QMapboxGL::MapChangeRegionDidChange);
|
||||
} else {
|
||||
emit mapChanged(QMapboxGL::MapChangeRegionDidChangeAnimated);
|
||||
#if defined(__APPLE__) && QT_VERSION < 0x050000
|
||||
// FIXME Qt 4.x provides an incomplete FBO at start.
|
||||
// See https://bugreports.qt.io/browse/QTBUG-36802 for details.
|
||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void QMapboxGLPrivate::onWillStartLoadingMap()
|
||||
{
|
||||
emit mapChanged(QMapboxGL::MapChangeWillStartLoadingMap);
|
||||
}
|
||||
|
||||
void QMapboxGLPrivate::onDidFinishLoadingMap()
|
||||
{
|
||||
emit mapChanged(QMapboxGL::MapChangeDidFinishLoadingMap);
|
||||
}
|
||||
|
||||
void QMapboxGLPrivate::onDidFailLoadingMap(std::exception_ptr)
|
||||
{
|
||||
emit mapChanged(QMapboxGL::MapChangeDidFailLoadingMap);
|
||||
}
|
||||
|
||||
void QMapboxGLPrivate::onWillStartRenderingFrame()
|
||||
{
|
||||
emit mapChanged(QMapboxGL::MapChangeWillStartRenderingFrame);
|
||||
}
|
||||
|
||||
void QMapboxGLPrivate::onDidFinishRenderingFrame(mbgl::MapObserver::RenderMode mode)
|
||||
{
|
||||
if (mode == mbgl::MapObserver::RenderMode::Partial) {
|
||||
emit mapChanged(QMapboxGL::MapChangeDidFinishRenderingFrame);
|
||||
} else {
|
||||
emit mapChanged(QMapboxGL::MapChangeDidFinishRenderingFrameFullyRendered);
|
||||
}
|
||||
}
|
||||
|
||||
void QMapboxGLPrivate::onWillStartRenderingMap()
|
||||
{
|
||||
emit mapChanged(QMapboxGL::MapChangeWillStartLoadingMap);
|
||||
}
|
||||
|
||||
void QMapboxGLPrivate::onDidFinishRenderingMap(mbgl::MapObserver::RenderMode mode)
|
||||
{
|
||||
if (mode == mbgl::MapObserver::RenderMode::Partial) {
|
||||
emit mapChanged(QMapboxGL::MapChangeDidFinishRenderingMap);
|
||||
} else {
|
||||
emit mapChanged(QMapboxGL::MapChangeDidFinishRenderingMapFullyRendered);
|
||||
}
|
||||
}
|
||||
|
||||
void QMapboxGLPrivate::onDidFinishLoadingStyle()
|
||||
{
|
||||
emit mapChanged(QMapboxGL::MapChangeDidFinishLoadingStyle);
|
||||
}
|
||||
|
||||
void QMapboxGLPrivate::onSourceChanged(mbgl::style::Source&)
|
||||
{
|
||||
std::string attribution;
|
||||
for (const auto& source : mapObj->getStyle().getSources()) {
|
||||
// Avoid duplicates by using the most complete attribution HTML snippet.
|
||||
if (source->getAttribution() && (attribution.size() < source->getAttribution()->size()))
|
||||
attribution = *source->getAttribution();
|
||||
}
|
||||
emit copyrightsChanged(QString::fromStdString(attribution));
|
||||
emit mapChanged(QMapboxGL::MapChangeSourceDidChange);
|
||||
}
|
||||
|
||||
/*!
|
||||
Initializes an OpenGL extension function such as Vertex Array Objects (VAOs),
|
||||
required by Mapbox GL Native engine.
|
||||
*/
|
||||
mbgl::gl::ProcAddress QMapboxGLPrivate::getExtensionFunctionPointer(const char* name) {
|
||||
#if QT_VERSION >= 0x050000
|
||||
QOpenGLContext* thisContext = QOpenGLContext::currentContext();
|
||||
return thisContext->getProcAddress(name);
|
||||
#else
|
||||
const QGLContext* thisContext = QGLContext::currentContext();
|
||||
return reinterpret_cast<mbgl::gl::ProcAddress>(thisContext->getProcAddress(name));
|
||||
#endif
|
||||
|
||||
m_renderQueued.clear();
|
||||
m_mapRenderer->render();
|
||||
}
|
||||
|
||||
void QMapboxGLPrivate::connectionEstablished()
|
||||
void QMapboxGLPrivate::setFramebufferObject(quint32 fbo, const QSize& size)
|
||||
{
|
||||
mbgl::NetworkStatus::Reachable();
|
||||
std::lock_guard<std::recursive_mutex> lock(m_mapRendererMutex);
|
||||
|
||||
if (!m_mapRenderer) {
|
||||
createRenderer();
|
||||
}
|
||||
|
||||
m_mapRenderer->updateFramebuffer(fbo, sanitizedSize(size));
|
||||
}
|
||||
|
||||
void QMapboxGLPrivate::requestRendering()
|
||||
{
|
||||
if (!m_renderQueued.test_and_set()) {
|
||||
emit needsRendering();
|
||||
}
|
||||
}
|
||||
|
||||
95
platform/qt/src/qmapboxgl_map_observer.cpp
Normal file
95
platform/qt/src/qmapboxgl_map_observer.cpp
Normal file
@@ -0,0 +1,95 @@
|
||||
#include "qmapboxgl_map_observer.hpp"
|
||||
|
||||
#include "qmapboxgl_p.hpp"
|
||||
|
||||
QMapboxGLMapObserver::QMapboxGLMapObserver(QMapboxGLPrivate *d)
|
||||
: d_ptr(d)
|
||||
{
|
||||
}
|
||||
|
||||
QMapboxGLMapObserver::~QMapboxGLMapObserver()
|
||||
{
|
||||
}
|
||||
|
||||
void QMapboxGLMapObserver::onCameraWillChange(mbgl::MapObserver::CameraChangeMode mode)
|
||||
{
|
||||
if (mode == mbgl::MapObserver::CameraChangeMode::Immediate) {
|
||||
emit mapChanged(QMapboxGL::MapChangeRegionWillChange);
|
||||
} else {
|
||||
emit mapChanged(QMapboxGL::MapChangeRegionWillChangeAnimated);
|
||||
}
|
||||
}
|
||||
|
||||
void QMapboxGLMapObserver::onCameraIsChanging()
|
||||
{
|
||||
emit mapChanged(QMapboxGL::MapChangeRegionIsChanging);
|
||||
}
|
||||
|
||||
void QMapboxGLMapObserver::onCameraDidChange(mbgl::MapObserver::CameraChangeMode mode)
|
||||
{
|
||||
if (mode == mbgl::MapObserver::CameraChangeMode::Immediate) {
|
||||
emit mapChanged(QMapboxGL::MapChangeRegionDidChange);
|
||||
} else {
|
||||
emit mapChanged(QMapboxGL::MapChangeRegionDidChangeAnimated);
|
||||
}
|
||||
}
|
||||
|
||||
void QMapboxGLMapObserver::onWillStartLoadingMap()
|
||||
{
|
||||
emit mapChanged(QMapboxGL::MapChangeWillStartLoadingMap);
|
||||
}
|
||||
|
||||
void QMapboxGLMapObserver::onDidFinishLoadingMap()
|
||||
{
|
||||
emit mapChanged(QMapboxGL::MapChangeDidFinishLoadingMap);
|
||||
}
|
||||
|
||||
void QMapboxGLMapObserver::onDidFailLoadingMap(std::exception_ptr)
|
||||
{
|
||||
emit mapChanged(QMapboxGL::MapChangeDidFailLoadingMap);
|
||||
}
|
||||
|
||||
void QMapboxGLMapObserver::onWillStartRenderingFrame()
|
||||
{
|
||||
emit mapChanged(QMapboxGL::MapChangeWillStartRenderingFrame);
|
||||
}
|
||||
|
||||
void QMapboxGLMapObserver::onDidFinishRenderingFrame(mbgl::MapObserver::RenderMode mode)
|
||||
{
|
||||
if (mode == mbgl::MapObserver::RenderMode::Partial) {
|
||||
emit mapChanged(QMapboxGL::MapChangeDidFinishRenderingFrame);
|
||||
} else {
|
||||
emit mapChanged(QMapboxGL::MapChangeDidFinishRenderingFrameFullyRendered);
|
||||
}
|
||||
}
|
||||
|
||||
void QMapboxGLMapObserver::onWillStartRenderingMap()
|
||||
{
|
||||
emit mapChanged(QMapboxGL::MapChangeWillStartLoadingMap);
|
||||
}
|
||||
|
||||
void QMapboxGLMapObserver::onDidFinishRenderingMap(mbgl::MapObserver::RenderMode mode)
|
||||
{
|
||||
if (mode == mbgl::MapObserver::RenderMode::Partial) {
|
||||
emit mapChanged(QMapboxGL::MapChangeDidFinishRenderingMap);
|
||||
} else {
|
||||
emit mapChanged(QMapboxGL::MapChangeDidFinishRenderingMapFullyRendered);
|
||||
}
|
||||
}
|
||||
|
||||
void QMapboxGLMapObserver::onDidFinishLoadingStyle()
|
||||
{
|
||||
emit mapChanged(QMapboxGL::MapChangeDidFinishLoadingStyle);
|
||||
}
|
||||
|
||||
void QMapboxGLMapObserver::onSourceChanged(mbgl::style::Source&)
|
||||
{
|
||||
std::string attribution;
|
||||
for (const auto& source : d_ptr->mapObj->getStyle().getSources()) {
|
||||
// Avoid duplicates by using the most complete attribution HTML snippet.
|
||||
if (source->getAttribution() && (attribution.size() < source->getAttribution()->size()))
|
||||
attribution = *source->getAttribution();
|
||||
}
|
||||
emit copyrightsChanged(QString::fromStdString(attribution));
|
||||
emit mapChanged(QMapboxGL::MapChangeSourceDidChange);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user