Skip to content
This repository was archived by the owner on Aug 8, 2023. It is now read-only.

Custom vector source #8473

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions cmake/core-files.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -365,9 +365,13 @@ set(MBGL_CORE_FILES
src/mbgl/style/layers/symbol_layer_properties.hpp

# style/sources
include/mbgl/style/sources/custom_vector_source.hpp
include/mbgl/style/sources/geojson_source.hpp
include/mbgl/style/sources/raster_source.hpp
include/mbgl/style/sources/vector_source.hpp
src/mbgl/style/sources/custom_vector_source.cpp
src/mbgl/style/sources/custom_vector_source_impl.cpp
src/mbgl/style/sources/custom_vector_source_impl.hpp
src/mbgl/style/sources/geojson_source.cpp
src/mbgl/style/sources/geojson_source_impl.cpp
src/mbgl/style/sources/geojson_source_impl.hpp
Expand Down Expand Up @@ -422,6 +426,7 @@ set(MBGL_CORE_FILES
src/mbgl/tile/tile_cache.cpp
src/mbgl/tile/tile_cache.hpp
src/mbgl/tile/tile_id.hpp
src/mbgl/tile/tile_id_hash.hpp
src/mbgl/tile/tile_id_io.cpp
src/mbgl/tile/tile_loader.hpp
src/mbgl/tile/tile_loader_impl.hpp
Expand Down
1 change: 1 addition & 0 deletions cmake/test-files.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ set(MBGL_TEST_FILES
test/style/conversion/stringify.test.cpp

# style
test/style/custom_vector_source.test.cpp
test/style/filter.test.cpp

# style/function
Expand Down
9 changes: 9 additions & 0 deletions include/mbgl/style/conversion/geojson_options.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,15 @@ struct Converter<GeoJSONOptions> {
Result<GeoJSONOptions> operator()(const V& value) const {
GeoJSONOptions options;

const auto minzoomValue = objectMember(value, "minzoom");
if (minzoomValue) {
if (toNumber(*minzoomValue)) {
options.minzoom = static_cast<uint8_t>(*toNumber(*minzoomValue));
} else {
return Error{ "GeoJSON source minzoom value must be a number" };
}
}

const auto maxzoomValue = objectMember(value, "maxzoom");
if (maxzoomValue) {
if (toNumber(*maxzoomValue)) {
Expand Down
34 changes: 34 additions & 0 deletions include/mbgl/style/sources/custom_vector_source.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#pragma once

#include <mbgl/style/source.hpp>
#include <mbgl/style/sources/geojson_source.hpp>
#include <mbgl/util/geo.hpp>
#include <mbgl/util/geojson.hpp>

namespace mbgl {
namespace style {

class CustomVectorSource : public Source {
public:
CustomVectorSource(std::string id,
GeoJSONOptions options,
std::function<void(const CanonicalTileID&)> fetchTile);

void setTileData(const CanonicalTileID&, const mapbox::geojson::geojson&);
void reloadTile(const CanonicalTileID&);
void reloadRegion(mbgl::LatLngBounds bounds, uint8_t z);
void reload();

// Private implementation

class Impl;
Impl* const impl;
};

template <>
inline bool Source::is<CustomVectorSource>() const {
return type == SourceType::Vector;
}

} // namespace style
} // namespace mbgl
3 changes: 3 additions & 0 deletions include/mbgl/style/sources/geojson_source.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <mbgl/style/source.hpp>
#include <mbgl/util/geojson.hpp>
#include <mbgl/util/optional.hpp>
#include <mbgl/util/constants.hpp>

#include <mapbox/geojson.hpp>

Expand All @@ -26,7 +27,9 @@ using SuperclusterPointer = std::unique_ptr<mapbox::supercluster::Supercluster>;

struct GeoJSONOptions {
// GeoJSON-VT options
uint8_t minzoom = 0;
uint8_t maxzoom = 18;
uint16_t tileSize = util::tileSize;
uint16_t buffer = 128;
double tolerance = 0.375;

Expand Down
1 change: 1 addition & 0 deletions platform/darwin/docs/theme/assets/css/jazzy.css.scss
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,7 @@ pre code {
.nav-group-task[data-name="MGLStyleFunction"],
.nav-group-task[data-name="MGLStyleLayer"],
.nav-group-task[data-name="MGLTileSource"],
.nav-group-task[data-name="MGLAbstractShapeSource"],
.nav-group-task[data-name="MGLVectorStyleLayer"] {
.nav-group-task-link::after {
@extend %nav-group-task-gloss;
Expand Down
99 changes: 99 additions & 0 deletions platform/darwin/src/MGLAbstractShapeSource.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#import "MGLSource.h"

/**
Options for `MGLShapeSource` objects.
*/
typedef NSString *MGLShapeSourceOption NS_STRING_ENUM;

/**
An `NSNumber` object containing a Boolean enabling or disabling clustering.
If the `shape` property contains point shapes, setting this option to
`YES` clusters the points by radius into groups. The default value is `NO`.

This attribute corresponds to the
<a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources-geojson-cluster"><code>cluster</code></a>
source property in the Mapbox Style Specification.

This option only affects point features within a shape source.
*/
extern MGL_EXPORT const MGLShapeSourceOption MGLShapeSourceOptionClustered;

/**
An `NSNumber` object containing an integer; specifies the radius of each
cluster if clustering is enabled. A value of 512 produces a radius equal to
the width of a tile. The default value is 50.
*/
extern MGL_EXPORT const MGLShapeSourceOption MGLShapeSourceOptionClusterRadius;

/**
An `NSNumber` object containing an integer; specifies the maximum zoom level at
which to cluster points if clustering is enabled. Defaults to one zoom level
less than the value of `MGLShapeSourceOptionMaximumZoomLevel` so that, at the
maximum zoom level, the shapes are not clustered.

This attribute corresponds to the
<a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources-geojson-clusterMaxZoom"><code>clusterMaxZoom</code></a>
source property in the Mapbox Style Specification.
*/
extern MGL_EXPORT const MGLShapeSourceOption MGLShapeSourceOptionMaximumZoomLevelForClustering;

/**
An `NSNumber` object containing an integer; specifies the minimum zoom level at
which to create vector tiles. The default value is 0.

This attribute corresponds to the
<a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources-geojson-minzoom"><code>minzoom</code></a>
source property in the Mapbox Style Specification.
*/
extern const MGLShapeSourceOption MGLShapeSourceOptionMinimumZoomLevel;

/**
An `NSNumber` object containing an integer; specifies the maximum zoom level at
which to create vector tiles. A greater value produces greater detail at high
zoom levels. The default value is 18.

This attribute corresponds to the
<a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources-geojson-maxzoom"><code>maxzoom</code></a>
source property in the Mapbox Style Specification.
*/
extern MGL_EXPORT const MGLShapeSourceOption MGLShapeSourceOptionMaximumZoomLevel;

/**
An `NSNumber` object containing an integer; specifies the size of the tile
buffer on each side. A value of 0 produces no buffer. A value of 512 produces a
buffer as wide as the tile itself. Larger values produce fewer rendering
artifacts near tile edges and slower performance. The default value is 128.

This attribute corresponds to the
<a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources-geojson-buffer"><code>buffer</code></a>
source property in the Mapbox Style Specification.
*/
extern MGL_EXPORT const MGLShapeSourceOption MGLShapeSourceOptionBuffer;

/**
An `NSNumber` object containing a double; specifies the Douglas-Peucker
simplification tolerance. A greater value produces simpler geometries and
improves performance. The default value is 0.375.

This attribute corresponds to the
<a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources-geojson-tolerance"><code>tolerance</code></a>
source property in the Mapbox Style Specification.
*/
extern MGL_EXPORT const MGLShapeSourceOption MGLShapeSourceOptionSimplificationTolerance;

/**
`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
`MGLStyle` object along with an `MGLVectorStyleLayer` object. The vector style
layer defines the appearance of any content supplied by the shape source.


Do not create instances of this class directly, and do not create your own
subclasses of this class. Instead, create instances of `MGLShapeSource` or
`MGLComputedShapeSource`.
*/
MGL_EXPORT
@interface MGLAbstractShapeSource : MGLSource


@end
81 changes: 81 additions & 0 deletions platform/darwin/src/MGLAbstractShapeSource.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#import "MGLAbstractShapeSource.h"
#import "MGLAbstractShapeSource_Private.h"

const MGLShapeSourceOption MGLShapeSourceOptionBuffer = @"MGLShapeSourceOptionBuffer";
const MGLShapeSourceOption MGLShapeSourceOptionClusterRadius = @"MGLShapeSourceOptionClusterRadius";
const MGLShapeSourceOption MGLShapeSourceOptionClustered = @"MGLShapeSourceOptionClustered";
const MGLShapeSourceOption MGLShapeSourceOptionMaximumZoomLevel = @"MGLShapeSourceOptionMaximumZoomLevel";
const MGLShapeSourceOption MGLShapeSourceOptionMaximumZoomLevelForClustering = @"MGLShapeSourceOptionMaximumZoomLevelForClustering";
const MGLShapeSourceOption MGLShapeSourceOptionMinimumZoomLevel = @"MGLShapeSourceOptionMinimumZoomLevel";
const MGLShapeSourceOption MGLShapeSourceOptionSimplificationTolerance = @"MGLShapeSourceOptionSimplificationTolerance";

@interface MGLAbstractShapeSource ()

@end

@implementation MGLAbstractShapeSource

@end

mbgl::style::GeoJSONOptions MGLGeoJSONOptionsFromDictionary(NS_DICTIONARY_OF(MGLShapeSourceOption, id) *options) {
auto geoJSONOptions = mbgl::style::GeoJSONOptions();

if (NSNumber *value = options[MGLShapeSourceOptionMinimumZoomLevel]) {
if (![value isKindOfClass:[NSNumber class]]) {
[NSException raise:NSInvalidArgumentException
format:@"MGLShapeSourceOptionMaximumZoomLevel must be an NSNumber."];
}
geoJSONOptions.minzoom = value.integerValue;
}

if (NSNumber *value = options[MGLShapeSourceOptionMaximumZoomLevel]) {
if (![value isKindOfClass:[NSNumber class]]) {
[NSException raise:NSInvalidArgumentException
format:@"MGLShapeSourceOptionMaximumZoomLevel must be an NSNumber."];
}
geoJSONOptions.maxzoom = value.integerValue;
}

if (NSNumber *value = options[MGLShapeSourceOptionBuffer]) {
if (![value isKindOfClass:[NSNumber class]]) {
[NSException raise:NSInvalidArgumentException
format:@"MGLShapeSourceOptionBuffer must be an NSNumber."];
}
geoJSONOptions.buffer = value.integerValue;
}

if (NSNumber *value = options[MGLShapeSourceOptionSimplificationTolerance]) {
if (![value isKindOfClass:[NSNumber class]]) {
[NSException raise:NSInvalidArgumentException
format:@"MGLShapeSourceOptionSimplificationTolerance must be an NSNumber."];
}
geoJSONOptions.tolerance = value.doubleValue;
}

if (NSNumber *value = options[MGLShapeSourceOptionClusterRadius]) {
if (![value isKindOfClass:[NSNumber class]]) {
[NSException raise:NSInvalidArgumentException
format:@"MGLShapeSourceOptionClusterRadius must be an NSNumber."];
}
geoJSONOptions.clusterRadius = value.integerValue;
}

if (NSNumber *value = options[MGLShapeSourceOptionMaximumZoomLevelForClustering]) {
if (![value isKindOfClass:[NSNumber class]]) {
[NSException raise:NSInvalidArgumentException
format:@"MGLShapeSourceOptionMaximumZoomLevelForClustering must be an NSNumber."];
}
geoJSONOptions.clusterMaxZoom = value.integerValue;
}

if (NSNumber *value = options[MGLShapeSourceOptionClustered]) {
if (![value isKindOfClass:[NSNumber class]]) {
[NSException raise:NSInvalidArgumentException
format:@"MGLShapeSourceOptionClustered must be an NSNumber."];
}
geoJSONOptions.cluster = value.boolValue;
}

return geoJSONOptions;
}

18 changes: 18 additions & 0 deletions platform/darwin/src/MGLAbstractShapeSource_Private.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#import "MGLAbstractShapeSource.h"

#import "MGLFoundation.h"
#import "MGLTypes.h"
#import "MGLShape.h"

#include <mbgl/style/sources/geojson_source.hpp>

NS_ASSUME_NONNULL_BEGIN

@interface MGLAbstractShapeSource (Private)

MGL_EXPORT

mbgl::style::GeoJSONOptions MGLGeoJSONOptionsFromDictionary(NS_DICTIONARY_OF(MGLShapeSourceOption, id) *options);

@end
NS_ASSUME_NONNULL_END
77 changes: 77 additions & 0 deletions platform/darwin/src/MGLComputedShapeSource.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#import "MGLAbstractShapeSource.h"

#import "MGLFoundation.h"
#import "MGLGeometry.h"
#import "MGLTypes.h"
#import "MGLShape.h"

NS_ASSUME_NONNULL_BEGIN

@protocol MGLFeature;

/**
Data source for `MGLComputedShapeSource`. This protocol defines two optional methods for fetching
data, one based on tile coordinates, and one based on a bounding box. Classes that implement this
protocol must implement one, and only one of the methods.
*/
@protocol MGLComputedShapeSourceDataSource <NSObject>

@optional
/**
Fetch features for a tile. This will not be called on the main queue, it will be called on the caller's requestQueue.
@param x tile X coordinate
@param y tile Y coordinate
@param zoomLevel tile zoom level
*/
- (NSArray<MGLShape <MGLFeature> *>*)featuresInTileAtX:(NSUInteger)x y:(NSUInteger)y zoomLevel:(NSUInteger)zoomLevel;

/**
Fetch features for a tile. This will not be called on the main queue, it will be called on the caller's requestQueue.
@param bounds The bounds to fetch data for
@param zoomLevel tile zoom level
*/
- (NSArray<MGLShape <MGLFeature> *>*)featuresInCoordinateBounds:(MGLCoordinateBounds)bounds zoomLevel:(NSUInteger)zoomLevel;

@end

/**
A source for vector data that is fetched one tile at a time. Useful for sources that are
too large to fit in memory, or are already divided into tiles, but not in Mapbox Vector Tile format.
*/
MGL_EXPORT
@interface MGLComputedShapeSource : MGLAbstractShapeSource

/**
Returns a custom vector data source initialized with an identifier, data source, and a
dictionary of options for the source according to the
<a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources-geojson">style
specification</a>.

@param identifier A string that uniquely identifies the source.
@param options An `NSDictionary` of options for this source.
*/
- (instancetype)initWithIdentifier:(NSString *)identifier options:(nullable NS_DICTIONARY_OF(MGLShapeSourceOption, id) *)options NS_DESIGNATED_INITIALIZER;

/**
Request that the source reloads a region.
*/
- (void)reloadTileInCoordinateBounds:(MGLCoordinateBounds)bounds zoomLevel:(NSUInteger)zoomLevel;

/**
Reload all tiles.
*/
- (void)reloadData;

/**
An object that implements the `MGLComputedShapeSource` protocol that will be queried for tile data.
*/
@property (nonatomic, weak, nullable) id<MGLComputedShapeSourceDataSource> dataSource;

/**
A queue that calls to the data source will be made on.
*/
@property (nonatomic, readonly) NSOperationQueue *requestQueue;

@end

NS_ASSUME_NONNULL_END
Loading