summaryrefslogtreecommitdiff
path: root/platform/darwin
diff options
context:
space:
mode:
authorTobrun <tobrun@mapbox.com>2017-06-02 23:41:14 +0200
committerGitHub <noreply@github.com>2017-06-02 23:41:14 +0200
commit2d039d3c6b0f62a7545563f7ef4e966aed8ba410 (patch)
tree353d2106c561c3329886691334a953d4b450840d /platform/darwin
parente82649139b69a4794b944b4a61822dd82a4d6abc (diff)
downloadqtlocation-mapboxgl-2d039d3c6b0f62a7545563f7ef4e966aed8ba410.tar.gz
Merge release-ios-v3.6.0-android-v5.1.0 to master (#9170)
* [android] Update release script to support CircleCI builds (#8950) * update release script to trigger builds on circleci now * update release script to trigger builds on circleci now * [core] When a layer is added, reload its source's tiles * [android] - keep observer when timeout occurs, make observer param nullable, fixup log messages (#8919) * [android] - avoid crashing when deleting already deleted region (#8920) * [android] - update LOST to 2.3.0 (#8872) * [android] - update proguard config, allow debug mimification, update OkHttp to latest version (#8944) * [core, android, ios, macos, qt] v10 default styles Upgraded from v9 default styles to v10 wherever the developer expects to get the latest and greatest, as well as in a couple tests where it may be beneficial to ensure that we can handle a two-digit version number in the style URL. Cherry-picked from ed54849e9909e7f7cd8724b39b2bc94f16cf9a11. * [ios, macos] Updated documented default style version MGLStyleDefaultVersion is just for Streets now. Deleted style version documentation tests because not all styles are on the same version. Cherry-picked from ca97dd8cf4c70a5ed380c99700749fd3239715f0. * [ios, macos] Undeprecated unversioned style URL factory methods Undeprecated the unversioned style URL factory methods in MGLStyle for consistency with the Android and Qt SDKs. Added warnings about using them with the runtime styling API. Refactored mbgl::util::default_styles to track different versions for different styles. Cherry-picked from 9e384b78fbcf46d66d390122eefdf273f91b314e. * [core, android, ios, macos] Added Traffic Day/Night to default styles The Styles API section of the Mapbox API Documentation site now lists Traffic Day v2 and Traffic Night v2, so this change adds those styles to all the places where styles are listed. Also switched iosapp and macosapp to unversioned style factory methods since MGLStyleDefaultVersion is no longer applicable for all styles. Cherry-picked from 4d6f54553d277c0af24a0b8ff03d2dd7e9284ca2. * [android] Release android-v5.1.0-beta.2 (#8976) * [android] url getter on sources * [android] fix ui test filter in makefile * [android] - build SNAPSHOT from release branch (#8958) * [android] - update changelog for 5.1.0-beta.2 * [android] - bump version number * [android] - Camera change listener v2.0 * [core] allow filesource url transform reset * [android] Update attribution wordmark (#8774) * Update wordmark on android * Moved attribution i icon to the right of mapbox word (in mapview preview image) * update padding and margin * [android] update hardcoded branch name * revert version to 5.1.0-SNAPSHOT * [android] - MarkerView deselect events with OnMarkerViewClickListener integration (#8996) * [android] - publish SNAPSHOT from release 5.1.0 branch (#8995) * [ios, macos] edited identity interpolation mode documentation (#8657) * [ios, macos] Factored out tile URL template guide Factored out redundant tile URL template documentation from the MGLRasterSource and MGLVectorSource documentation into a jazzy guide. This documentation used to live in one place, on a method on MGLTileSource, but that method had to be moved to MGLTileSource’s concrete subclasses. A jazzy guide is easier to link to, in any case. * [ios] Telemetry button in modal view controllers (#9027) Fixes #8980. * [android] - bump tools and support lib version due to SNAPSHOT dependencies (#9046) * [android] - bump tools and support lib version for SNAPSHOT dependencies * revert unsupported Circle CI build tools version * [core] Make destructor virtual to avoid object splicing during destruction * [core] add error for non-virtual destructor deletes + add virtual dtors * [android] - remove marker from selected markers when removing marker from annotation manager. (#9047) * Observe layout guides (#7716) * [ios] observe layout guides * [ios] update changelog * [ios, macos] Change == to = in style function initializers * [ios] Add annotation view initializer with annotation and reuse id (#9029) * [ios] Remove annotation view from container view when annotation removed (#9025) The annotation container view keeps an array of annotation views that is separate from the array of subviews that is a property of the UIView parent class. This removes an annotation view from that container view array when the associated annotation is removed. This avoids issue related to previously removed annotation views continuing to be involved in map view logic around annotation view selection due to taps. * [android] - correct bearing conversion when animating the map with jumpTo, easeTo and animateTo. (#9050) * [ios, macos] Updated `maximumZoomLevel` description, cherry-picked #8818 (#8842) Cherry-picked from a3e4e67ea68c455178d5c5ef3d864972fcf41147. * [ios] Updated podspecs and changelog for v3.5.3 (#8870) Cherry-picked from 25c19902a22e240da4e7ebf1974125b7e67bd21e. * [ios] Update podspecs and changelog for iOS v3.5.4 Cherry-picked from db7bb509e95d737199efa73a47bdcc973966ed97. * [ios, macos] Updated changelogs * [ios, macos] changed TRUE -> 'true' (#9059) fixes #9056 * [ios, macos] Light property implementation in MGLStyle (#9043) * [ios, macos] Add MGLLight to MGLStyle * [ios, macos] Implement Objc bindings for Light object * [ios, macos] Remove rawLight from MGLLight and re-implement it as value class * [ios, macos] Fix build on macos * [ios, macos] Add MGLLight documentation, Move MGLLightPosition to MGLLight * [ios, macos] Add MGLLight tests. * [ios, macos] Update changelogs * [ios, macos] Fix misspelling * [ios, macos] Fix MGLLightAnchor enum property names * [ios, macos] Update documentation. Improve varialble naming. * [ios, macos] Rename MGLLightPosition to MGLSphericalPosition * [ios, macos] Update data types of MGLSphericalPosition * [android] - horizontally rotated in snapshot (#9083) * Cherry-pick arabic text to release branch v3.6.0 (#9071) * [core] Throttle tiles to redo symbol placement at most once every 300ms. Fixes issue #8435 and prepares for pitch-scaling changes in issue #8967. * [core] Disable letter-spacing for Arabic labels (issue #9057) * [ios,macos] multipolygon coordinate (#8713) * [ios] MGLMultiPolygon's coordinate property implemented * [ios,macos] Add polylabalel to project config * [ios,macos] Change coordinate property for MGLPolyline,MGLPolygon,MGLMultiPolygon * [macos] Change project configuration to support polilabel * [ios,macos] Add MGLLocationCoordinate2DFromPoint * [ios, macos] Update changelogs * [ios, macos] remove unnecesary variables * [ios, macos] Add radians conversions * [ios, macos] Add coordinate calc to MGLPolyline * [ios, macos] Move radian fuctions to MGLGeometry_Private.h * [ios, macos] Fix code style * [ios, macos] Fix code indentation * [ios, macos] Fix radian per meters constant * [ios, macos] Add test scenarios to testPolyline * [ios, macos] Fix test accuracy * [ios, macos] More robust Streets localization Added Arabic, Portuguese, and Simplified Chinese to the list of languages with specialized fields in the Mapbox Streets source. Rely on NSBundle to select the most appropriate locale based on the user’s preferred languages. * [ios] Fallback to Mapbox.bundle as the framework bundle (#9074) Fixes an issue where localizations could not be found when using static builds. Throws exception if our bundle can't be found. * [ios] Move image resources to an asset catalog & switch to PDFs * [ios, macos] Updated changelogs Reorganized the changelogs with a new packaging section. Added blurbs about #9062, #8713, #9060, and #9031. * [ios] Update pods spec for iOS v3.6.0-beta.1 * [macos] Enable View ‣ Traffic Night Enable the View ‣ Traffic Night menu item and check it when that style is active. * [android] - stop location updates when toggle MyLocationView state (#9099) * [android] - LatLngBounds bearing default value (#9102) * [ios, macos] Fix MGLLight.achor to accept style functions * [ios] Fix annotation initializers for subclasses of MGLAnnotationView (#9104) Use a common init function in both of the provided initializers so that subclasses of `MGLAnnotationView` written in Swift don't need to override `init(annotation, reuseIdentifier)` * [ios] Moved `MGLLight` in jazzy table of contents (#9111) * [android] - logo placement for creating a Mapview programatically (#9094) * [android] - Correct logo placement for creating a Mapview programatically, fixup non default placements * Fixed NIGHTY_TWO_DP typo to NINETY_TWO_DP * [android] - add binding support for Light (#9013) * [android] Update Lost to final version 3.0.0 (#9112) * update lost to final version 3.0.0 * bump MAS version to 2.1.1 * [android] - convert dp to pixels when getting meters per pixel at. (#9048) * Release Android v5.1.0-beta.3 (#9115) * [android] - Changelog update for Android release v5.1.0-beta.3 * update CI & version * reset release properties * [android] - harden orientation changes (#9128) * [ios] Remove filter of single metric event * [ios] remove layout guide observers * Migrate to GL JS–powered feedback form (#9078) * [ios, macos] Updated feedback URL * [ios, macos] Add referrer, heading, pitch to feedback URL * [ios, macos] Updated changelogs for feedback changes * [ios] Vary referrer by platform * [android] - javadoc update for 5.1.0 release (#9138) * [android] - javadoc update for 5.1.0 release * oxford comma * Grammar/spelling tweaks * grammar tweak * grammar tweak * Grammar tweaks * Grammar tweaks * [android] fix missing access token variable issue (#9151) * [ios] Update pods spec for iOS v3.6.0-beta.2 * [android] Cherry picking 9133 (#9145) * [android] Fix tracking mode + camera race condition (#9133) * [android] fix tracking mode + camera race condition * fix resetTrackingModesIfRequired bug (comparing current camera position with target camera position * cherry pick #9133 and update CHANGELOG * add null check to prevent null pointer exception * add null check in custom location engine activity to prevent null pointer exception (#9159) * [core] Make TransformState LatLngBounds optional * [ios] Make annotation view rotation alignment configurable (#9147) This commit adds `rotatesWithMap` property on `MGLAnnotationView`. This property, when set to `YES` fixes the annotation to a map such that view follows map's rotation angle. This is useful when user wants to display rotation-dependent annotations (e.g. sector lights). * [android] - validate if gestures should execute (#9173)
Diffstat (limited to 'platform/darwin')
-rw-r--r--platform/darwin/docs/guides/Tile URL Templates.md.ejs109
-rw-r--r--platform/darwin/scripts/generate-style-code.js13
-rw-r--r--platform/darwin/src/MGLAttributionInfo.mm31
-rw-r--r--platform/darwin/src/MGLAttributionInfo_Private.h18
-rw-r--r--platform/darwin/src/MGLFillExtrusionStyleLayer.h2
-rw-r--r--platform/darwin/src/MGLGeometry_Private.h64
-rw-r--r--platform/darwin/src/MGLLight.h125
-rw-r--r--platform/darwin/src/MGLLight.mm113
-rw-r--r--platform/darwin/src/MGLLight_Private.h23
-rw-r--r--platform/darwin/src/MGLOfflineStorage.mm14
-rw-r--r--platform/darwin/src/MGLPolygon.mm20
-rw-r--r--platform/darwin/src/MGLPolyline.mm65
-rw-r--r--platform/darwin/src/MGLRasterSource.h91
-rw-r--r--platform/darwin/src/MGLStyle.h9
-rw-r--r--platform/darwin/src/MGLStyle.mm17
-rw-r--r--platform/darwin/src/MGLStyleValue.h6
-rw-r--r--platform/darwin/src/MGLStyleValue.mm6
-rw-r--r--platform/darwin/src/MGLStyleValue_Private.h14
-rw-r--r--platform/darwin/src/MGLTypes.h1
-rw-r--r--platform/darwin/src/MGLVectorSource.h91
-rw-r--r--platform/darwin/src/NSBundle+MGLAdditions.h4
-rw-r--r--platform/darwin/src/NSBundle+MGLAdditions.m33
-rw-r--r--platform/darwin/src/NSValue+MGLAdditions.h29
-rw-r--r--platform/darwin/src/NSValue+MGLAdditions.m23
-rw-r--r--platform/darwin/src/NSValue+MGLStyleAttributeAdditions.h1
-rw-r--r--platform/darwin/src/NSValue+MGLStyleAttributeAdditions.mm15
-rw-r--r--platform/darwin/test/MGLAttributionInfoTests.m12
-rw-r--r--platform/darwin/test/MGLCodingTests.m119
-rw-r--r--platform/darwin/test/MGLDocumentationExampleTests.swift2
-rw-r--r--platform/darwin/test/MGLLightTest.mm217
30 files changed, 1064 insertions, 223 deletions
diff --git a/platform/darwin/docs/guides/Tile URL Templates.md.ejs b/platform/darwin/docs/guides/Tile URL Templates.md.ejs
new file mode 100644
index 0000000000..78fb297138
--- /dev/null
+++ b/platform/darwin/docs/guides/Tile URL Templates.md.ejs
@@ -0,0 +1,109 @@
+<%
+ const os = locals.os;
+ const iOS = os === 'iOS';
+ //const macOS = os === 'macOS';
+ //const cocoaPrefix = iOS ? 'UI' : 'NS';
+-%>
+<!--
+ This file is generated.
+ Edit platform/darwin/scripts/generate-style-code.js, then run `make darwin-style-code`.
+-->
+# Tile URL Templates
+
+`MGLTileSource` objects, specifically `MGLRasterSource` and `MGLVectorSource`
+objects, can be created using an initializer that accepts an array of tile URL
+templates. Tile URL templates are strings that specify the URLs of the vector
+tiles or raster tile images to load. A template resembles an absolute URL, but
+with any number of placeholder strings that the source evaluates based on the
+tile it needs to load. For example:
+
+* `http://www.example.com/tiles/{z}/{x}/{y}.pbf` could be
+ evaluated as `http://www.example.com/tiles/14/6/9.pbf`.
+* `http://www.example.com/tiles/{z}/{x}/{y}{ratio}.png` could be
+ evaluated as `http://www.example.com/tiles/14/6/9@2x.png`.
+
+Tile URL templates are also used to define tilesets in TileJSON manifests or
+[`raster`](https://www.mapbox.com/mapbox-gl-js/style-spec/#sources-raster-tiles)
+and
+[`vector`](https://www.mapbox.com/mapbox-gl-js/style-spec/#sources-vector-tiles)
+sources in style JSON files. See the
+[TileJSON specification](https://github.com/mapbox/tilejson-spec/tree/master/2.2.0)
+for information about tile URL templates in the context of a TileJSON or style
+JSON file.
+
+Tile sources support the following placeholder strings in tile URL templates,
+all of which are optional:
+
+<table>
+<thead>
+<tr><th>Placeholder string</th><th>Description</th></tr>
+</thead>
+<tbody>
+<tr>
+ <td><code>{x}</code></td>
+ <td>The index of the tile along the map’s x axis according to Spherical
+ Mercator projection. If the value is 0, the tile’s left edge corresponds
+ to the 180th meridian west. If the value is 2<sup><var>z</var></sup>−1,
+ the tile’s right edge corresponds to the 180th meridian east.</td>
+</tr>
+<tr>
+ <td><code>{y}</code></td>
+ <td>The index of the tile along the map’s y axis according to Spherical
+ Mercator projection. If the value is 0, the tile’s tile edge corresponds
+ to arctan(sinh(π)), or approximately 85.0511 degrees north. If the value
+ is 2<sup><var>z</var></sup>−1, the tile’s bottom edge corresponds to
+ −arctan(sinh(π)), or approximately 85.0511 degrees south. The y axis is
+ inverted if the <code>options</code> parameter contains
+ <code>MGLTileSourceOptionTileCoordinateSystem</code> with a value of
+ <code>MGLTileCoordinateSystemTMS</code>.</td>
+</tr>
+<tr>
+ <td><code>{z}</code></td>
+ <td>The tile’s zoom level. At zoom level 0, each tile covers the entire
+ world map; at zoom level 1, it covers ¼ of the world; at zoom level 2,
+ <sup>1</sup>⁄<sub>16</sub> of the world, and so on. For tiles loaded by
+ a <code>MGLRasterSource</code> object, whether the tile zoom level
+ matches the map’s current zoom level depends on the value of the
+ source’s tile size as specified in the
+ <code>MGLTileSourceOptionTileSize</code> key of the <code>options</code>
+ parameter.</td>
+</tr>
+<tr>
+ <td><code>{bbox-epsg-3857}</code></td>
+ <td>The tile’s bounding box, expressed as a comma-separated list of the
+ tile’s western, southern, eastern, and northern extents according to
+ Spherical Mercator (EPSG:3857) projection. The bounding box is typically
+ used with map services conforming to the
+ <a href="http://www.opengeospatial.org/standards/wms">Web Map Service</a>
+ protocol.</td>
+</tr>
+<tr>
+ <td><code>{quadkey}</code></td>
+ <td>A quadkey indicating both the tile’s location and its zoom level. The
+ quadkey is typically used with
+ <a href="https://msdn.microsoft.com/en-us/library/bb259689.aspx">Bing Maps</a>.
+ </td>
+</tr>
+<tr>
+ <td><code>{ratio}</code></td>
+ <td>A suffix indicating the resolution of the tile image. The suffix is the
+ empty string for standard resolution displays and <code>@2x</code> for
+<% if (iOS) { -%>
+ Retina displays, including displays for which <code>UIScreen.scale</code>
+ is 3.
+<% } else { -%>
+ Retina displays.
+<% } -%>
+ </td>
+</tr>
+<tr>
+ <td><code>{prefix}</code></td>
+ <td>Two hexadecimal digits chosen such that each visible tile has a
+ different prefix. The prefix is typically used for domain sharding.</td>
+</tr>
+</tbody>
+</table>
+
+For more information about the `{x}`, `{y}`, and `{z}` placeholder strings,
+consult the
+[OpenStreetMap Wiki](https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames).
diff --git a/platform/darwin/scripts/generate-style-code.js b/platform/darwin/scripts/generate-style-code.js
index 330a8f1d03..7efc8d441c 100644
--- a/platform/darwin/scripts/generate-style-code.js
+++ b/platform/darwin/scripts/generate-style-code.js
@@ -522,8 +522,9 @@ global.setSourceLayer = function() {
const layerH = ejs.compile(fs.readFileSync('platform/darwin/src/MGLStyleLayer.h.ejs', 'utf8'), { strict: true });
const layerM = ejs.compile(fs.readFileSync('platform/darwin/src/MGLStyleLayer.mm.ejs', 'utf8'), { strict: true});
const testLayers = ejs.compile(fs.readFileSync('platform/darwin/test/MGLStyleLayerTests.mm.ejs', 'utf8'), { strict: true});
-const guideMD = ejs.compile(fs.readFileSync('platform/darwin/docs/guides/For Style Authors.md.ejs', 'utf8'), { strict: true });
+const forStyleAuthorsMD = ejs.compile(fs.readFileSync('platform/darwin/docs/guides/For Style Authors.md.ejs', 'utf8'), { strict: true });
const ddsGuideMD = ejs.compile(fs.readFileSync('platform/darwin/docs/guides/Using Style Functions at Runtime.md.ejs', 'utf8'), { strict: true });
+const templatesMD = ejs.compile(fs.readFileSync('platform/darwin/docs/guides/Tile URL Templates.md.ejs', 'utf8'), { strict: true });
const layers = _(spec.layer.type.values).map((value, layerType) => {
const layoutProperties = Object.keys(spec[`layout_${layerType}`]).reduce((memo, name) => {
@@ -635,12 +636,12 @@ global.guideExample = function (guide, exampleId, os) {
return '```swift\n' + example + '\n```';
};
-fs.writeFileSync(`platform/ios/docs/guides/For Style Authors.md`, guideMD({
+fs.writeFileSync(`platform/ios/docs/guides/For Style Authors.md`, forStyleAuthorsMD({
os: 'iOS',
renamedProperties: renamedPropertiesByLayerType,
layers: layers,
}));
-fs.writeFileSync(`platform/macos/docs/guides/For Style Authors.md`, guideMD({
+fs.writeFileSync(`platform/macos/docs/guides/For Style Authors.md`, forStyleAuthorsMD({
os: 'macOS',
renamedProperties: renamedPropertiesByLayerType,
layers: layers,
@@ -651,3 +652,9 @@ fs.writeFileSync(`platform/ios/docs/guides/Using Style Functions at Runtime.md`,
fs.writeFileSync(`platform/macos/docs/guides/Using Style Functions at Runtime.md`, ddsGuideMD({
os: 'macOS',
}));
+fs.writeFileSync(`platform/ios/docs/guides/Tile URL Templates.md`, templatesMD({
+ os: 'iOS',
+}));
+fs.writeFileSync(`platform/macos/docs/guides/Tile URL Templates.md`, templatesMD({
+ os: 'macOS',
+}));
diff --git a/platform/darwin/src/MGLAttributionInfo.mm b/platform/darwin/src/MGLAttributionInfo.mm
index 7583244491..770aeb25e7 100644
--- a/platform/darwin/src/MGLAttributionInfo.mm
+++ b/platform/darwin/src/MGLAttributionInfo.mm
@@ -6,8 +6,10 @@
#import <Cocoa/Cocoa.h>
#endif
+#import "MGLAccountManager.h"
#import "MGLMapCamera.h"
#import "NSArray+MGLAdditions.h"
+#import "NSBundle+MGLAdditions.h"
#import "NSString+MGLAdditions.h"
#include <string>
@@ -126,13 +128,34 @@
}
- (nullable NSURL *)feedbackURLAtCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate zoomLevel:(double)zoomLevel {
+ return [self feedbackURLForStyleURL:nil atCenterCoordinate:centerCoordinate zoomLevel:zoomLevel direction:0 pitch:0];
+}
+
+- (nullable NSURL *)feedbackURLForStyleURL:(nullable NSURL *)styleURL atCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate zoomLevel:(double)zoomLevel direction:(CLLocationDirection)direction pitch:(CGFloat)pitch {
if (!self.feedbackLink) {
return nil;
}
-
- NSURLComponents *components = [NSURLComponents componentsWithURL:self.URL resolvingAgainstBaseURL:NO];
- components.fragment = [NSString stringWithFormat:@"/%.5f/%.5f/%i",
- centerCoordinate.longitude, centerCoordinate.latitude, (int)round(zoomLevel + 1)];
+
+ NSURLComponents *components = [NSURLComponents componentsWithString:@"https://www.mapbox.com/feedback/"];
+ components.fragment = [NSString stringWithFormat:@"/%.5f/%.5f/%.2f/%.1f/%i",
+ centerCoordinate.longitude, centerCoordinate.latitude, zoomLevel,
+ direction, (int)round(pitch)];
+
+ NSURLQueryItem *referrerQueryItem = [NSURLQueryItem queryItemWithName:@"referrer"
+ value:[NSBundle mgl_applicationBundleIdentifier]];
+ NSMutableArray<NSURLQueryItem *> *queryItems = [NSMutableArray arrayWithObject:referrerQueryItem];
+ if ([styleURL.scheme isEqualToString:@"mapbox"] && [styleURL.host isEqualToString:@"styles"]) {
+ NSArray<NSString *> *stylePathComponents = styleURL.pathComponents;
+ if (stylePathComponents.count >= 3) {
+ [queryItems addObjectsFromArray:@[
+ [NSURLQueryItem queryItemWithName:@"owner" value:stylePathComponents[1]],
+ [NSURLQueryItem queryItemWithName:@"id" value:stylePathComponents[2]],
+ [NSURLQueryItem queryItemWithName:@"access_token" value:[MGLAccountManager accessToken]],
+ ]];
+ }
+ }
+ components.queryItems = queryItems;
+
return components.URL;
}
diff --git a/platform/darwin/src/MGLAttributionInfo_Private.h b/platform/darwin/src/MGLAttributionInfo_Private.h
index 08bc6bfc4d..c639752ac3 100644
--- a/platform/darwin/src/MGLAttributionInfo_Private.h
+++ b/platform/darwin/src/MGLAttributionInfo_Private.h
@@ -20,6 +20,24 @@ NS_ASSUME_NONNULL_BEGIN
+ (NSAttributedString *)attributedStringForAttributionInfos:(NS_ARRAY_OF(MGLAttributionInfo *) *)attributionInfos;
+/**
+ Returns a copy of the `URL` property modified to account for the given style
+ URL, center coordinate, and zoom level.
+
+ @param styleURL The map’s style URL.
+ @param centerCoordinate The map’s center coordinate.
+ @param zoomLevel The map’s zoom level. See the `MGLMapView.zoomLevel` property
+ for more information.
+ @param direction The heading of the map, measured in degrees clockwise from
+ true north.
+ @param pitch Pitch toward the horizon measured in degrees, with 0 degrees
+ resulting in a two-dimensional map.
+ @return A modified URL containing a fragment that points to the specified
+ viewport. If the `feedbackLink` property is set to `NO`, this method returns
+ `nil`.
+ */
+- (nullable NSURL *)feedbackURLForStyleURL:(nullable NSURL *)styleURL atCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate zoomLevel:(double)zoomLevel direction:(CLLocationDirection)direction pitch:(CGFloat)pitch;
+
@end
@interface NSMutableArray (MGLAttributionInfoAdditions)
diff --git a/platform/darwin/src/MGLFillExtrusionStyleLayer.h b/platform/darwin/src/MGLFillExtrusionStyleLayer.h
index 84f6bedde4..c4fb9aa77e 100644
--- a/platform/darwin/src/MGLFillExtrusionStyleLayer.h
+++ b/platform/darwin/src/MGLFillExtrusionStyleLayer.h
@@ -46,7 +46,7 @@ typedef NS_ENUM(NSUInteger, MGLFillExtrusionTranslationAnchor) {
layer.sourceLayerIdentifier = "building"
layer.fillExtrusionHeight = MGLStyleValue(interpolationMode: .identity, sourceStops: nil, attributeName: "height", options: nil)
layer.fillExtrusionBase = MGLStyleValue(interpolationMode: .identity, sourceStops: nil, attributeName: "min_height", options: nil)
- layer.predicate = NSPredicate(format: "extrude == TRUE")
+ layer.predicate = NSPredicate(format: "extrude == 'true'")
mapView.style?.addLayer(layer)
```
*/
diff --git a/platform/darwin/src/MGLGeometry_Private.h b/platform/darwin/src/MGLGeometry_Private.h
index 3e029e8ee0..7ad8314a79 100644
--- a/platform/darwin/src/MGLGeometry_Private.h
+++ b/platform/darwin/src/MGLGeometry_Private.h
@@ -8,6 +8,26 @@
#import <mbgl/util/geo.hpp>
#import <mbgl/util/geometry.hpp>
+typedef double MGLLocationRadians;
+typedef double MGLRadianDistance;
+typedef double MGLRadianDirection;
+
+/** Defines the coordinate by a `MGLRadianCoordinate2D`. */
+typedef struct MGLRadianCoordinate2D {
+ MGLLocationRadians latitude;
+ MGLLocationRadians longitude;
+} MGLRadianCoordinate2D;
+
+/**
+ Creates a new `MGLRadianCoordinate2D` from the given latitudinal and longitudinal.
+ */
+NS_INLINE MGLRadianCoordinate2D MGLRadianCoordinate2DMake(MGLLocationRadians latitude, MGLLocationRadians longitude) {
+ MGLRadianCoordinate2D radianCoordinate;
+ radianCoordinate.latitude = latitude;
+ radianCoordinate.longitude = longitude;
+ return radianCoordinate;
+}
+
/// Returns the smallest rectangle that contains both the given rectangle and
/// the given point.
CGRect MGLExtendRect(CGRect rect, CGPoint point);
@@ -18,6 +38,10 @@ NS_INLINE mbgl::Point<double> MGLPointFromLocationCoordinate2D(CLLocationCoordin
return mbgl::Point<double>(coordinate.longitude, coordinate.latitude);
}
+NS_INLINE CLLocationCoordinate2D MGLLocationCoordinate2DFromPoint(mbgl::Point<double> point) {
+ return CLLocationCoordinate2DMake(point.y, point.x);
+}
+
NS_INLINE CLLocationCoordinate2D MGLLocationCoordinate2DFromLatLng(mbgl::LatLng latLng) {
return CLLocationCoordinate2DMake(latLng.latitude(), latLng.longitude());
}
@@ -59,3 +83,43 @@ CLLocationDistance MGLAltitudeForZoomLevel(double zoomLevel, CGFloat pitch, CLLo
@param size The size of the viewport.
@return A zero-based zoom level. */
double MGLZoomLevelForAltitude(CLLocationDistance altitude, CGFloat pitch, CLLocationDegrees latitude, CGSize size);
+
+/** Returns MGLRadianCoordinate2D, converted from CLLocationCoordinate2D. */
+NS_INLINE MGLRadianCoordinate2D MGLRadianCoordinateFromLocationCoordinate(CLLocationCoordinate2D locationCoordinate) {
+ return MGLRadianCoordinate2DMake(MGLRadiansFromDegrees(locationCoordinate.latitude),
+ MGLRadiansFromDegrees(locationCoordinate.longitude));
+}
+
+/*
+ Returns the distance in radians given two coordinates.
+ */
+NS_INLINE MGLRadianDistance MGLDistanceBetweenRadianCoordinates(MGLRadianCoordinate2D from, MGLRadianCoordinate2D to)
+{
+ double a = pow(sin((to.latitude - from.latitude) / 2), 2)
+ + pow(sin((to.longitude - from.longitude) / 2), 2) * cos(from.latitude) * cos(to.latitude);
+
+ return 2 * atan2(sqrt(a), sqrt(1 - a));
+}
+
+/*
+ Returns direction in radians given two coordinates.
+ */
+NS_INLINE MGLRadianDirection MGLRadianCoordinatesDirection(MGLRadianCoordinate2D from, MGLRadianCoordinate2D to) {
+ double a = sin(to.longitude - from.longitude) * cos(to.latitude);
+ double b = cos(from.latitude) * sin(to.latitude)
+ - sin(from.latitude) * cos(to.latitude) * cos(to.longitude - from.longitude);
+ return atan2(a, b);
+}
+
+/*
+ Returns coordinate at a given distance and direction away from coordinate.
+ */
+NS_INLINE MGLRadianCoordinate2D MGLRadianCoordinateAtDistanceFacingDirection(MGLRadianCoordinate2D coordinate,
+ MGLRadianDistance distance,
+ MGLRadianDirection direction) {
+ double otherLatitude = asin(sin(coordinate.latitude) * cos(distance)
+ + cos(coordinate.latitude) * sin(distance) * cos(direction));
+ double otherLongitude = coordinate.longitude + atan2(sin(direction) * sin(distance) * cos(coordinate.latitude),
+ cos(distance) - sin(coordinate.latitude) * sin(otherLatitude));
+ return MGLRadianCoordinate2DMake(otherLatitude, otherLongitude);
+}
diff --git a/platform/darwin/src/MGLLight.h b/platform/darwin/src/MGLLight.h
new file mode 100644
index 0000000000..ef9811bd33
--- /dev/null
+++ b/platform/darwin/src/MGLLight.h
@@ -0,0 +1,125 @@
+#import <CoreLocation/CoreLocation.h>
+
+#import "MGLFoundation.h"
+#import "MGLStyleValue.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+
+/** Options to specify extruded geometries are lit relative to the map or viewport. */
+typedef NS_ENUM(NSUInteger, MGLLightAnchor) {
+ /** The position of the light source is aligned to the rotation of the map. */
+ MGLLightAnchorMap,
+ /** The position of the light source is aligned to the rotation of the viewport. */
+ MGLLightAnchorViewport
+};
+
+/**
+ A structure containing information about the position of the light source
+ relative to lit geometries.
+ */
+typedef struct MGLSphericalPosition {
+ /** Distance from the center of the base of an object to its light. */
+ CLLocationDistance radial;
+ /** Position of the light relative to 0° (0° when `MGLLight.anchor` is set to viewport corresponds
+ to the top of the viewport, or 0° when `MGLLight.anchor` is set to map corresponds to due north,
+ and degrees proceed clockwise). */
+ CLLocationDirection azimuthal;
+ /** Indicates the height of the light (from 0°, directly above, to 180°, directly below). */
+ CLLocationDirection polar;
+} MGLSphericalPosition;
+
+/**
+ Creates a new `MGLSphericalPosition` from the given radial, azimuthal, polar.
+
+ @param radial The radial coordinate.
+ @param azimuthal The azimuthal angle.
+ @param polar The polar angle.
+
+ @return Returns a `MGLSphericalPosition` struct containing the position attributes.
+ */
+NS_INLINE MGLSphericalPosition MGLSphericalPositionMake(CLLocationDistance radial, CLLocationDirection azimuthal, CLLocationDirection polar) {
+ MGLSphericalPosition position;
+ position.radial = radial;
+ position.azimuthal = azimuthal;
+ position.polar = polar;
+
+ return position;
+}
+
+/**
+ An `MGLLight` object represents the light source for extruded geometries in `MGLStyle`.
+ */
+MGL_EXPORT
+@interface MGLLight : NSObject
+
+/**
+ `anchor` Whether extruded geometries are lit relative to the map or viewport.
+
+ This property corresponds to the <a
+ href="https://www.mapbox.com/mapbox-gl-js/style-spec/#light-anchor"><code>anchor</code></a>
+ light property in the Mapbox Style Specification.
+ */
+@property (nonatomic) MGLStyleValue<NSValue *> *anchor;
+
+/**
+ Values describing animated transitions to `anchor` property.
+ */
+@property (nonatomic) MGLTransition anchorTransition;
+
+
+/**
+ Position of the light source relative to lit (extruded) geometries.
+
+ This property corresponds to the <a
+ href="https://www.mapbox.com/mapbox-gl-js/style-spec/#light-position"><code>position</code></a>
+ light property in the Mapbox Style Specification.
+ */
+@property (nonatomic) MGLStyleValue<NSValue *> *position;
+
+/**
+ Values describing animated transitions to `position` property.
+ */
+@property (nonatomic) MGLTransition positionTransiton;
+
+
+#if TARGET_OS_IPHONE
+/**
+ Color tint for lighting extruded geometries.
+
+ This property corresponds to the <a
+ href="https://www.mapbox.com/mapbox-gl-js/style-spec/#light-color"><code>color</code></a>
+ light property in the Mapbox Style Specification.
+ */
+@property (nonatomic) MGLStyleValue<UIColor *> *color;
+#else
+
+/**
+ Color tint for lighting extruded geometries.
+ */
+@property (nonatomic) MGLStyleValue<NSColor *> *color;
+#endif
+
+/**
+ Values describing animated transitions to `color` property.
+ */
+@property (nonatomic) MGLTransition colorTransiton;
+
+
+/**
+ Intensity of lighting (on a scale from 0 to 1). Higher numbers will present as more extreme contrast.
+
+ This property corresponds to the <a
+ href="https://www.mapbox.com/mapbox-gl-js/style-spec/#light-intensity"><code>intensity</code></a>
+ light property in the Mapbox Style Specification.
+ */
+@property(nonatomic) MGLStyleValue<NSNumber *> *intensity;
+
+/**
+ Values describing animated transitions to `intensity` property.
+ */
+@property (nonatomic) MGLTransition intensityTransition;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/platform/darwin/src/MGLLight.mm b/platform/darwin/src/MGLLight.mm
new file mode 100644
index 0000000000..262fad3b07
--- /dev/null
+++ b/platform/darwin/src/MGLLight.mm
@@ -0,0 +1,113 @@
+#import "MGLLight.h"
+
+#import "MGLTypes.h"
+#import "NSDate+MGLAdditions.h"
+#import "MGLStyleValue_Private.h"
+#import "NSValue+MGLAdditions.h"
+
+#import <mbgl/style/light.hpp>
+#import <mbgl/style/types.hpp>
+
+namespace mbgl {
+
+ MBGL_DEFINE_ENUM(MGLLightAnchor, {
+ { MGLLightAnchorMap, "map" },
+ { MGLLightAnchorViewport, "viewport" },
+ });
+
+}
+
+NS_INLINE MGLTransition MGLTransitionFromOptions(const mbgl::style::TransitionOptions& options) {
+ MGLTransition transition;
+ transition.duration = MGLTimeIntervalFromDuration(options.duration.value_or(mbgl::Duration::zero()));
+ transition.delay = MGLTimeIntervalFromDuration(options.delay.value_or(mbgl::Duration::zero()));
+
+ return transition;
+}
+
+NS_INLINE mbgl::style::TransitionOptions MGLOptionsFromTransition(MGLTransition transition) {
+ mbgl::style::TransitionOptions options { { MGLDurationFromTimeInterval(transition.duration) }, { MGLDurationFromTimeInterval(transition.delay) } };
+ return options;
+}
+
+@interface MGLLight()
+
+@end
+
+@implementation MGLLight
+
+- (instancetype)initWithMBGLLight:(const mbgl::style::Light *)mbglLight
+{
+ if (self = [super init]) {
+ auto anchor = mbglLight->getAnchor();
+ MGLStyleValue<NSValue *> *anchorStyleValue;
+ if (anchor.isUndefined()) {
+ mbgl::style::PropertyValue<mbgl::style::LightAnchorType> defaultAnchor = mbglLight->getDefaultAnchor();
+ anchorStyleValue = MGLStyleValueTransformer<mbgl::style::LightAnchorType, NSValue *, mbgl::style::LightAnchorType, MGLLightAnchor>().toEnumStyleValue(defaultAnchor);
+ } else {
+ anchorStyleValue = MGLStyleValueTransformer<mbgl::style::LightAnchorType, NSValue *, mbgl::style::LightAnchorType, MGLLightAnchor>().toEnumStyleValue(anchor);
+ }
+
+ _anchor = anchorStyleValue;
+
+ _anchorTransition = MGLTransitionFromOptions(mbglLight->getAnchorTransition());
+
+ auto positionValue = mbglLight->getPosition();
+ if (positionValue.isUndefined()) {
+ _position = MGLStyleValueTransformer<mbgl::style::Position, NSValue *>().toStyleValue(mbglLight->getDefaultPosition());
+ } else {
+ _position = MGLStyleValueTransformer<mbgl::style::Position, NSValue *>().toStyleValue(positionValue);
+ }
+
+ _positionTransiton = MGLTransitionFromOptions(mbglLight->getPositionTransition());
+
+ auto colorValue = mbglLight->getColor();
+ if (colorValue.isUndefined()) {
+ _color = MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toStyleValue(mbglLight->getDefaultColor());
+ } else {
+ _color = MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toStyleValue(colorValue);
+ }
+
+ _colorTransiton = MGLTransitionFromOptions(mbglLight->getColorTransition());
+
+ auto intensityValue = mbglLight->getIntensity();
+ if (intensityValue.isUndefined()) {
+ _intensity = MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(mbglLight->getDefaultIntensity());
+ } else {
+ _intensity = MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(intensityValue);
+ }
+
+ _intensityTransition = MGLTransitionFromOptions(mbglLight->getIntensityTransition());
+ }
+
+ return self;
+}
+
+- (mbgl::style::Light)mbglLight
+{
+ mbgl::style::Light mbglLight;
+
+ auto anchor = MGLStyleValueTransformer<mbgl::style::LightAnchorType, NSValue *, mbgl::style::LightAnchorType, MGLLightAnchor>().toEnumPropertyValue(self.anchor);
+ mbglLight.setAnchor(anchor);
+
+ mbglLight.setAnchorTransition(MGLOptionsFromTransition(self.anchorTransition));
+
+ auto position = MGLStyleValueTransformer<mbgl::style::Position, NSValue *>().toInterpolatablePropertyValue(self.position);
+ mbglLight.setPosition(position);
+
+ mbglLight.setPositionTransition(MGLOptionsFromTransition(self.positionTransiton));
+
+ auto color = MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toInterpolatablePropertyValue(self.color);
+ mbglLight.setColor(color);
+
+ mbglLight.setColorTransition(MGLOptionsFromTransition(self.colorTransiton));
+
+ auto intensity = MGLStyleValueTransformer<float, NSNumber *>().toInterpolatablePropertyValue(self.intensity);
+ mbglLight.setIntensity(intensity);
+
+ mbglLight.setIntensityTransition(MGLOptionsFromTransition(self.intensityTransition));
+
+ return mbglLight;
+}
+
+@end
diff --git a/platform/darwin/src/MGLLight_Private.h b/platform/darwin/src/MGLLight_Private.h
new file mode 100644
index 0000000000..dbc29c1eff
--- /dev/null
+++ b/platform/darwin/src/MGLLight_Private.h
@@ -0,0 +1,23 @@
+#import <Foundation/Foundation.h>
+
+#import "MGLLight.h"
+
+namespace mbgl {
+ namespace style {
+ class Light;
+ }
+}
+
+@interface MGLLight (Private)
+
+/**
+ Initializes and returns a `MGLLight` associated with a style's light.
+ */
+- (instancetype)initWithMBGLLight:(const mbgl::style::Light *)mbglLight;
+
+/**
+ Returns an `mbgl::style::Light` representation of the `MGLLight`.
+ */
+- (mbgl::style::Light)mbglLight;
+
+@end
diff --git a/platform/darwin/src/MGLOfflineStorage.mm b/platform/darwin/src/MGLOfflineStorage.mm
index 195ef3c36a..81774ad3cb 100644
--- a/platform/darwin/src/MGLOfflineStorage.mm
+++ b/platform/darwin/src/MGLOfflineStorage.mm
@@ -7,6 +7,7 @@
#import "MGLOfflinePack_Private.h"
#import "MGLOfflineRegion_Private.h"
#import "MGLTilePyramidOfflineRegion.h"
+#import "NSBundle+MGLAdditions.h"
#import "NSValue+MGLAdditions.h"
#include <mbgl/util/string.hpp>
@@ -132,7 +133,7 @@ NSString * const MGLOfflinePackMaximumCountUserInfoKey = MGLOfflinePackUserInfoK
appropriateForURL:nil
create:YES
error:nil];
- NSString *bundleIdentifier = [self bundleIdentifier];
+ NSString *bundleIdentifier = [NSBundle mgl_applicationBundleIdentifier];
if (!bundleIdentifier) {
// There’s no main bundle identifier when running in a unit test bundle.
bundleIdentifier = [NSBundle bundleForClass:self].bundleIdentifier;
@@ -166,7 +167,7 @@ NSString * const MGLOfflinePackMaximumCountUserInfoKey = MGLOfflinePackUserInfoK
NSString *legacyCachePath = [legacyPaths.firstObject stringByAppendingPathComponent:MGLOfflineStorageFileName3_2_0_beta_1];
#elif TARGET_OS_MAC
// ~/Library/Caches/tld.app.bundle.id/offline.db
- NSString *bundleIdentifier = [self bundleIdentifier];
+ NSString *bundleIdentifier = [NSBundle mgl_applicationBundleIdentifier];
NSURL *legacyCacheDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSCachesDirectory
inDomain:NSUserDomainMask
appropriateForURL:nil
@@ -219,15 +220,6 @@ NSString * const MGLOfflinePackMaximumCountUserInfoKey = MGLOfflinePackUserInfoK
return self;
}
-+ (NSString *)bundleIdentifier {
- NSString *bundleIdentifier = [NSBundle mainBundle].bundleIdentifier;
- if (!bundleIdentifier) {
- // There’s no main bundle identifier when running in a unit test bundle.
- bundleIdentifier = [NSBundle bundleForClass:self].bundleIdentifier;
- }
- return bundleIdentifier;
-}
-
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
[[MGLNetworkConfiguration sharedManager] removeObserver:self forKeyPath:@"apiBaseURL"];
diff --git a/platform/darwin/src/MGLPolygon.mm b/platform/darwin/src/MGLPolygon.mm
index ceafe873bf..d966ff13ce 100644
--- a/platform/darwin/src/MGLPolygon.mm
+++ b/platform/darwin/src/MGLPolygon.mm
@@ -6,6 +6,7 @@
#import "MGLPolygon+MGLAdditions.h"
#import <mbgl/util/geojson.hpp>
+#import <mapbox/polylabel.hpp>
@implementation MGLPolygon
@@ -54,6 +55,13 @@
return [super hash] + [[self geoJSONDictionary] hash];
}
+- (CLLocationCoordinate2D)coordinate {
+ // pole of inaccessibility
+ auto poi = mapbox::polylabel([self polygon]);
+
+ return MGLLocationCoordinate2DFromPoint(poi);
+}
+
- (mbgl::LinearRing<double>)ring {
NSUInteger count = self.pointCount;
CLLocationCoordinate2D *coordinates = self.coordinates;
@@ -155,11 +163,17 @@
return hash;
}
+- (CLLocationCoordinate2D)coordinate {
+ MGLPolygon *firstPolygon = self.polygons.firstObject;
+
+ return firstPolygon.coordinate;
+}
+
- (BOOL)intersectsOverlayBounds:(MGLCoordinateBounds)overlayBounds {
return MGLCoordinateBoundsIntersectsCoordinateBounds(_overlayBounds, overlayBounds);
}
-- (mbgl::Geometry<double>)geometryObject {
+- (mbgl::MultiPolygon<double>)multiPolygon {
mbgl::MultiPolygon<double> multiPolygon;
multiPolygon.reserve(self.polygons.count);
for (MGLPolygon *polygon in self.polygons) {
@@ -173,6 +187,10 @@
return multiPolygon;
}
+- (mbgl::Geometry<double>)geometryObject {
+ return [self multiPolygon];
+}
+
- (NSDictionary *)geoJSONDictionary {
NSMutableArray *coordinates = [[NSMutableArray alloc] initWithCapacity:self.polygons.count];
for (MGLPolygonFeature *feature in self.polygons) {
diff --git a/platform/darwin/src/MGLPolyline.mm b/platform/darwin/src/MGLPolyline.mm
index ae4fbe61de..fd75dc2795 100644
--- a/platform/darwin/src/MGLPolyline.mm
+++ b/platform/darwin/src/MGLPolyline.mm
@@ -6,6 +6,7 @@
#import "MGLPolyline+MGLAdditions.h"
#import <mbgl/util/geojson.hpp>
+#import <mapbox/polylabel.hpp>
@implementation MGLPolyline
@@ -52,6 +53,61 @@
return self == other || ([other isKindOfClass:[MGLPolyline class]] && [super isEqual:other]);
}
+- (CLLocationCoordinate2D)coordinate {
+ NSUInteger count = self.pointCount;
+ NSAssert(count > 0, @"Polyline must have coordinates");
+
+ CLLocationCoordinate2D *coordinates = self.coordinates;
+ CLLocationDistance middle = [self length] / 2.0;
+ CLLocationDistance traveled = 0.0;
+
+ if (count > 1 || middle > traveled) {
+ for (NSUInteger i = 0; i < count; i++) {
+
+ MGLRadianCoordinate2D from = MGLRadianCoordinateFromLocationCoordinate(coordinates[i]);
+ MGLRadianCoordinate2D to = MGLRadianCoordinateFromLocationCoordinate(coordinates[i + 1]);
+
+ if (traveled >= middle) {
+ double overshoot = middle - traveled;
+ if (overshoot == 0) {
+ return coordinates[i];
+ }
+ to = MGLRadianCoordinateFromLocationCoordinate(coordinates[i - 1]);
+ CLLocationDirection direction = [self direction:from to:to] - 180;
+ MGLRadianCoordinate2D otherCoordinate = MGLRadianCoordinateAtDistanceFacingDirection(from,
+ overshoot/mbgl::util::EARTH_RADIUS_M,
+ MGLRadiansFromDegrees(direction));
+ return CLLocationCoordinate2DMake(MGLDegreesFromRadians(otherCoordinate.latitude),
+ MGLDegreesFromRadians(otherCoordinate.longitude));
+ }
+
+ traveled += (MGLDistanceBetweenRadianCoordinates(from, to) * mbgl::util::EARTH_RADIUS_M);
+
+ }
+ }
+
+ return coordinates[count - 1];
+}
+
+- (CLLocationDistance)length
+{
+ CLLocationDistance length = 0.0;
+
+ NSUInteger count = self.pointCount;
+ CLLocationCoordinate2D *coordinates = self.coordinates;
+
+ for (NSUInteger i = 0; i < count - 1; i++) {
+ length += (MGLDistanceBetweenRadianCoordinates(MGLRadianCoordinateFromLocationCoordinate(coordinates[i]), MGLRadianCoordinateFromLocationCoordinate(coordinates[i + 1])) * mbgl::util::EARTH_RADIUS_M);
+ }
+
+ return length;
+}
+
+- (CLLocationDirection)direction:(MGLRadianCoordinate2D)from to:(MGLRadianCoordinate2D)to
+{
+ return MGLDegreesFromRadians(MGLRadianCoordinatesDirection(from, to));
+}
+
@end
@interface MGLMultiPolyline ()
@@ -114,6 +170,15 @@
return hash;
}
+- (CLLocationCoordinate2D)coordinate {
+ MGLPolyline *polyline = self.polylines.firstObject;
+ CLLocationCoordinate2D *coordinates = polyline.coordinates;
+ NSAssert([polyline pointCount] > 0, @"Polyline must have coordinates");
+ CLLocationCoordinate2D firstCoordinate = coordinates[0];
+
+ return firstCoordinate;
+}
+
- (BOOL)intersectsOverlayBounds:(MGLCoordinateBounds)overlayBounds {
return MGLCoordinateBoundsIntersectsCoordinateBounds(_overlayBounds, overlayBounds);
}
diff --git a/platform/darwin/src/MGLRasterSource.h b/platform/darwin/src/MGLRasterSource.h
index 519784f4f1..4f4b7c96c3 100644
--- a/platform/darwin/src/MGLRasterSource.h
+++ b/platform/darwin/src/MGLRasterSource.h
@@ -108,96 +108,13 @@ MGL_EXPORT
Returns a raster source initialized an identifier, tile URL templates, and
options.
+ Tile URL templates are strings that specify the URLs of the raster tile images
+ to load. See the “<a href="../tile-url-templates.html">Tile URL Templates</a>”
+ guide for information about the format of a tile URL template.
+
After initializing and configuring the source, add it to a map view’s style
using the `-[MGLStyle addSource:]` method.
- #### Tile URL templates
-
- Tile URL templates are strings that specify the URLs of the tile images to
- load. Each template resembles an absolute URL, but with any number of
- placeholder strings that the source evaluates based on the tile it needs to
- load. For example:
-
- <ul>
- <li><code>http://www.example.com/tiles/{z}/{x}/{y}.pbf</code> could be
- evaluated as <code>http://www.example.com/tiles/14/6/9.pbf</code>.</li>
- <li><code>http://www.example.com/tiles/{z}/{x}/{y}{ratio}.png</code> could be
- evaluated as <code>http://www.example.com/tiles/14/6/9@2x.png</code>.</li>
- </ul>
-
- Tile sources support the following placeholder strings in tile URL templates,
- all of which are optional:
-
- <table>
- <thead>
- <tr><th>Placeholder string</th><th>Description</th></tr>
- </thead>
- <tbody>
- <tr>
- <td><code>{x}</code></td>
- <td>The index of the tile along the map’s x axis according to Spherical
- Mercator projection. If the value is 0, the tile’s left edge corresponds
- to the 180th meridian west. If the value is 2<sup><var>z</var></sup>−1,
- the tile’s right edge corresponds to the 180th meridian east.</td>
- </tr>
- <tr>
- <td><code>{y}</code></td>
- <td>The index of the tile along the map’s y axis according to Spherical
- Mercator projection. If the value is 0, the tile’s tile edge corresponds
- to arctan(sinh(π)), or approximately 85.0511 degrees north. If the value
- is 2<sup><var>z</var></sup>−1, the tile’s bottom edge corresponds to
- −arctan(sinh(π)), or approximately 85.0511 degrees south. The y axis is
- inverted if the <code>options</code> parameter contains
- <code>MGLTileSourceOptionTileCoordinateSystem</code> with a value of
- <code>MGLTileCoordinateSystemTMS</code>.</td>
- </tr>
- <tr>
- <td><code>{z}</code></td>
- <td>The tile’s zoom level. At zoom level 0, each tile covers the entire
- world map; at zoom level 1, it covers ¼ of the world; at zoom level 2,
- <sup>1</sup>⁄<sub>16</sub> of the world, and so on. For tiles loaded by
- a <code>MGLRasterSource</code> object, whether the tile zoom level
- matches the map’s current zoom level depends on the value of the
- source’s tile size as specified in the
- <code>MGLTileSourceOptionTileSize</code> key of the
- <code>options</code> parameter.</td>
- </tr>
- <tr>
- <td><code>{bbox-epsg-3857}</code></td>
- <td>The tile’s bounding box, expressed as a comma-separated list of the
- tile’s western, southern, eastern, and northern extents according to
- Spherical Mercator (EPSG:3857) projection. The bounding box is typically
- used with map services conforming to the
- <a href="http://www.opengeospatial.org/standards/wms">Web Map Service</a>
- protocol.</td>
- </tr>
- <tr>
- <td><code>{quadkey}</code></td>
- <td>A quadkey indicating both the tile’s location and its zoom level. The
- quadkey is typically used with
- <a href="https://msdn.microsoft.com/en-us/library/bb259689.aspx">Bing Maps</a>.
- </td>
- </tr>
- <tr>
- <td><code>{ratio}</code></td>
- <td>A suffix indicating the resolution of the tile image. The suffix is the
- empty string for standard resolution displays and <code>@2x</code> for
- Retina displays, including displays for which
- <code>NSScreen.backingScaleFactor</code> or <code>UIScreen.scale</code>
- is 3.</td>
- </tr>
- <tr>
- <td><code>{prefix}</code></td>
- <td>Two hexadecimal digits chosen such that each visible tile has a
- different prefix. The prefix is typically used for domain sharding.</td>
- </tr>
- </tbody>
- </table>
-
- For more information about the `{x}`, `{y}`, and `{z}` placeholder strings,
- consult the
- <a href="https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames">OpenStreetMap Wiki</a>.
-
@param identifier A string that uniquely identifies the source in the style to
which it is added.
@param tileURLTemplates An array of tile URL template strings. Only the first
diff --git a/platform/darwin/src/MGLStyle.h b/platform/darwin/src/MGLStyle.h
index ccec863236..6fb4a6cc6b 100644
--- a/platform/darwin/src/MGLStyle.h
+++ b/platform/darwin/src/MGLStyle.h
@@ -6,6 +6,7 @@
#import "MGLTypes.h"
@class MGLSource;
+@class MGLLight;
NS_ASSUME_NONNULL_BEGIN
@@ -548,6 +549,14 @@ MGL_EXPORT
*/
- (void)removeImageForName:(NSString *)name;
+
+#pragma mark Managing the Style's Light
+
+/**
+ Provides global light source for the style.
+ */
+@property (nonatomic, strong) MGLLight *light;
+
@end
NS_ASSUME_NONNULL_END
diff --git a/platform/darwin/src/MGLStyle.mm b/platform/darwin/src/MGLStyle.mm
index 5f26b4fed2..2e6f2bc29a 100644
--- a/platform/darwin/src/MGLStyle.mm
+++ b/platform/darwin/src/MGLStyle.mm
@@ -14,6 +14,7 @@
#import "MGLStyle_Private.h"
#import "MGLStyleLayer_Private.h"
#import "MGLSource_Private.h"
+#import "MGLLight_Private.h"
#import "NSDate+MGLAdditions.h"
@@ -28,6 +29,7 @@
#include <mbgl/map/map.hpp>
#include <mbgl/util/default_styles.hpp>
#include <mbgl/style/image.hpp>
+#include <mbgl/style/light.hpp>
#include <mbgl/style/layers/fill_layer.hpp>
#include <mbgl/style/layers/fill_extrusion_layer.hpp>
#include <mbgl/style/layers/line_layer.hpp>
@@ -556,6 +558,21 @@ static NSURL *MGLStyleURL_emerald;
return transition;
}
+#pragma mark Style light
+
+- (void)setLight:(MGLLight *)light
+{
+ std::unique_ptr<mbgl::style::Light> mbglLight = std::make_unique<mbgl::style::Light>([light mbglLight]);
+ self.mapView.mbglMap->setLight(std::move(mbglLight));
+}
+
+- (MGLLight *)light
+{
+ auto mbglLight = self.mapView.mbglMap->getLight();
+ MGLLight *light = [[MGLLight alloc] initWithMBGLLight:mbglLight];
+ return light;
+}
+
- (NSString *)description
{
return [NSString stringWithFormat:@"<%@: %p; name = %@, URL = %@>",
diff --git a/platform/darwin/src/MGLStyleValue.h b/platform/darwin/src/MGLStyleValue.h
index 70074c8a13..2bb3aca4f4 100644
--- a/platform/darwin/src/MGLStyleValue.h
+++ b/platform/darwin/src/MGLStyleValue.h
@@ -75,9 +75,9 @@ typedef NS_ENUM(NSUInteger, MGLInterpolationMode) {
*/
MGLInterpolationModeCategorical,
/**
- Values between two stops are not interpolated. Instead, values are set to their
- input value. Use identity interpolation mode to show attribute values that can be
- used as style values.
+ Values between two stops are not interpolated. Instead, for any given feature, the
+ style value matches a value in that feature’s attributes dictionary. Use identity
+ interpolation mode to show attribute values that can be used as style values.
*/
MGLInterpolationModeIdentity
};
diff --git a/platform/darwin/src/MGLStyleValue.mm b/platform/darwin/src/MGLStyleValue.mm
index 33b6babadf..4dd6b550d8 100644
--- a/platform/darwin/src/MGLStyleValue.mm
+++ b/platform/darwin/src/MGLStyleValue.mm
@@ -128,7 +128,7 @@ const MGLStyleFunctionOption MGLStyleFunctionOptionDefaultValue = @"MGLStyleFunc
return {};
}
- if (self == [super init]) {
+ if (self = [super init]) {
self.interpolationMode = interpolationMode;
self.stops = stops;
@@ -181,7 +181,7 @@ const MGLStyleFunctionOption MGLStyleFunctionOptionDefaultValue = @"MGLStyleFunc
}
- (instancetype)initWithInterpolationMode:(MGLInterpolationMode)interpolationMode stops:(NSDictionary *)stops attributeName:(NSString *)attributeName options:(NSDictionary *)options {
- if (self == [super init]) {
+ if (self = [super init]) {
self.interpolationMode = interpolationMode;
self.stops = stops;
_attributeName = attributeName;
@@ -251,7 +251,7 @@ const MGLStyleFunctionOption MGLStyleFunctionOptionDefaultValue = @"MGLStyleFunc
}
- (instancetype)initWithInterpolationMode:(MGLInterpolationMode)interpolationMode stops:(NSDictionary *)stops attributeName:(NSString *)attributeName options:(NSDictionary *)options {
- if (self == [super init]) {
+ if (self = [super init]) {
self.interpolationMode = interpolationMode;
self.stops = stops;
_attributeName = attributeName;
diff --git a/platform/darwin/src/MGLStyleValue_Private.h b/platform/darwin/src/MGLStyleValue_Private.h
index 263b54d7e5..2155c657bd 100644
--- a/platform/darwin/src/MGLStyleValue_Private.h
+++ b/platform/darwin/src/MGLStyleValue_Private.h
@@ -3,11 +3,13 @@
#import "MGLStyleValue.h"
#import "NSValue+MGLStyleAttributeAdditions.h"
+#import "NSValue+MGLAdditions.h"
#import "MGLTypes.h"
#import "MGLConversion.h"
#include <mbgl/style/conversion/data_driven_property_value.hpp>
#include <mbgl/style/conversion.hpp>
+#import <mbgl/style/types.hpp>
#import <mbgl/util/enum.hpp>
@@ -415,6 +417,12 @@ private: // Private utilities for converting from mgl to mbgl values
mbglValue.push_back(mbglElement);
}
}
+
+ void getMBGLValue(NSValue *rawValue, mbgl::style::Position &mbglValue) {
+ auto spherical = rawValue.mgl_lightPositionArrayValue;
+ mbgl::style::Position position(spherical);
+ mbglValue = position;
+ }
// Enumerations
template <typename MBGLEnum = MBGLType,
@@ -473,6 +481,12 @@ private: // Private utilities for converting from mbgl to mgl values
}
return array;
}
+
+ static NSValue *toMGLRawStyleValue(const mbgl::style::Position &mbglStopValue) {
+ std::array<float, 3> spherical = mbglStopValue.getSpherical();
+ MGLSphericalPosition position = MGLSphericalPositionMake(spherical[0], spherical[1], spherical[2]);
+ return [NSValue valueWithMGLSphericalPosition:position];
+ }
// Enumerations
template <typename MBGLEnum = MBGLType, typename MGLEnum = ObjCEnum>
diff --git a/platform/darwin/src/MGLTypes.h b/platform/darwin/src/MGLTypes.h
index c06fd8b0e7..16f510b5a6 100644
--- a/platform/darwin/src/MGLTypes.h
+++ b/platform/darwin/src/MGLTypes.h
@@ -1,4 +1,5 @@
#import <Foundation/Foundation.h>
+#import <CoreGraphics/CoreGraphics.h>
#import "MGLFoundation.h"
diff --git a/platform/darwin/src/MGLVectorSource.h b/platform/darwin/src/MGLVectorSource.h
index a48434f7a3..968be3c0e0 100644
--- a/platform/darwin/src/MGLVectorSource.h
+++ b/platform/darwin/src/MGLVectorSource.h
@@ -74,96 +74,13 @@ MGL_EXPORT
Returns a vector source initialized an identifier, tile URL templates, and
options.
+ Tile URL templates are strings that specify the URLs of the vector tiles to
+ load. See the “<a href="../tile-url-templates.html">Tile URL Templates</a>”
+ guide for information about the format of a tile URL template.
+
After initializing and configuring the source, add it to a map view’s style
using the `-[MGLStyle addSource:]` method.
- #### Tile URL templates
-
- Tile URL templates are strings that specify the URLs of the tile images to
- load. Each template resembles an absolute URL, but with any number of
- placeholder strings that the source evaluates based on the tile it needs to
- load. For example:
-
- <ul>
- <li><code>http://www.example.com/tiles/{z}/{x}/{y}.pbf</code> could be
- evaluated as <code>http://www.example.com/tiles/14/6/9.pbf</code>.</li>
- <li><code>http://www.example.com/tiles/{z}/{x}/{y}{ratio}.png</code> could be
- evaluated as <code>http://www.example.com/tiles/14/6/9@2x.png</code>.</li>
- </ul>
-
- Tile sources support the following placeholder strings in tile URL templates,
- all of which are optional:
-
- <table>
- <thead>
- <tr><th>Placeholder string</th><th>Description</th></tr>
- </thead>
- <tbody>
- <tr>
- <td><code>{x}</code></td>
- <td>The index of the tile along the map’s x axis according to Spherical
- Mercator projection. If the value is 0, the tile’s left edge corresponds
- to the 180th meridian west. If the value is 2<sup><var>z</var></sup>−1,
- the tile’s right edge corresponds to the 180th meridian east.</td>
- </tr>
- <tr>
- <td><code>{y}</code></td>
- <td>The index of the tile along the map’s y axis according to Spherical
- Mercator projection. If the value is 0, the tile’s tile edge corresponds
- to arctan(sinh(π)), or approximately 85.0511 degrees north. If the value
- is 2<sup><var>z</var></sup>−1, the tile’s bottom edge corresponds to
- −arctan(sinh(π)), or approximately 85.0511 degrees south. The y axis is
- inverted if the <code>options</code> parameter contains
- <code>MGLTileSourceOptionTileCoordinateSystem</code> with a value of
- <code>MGLTileCoordinateSystemTMS</code>.</td>
- </tr>
- <tr>
- <td><code>{z}</code></td>
- <td>The tile’s zoom level. At zoom level 0, each tile covers the entire
- world map; at zoom level 1, it covers ¼ of the world; at zoom level 2,
- <sup>1</sup>⁄<sub>16</sub> of the world, and so on. For tiles loaded by
- a <code>MGLRasterSource</code> object, whether the tile zoom level
- matches the map’s current zoom level depends on the value of the
- source’s tile size as specified in the
- <code>MGLTileSourceOptionTileSize</code> key of the
- <code>options</code> parameter.</td>
- </tr>
- <tr>
- <td><code>{bbox-epsg-3857}</code></td>
- <td>The tile’s bounding box, expressed as a comma-separated list of the
- tile’s western, southern, eastern, and northern extents according to
- Spherical Mercator (EPSG:3857) projection. The bounding box is typically
- used with map services conforming to the
- <a href="http://www.opengeospatial.org/standards/wms">Web Map Service</a>
- protocol.</td>
- </tr>
- <tr>
- <td><code>{quadkey}</code></td>
- <td>A quadkey indicating both the tile’s location and its zoom level. The
- quadkey is typically used with
- <a href="https://msdn.microsoft.com/en-us/library/bb259689.aspx">Bing Maps</a>.
- </td>
- </tr>
- <tr>
- <td><code>{ratio}</code></td>
- <td>A suffix indicating the resolution of the tile image. The suffix is the
- empty string for standard resolution displays and <code>@2x</code> for
- Retina displays, including displays for which
- <code>NSScreen.backingScaleFactor</code> or <code>UIScreen.scale</code>
- is 3.</td>
- </tr>
- <tr>
- <td><code>{prefix}</code></td>
- <td>Two hexadecimal digits chosen such that each visible tile has a
- different prefix. The prefix is typically used for domain sharding.</td>
- </tr>
- </tbody>
- </table>
-
- For more information about the `{x}`, `{y}`, and `{z}` placeholder strings,
- consult the
- <a href="https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames">OpenStreetMap Wiki</a>.
-
@param identifier A string that uniquely identifies the source in the style to
which it is added.
@param tileURLTemplates An array of tile URL template strings. Only the first
diff --git a/platform/darwin/src/NSBundle+MGLAdditions.h b/platform/darwin/src/NSBundle+MGLAdditions.h
index 1fc9e8b896..ad5e9d5369 100644
--- a/platform/darwin/src/NSBundle+MGLAdditions.h
+++ b/platform/darwin/src/NSBundle+MGLAdditions.h
@@ -36,9 +36,7 @@ NS_ASSUME_NONNULL_BEGIN
+ (nullable NS_DICTIONARY_OF(NSString *, id) *)mgl_frameworkInfoDictionary;
-/// The relative path to the directory containing the SDK’s resource files, or
-/// `nil` if the files are located directly within the bundle’s root directory.
-@property (readonly, copy, nullable) NSString *mgl_resourcesDirectory;
++ (nullable NSString *)mgl_applicationBundleIdentifier;
@end
diff --git a/platform/darwin/src/NSBundle+MGLAdditions.m b/platform/darwin/src/NSBundle+MGLAdditions.m
index 76d9cc0db7..f383a50300 100644
--- a/platform/darwin/src/NSBundle+MGLAdditions.m
+++ b/platform/darwin/src/NSBundle+MGLAdditions.m
@@ -6,12 +6,19 @@
+ (instancetype)mgl_frameworkBundle {
NSBundle *bundle = [self bundleForClass:[MGLAccountManager class]];
- if (![bundle.infoDictionary[@"CFBundlePackageType"] isEqualToString:@"FMWK"] && !bundle.mgl_resourcesDirectory) {
+
+ if (![bundle.infoDictionary[@"CFBundlePackageType"] isEqualToString:@"FMWK"]) {
// For static frameworks, the bundle is the containing application
- // bundle but the resources are still in the framework bundle.
- bundle = [NSBundle bundleWithPath:[bundle.privateFrameworksPath
- stringByAppendingPathComponent:@"Mapbox.framework"]];
+ // bundle but the resources are in Mapbox.bundle.
+ NSString *bundlePath = [bundle pathForResource:@"Mapbox" ofType:@"bundle"];
+ if (bundlePath) {
+ bundle = [self bundleWithPath:bundlePath];
+ } else {
+ [NSException raise:@"MGLBundleNotFoundException" format:
+ @"The Mapbox framework bundle could not be found. If using the Mapbox iOS SDK as a static framework, make sure that Mapbox.bundle is copied into the root of the app bundle."];
+ }
}
+
return bundle;
}
@@ -21,18 +28,16 @@
+ (nullable NS_DICTIONARY_OF(NSString *, id) *)mgl_frameworkInfoDictionary {
NSBundle *bundle = self.mgl_frameworkBundle;
- if (bundle.mgl_resourcesDirectory) {
- NSString *infoPlistPath = [bundle pathForResource:@"Info"
- ofType:@"plist"
- inDirectory:bundle.mgl_resourcesDirectory];
- return [NSDictionary dictionaryWithContentsOfFile:infoPlistPath];
- } else {
- return bundle.infoDictionary;
- }
+ return bundle.infoDictionary;
}
-- (NSString *)mgl_resourcesDirectory {
- return [self pathForResource:@"Mapbox" ofType:@"bundle"] ? @"Mapbox.bundle" : nil;
++ (nullable NSString *)mgl_applicationBundleIdentifier {
+ NSString *bundleIdentifier = [NSBundle mainBundle].bundleIdentifier;
+ if (!bundleIdentifier) {
+ // There’s no main bundle identifier when running in a unit test bundle.
+ bundleIdentifier = [NSBundle bundleForClass:[MGLAccountManager class]].bundleIdentifier;
+ }
+ return bundleIdentifier;
}
@end
diff --git a/platform/darwin/src/NSValue+MGLAdditions.h b/platform/darwin/src/NSValue+MGLAdditions.h
index e6755021d0..0aaa2a337a 100644
--- a/platform/darwin/src/NSValue+MGLAdditions.h
+++ b/platform/darwin/src/NSValue+MGLAdditions.h
@@ -1,6 +1,7 @@
#import <Foundation/Foundation.h>
#import "MGLGeometry.h"
+#import "MGLLight.h"
#import "MGLOfflinePack.h"
#import "MGLTypes.h"
@@ -87,6 +88,34 @@ NS_ASSUME_NONNULL_BEGIN
*/
@property (readonly) MGLTransition MGLTransitionValue;
+/**
+ Creates a new value object containing the given `MGLSphericalPosition`
+ structure.
+
+ @param lightPosition The value for the new object.
+ @return A new value object that contains the light position information.
+ */
++ (instancetype)valueWithMGLSphericalPosition:(MGLSphericalPosition)lightPosition;
+
+/**
+ The `MGLSphericalPosition` structure representation of the value.
+ */
+@property (readonly) MGLSphericalPosition MGLSphericalPositionValue;
+
+/**
+ Creates a new value object containing the given `MGLLightAnchor`
+ enum.
+
+ @param lightAnchor The value for the new object.
+ @return A new value object that contains the light anchor information.
+ */
++ (NSValue *)valueWithMGLLightAnchor:(MGLLightAnchor)lightAnchor;
+
+/**
+ The `MGLLightAnchor` enum representation of the value.
+ */
+@property (readonly) MGLLightAnchor MGLLightAnchorValue;
+
@end
NS_ASSUME_NONNULL_END
diff --git a/platform/darwin/src/NSValue+MGLAdditions.m b/platform/darwin/src/NSValue+MGLAdditions.m
index a95ef23941..ef894f0eb4 100644
--- a/platform/darwin/src/NSValue+MGLAdditions.m
+++ b/platform/darwin/src/NSValue+MGLAdditions.m
@@ -58,4 +58,27 @@
return transition;
}
++ (NSValue *)valueWithMGLSphericalPosition:(MGLSphericalPosition)lightPosition
+{
+ return [NSValue value:&lightPosition withObjCType:@encode(MGLSphericalPosition)];
+}
+
+- (MGLSphericalPosition)MGLSphericalPositionValue
+{
+ MGLSphericalPosition lightPosition;
+ [self getValue:&lightPosition];
+ return lightPosition;
+}
+
++ (NSValue *)valueWithMGLLightAnchor:(MGLLightAnchor)lightAnchor {
+ return [NSValue value:&lightAnchor withObjCType:@encode(MGLLightAnchor)];
+}
+
+- (MGLLightAnchor)MGLLightAnchorValue
+{
+ MGLLightAnchor achorType;
+ [self getValue:&achorType];
+ return achorType;
+}
+
@end
diff --git a/platform/darwin/src/NSValue+MGLStyleAttributeAdditions.h b/platform/darwin/src/NSValue+MGLStyleAttributeAdditions.h
index 60c1ee4075..0f1e511694 100644
--- a/platform/darwin/src/NSValue+MGLStyleAttributeAdditions.h
+++ b/platform/darwin/src/NSValue+MGLStyleAttributeAdditions.h
@@ -9,5 +9,6 @@
- (std::array<float, 2>)mgl_offsetArrayValue;
- (std::array<float, 4>)mgl_paddingArrayValue;
+- (std::array<float, 3>)mgl_lightPositionArrayValue;
@end
diff --git a/platform/darwin/src/NSValue+MGLStyleAttributeAdditions.mm b/platform/darwin/src/NSValue+MGLStyleAttributeAdditions.mm
index e66145aec1..a41950b6b3 100644
--- a/platform/darwin/src/NSValue+MGLStyleAttributeAdditions.mm
+++ b/platform/darwin/src/NSValue+MGLStyleAttributeAdditions.mm
@@ -1,5 +1,5 @@
#import "NSValue+MGLStyleAttributeAdditions.h"
-
+#import "MGLLight.h"
#if TARGET_OS_IPHONE
#import <UIKit/UIKit.h>
#define MGLEdgeInsets UIEdgeInsets
@@ -61,4 +61,17 @@
};
}
+- (std::array<float, 3>)mgl_lightPositionArrayValue
+{
+ NSAssert(strcmp(self.objCType, @encode(MGLSphericalPosition)) == 0, @"Value does not represent an MGLSphericalPosition");
+ MGLSphericalPosition lightPosition;
+ [self getValue:&lightPosition];
+ // Style specification defines padding in clockwise order: top, right, bottom, left.
+ return {
+ static_cast<float>(lightPosition.radial),
+ static_cast<float>(lightPosition.azimuthal),
+ static_cast<float>(lightPosition.polar),
+ };
+}
+
@end
diff --git a/platform/darwin/test/MGLAttributionInfoTests.m b/platform/darwin/test/MGLAttributionInfoTests.m
index e258671c09..ed4927d44b 100644
--- a/platform/darwin/test/MGLAttributionInfoTests.m
+++ b/platform/darwin/test/MGLAttributionInfoTests.m
@@ -46,8 +46,18 @@
XCTAssertEqualObjects(infos[3].title.string, @"Improve this map");
XCTAssertEqualObjects(infos[3].URL, [NSURL URLWithString:@"https://www.mapbox.com/map-feedback/"]);
XCTAssertTrue(infos[3].feedbackLink);
+ NSURL *styleURL = [MGLStyle satelliteStreetsStyleURLWithVersion:99];
+#if TARGET_OS_IPHONE
+ XCTAssertEqualObjects([infos[3] feedbackURLAtCenterCoordinate:mapbox zoomLevel:14],
+ [NSURL URLWithString:@"https://www.mapbox.com/feedback/?referrer=com.mapbox.sdk.ios#/77.63680/12.98108/14.00/0.0/0"]);
+ XCTAssertEqualObjects([infos[3] feedbackURLForStyleURL:styleURL atCenterCoordinate:mapbox zoomLevel:3.14159 direction:90.9 pitch:12.5],
+ [NSURL URLWithString:@"https://www.mapbox.com/feedback/?referrer=com.mapbox.sdk.ios&owner=mapbox&id=satellite-streets-v99&access_token#/77.63680/12.98108/3.14/90.9/13"]);
+#else
XCTAssertEqualObjects([infos[3] feedbackURLAtCenterCoordinate:mapbox zoomLevel:14],
- [NSURL URLWithString:@"https://www.mapbox.com/map-feedback/#/77.63680/12.98108/15"]);
+ [NSURL URLWithString:@"https://www.mapbox.com/feedback/?referrer=com.mapbox.MapboxGL#/77.63680/12.98108/14.00/0.0/0"]);
+ XCTAssertEqualObjects([infos[3] feedbackURLForStyleURL:styleURL atCenterCoordinate:mapbox zoomLevel:3.14159 direction:90.9 pitch:12.5],
+ [NSURL URLWithString:@"https://www.mapbox.com/feedback/?referrer=com.mapbox.MapboxGL&owner=mapbox&id=satellite-streets-v99&access_token#/77.63680/12.98108/3.14/90.9/13"]);
+#endif
}
- (void)testStyle {
diff --git a/platform/darwin/test/MGLCodingTests.m b/platform/darwin/test/MGLCodingTests.m
index ff0d674ad1..ac61672b76 100644
--- a/platform/darwin/test/MGLCodingTests.m
+++ b/platform/darwin/test/MGLCodingTests.m
@@ -66,12 +66,54 @@
[unarchivedPolyline replaceCoordinatesInRange:NSMakeRange(0, 1) withCoordinates:otherCoordinates];
XCTAssertNotEqualObjects(polyline, unarchivedPolyline);
+
+ CLLocationCoordinate2D multiLineCoordinates[] = {
+ CLLocationCoordinate2DMake(51.000000, 0.000000),
+ CLLocationCoordinate2DMake(51.000000, 1.000000),
+ CLLocationCoordinate2DMake(51.000000, 2.000000),
+ };
+
+ NSUInteger multiLineCoordinatesCount = sizeof(multiLineCoordinates) / sizeof(CLLocationCoordinate2D);
+ MGLPolyline *multiLine = [MGLPolyline polylineWithCoordinates:multiLineCoordinates count:multiLineCoordinatesCount];
+ CLLocationCoordinate2D multiLineCenter = CLLocationCoordinate2DMake(51.000000, 1.000000);
+
+ XCTAssertEqual([multiLine coordinate].latitude, multiLineCenter.latitude);
+ XCTAssertEqual([multiLine coordinate].longitude, multiLineCenter.longitude);
+
+ CLLocationCoordinate2D segmentCoordinates[] = {
+ CLLocationCoordinate2DMake(35.040390, -85.311477),
+ CLLocationCoordinate2DMake(35.040390, -85.209510),
+ };
+
+ NSUInteger segmentCoordinatesCount = sizeof(segmentCoordinates) / sizeof(CLLocationCoordinate2D);
+ MGLPolyline *segmentLine = [MGLPolyline polylineWithCoordinates:segmentCoordinates count:segmentCoordinatesCount];
+ CLLocationCoordinate2D segmentCenter = CLLocationCoordinate2DMake(35.0404006631, -85.2604935);
+
+ XCTAssertEqualWithAccuracy([segmentLine coordinate].latitude, segmentCenter.latitude, 0.0001);
+ XCTAssertEqualWithAccuracy([segmentLine coordinate].longitude, segmentCenter.longitude, 0.0001);
+
+ CLLocationCoordinate2D sfToBerkeleyCoordinates[] = {
+ CLLocationCoordinate2DMake(37.782440, -122.397111),
+ CLLocationCoordinate2DMake(37.818384, -122.352994),
+ CLLocationCoordinate2DMake(37.831401, -122.274545),
+ CLLocationCoordinate2DMake(37.862172, -122.262700),
+ };
+
+ NSUInteger sfToBerkeleyCoordinatesCount = sizeof(sfToBerkeleyCoordinates) / sizeof(CLLocationCoordinate2D);
+ MGLPolyline *sfToBerkeleyLine = [MGLPolyline polylineWithCoordinates:sfToBerkeleyCoordinates count:sfToBerkeleyCoordinatesCount];
+ CLLocationCoordinate2D sfToBerkeleyCenter = CLLocationCoordinate2DMake(37.8230575118,-122.324867587);
+
+ XCTAssertEqualWithAccuracy([sfToBerkeleyLine coordinate].latitude, sfToBerkeleyCenter.latitude, 0.0001);
+ XCTAssertEqualWithAccuracy([sfToBerkeleyLine coordinate].longitude, sfToBerkeleyCenter.longitude, 0.0001);
+
}
- (void)testPolygon {
CLLocationCoordinate2D coordinates[] = {
- CLLocationCoordinate2DMake(0.664482398, 1.8865675),
- CLLocationCoordinate2DMake(2.13224687, 3.9984632)
+ CLLocationCoordinate2DMake(35.090745, -85.300259),
+ CLLocationCoordinate2DMake(35.092035, -85.298885),
+ CLLocationCoordinate2DMake(35.090639, -85.297416),
+ CLLocationCoordinate2DMake(35.089112, -85.298928)
};
NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D);
@@ -84,8 +126,24 @@
[NSKeyedArchiver archiveRootObject:polygon toFile:filePath];
MGLPolygon *unarchivedPolygon = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
+ [unarchivedPolygon coordinate];
XCTAssertEqualObjects(polygon, unarchivedPolygon);
+
+ CLLocationCoordinate2D squareCoordinates[] = {
+ CLLocationCoordinate2DMake(100.0, 0.0),
+ CLLocationCoordinate2DMake(101.0, 0.0),
+ CLLocationCoordinate2DMake(101.0, 1.0),
+ CLLocationCoordinate2DMake(100.0, 1.0),
+ };
+
+ NSUInteger squareCoordinatesCount = sizeof(squareCoordinates) / sizeof(CLLocationCoordinate2D);
+ MGLPolygon *squarePolygon = [MGLPolygon polygonWithCoordinates:squareCoordinates count:squareCoordinatesCount];
+ CLLocationCoordinate2D squareCenter = CLLocationCoordinate2DMake(100.5, 0.5);
+
+ XCTAssertEqual([squarePolygon coordinate].latitude, squareCenter.latitude);
+ XCTAssertEqual([squarePolygon coordinate].longitude, squareCenter.longitude);
+
}
- (void)testPolygonWithInteriorPolygons {
@@ -169,6 +227,11 @@
NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D);
MGLPointCollection *pointCollection = [MGLPointCollection pointCollectionWithCoordinates:coordinates count:numberOfCoordinates];
+ CLLocationCoordinate2D pointsCenter = CLLocationCoordinate2DMake(0, 1);
+
+ XCTAssertEqual([pointCollection coordinate].latitude, pointsCenter.latitude);
+ XCTAssertEqual([pointCollection coordinate].longitude, pointsCenter.longitude);
+
NSString *filePath = [self temporaryFilePathForClass:[MGLPointCollection class]];
[NSKeyedArchiver archiveRootObject:pointCollection toFile:filePath];
@@ -218,6 +281,30 @@
CLLocationCoordinate2DMake(20, 21),
CLLocationCoordinate2DMake(30, 31),
};
+
+ CLLocationCoordinate2D line1[] = {
+ CLLocationCoordinate2DMake(100, 40),
+ CLLocationCoordinate2DMake(105, 45),
+ CLLocationCoordinate2DMake(110, 55)
+ };
+
+ CLLocationCoordinate2D line2[] = {
+ CLLocationCoordinate2DMake(105, 40),
+ CLLocationCoordinate2DMake(110, 45),
+ CLLocationCoordinate2DMake(115, 55)
+ };
+
+ NSUInteger road1CoordinatesCount = sizeof(line1) / sizeof(CLLocationCoordinate2D);
+ NSUInteger road2CoordinatesCount = sizeof(line2) / sizeof(CLLocationCoordinate2D);
+
+ MGLPolyline *road1Polyline = [MGLPolyline polylineWithCoordinates:line1 count:road1CoordinatesCount];
+ MGLPolyline *road2Polyline = [MGLPolyline polylineWithCoordinates:line1 count:road2CoordinatesCount];
+
+ MGLMultiPolyline *roads = [MGLMultiPolyline multiPolylineWithPolylines:@[road1Polyline, road2Polyline]];
+ CLLocationCoordinate2D roadCenter = CLLocationCoordinate2DMake(100, 40);
+
+ XCTAssertEqual([roads coordinate].latitude, roadCenter.latitude);
+ XCTAssertEqual([roads coordinate].longitude, roadCenter.longitude);
NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D);
@@ -248,6 +335,31 @@
CLLocationCoordinate2DMake(20, 21),
CLLocationCoordinate2DMake(30, 31),
};
+
+ CLLocationCoordinate2D outerSquare[] = {
+ CLLocationCoordinate2DMake(100.0, 0.0),
+ CLLocationCoordinate2DMake(101.0, 0.0),
+ CLLocationCoordinate2DMake(101.0, 1.0),
+ CLLocationCoordinate2DMake(100.0, 1.0),
+ };
+
+ CLLocationCoordinate2D innerSquare[] = {
+ CLLocationCoordinate2DMake(100.35, 0.35),
+ CLLocationCoordinate2DMake(100.65, 0.35),
+ CLLocationCoordinate2DMake(100.65, 0.65),
+ CLLocationCoordinate2DMake(100.35, 0.65),
+ };
+
+ NSUInteger outerCoordinatesCount = sizeof(outerSquare) / sizeof(CLLocationCoordinate2D);
+ NSUInteger innerCoordinatesCount = sizeof(innerSquare) / sizeof(CLLocationCoordinate2D);
+
+ MGLPolygon *innerPolygonSquare = [MGLPolygon polygonWithCoordinates:innerSquare count:innerCoordinatesCount];
+ MGLPolygon *outerPolygonSquare = [MGLPolygon polygonWithCoordinates:outerSquare count:outerCoordinatesCount interiorPolygons:@[innerPolygonSquare]];
+ MGLMultiPolygon *squares = [MGLMultiPolygon multiPolygonWithPolygons:@[outerPolygonSquare, innerPolygonSquare]];
+ CLLocationCoordinate2D squareCenter = CLLocationCoordinate2DMake(100.5, 0.5);
+
+ XCTAssertEqual([squares coordinate].latitude, squareCenter.latitude);
+ XCTAssertEqual([squares coordinate].longitude, squareCenter.longitude);
NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D);
@@ -265,9 +377,10 @@
MGLMultiPolygon *unarchivedMultiPolygon = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
MGLMultiPolygon *anotherMultiPolygon = [MGLMultiPolygon multiPolygonWithPolygons:[polygons subarrayWithRange:NSMakeRange(0, polygons.count/2)]];
-
+
XCTAssertEqualObjects(multiPolygon, unarchivedMultiPolygon);
XCTAssertNotEqualObjects(anotherMultiPolygon, unarchivedMultiPolygon);
+
}
- (void)testShapeCollection {
diff --git a/platform/darwin/test/MGLDocumentationExampleTests.swift b/platform/darwin/test/MGLDocumentationExampleTests.swift
index 6d2dc597a9..48e6b17f44 100644
--- a/platform/darwin/test/MGLDocumentationExampleTests.swift
+++ b/platform/darwin/test/MGLDocumentationExampleTests.swift
@@ -168,7 +168,7 @@ class MGLDocumentationExampleTests: XCTestCase, MGLMapViewDelegate {
layer.sourceLayerIdentifier = "building"
layer.fillExtrusionHeight = MGLStyleValue(interpolationMode: .identity, sourceStops: nil, attributeName: "height", options: nil)
layer.fillExtrusionBase = MGLStyleValue(interpolationMode: .identity, sourceStops: nil, attributeName: "min_height", options: nil)
- layer.predicate = NSPredicate(format: "extrude == TRUE")
+ layer.predicate = NSPredicate(format: "extrude == 'true'")
mapView.style?.addLayer(layer)
//#-end-example-code
diff --git a/platform/darwin/test/MGLLightTest.mm b/platform/darwin/test/MGLLightTest.mm
new file mode 100644
index 0000000000..2c3d1c7bd1
--- /dev/null
+++ b/platform/darwin/test/MGLLightTest.mm
@@ -0,0 +1,217 @@
+#import <XCTest/XCTest.h>
+#import <Mapbox/Mapbox.h>
+
+#import "MGLLight_Private.h"
+
+#import "../../darwin/src/NSDate+MGLAdditions.h"
+
+#import <mbgl/style/light.hpp>
+#import <mbgl/style/types.hpp>
+#include <mbgl/style/transition_options.hpp>
+
+@interface MGLLightTest : XCTestCase
+
+@end
+
+@implementation MGLLightTest
+
+- (void)testProperties {
+
+ MGLTransition defaultTransition = MGLTransitionMake(0, 0);
+ MGLTransition transition = MGLTransitionMake(6, 3);
+ mbgl::style::TransitionOptions transitionOptions { { MGLDurationFromTimeInterval(6) }, { MGLDurationFromTimeInterval(3) } };
+
+ // anchor
+ {
+ mbgl::style::Light light;
+ MGLLight *mglLight = [[MGLLight alloc] initWithMBGLLight:&light];
+
+ NSAssert([mglLight.anchor isKindOfClass:[MGLConstantStyleValue class]], @"mglLight.anchor isn’t a MGLConstantStyleValue.");
+ NSValue *anchorValue = ((MGLConstantStyleValue *)mglLight.anchor).rawValue;
+ XCTAssertEqual(anchorValue.MGLLightAnchorValue, MGLLightAnchorViewport);
+ XCTAssertEqual(mglLight.anchorTransition.delay, defaultTransition.delay);
+ XCTAssertEqual(mglLight.anchorTransition.duration, defaultTransition.duration);
+
+ auto lightFromMGLlight = [mglLight mbglLight];
+
+ XCTAssertEqual(light.getDefaultAnchor(), lightFromMGLlight.getAnchor().asConstant());
+ auto anchorTransition = lightFromMGLlight.getAnchorTransition();
+ XCTAssert(anchorTransition.delay && MGLTimeIntervalFromDuration(*anchorTransition.delay) == defaultTransition.delay);
+ XCTAssert(anchorTransition.duration && MGLTimeIntervalFromDuration(*anchorTransition.duration) == defaultTransition.duration);
+
+ MGLStyleValue<NSValue *> *anchorStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLLightAnchor:MGLLightAnchorMap]];
+ mglLight.anchor = anchorStyleValue;
+ mglLight.anchorTransition = transition;
+ NSAssert([mglLight.anchor isKindOfClass:[MGLConstantStyleValue class]], @"mglLight.anchor isn’t a MGLConstantStyleValue.");
+ anchorValue = ((MGLConstantStyleValue *)mglLight.anchor).rawValue;
+
+ XCTAssertEqual(anchorValue.MGLLightAnchorValue, MGLLightAnchorMap);
+ XCTAssertEqual(mglLight.anchorTransition.delay, transition.delay);
+ XCTAssertEqual(mglLight.anchorTransition.duration, transition.duration);
+
+ mbgl::style::PropertyValue<mbgl::style::LightAnchorType> anchorProperty = { mbgl::style::LightAnchorType::Map };
+ light.setAnchor(anchorProperty);
+ light.setAnchorTransition(transitionOptions);
+
+ lightFromMGLlight = [mglLight mbglLight];
+
+ XCTAssertEqual(light.getAnchor().asConstant(), lightFromMGLlight.getAnchor().asConstant());
+ anchorTransition = lightFromMGLlight.getAnchorTransition();
+ XCTAssert(anchorTransition.delay && MGLTimeIntervalFromDuration(*anchorTransition.delay) == transition.delay);
+ XCTAssert(anchorTransition.duration && MGLTimeIntervalFromDuration(*anchorTransition.duration) == transition.duration);
+
+ }
+
+ // position
+ {
+ mbgl::style::Light light;
+ MGLLight *mglLight = [[MGLLight alloc] initWithMBGLLight:&light];
+ NSAssert([mglLight.position isKindOfClass:[MGLConstantStyleValue class]], @"mglLight.position isn’t a MGLConstantStyleValue.");
+ NSValue *positionValue = ((MGLConstantStyleValue *)mglLight.position).rawValue;
+ auto positionArray = light.getDefaultPosition().getSpherical();
+ MGLSphericalPosition defaultPosition = MGLSphericalPositionMake(positionArray[0], positionArray[1], positionArray[2]);
+
+ XCTAssert(defaultPosition.radial == positionValue.MGLSphericalPositionValue.radial);
+ XCTAssert(defaultPosition.azimuthal == positionValue.MGLSphericalPositionValue.azimuthal);
+ XCTAssert(defaultPosition.polar == positionValue.MGLSphericalPositionValue.polar);
+ XCTAssertEqual(mglLight.positionTransiton.delay, defaultTransition.delay);
+ XCTAssertEqual(mglLight.positionTransiton.duration, defaultTransition.duration);
+
+ auto lightFromMGLlight = [mglLight mbglLight];
+
+ XCTAssertEqual(positionArray, lightFromMGLlight.getPosition().asConstant().getSpherical());
+ auto positionTransition = lightFromMGLlight.getPositionTransition();
+ XCTAssert(positionTransition.delay && MGLTimeIntervalFromDuration(*positionTransition.delay) == defaultTransition.delay);
+ XCTAssert(positionTransition.duration && MGLTimeIntervalFromDuration(*positionTransition.duration) == defaultTransition.duration);
+
+ defaultPosition = MGLSphericalPositionMake(6, 180, 90);
+ MGLStyleValue<NSValue *> *positionStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLSphericalPosition:defaultPosition]];
+ mglLight.position = positionStyleValue;
+ mglLight.positionTransiton = transition;
+
+ NSAssert([mglLight.position isKindOfClass:[MGLConstantStyleValue class]], @"mglLight.position isn’t a MGLConstantStyleValue.");
+ positionValue = ((MGLConstantStyleValue *)mglLight.position).rawValue;
+
+ XCTAssert(defaultPosition.radial == positionValue.MGLSphericalPositionValue.radial);
+ XCTAssert(defaultPosition.azimuthal == positionValue.MGLSphericalPositionValue.azimuthal);
+ XCTAssert(defaultPosition.polar == positionValue.MGLSphericalPositionValue.polar);
+ XCTAssertEqual(mglLight.positionTransiton.delay, transition.delay);
+ XCTAssertEqual(mglLight.positionTransiton.duration, transition.duration);
+
+ lightFromMGLlight = [mglLight mbglLight];
+
+ positionArray = { { 6, 180, 90 } };
+ mbgl::style::Position position = { positionArray };
+ mbgl::style::PropertyValue<mbgl::style::Position> positionProperty = { position };
+ light.setPosition(positionProperty);
+ light.setPositionTransition(transitionOptions);
+
+ XCTAssertEqual(positionArray, lightFromMGLlight.getPosition().asConstant().getSpherical());
+ positionTransition = lightFromMGLlight.getPositionTransition();
+ XCTAssert(positionTransition.delay && MGLTimeIntervalFromDuration(*positionTransition.delay) == transition.delay);
+ XCTAssert(positionTransition.duration && MGLTimeIntervalFromDuration(*positionTransition.duration) == transition.duration);
+
+ }
+
+ // color
+ {
+ mbgl::style::Light light;
+ MGLLight *mglLight = [[MGLLight alloc] initWithMBGLLight:&light];
+ NSAssert([mglLight.color isKindOfClass:[MGLConstantStyleValue class]], @"mglLight.color isn’t a MGLConstantStyleValue.");
+ MGLColor *colorValue = ((MGLConstantStyleValue *)mglLight.color).rawValue;
+ auto color = light.getDefaultColor();
+ const CGFloat *colorComponents = CGColorGetComponents(colorValue.CGColor);
+
+ XCTAssert(color.r == colorComponents[0] && color.g == colorComponents[1] && color.b == colorComponents[2] &&
+ color.a == colorComponents[3]);
+ XCTAssertEqual(mglLight.colorTransiton.delay, defaultTransition.delay);
+ XCTAssertEqual(mglLight.colorTransiton.duration, defaultTransition.duration);
+
+ auto lightFromMGLlight = [mglLight mbglLight];
+
+ XCTAssertEqual(color, lightFromMGLlight.getColor().asConstant());
+ auto colorTransition = lightFromMGLlight.getColorTransition();
+ XCTAssert(colorTransition.delay && MGLTimeIntervalFromDuration(*colorTransition.delay) == defaultTransition.delay);
+ XCTAssert(colorTransition.duration && MGLTimeIntervalFromDuration(*colorTransition.duration) == defaultTransition.duration);
+
+ MGLStyleValue<MGLColor *> *colorStyleValue = [MGLStyleValue<MGLColor *> valueWithRawValue:[MGLColor blackColor]];
+ mglLight.color = colorStyleValue;
+ mglLight.colorTransiton = transition;
+
+ NSAssert([mglLight.color isKindOfClass:[MGLConstantStyleValue class]], @"mglLight.color isn’t a MGLConstantStyleValue.");
+ colorValue = ((MGLConstantStyleValue *)mglLight.color).rawValue;
+
+ XCTAssertEqual([MGLColor blackColor], colorValue);
+ XCTAssertEqual(mglLight.colorTransiton.delay, transition.delay);
+ XCTAssertEqual(mglLight.colorTransiton.duration, transition.duration);
+
+ mbgl::style::PropertyValue<mbgl::Color> colorProperty = { { 0, 0, 0, 1 } };
+ light.setColor(colorProperty);
+ light.setColorTransition(transitionOptions);
+
+ lightFromMGLlight = [mglLight mbglLight];
+
+ colorComponents = CGColorGetComponents(colorValue.CGColor);
+ color = lightFromMGLlight.getColor().asConstant();
+ XCTAssertEqual(light.getColor().asConstant(),lightFromMGLlight.getColor().asConstant());
+ colorTransition = lightFromMGLlight.getColorTransition();
+ XCTAssert(colorTransition.delay && MGLTimeIntervalFromDuration(*colorTransition.delay) == transition.delay);
+ XCTAssert(colorTransition.duration && MGLTimeIntervalFromDuration(*colorTransition.duration) == transition.duration);
+ }
+
+ // intensity
+ {
+ mbgl::style::Light light;
+ MGLLight *mglLight = [[MGLLight alloc] initWithMBGLLight:&light];
+ NSAssert([mglLight.intensity isKindOfClass:[MGLConstantStyleValue class]], @"mglLight.intensity isn’t a MGLConstantStyleValue.");
+ NSNumber *intensityNumber = ((MGLConstantStyleValue *)mglLight.intensity).rawValue;
+ auto intensity = light.getDefaultIntensity();
+
+ XCTAssert(intensityNumber.floatValue == intensity);
+ XCTAssertEqual(mglLight.intensityTransition.delay, defaultTransition.delay);
+ XCTAssertEqual(mglLight.intensityTransition.duration, defaultTransition.duration);
+
+ auto lightFromMGLlight = [mglLight mbglLight];
+
+ XCTAssertEqual(intensity, lightFromMGLlight.getIntensity().asConstant());
+ auto intensityTransition = lightFromMGLlight.getIntensityTransition();
+ XCTAssert(intensityTransition.delay && MGLTimeIntervalFromDuration(*intensityTransition.delay) == defaultTransition.delay);
+ XCTAssert(intensityTransition.duration && MGLTimeIntervalFromDuration(*intensityTransition.duration) == defaultTransition.duration);
+
+ NSNumber *intensityValue = @0.4;
+ MGLStyleValue<NSNumber *> *intensityStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:intensityValue];
+ mglLight.intensity = intensityStyleValue;
+ mglLight.intensityTransition = transition;
+
+ NSAssert([mglLight.intensity isKindOfClass:[MGLConstantStyleValue class]], @"mglLight.intensity isn’t a MGLConstantStyleValue.");
+ intensityNumber = ((MGLConstantStyleValue *)mglLight.intensity).rawValue;
+ XCTAssert(intensityNumber.floatValue == intensityValue.floatValue);
+ XCTAssertEqual(mglLight.intensityTransition.delay, transition.delay);
+ XCTAssertEqual(mglLight.intensityTransition.duration, transition.duration);
+
+ mbgl::style::PropertyValue<float> intensityProperty = { 0.4 };
+ light.setIntensity(intensityProperty);
+ light.setIntensityTransition(transitionOptions);
+
+ lightFromMGLlight = [mglLight mbglLight];
+
+ XCTAssertEqual(light.getIntensity().asConstant(), lightFromMGLlight.getIntensity().asConstant());
+ intensityTransition = lightFromMGLlight.getIntensityTransition();
+ XCTAssert(intensityTransition.delay && MGLTimeIntervalFromDuration(*intensityTransition.delay) == transition.delay);
+ XCTAssert(intensityTransition.duration && MGLTimeIntervalFromDuration(*intensityTransition.duration) == transition.duration);
+
+ }
+
+}
+
+- (void)testValueAdditions {
+ MGLSphericalPosition position = MGLSphericalPositionMake(1.15, 210, 30);
+
+ XCTAssertEqual([NSValue valueWithMGLSphericalPosition:position].MGLSphericalPositionValue.radial, position.radial);
+ XCTAssertEqual([NSValue valueWithMGLSphericalPosition:position].MGLSphericalPositionValue.azimuthal, position.azimuthal);
+ XCTAssertEqual([NSValue valueWithMGLSphericalPosition:position].MGLSphericalPositionValue.polar, position.polar);
+ XCTAssertEqual([NSValue valueWithMGLLightAnchor:MGLLightAnchorMap].MGLLightAnchorValue, MGLLightAnchorMap);
+ XCTAssertEqual([NSValue valueWithMGLLightAnchor:MGLLightAnchorViewport].MGLLightAnchorValue, MGLLightAnchorViewport);
+}
+
+@end