-
Notifications
You must be signed in to change notification settings - Fork 35
Conversation
|
||
func mapView(_ mapView: MGLMapView, didFinishLoading style: MGLStyle) { | ||
|
||
// Access the Mapbox Streets source and use it to create a `MGLFillExtrusionLayer`. |
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.
MGLFillExtrusionStyleLayer
seems to be the name of the layer class.
func mapView(_ mapView: MGLMapView, didFinishLoading style: MGLStyle) { | ||
|
||
// Access the Mapbox Streets source and use it to create a `MGLFillExtrusionLayer`. | ||
let source = style.source(withIdentifier: "composite") |
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 "composite"
chosen for a particular reason (e.g., does this exist in the source) or is this an arbitrary name?
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.
"composite"
is the identifier of the source in the style. I'll clarify that in the comment!
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.
For a more robust solution (which may be overkill for this particular example), see this extension method used in the navigation SDK. You’d filter style.sources
by isMapboxStreets
and create a Streets source if there isn’t one.
|
||
// Access the Mapbox Streets source and use it to create a `MGLFillExtrusionLayer`. | ||
let source = style.source(withIdentifier: "composite") | ||
let layer = MGLFillExtrusionStyleLayer(identifier: "buildings", source: source!) |
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 it safe to force unwrap source
?
layer.sourceLayerIdentifier = "building" | ||
|
||
// Filter out buildings that should not extrude. | ||
layer.predicate = NSPredicate(format: "extrude != false AND height >=0") |
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.
For my own curiosity — what constitutes a building with extrude == false
? How is that determined?
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.
From what I've read here, extrude
may be false
if it is a complex building that requires a lot of building parts to render it correctly (like the Colosseum). This tells the renderer to skip rendering the overall building, and instead render the individual building parts.
This is mostly to catch some strange rendering that @incanus and I noticed when we were testing this out on Lower Manhattan. (which is a bug that he reported)
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.
Yep, that’s correct. According to the Mapbox Streets source documentation:
The
extrude
field istrue
orfalse
depending one whether the object should be included in 3D-extrusion renderings. For example a complex building might have variousbuilding:part
objects mapped with different heights, in addition to a building object representing the footprint of the entire building. Only thebuilding:part
objects are needed for 3D rendering, so the full footprint outline will have anextrude
value offalse
.
For a lower-level understanding of this value, see the OpenStreetMap documentation about 3D building outlines.
|
||
// Insert the fill extrusion layer below a POI label layer. | ||
let symbolLayer = style.layer(withIdentifier: "poi-scalerank3") | ||
style.insertLayer(layer, below: symbolLayer!) |
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 symbolLayer
safe to force unwrap? When dealing with layer identifiers, I think it’s going to be important to note that these are only guaranteed to exist in certain Mapbox sources/styles, and then only for specific versions.
/cc @1ec5
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.
I'll err on the side of safety 🙇♀️
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.
See this StackOverflow post for a more robust solution.
Nice example. Since it requires v3.6.0, we should create a release branch here and retarget this PR against that. |
Podfile
Outdated
@@ -3,7 +3,7 @@ use_frameworks! | |||
|
|||
target 'Examples' do | |||
# Pods for Examples | |||
pod 'Mapbox-iOS-SDK-symbols', :podspec => 'https://raw.githubusercontent.com/mapbox/mapbox-gl-native/ios-v3.5.3/platform/ios/Mapbox-iOS-SDK-symbols.podspec' | |||
pod 'Mapbox-iOS-SDK-symbols', :podspec => 'https://raw.githubusercontent.com/mapbox/mapbox-gl-native/ios-v3.6.0-alpha.1/platform/ios/Mapbox-iOS-SDK-symbols.podspec' |
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.
Let’s break the version bump out into its own commit.
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.
Created a release-v3.6.0
branch. Will update the podfile in there as needed!
e6c0da0
to
de63625
Compare
MGLMapView *mapView = [[MGLMapView alloc] initWithFrame:self.view.bounds styleURL:[MGLStyle lightStyleURLWithVersion:9]]; | ||
|
||
// Center the map on the Colosseum in Rome, Italy. | ||
[mapView setCenterCoordinate:CLLocationCoordinate2DMake(41.8902, 12.4922)]; |
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: use dot notation: mapView.centerCoordinate = …
.
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.
Actually, we’re setting the camera right below. Let’s combine the two statements.
layer.sourceLayerIdentifier = @"building"; | ||
|
||
// Filter out buildings that should not extrude. | ||
layer.predicate = [NSPredicate predicateWithFormat:@"extrude != false AND height >=0"]; |
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.
extrude
can only be true or false, right? extrude = true
reads better in this case.
layer.predicate = [NSPredicate predicateWithFormat:@"extrude != false AND height >=0"]; | ||
|
||
// Set the fill extrusion height to the value for the building height attribute. | ||
layer.fillExtrusionHeight = [MGLStyleValue valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"height" options: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.
We should set fillExtrusionBase
too, so that roofs and skywalks don’t fill the space below. The coliseum will probably look a little better that way, too.
layer.sourceLayerIdentifier = "building" | ||
|
||
// Filter out buildings that should not extrude. | ||
layer.predicate = NSPredicate(format: "extrude != false AND height >=0") |
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: missing a space between >=
and 0
.
layer.fillExtrusionOpacity = MGLStyleValue(rawValue: 0.75) | ||
layer.fillExtrusionColor = MGLStyleValue(rawValue: .white) | ||
|
||
// Insert the fill extrusion layer below a POI label layer. Use the `layers` property on a style to verify built-in layer identifiers. |
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 comment may lead a developer to think they have to use the layers
property to obtain the correct layer at runtime, whereas we merely intend to point out that it’s a helpful tool for discovering the layer identifier.
If you aren’t sure what the layer is called, you can view the style in Mapbox Studio or iterate over the style’s
layers
property, printing out each layer’sidentifier
.
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.
😍 awesome! Nice building choice.
|
||
- (void)mapView:(MGLMapView *)mapView didFinishLoadingStyle:(MGLStyle *)style { | ||
|
||
// Access the Mapbox Streets source and use it to create a `MGLFillExtrusionStyleLayer`. The source identifier is `composite`. Use the `sources` property on a style to verify source identifiers. |
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.
It might be a good idea to reference the Style Specification here: https://www.mapbox.com/mapbox-gl-js/style-spec
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 comment refers to properties in the runtime styling API to use as a debugging aid. There are so many differences between the runtime styling API and the style specification’s documentation on sources that we’d want to link to the more detailed API reference instead.
In any case, I think #86 (comment) is relevant here as well:
If you aren’t sure what the
source
is called, you can view the style in Mapbox Studio or iterate over the style’ssources
property, printing out each source’s identifier.
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.
Two more issues to address, but otherwise this PR is good to go.
@@ -41,14 +40,14 @@ - (void)mapView:(MGLMapView *)mapView didFinishLoadingStyle:(MGLStyle *)style { | |||
layer.sourceLayerIdentifier = @"building"; | |||
|
|||
// Filter out buildings that should not extrude. | |||
layer.predicate = [NSPredicate predicateWithFormat:@"extrude != false AND height >=0"]; |
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.
We do want to extrude. #86 was a suggestion to change this to extrude = true
, not to remove the condition. By removing the condition, buildings like the Eiffel Tower will get extruded quite humorously.
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.
Awesome! I just edited it. Was running into issues because of mapbox/mapbox-gl-native#9056
layer.predicate = [NSPredicate predicateWithFormat:@"height >= 0"]; | ||
|
||
// Set the fill extrusion height to the value for the building height attribute. | ||
layer.fillExtrusionHeight = [MGLStyleValue valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"height" options: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.
Remember to set fillExtrusionBase
too: #86 (comment).
@@ -40,10 +40,11 @@ - (void)mapView:(MGLMapView *)mapView didFinishLoadingStyle:(MGLStyle *)style { | |||
layer.sourceLayerIdentifier = @"building"; | |||
|
|||
// Filter out buildings that should not extrude. | |||
layer.predicate = [NSPredicate predicateWithFormat:@"height >= 0"]; | |||
layer.predicate = [NSPredicate predicateWithFormat:@"extrude == %@ AND height >= 0", @"true"]; |
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: Per mapbox/mapbox-gl-native#9056 (comment), this can be written extrude == 'true'
.
Basic 3D extrusions example for when 3.6.0 lands.
cc @incanus