-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Add tile template option to raster and vector sources #6316
Conversation
@boundsj, thanks for your PR! By analyzing this pull request, we identified @1ec5, @incanus and @friedbunny to be potential reviewers. |
|
||
@interface MGLRasterSource : MGLSource | ||
|
||
@property (nonatomic, readonly, copy) NSURL *URL; | ||
@property (nonatomic, readonly, assign) CGFloat tileSize; | ||
@property (nonatomic, readonly, copy) NS_ARRAY_OF(NSString *) *tileURLTemplates; | ||
@property (nonatomic, readonly) uint8_t minimumZoomLevel; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These should be NSUInteger
-typed. In general, we should prefer Foundation typealiases over the compiler’s built-in numeric primitives in Objective-C code. It’s fine if the whole range of NSUInteger
won’t work; if it fails hard, we can clamp the value to whatever range is supported.
We should probably add an MGLTileSet class that exposes all the options |
9d33392
to
c0fb939
Compare
This work has started in c0fb939 |
|
||
@implementation MGLTileSet | ||
{ | ||
BOOL _minimumZoomLevelIsSet; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the minimum and maximum zoom levels are optional, then do they need to be represented as NSNumbers publicly? Otherwise, if you use the -initWithTileURLTemplates:
initializer, these properties end up being 0.
This reverts a previous change to vector / raster sources that added initializers to those classes so they could take certain tileset properties and create their own mbgl::Tileset objects. Now, a new MGLTileSet class that wraps all available core Tileset options can be created and passed into the sources. The sources pass that tileset object along to core.
This also adds a temporary example to iosapp to show raster sources working (actually vector on top of raster from 3rd party sources using tile URL templates directly)
This changes the type of the minimum and maximum zoom level from a BOOL to an NSNumber. With this commit, a client that does not set the values will still see them represented as nil in the underlying object even though those nil values will translate to non nil defaults in core (0 for minimum and 22 for maximum). In addition, this adds tests for MGLTileSet and an initial attempt at documentation.
c0fb939
to
9bf02ec
Compare
With the latest changes here, you can now mash up vector and raster sources created with tile sets: // Use raster tile URL templates directly (i.e. mapbox://tiles/mapbox.satellite/{z}/{x}/{y}{ratio}.png)
// This is Stamen's terrain
MGLTileSet *rasterTileSet = [[MGLTileSet alloc] initWithTileURLTemplates:@[@"http://a.tile.stamen.com/terrain-background/{z}/{x}/{y}.jpg"]];
MGLRasterSource *rasterSource = [[MGLRasterSource alloc] initWithSourceIdentifier:@"raster-source" tileSize:256 tileSet:rasterTileSet];
[self.mapView.style addSource:rasterSource];
MGLRasterStyleLayer *rasterLayer = [[MGLRasterStyleLayer alloc] initWithLayerIdentifier:@"raster-layer" source:rasterSource];
[self.mapView.style addLayer:rasterLayer];
// Use vector tile URL templates directly. This is Mapzen's vector tile service
MGLTileSet *vectorTileSet = [[MGLTileSet alloc] initWithTileURLTemplates:@[@"https://vector.mapzen.com/osm/all/{z}/{x}/{y}.mvt?api_key=akey"]];
MGLVectorSource *vectorSource = [[MGLVectorSource alloc] initWithSourceIdentifier:@"mapzen" tileSet:vectorTileSet];
[self.mapView.style addSource:vectorSource];
MGLFillStyleLayer *buildingsFillLayer = [[MGLFillStyleLayer alloc] initWithLayerIdentifier:@"filllayer" source:vectorSource sourceLayer:@"buildings"];
buildingsFillLayer.fillColor = [UIColor magentaColor];
[self.mapView.style addLayer:buildingsFillLayer]; Not exactly "Streets"The current implementation does not attempt to reflect the mbgl object's default minimum and maximum zoom values if the Objective-C object's properties are nil. However, documentation was added that states that the defaults will be used if the Objective-C tile set object is used to initialize a source and the min/max values are nil. cc @1ec5 |
@interface MGLTileSet : NSObject | ||
|
||
/** | ||
A REQUIRED `NSArray` of `NSString` objects that represent the tile templates. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Optionality should be indicated through nullability qualifiers; shouting isn't needed here.
the maximum zoom level at which to display tiles. | ||
@return The initialized tile set object. | ||
*/ | ||
- (instancetype)initWithTileURLTemplates:(NS_ARRAY_OF(NSString *) *)tileURLTemplates minimumZoomLevel:(NSNumber *)minimumZoomLevel maximumZoomLevel:(NSNumber *)maximumZoomLevel; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The zoom level parameters should either be nullable or, better yet, primitive typed.
// has the correct URL templates | ||
XCTAssertEqual(mbglTileset.tiles[0], "tile.1"); | ||
XCTAssertEqual(mbglTileset.tiles[1], "tile.2"); | ||
XCTAssertEqual(mbglTileset.tiles[2], "tile.3"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also assert on the tile set count.
XCTAssertEqual([tileSet mbglTileset].zoomRange.max, 2); | ||
|
||
// when the tile set has an attribution | ||
tileSet.attribution = @"my tileset"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also test that Unicode characters are preserved.
|
||
// when the tile set has min and/or max zoom level set | ||
tileSet.minimumZoomLevel = @(1); | ||
tileSet.maximumZoomLevel = @(2); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the developer sets a maximum zoom level less than the minimum, what happens? Would it be possible to test for an Objective-C exception being thrown (ideal)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
0fc9cbc throws Objective-C exceptions if values are crossed initially or later on in setters. This avoids a more shocking C++ exception that happens later when the doomed threshold is crossed when the map is zoomed.
Alternatively, we could ignore invalid values and log a warning avoiding an exception altogether.
This updates the initializer to take an integer value for the zoom level. Logic is also added to throw an exception early if the initial values are invalid or if they are set to invalid values later in property setters.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Almost there.
of 0 to 22. The default value is 0 and the source will use the default value | ||
An `NSNumber` object containing an integer; specifies the minimum zoom level at | ||
which the source will display tiles. The value should be in the range of 0 to | ||
22. The default value is 0 and the source will use the default value | ||
if `minimumZoomLevel` is nil; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This sentence and two more below end in semicolons instead of periods.
*/ | ||
@property (nonatomic, nullable) NSNumber *maximumZoomLevel; | ||
|
||
/** | ||
An OPTIONAL `NSString` object; Contains an attribution to be displayed | ||
when the map is shown to a user. The default value is nil; | ||
An `NSString` object; Contains an attribution to be displayed when the map is |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: replace the semicolon with “that” and lowercase “contains” (plus one more below).
@@ -43,7 +44,7 @@ - (void)testMBGLTileSet { | |||
XCTAssertEqual([tileSet mbglTileset].zoomRange.max, 2); | |||
|
|||
// when the tile set has an attribution | |||
tileSet.attribution = @"my tileset"; | |||
tileSet.attribution = @"my tileset ©"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
© is a decent test, since it falls outside of ASCII. In #5999, I used ©️, which pairs © with a variation selector for an emoji look. But something outside the Basic Multilingual Plane, for example in the Miscellaneous Symbols and Pictographs block, would be even better for detecting mojibake.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! I think 0e31030 should probably wrap this up
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎈
Fixes #6245