Skip to content
This repository has been archived by the owner on Jun 14, 2024. It is now read-only.

Extrusions example #86

Merged
merged 6 commits into from
May 22, 2017
Merged

Extrusions example #86

merged 6 commits into from
May 22, 2017

Conversation

jmkiley
Copy link
Contributor

@jmkiley jmkiley commented May 12, 2017

Basic 3D extrusions example for when 3.6.0 lands.

screenshot 2017-05-12 10 46 22

cc @incanus

@jmkiley jmkiley self-assigned this May 12, 2017
@jmkiley jmkiley changed the title Extrusions example [do not merge] Extrusions example May 12, 2017
@jmkiley jmkiley added this to the ios-v3.6.0 milestone May 12, 2017

func mapView(_ mapView: MGLMapView, didFinishLoading style: MGLStyle) {

// Access the Mapbox Streets source and use it to create a `MGLFillExtrusionLayer`.
Copy link
Contributor

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")
Copy link
Contributor

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?

Copy link
Contributor Author

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!

Copy link
Contributor

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!)
Copy link
Contributor

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")
Copy link
Contributor

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?

Copy link
Contributor Author

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)

screen shot 2017-05-10 at 11 41 44 am

Copy link
Contributor

@1ec5 1ec5 May 13, 2017

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 is true or false depending one whether the object should be included in 3D-extrusion renderings. For example a complex building might have various building:part objects mapped with different heights, in addition to a building object representing the footprint of the entire building. Only the building:part objects are needed for 3D rendering, so the full footprint outline will have an extrude value of false.

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!)
Copy link
Contributor

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

Copy link
Contributor Author

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 🙇‍♀️

Copy link
Contributor

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.

@friedbunny
Copy link
Contributor

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'
Copy link
Contributor

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.

Copy link
Contributor Author

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!

@jmkiley jmkiley changed the base branch from master to release-v3.6.0 May 12, 2017 21:18
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)];
Copy link
Contributor

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 = ….

Copy link
Contributor

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"];
Copy link
Contributor

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];
Copy link
Contributor

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")
Copy link
Contributor

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.
Copy link
Contributor

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’s identifier.

Copy link
Contributor

@captainbarbosa captainbarbosa left a 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.
Copy link
Contributor

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

Copy link
Contributor

@1ec5 1ec5 May 13, 2017

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’s sources property, printing out each source’s identifier.

Copy link
Contributor

@1ec5 1ec5 left a 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"];
Copy link
Contributor

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.

Copy link
Contributor Author

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];
Copy link
Contributor

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"];
Copy link
Contributor

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'.

@jmkiley jmkiley merged commit 20f9bfc into release-v3.6.0 May 22, 2017
@jmkiley jmkiley deleted the extrusions-example branch May 22, 2017 17:45
@1ec5 1ec5 changed the title [do not merge] Extrusions example Extrusions example May 22, 2017
jmkiley added a commit that referenced this pull request May 24, 2017
jmkiley added a commit that referenced this pull request Jun 29, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants