[darwin] arbitrary offline region geometries
This commit is contained in:
committed by
Ivo van Dongen
parent
4fedcf8d06
commit
ca0f2f925d
@@ -3,6 +3,9 @@
|
||||
#import "MGLOfflineStorage_Private.h"
|
||||
#import "MGLOfflineRegion_Private.h"
|
||||
#import "MGLTilePyramidOfflineRegion.h"
|
||||
#import "MGLTilePyramidOfflineRegion_Private.h"
|
||||
#import "MGLShapeOfflineRegion.h"
|
||||
#import "MGLShapeOfflineRegion_Private.h"
|
||||
|
||||
#import "NSValue+MGLAdditions.h"
|
||||
|
||||
@@ -27,6 +30,12 @@ const MGLExceptionName MGLInvalidOfflinePackException = @"MGLInvalidOfflinePackE
|
||||
} \
|
||||
} while (NO);
|
||||
|
||||
@interface MGLTilePyramidOfflineRegion () <MGLOfflineRegion_Private, MGLTilePyramidOfflineRegion_Private>
|
||||
@end
|
||||
|
||||
@interface MGLShapeOfflineRegion () <MGLOfflineRegion_Private, MGLShapeOfflineRegion_Private>
|
||||
@end
|
||||
|
||||
class MBGLOfflineRegionObserver : public mbgl::OfflineRegionObserver {
|
||||
public:
|
||||
MBGLOfflineRegionObserver(MGLOfflinePack *pack_) : pack(pack_) {}
|
||||
@@ -78,7 +87,17 @@ private:
|
||||
|
||||
const mbgl::OfflineRegionDefinition ®ionDefinition = _mbglOfflineRegion->getDefinition();
|
||||
NSAssert([MGLTilePyramidOfflineRegion conformsToProtocol:@protocol(MGLOfflineRegion_Private)], @"MGLTilePyramidOfflineRegion should conform to MGLOfflineRegion_Private.");
|
||||
return [(id <MGLOfflineRegion_Private>)[MGLTilePyramidOfflineRegion alloc] initWithOfflineRegionDefinition:regionDefinition];
|
||||
NSAssert([MGLShapeOfflineRegion conformsToProtocol:@protocol(MGLOfflineRegion_Private)], @"MGLShapeOfflineRegion should conform to MGLOfflineRegion_Private.");
|
||||
|
||||
|
||||
|
||||
return regionDefinition.match(
|
||||
[&] (const mbgl::OfflineTilePyramidRegionDefinition def){
|
||||
return (id <MGLOfflineRegion>)[[MGLTilePyramidOfflineRegion alloc] initWithOfflineRegionDefinition:def];
|
||||
},
|
||||
[&] (const mbgl::OfflineGeometryRegionDefinition& def){
|
||||
return (id <MGLOfflineRegion>)[[MGLShapeOfflineRegion alloc] initWithOfflineRegionDefinition:def];
|
||||
});
|
||||
}
|
||||
|
||||
- (NSData *)context {
|
||||
|
||||
@@ -4,12 +4,21 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
An object conforming to the `MGLOfflineRegion` protocol determines which
|
||||
resources are required by an `MGLOfflinePack` object. At present, only
|
||||
instances of `MGLTilePyramidOfflineRegion` may be used as `MGLOfflinePack`
|
||||
regions, but additional conforming implementations may be added in the future.
|
||||
resources are required by an `MGLOfflinePack` object.
|
||||
*/
|
||||
@protocol MGLOfflineRegion <NSObject>
|
||||
|
||||
/**
|
||||
URL of the style whose resources are required for offline viewing.
|
||||
|
||||
In addition to the JSON stylesheet, different styles may require different font
|
||||
glyphs, sprite sheets, and other resources.
|
||||
|
||||
The URL may be a full HTTP or HTTPS URL or a Mapbox URL indicating the style’s
|
||||
map ID (`mapbox://styles/{user}/{style}`).
|
||||
*/
|
||||
@property (nonatomic, readonly) NSURL *styleURL;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -8,15 +8,6 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@protocol MGLOfflineRegion_Private <MGLOfflineRegion>
|
||||
|
||||
/**
|
||||
Initializes and returns an offline region backed by the given C++ region
|
||||
definition object.
|
||||
|
||||
@param definition A reference to an offline region definition backing the
|
||||
offline region.
|
||||
*/
|
||||
- (instancetype)initWithOfflineRegionDefinition:(const mbgl::OfflineRegionDefinition &)definition;
|
||||
|
||||
/**
|
||||
Creates and returns a C++ offline region definition corresponding to the
|
||||
receiver.
|
||||
|
||||
@@ -285,7 +285,7 @@ const MGLExceptionName MGLUnsupportedRegionTypeException = @"MGLUnsupportedRegio
|
||||
return;
|
||||
}
|
||||
|
||||
const mbgl::OfflineTilePyramidRegionDefinition regionDefinition = [(id <MGLOfflineRegion_Private>)region offlineRegionDefinition];
|
||||
const mbgl::OfflineRegionDefinition regionDefinition = [(id <MGLOfflineRegion_Private>)region offlineRegionDefinition];
|
||||
mbgl::OfflineRegionMetadata metadata(context.length);
|
||||
[context getBytes:&metadata[0] length:metadata.size()];
|
||||
self.mbglFileSource->createOfflineRegion(regionDefinition, metadata, [&, completion](mbgl::expected<mbgl::OfflineRegion, std::exception_ptr> mbglOfflineRegion) {
|
||||
|
||||
72
platform/darwin/src/MGLShapeOfflineRegion.h
Normal file
72
platform/darwin/src/MGLShapeOfflineRegion.h
Normal file
@@ -0,0 +1,72 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "MGLFoundation.h"
|
||||
#import "MGLOfflineRegion.h"
|
||||
#import "MGLShape.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
An offline region defined by a style URL, geographic shape, and
|
||||
range of zoom levels.
|
||||
|
||||
This class requires fewer resources than MGLTilePyramidOfflineRegion
|
||||
for irregularly shaped regions.
|
||||
*/
|
||||
MGL_EXPORT
|
||||
@interface MGLShapeOfflineRegion : NSObject <MGLOfflineRegion, NSSecureCoding, NSCopying>
|
||||
|
||||
/**
|
||||
The shape for the geographic region covered by the downloaded
|
||||
tiles.
|
||||
*/
|
||||
@property (nonatomic, readonly) MGLShape *shape;
|
||||
|
||||
/**
|
||||
The minimum zoom level for which to download tiles and other resources.
|
||||
|
||||
For more information about zoom levels, `-[MGLMapView zoomLevel]`.
|
||||
*/
|
||||
@property (nonatomic, readonly) double minimumZoomLevel;
|
||||
|
||||
/**
|
||||
The maximum zoom level for which to download tiles and other resources.
|
||||
|
||||
For more information about zoom levels, `-[MGLMapView zoomLevel]`.
|
||||
*/
|
||||
@property (nonatomic, readonly) double maximumZoomLevel;
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
/**
|
||||
Initializes a newly created offline region with the given style URL, geometry,
|
||||
and range of zoom levels.
|
||||
|
||||
This is the designated initializer for `MGLShapeOfflineRegion`.
|
||||
|
||||
@param styleURL URL of the map style for which to download resources. The URL
|
||||
may be a full HTTP or HTTPS URL or a Mapbox URL indicating the style’s map
|
||||
ID (`mapbox://styles/{user}/{style}`). Specify `nil` for the default style.
|
||||
Relative file URLs cannot be used as offline style URLs. To download the
|
||||
online resources required by a local style, specify a URL to an online copy
|
||||
of the style.
|
||||
@param shape The shape of the geographic region to be covered by
|
||||
the downloaded tiles.
|
||||
@param minimumZoomLevel The minimum zoom level to be covered by the downloaded
|
||||
tiles. This parameter should be set to at least 0 but no greater than the
|
||||
value of the `maximumZoomLevel` parameter. For each required tile source, if
|
||||
this parameter is set to a value less than the tile source’s minimum zoom
|
||||
level, the download covers zoom levels down to the tile source’s minimum
|
||||
zoom level.
|
||||
@param maximumZoomLevel The maximum zoom level to be covered by the downloaded
|
||||
tiles. This parameter should be set to at least the value of the
|
||||
`minimumZoomLevel` parameter. For each required tile source, if this
|
||||
parameter is set to a value greater than the tile source’s minimum zoom
|
||||
level, the download covers zoom levels up to the tile source’s maximum zoom
|
||||
level.
|
||||
*/
|
||||
- (instancetype)initWithStyleURL:(nullable NSURL *)styleURL shape:(MGLShape *)shape fromZoomLevel:(double)minimumZoomLevel toZoomLevel:(double)maximumZoomLevel NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
120
platform/darwin/src/MGLShapeOfflineRegion.mm
Normal file
120
platform/darwin/src/MGLShapeOfflineRegion.mm
Normal file
@@ -0,0 +1,120 @@
|
||||
#import "MGLShapeOfflineRegion.h"
|
||||
|
||||
#if !TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#else
|
||||
#import <UIKit/UIKit.h>
|
||||
#endif
|
||||
|
||||
#import "MGLOfflineRegion_Private.h"
|
||||
#import "MGLShapeOfflineRegion_Private.h"
|
||||
#import "MGLFeature_Private.h"
|
||||
#import "MGLShape_Private.h"
|
||||
#import "MGLStyle.h"
|
||||
|
||||
@interface MGLShapeOfflineRegion () <MGLOfflineRegion_Private, MGLShapeOfflineRegion_Private>
|
||||
|
||||
@end
|
||||
|
||||
@implementation MGLShapeOfflineRegion {
|
||||
NSURL *_styleURL;
|
||||
}
|
||||
|
||||
@synthesize styleURL = _styleURL;
|
||||
|
||||
+ (BOOL)supportsSecureCoding {
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
[NSException raise:@"Method unavailable"
|
||||
format:
|
||||
@"-[MGLShapeOfflineRegion init] is unavailable. "
|
||||
@"Use -initWithStyleURL:shape:fromZoomLevel:toZoomLevel: instead."];
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (instancetype)initWithStyleURL:(NSURL *)styleURL shape:(MGLShape *)shape fromZoomLevel:(double)minimumZoomLevel toZoomLevel:(double)maximumZoomLevel {
|
||||
if (self = [super init]) {
|
||||
if (!styleURL) {
|
||||
styleURL = [MGLStyle streetsStyleURLWithVersion:MGLStyleDefaultVersion];
|
||||
}
|
||||
|
||||
if (!styleURL.scheme) {
|
||||
[NSException raise:@"Invalid style URL" format:
|
||||
@"%@ does not support setting a relative file URL as the style URL. "
|
||||
@"To download the online resources required by this style, "
|
||||
@"specify a URL to an online copy of this style. "
|
||||
@"For Mapbox-hosted styles, use the mapbox: scheme.",
|
||||
NSStringFromClass([self class])];
|
||||
}
|
||||
|
||||
_styleURL = styleURL;
|
||||
_shape = shape;
|
||||
_minimumZoomLevel = minimumZoomLevel;
|
||||
_maximumZoomLevel = maximumZoomLevel;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithOfflineRegionDefinition:(const mbgl::OfflineGeometryRegionDefinition &)definition {
|
||||
NSURL *styleURL = [NSURL URLWithString:@(definition.styleURL.c_str())];
|
||||
MGLShape *shape = MGLShapeFromGeoJSON(definition.geometry);
|
||||
return [self initWithStyleURL:styleURL shape:shape fromZoomLevel:definition.minZoom toZoomLevel:definition.maxZoom];
|
||||
}
|
||||
|
||||
- (const mbgl::OfflineRegionDefinition)offlineRegionDefinition {
|
||||
#if TARGET_OS_IPHONE || TARGET_OS_SIMULATOR
|
||||
const float scaleFactor = [UIScreen instancesRespondToSelector:@selector(nativeScale)] ? [[UIScreen mainScreen] nativeScale] : [[UIScreen mainScreen] scale];
|
||||
#elif TARGET_OS_MAC
|
||||
const float scaleFactor = [NSScreen mainScreen].backingScaleFactor;
|
||||
#endif
|
||||
return mbgl::OfflineGeometryRegionDefinition(_styleURL.absoluteString.UTF8String,
|
||||
_shape.geometryObject,
|
||||
_minimumZoomLevel, _maximumZoomLevel,
|
||||
scaleFactor);
|
||||
}
|
||||
|
||||
- (nullable instancetype)initWithCoder:(NSCoder *)coder {
|
||||
NSURL *styleURL = [coder decodeObjectForKey:@"styleURL"];
|
||||
MGLShape * shape = [coder decodeObjectForKey:@"shape"];
|
||||
double minimumZoomLevel = [coder decodeDoubleForKey:@"minimumZoomLevel"];
|
||||
double maximumZoomLevel = [coder decodeDoubleForKey:@"maximumZoomLevel"];
|
||||
|
||||
return [self initWithStyleURL:styleURL shape:shape fromZoomLevel:minimumZoomLevel toZoomLevel:maximumZoomLevel];
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(NSCoder *)coder
|
||||
{
|
||||
[coder encodeObject:_styleURL forKey:@"styleURL"];
|
||||
[coder encodeObject:_shape forKey:@"shape"];
|
||||
[coder encodeDouble:_maximumZoomLevel forKey:@"maximumZoomLevel"];
|
||||
[coder encodeDouble:_minimumZoomLevel forKey:@"minimumZoomLevel"];
|
||||
}
|
||||
|
||||
- (id)copyWithZone:(nullable NSZone *)zone {
|
||||
return [[[self class] allocWithZone:zone] initWithStyleURL:_styleURL shape:_shape fromZoomLevel:_minimumZoomLevel toZoomLevel:_maximumZoomLevel];
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(id)other {
|
||||
if (other == self) {
|
||||
return YES;
|
||||
}
|
||||
if (![other isKindOfClass:[self class]]) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
MGLShapeOfflineRegion *otherRegion = other;
|
||||
return (_minimumZoomLevel == otherRegion->_minimumZoomLevel
|
||||
&& _maximumZoomLevel == otherRegion->_maximumZoomLevel
|
||||
&& _shape.geometryObject == otherRegion->_shape.geometryObject
|
||||
&& [_styleURL isEqual:otherRegion->_styleURL]);
|
||||
}
|
||||
|
||||
- (NSUInteger)hash {
|
||||
return (_styleURL.hash
|
||||
+ _shape.hash
|
||||
+ @(_minimumZoomLevel).hash + @(_maximumZoomLevel).hash);
|
||||
}
|
||||
|
||||
@end
|
||||
22
platform/darwin/src/MGLShapeOfflineRegion_Private.h
Normal file
22
platform/darwin/src/MGLShapeOfflineRegion_Private.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "MGLOfflineRegion.h"
|
||||
|
||||
#include <mbgl/storage/offline.hpp>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@protocol MGLShapeOfflineRegion_Private <MGLOfflineRegion>
|
||||
|
||||
/**
|
||||
Initializes and returns an offline region backed by the given C++ region
|
||||
definition object.
|
||||
|
||||
@param definition A reference to an offline region definition backing the
|
||||
offline region.
|
||||
*/
|
||||
- (instancetype)initWithOfflineRegionDefinition:(const mbgl::OfflineGeometryRegionDefinition &)definition;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -9,21 +9,13 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
/**
|
||||
An offline region defined by a style URL, geographic coordinate bounds, and
|
||||
range of zoom levels.
|
||||
|
||||
To minimize the resources required by an irregularly shaped offline region,
|
||||
use the MGLShapeOfflineRegion class instead.
|
||||
*/
|
||||
MGL_EXPORT
|
||||
@interface MGLTilePyramidOfflineRegion : NSObject <MGLOfflineRegion, NSSecureCoding, NSCopying>
|
||||
|
||||
/**
|
||||
URL of the style whose resources are required for offline viewing.
|
||||
|
||||
In addition to the JSON stylesheet, different styles may require different font
|
||||
glyphs, sprite sheets, and other resources.
|
||||
|
||||
The URL may be a full HTTP or HTTPS URL or a Mapbox URL indicating the style’s
|
||||
map ID (`mapbox://styles/{user}/{style}`).
|
||||
*/
|
||||
@property (nonatomic, readonly) NSURL *styleURL;
|
||||
|
||||
/**
|
||||
The coordinate bounds for the geographic region covered by the downloaded
|
||||
tiles.
|
||||
|
||||
@@ -5,10 +5,11 @@
|
||||
#endif
|
||||
|
||||
#import "MGLOfflineRegion_Private.h"
|
||||
#import "MGLTilePyramidOfflineRegion_Private.h"
|
||||
#import "MGLGeometry_Private.h"
|
||||
#import "MGLStyle.h"
|
||||
|
||||
@interface MGLTilePyramidOfflineRegion () <MGLOfflineRegion_Private>
|
||||
@interface MGLTilePyramidOfflineRegion () <MGLOfflineRegion_Private, MGLTilePyramidOfflineRegion_Private>
|
||||
|
||||
@end
|
||||
|
||||
@@ -52,7 +53,7 @@
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithOfflineRegionDefinition:(const mbgl::OfflineRegionDefinition &)definition {
|
||||
- (instancetype)initWithOfflineRegionDefinition:(const mbgl::OfflineTilePyramidRegionDefinition &)definition {
|
||||
NSURL *styleURL = [NSURL URLWithString:@(definition.styleURL.c_str())];
|
||||
MGLCoordinateBounds bounds = MGLCoordinateBoundsFromLatLngBounds(definition.bounds);
|
||||
return [self initWithStyleURL:styleURL bounds:bounds fromZoomLevel:definition.minZoom toZoomLevel:definition.maxZoom];
|
||||
|
||||
22
platform/darwin/src/MGLTilePyramidOfflineRegion_Private.h
Normal file
22
platform/darwin/src/MGLTilePyramidOfflineRegion_Private.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "MGLOfflineRegion.h"
|
||||
|
||||
#include <mbgl/storage/offline.hpp>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@protocol MGLTilePyramidOfflineRegion_Private <MGLOfflineRegion>
|
||||
|
||||
/**
|
||||
Initializes and returns an offline region backed by the given C++ region
|
||||
definition object.
|
||||
|
||||
@param definition A reference to an offline region definition backing the
|
||||
offline region.
|
||||
*/
|
||||
- (instancetype)initWithOfflineRegionDefinition:(const mbgl::OfflineTilePyramidRegionDefinition &)definition;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
Reference in New Issue
Block a user