Skip to content
This repository was archived by the owner on Aug 8, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
86b560e
correction path to JAVA_HOME (Added /Contents/Home
tobrun Aug 23, 2015
5636eb8
Replaced name outdated menu item of Android Studio
tobrun Aug 23, 2015
d513910
port mat4.perspective and mat4.rotate_x
ansis Aug 13, 2015
8d22e2b
port perspective projection matrix from -js
ansis Aug 14, 2015
2535e66
hacks to see stuff
ansis Aug 14, 2015
f0885d3
port mat2 from gl-matrix
ansis Aug 14, 2015
3027f8c
port line rendering fixes for perspective views
ansis Aug 14, 2015
be36ce0
fix fill antialiasing for perspective views
ansis Aug 14, 2015
494489f
fix symbol rendering in perspective view
ansis Aug 14, 2015
bc92c2d
fix symbol collision detection in perspective view
ansis Aug 14, 2015
554425b
fix earthquakes in perspective view
ansis Aug 14, 2015
cef1b25
port invert and transformMat4 from gl-matrix
ansis Aug 17, 2015
0d68c4f
load correct covering tiles in perspective view
ansis Aug 17, 2015
9e68e49
fix depth clipping in perspective view
ansis Aug 17, 2015
14dee43
add map.setPitch(pitch) and map.getPitch()
ansis Aug 18, 2015
19c256e
make fill-image tests less sensitive
ansis Aug 18, 2015
99c5976
port minor collision code cleanup, fix #1705
ansis Aug 20, 2015
51c9386
fix LatLng --> point for perspective views
ansis Aug 20, 2015
10f0d8d
fix circle rendering
ansis Aug 25, 2015
36d71c9
move the point origin back to bottom-left
ansis Aug 25, 2015
0e45694
Merge branch 'master' into perspective-without-y-flip
1ec5 Aug 25, 2015
d8ed33c
Merge remote-tracking branch 'upstream/master' into perspective-witho…
friedbunny Aug 26, 2015
42dc533
iOS perspective gesture support
friedbunny Aug 18, 2015
53c2102
Merge branch 'master' into perspective-without-y-flip
friedbunny Aug 27, 2015
d703e58
add Point <--> LatLng conversion tests
ansis Aug 27, 2015
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions include/mbgl/ios/MGLMapView.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,13 @@ IB_DESIGNABLE
* The default value of this property is `YES`. */
@property(nonatomic, getter=isRotateEnabled) BOOL rotateEnabled;

/** A Boolean value that determines whether the user may change the pitch (tilt) of the map.
*
* This property controls only user interactions with the map. If you set the value of this property to `NO`, you may still change the pitch of the map programmatically.
*
* The default value of this property is `YES`. */
@property(nonatomic, getter=isPitchEnabled) BOOL pitchEnabled;

/** The compass image view shown in the upper-right when the map is rotated. */
@property (nonatomic, readonly) UIImageView *compassView;

Expand Down Expand Up @@ -173,6 +180,20 @@ IB_DESIGNABLE
/** Resets the map rotation to a northern heading. */
- (IBAction)resetNorth;

/** The pitch of the map (measured in degrees).
*
* The default value `0` shows a completely flat map. Maximum value is `60`. */
@property (nonatomic) double pitch;

/** Changes the pitch of the map.
* @param pitch The pitch of the map (measured in degrees) relative to top-down.
*
* Changing the pitch tilts the map without changing the current center coordinate or zoom level. */
- (void)setPitch:(double)pitch;

/** Resets the map pitch to head-on. */
- (IBAction)resetPitch;

#pragma mark - Converting Map Coordinates

/** @name Converting Map Coordinates */
Expand Down
4 changes: 4 additions & 0 deletions include/mbgl/map/map.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,10 @@ class Map : private util::noncopyable {
double getBearing() const;
void resetNorth();

// Pitch
void setPitch(double pitch);
double getPitch() const;

// Size
uint16_t getWidth() const;
uint16_t getHeight() const;
Expand Down
1 change: 1 addition & 0 deletions include/mbgl/platform/darwin/settings_nsuserdefaults.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class Settings_NSUserDefaults {
double latitude = 0;
double zoom = 0;
double bearing = 0;
double pitch = 0;

MGLUserTrackingMode userTrackingMode = MGLUserTrackingModeNone;
bool showsUserLocation = false;
Expand Down
13 changes: 8 additions & 5 deletions include/mbgl/util/mat4.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,19 @@

namespace mbgl {

typedef std::array<float, 16> mat4;
typedef std::array<double, 16> mat4;

namespace matrix {

void identity(mat4& out);
void ortho(mat4& out, float left, float right, float bottom, float top, float near, float far);
bool invert(mat4& out, mat4& a);
void ortho(mat4& out, double left, double right, double bottom, double top, double near, double far);
void perspective(mat4& out, double fovy, double aspect, double near, double far);
void copy(mat4& out, const mat4& a);
void translate(mat4& out, const mat4& a, float x, float y, float z);
void rotate_z(mat4& out, const mat4& a, float rad);
void scale(mat4& out, const mat4& a, float x, float y, float z);
void translate(mat4& out, const mat4& a, double x, double y, double z);
void rotate_x(mat4& out, const mat4& a, double rad);
void rotate_z(mat4& out, const mat4& a, double rad);
void scale(mat4& out, const mat4& a, double x, double y, double z);
void multiply(mat4& out, const mat4& a, const mat4& b);

}
Expand Down
2 changes: 2 additions & 0 deletions ios/app/MBXViewController.mm
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ - (void)saveState:(__unused NSNotification *)notification
settings->latitude = self.mapView.centerCoordinate.latitude;
settings->zoom = self.mapView.zoomLevel;
settings->bearing = self.mapView.direction;
settings->pitch = self.mapView.pitch;
settings->debug = self.mapView.isDebugActive;
settings->userTrackingMode = self.mapView.userTrackingMode;
settings->showsUserLocation = self.mapView.showsUserLocation;
Expand All @@ -99,6 +100,7 @@ - (void)restoreState:(__unused NSNotification *)notification
settings->load();
[self.mapView setCenterCoordinate:CLLocationCoordinate2DMake(settings->latitude, settings->longitude) zoomLevel:settings->zoom animated:NO];
self.mapView.direction = settings->bearing;
self.mapView.pitch = settings->pitch;
self.mapView.userTrackingMode = settings->userTrackingMode;
self.mapView.showsUserLocation = settings->showsUserLocation;
[self.mapView setDebugActive:settings->debug];
Expand Down
3 changes: 3 additions & 0 deletions platform/darwin/settings_nsuserdefaults.mm
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
@"latitude" : @(latitude),
@"zoom" : @(zoom),
@"bearing" : @(bearing),
@"pitch" : @(pitch),
@"userTrackingMode" : @(userTrackingMode),
@"showsUserLocation" : @(showsUserLocation),
@"debug" : @(debug),
Expand All @@ -26,6 +27,7 @@
latitude = [settings[@"latitude"] doubleValue];
zoom = [settings[@"zoom"] doubleValue];
bearing = [settings[@"bearing"] doubleValue];
pitch = [settings[@"pitch"] doubleValue];
debug = [settings[@"debug"] boolValue];

unsigned uncheckedTrackingMode = [settings[@"trackingMode"] unsignedIntValue];
Expand All @@ -44,6 +46,7 @@
@"latitude" : @(latitude),
@"zoom" : @(zoom),
@"bearing" : @(bearing),
@"pitch" : @(pitch),
@"userTrackingMode" : @(userTrackingMode),
@"showsUserLocation" : @(showsUserLocation),
@"debug" : @(debug),
Expand Down
111 changes: 107 additions & 4 deletions platform/ios/MGLMapView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ @interface MGLMapView () <UIGestureRecognizerDelegate, GLKViewDelegate, CLLocati
@property (nonatomic) UIPinchGestureRecognizer *pinch;
@property (nonatomic) UIRotationGestureRecognizer *rotate;
@property (nonatomic) UILongPressGestureRecognizer *quickZoom;
@property (nonatomic) UIPanGestureRecognizer *twoFingerDrag;
@property (nonatomic) NSMapTable *annotationIDsByAnnotation;
@property (nonatomic) NS_MUTABLE_DICTIONARY_OF(NSString *, MGLAnnotationImage *) *annotationImages;
@property (nonatomic) std::vector<uint32_t> annotationsNearbyLastTap;
Expand Down Expand Up @@ -338,6 +339,15 @@ - (void)commonInit
[twoFingerTap requireGestureRecognizerToFail:_pinch];
[twoFingerTap requireGestureRecognizerToFail:_rotate];
[self addGestureRecognizer:twoFingerTap];

_twoFingerDrag = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleTwoFingerDragGesture:)];
_twoFingerDrag.minimumNumberOfTouches = 2;
_twoFingerDrag.maximumNumberOfTouches = 2;
_twoFingerDrag.delegate = self;
[_twoFingerDrag requireGestureRecognizerToFail:twoFingerTap];
[_twoFingerDrag requireGestureRecognizerToFail:_pan];
[self addGestureRecognizer:_twoFingerDrag];
_pitchEnabled = YES;

if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)
{
Expand Down Expand Up @@ -1326,6 +1336,59 @@ - (void)handleQuickZoomGesture:(UILongPressGestureRecognizer *)quickZoom
}
}

- (void)handleTwoFingerDragGesture:(UIPanGestureRecognizer *)twoFingerDrag
{
if ( ! self.isPitchEnabled) return;

_mbglMap->cancelTransitions();

if (twoFingerDrag.state == UIGestureRecognizerStateBegan)
{
[self trackGestureEvent:MGLEventGesturePitchStart forRecognizer:twoFingerDrag];
}
else if (twoFingerDrag.state == UIGestureRecognizerStateBegan || twoFingerDrag.state == UIGestureRecognizerStateChanged)
{
CGFloat gestureDistance = CGPoint([twoFingerDrag translationInView:twoFingerDrag.view]).y;
double currentPitch = _mbglMap->getPitch();
double minPitch = 0;
double maxPitch = 60.0;
double slowdown = 20.0;

double pitchNew = fmax(fmin(currentPitch - (gestureDistance / slowdown), maxPitch), minPitch);

_mbglMap->setPitch(pitchNew);
}
else if (twoFingerDrag.state == UIGestureRecognizerStateEnded || twoFingerDrag.state == UIGestureRecognizerStateCancelled)
{
[self unrotateIfNeededAnimated:YES];

//[self notifyMapChange:(mbgl::MapChangeRegionDidChange)];
}

}

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
if ([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]])
{
UIPanGestureRecognizer *panGesture = (UIPanGestureRecognizer *)gestureRecognizer;

if (panGesture.minimumNumberOfTouches == 2)
{
CGPoint velocity = [panGesture velocityInView:panGesture.view];
double gestureAngle = MGLDegreesFromRadians(atan(velocity.y / velocity.x));
double horizontalToleranceDegrees = 20.0;

// cancel if gesture angle is not 90º±20º (more or less vertical)
if ( ! (fabs((fabs(gestureAngle) - 90.0)) < horizontalToleranceDegrees))
{
return NO;
}
}
}
return YES;
}

- (void)handleCalloutAccessoryTapGesture:(UITapGestureRecognizer *)tap
{
if ([self.delegate respondsToSelector:@selector(mapView:annotation:calloutAccessoryControlTapped:)])
Expand Down Expand Up @@ -1419,6 +1482,11 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(N
return [NSSet setWithObject:@"allowsRotating"];
}

+ (NS_SET_OF(NSString *) *)keyPathsForValuesAffectingPitchEnabled
{
return [NSSet setWithObject:@"allowsPitching"];
}

- (void)setDebugActive:(BOOL)debugActive
{
_mbglMap->setDebug(debugActive);
Expand Down Expand Up @@ -1617,6 +1685,25 @@ - (void)setDirection:(CLLocationDirection)direction
[self setDirection:direction animated:NO];
}

- (double)pitch
{
return _mbglMap->getPitch();
}

- (void)setPitch:(double)pitch
{
// constrain pitch to between 0º and 60º
//
_mbglMap->setPitch(fmax(fmin(pitch, 60), 0));

//[self notifyMapChange:(mbgl::MapChangeRegionDidChange)];
}

- (void)resetPitch
{
[self setPitch:0];
}

- (CLLocationCoordinate2D)convertPoint:(CGPoint)point toCoordinateFromView:(nullable UIView *)view
{
CGPoint convertedPoint = [self convertPoint:point fromView:view];
Expand Down Expand Up @@ -2630,10 +2717,11 @@ - (void)notifyMapChange:(mbgl::MapChange)change
{
[self updateCompass];

if (self.pan.state == UIGestureRecognizerStateChanged ||
self.pinch.state == UIGestureRecognizerStateChanged ||
self.rotate.state == UIGestureRecognizerStateChanged ||
self.quickZoom.state == UIGestureRecognizerStateChanged) return;
if (self.pan.state == UIGestureRecognizerStateChanged ||
self.pinch.state == UIGestureRecognizerStateChanged ||
self.rotate.state == UIGestureRecognizerStateChanged ||
self.quickZoom.state == UIGestureRecognizerStateChanged ||
self.twoFingerDrag.state == UIGestureRecognizerStateChanged) return;

if (self.isAnimatingGesture) return;

Expand Down Expand Up @@ -3062,6 +3150,21 @@ - (void)setAllowsRotating:(BOOL)allowsRotating
self.rotateEnabled = allowsRotating;
}

+ (NS_SET_OF(NSString *) *)keyPathsForValuesAffectingAllowsPitching
{
return [NSSet setWithObject:@"pitchEnabled"];
}

- (BOOL)allowsPitching
{
return self.pitchEnabled;
}

- (void)setAllowsPitching:(BOOL)allowsPitching
{
self.pitchEnabled = allowsPitching;
}

- (void)didReceiveMemoryWarning
{
_mbglMap->onLowMemory();
Expand Down
1 change: 1 addition & 0 deletions platform/ios/MGLMapboxEvents.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ extern NSString *const MGLEventGestureQuickZoom;
extern NSString *const MGLEventGesturePanStart;
extern NSString *const MGLEventGesturePinchStart;
extern NSString *const MGLEventGestureRotateStart;
extern NSString *const MGLEventGesturePitchStart;

typedef NS_DICTIONARY_OF(NSString *, id) MGLMapboxEventAttributes;
typedef NS_MUTABLE_DICTIONARY_OF(NSString *, id) MGLMutableMapboxEventAttributes;
Expand Down
1 change: 1 addition & 0 deletions platform/ios/MGLMapboxEvents.m
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
NSString *const MGLEventGesturePanStart = @"Pan";
NSString *const MGLEventGesturePinchStart = @"Pinch";
NSString *const MGLEventGestureRotateStart = @"Rotation";
NSString *const MGLEventGesturePitchStart = @"Pitch";

const NSUInteger MGLMaximumEventsPerFlush = 20;
const NSTimeInterval MGLFlushInterval = 60;
Expand Down
4 changes: 1 addition & 3 deletions src/mbgl/map/live_tile_data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,7 @@ LiveTileData::LiveTileData(const TileID& id_,
style_,
style_.layers,
state,
std::make_unique<CollisionTile>(id_.z, 4096,
source_.tile_size * id.overscaling,
0, false)) {
std::make_unique<CollisionTile>(0, 0, false)) {
state = State::loaded;

if (!tile) {
Expand Down
16 changes: 14 additions & 2 deletions src/mbgl/map/map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,18 @@ void Map::resetNorth() {
}


#pragma mark - Pitch

void Map::setPitch(double pitch) {
transform->setPitch(std::min(pitch, 60.0) * M_PI / 180);
update(Update::Repaint);
}

double Map::getPitch() const {
return transform->getPitch() / M_PI * 180;
}


#pragma mark - Projection

void Map::getWorldBoundsMeters(ProjectedMeters& sw, ProjectedMeters& ne) const {
Expand All @@ -292,11 +304,11 @@ const LatLng Map::latLngForProjectedMeters(const ProjectedMeters projectedMeters
}

const vec2<double> Map::pixelForLatLng(const LatLng latLng) const {
return transform->getState().pixelForLatLng(latLng);
return transform->getState().latLngToPoint(latLng);
}

const LatLng Map::latLngForPixel(const vec2<double> pixel) const {
return transform->getState().latLngForPixel(pixel);
return transform->getState().pointToLatLng(pixel);
}

#pragma mark - Annotations
Expand Down
15 changes: 8 additions & 7 deletions src/mbgl/map/source.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <mbgl/storage/response.hpp>
#include <mbgl/util/math.hpp>
#include <mbgl/util/box.hpp>
#include <mbgl/util/tile_coordinate.hpp>
#include <mbgl/util/mapbox.hpp>
#include <mbgl/storage/file_source.hpp>
#include <mbgl/style/style_layer.hpp>
Expand Down Expand Up @@ -284,8 +285,8 @@ TileData::State Source::addTile(MapData& data,

// If we don't find working tile data, we're just going to load it.
if (info.type == SourceType::Vector) {
auto tileData = std::make_shared<VectorTileData>(normalized_id, style, info,
transformState.getAngle(), data.getCollisionDebug());
auto tileData = std::make_shared<VectorTileData>(normalized_id, style, info,
transformState.getAngle(), transformState.getPitch(), data.getCollisionDebug());
tileData->request(data.pixelRatio, callback);
new_tile.data = tileData;
} else if (info.type == SourceType::Raster) {
Expand Down Expand Up @@ -332,14 +333,14 @@ std::forward_list<TileID> Source::coveringTiles(const TransformState& state) con

// Map four viewport corners to pixel coordinates
box points = state.cornersToBox(z);
const vec2<double>& center = points.center;
const TileCoordinate center = state.pointToCoordinate({ state.getWidth() / 2.0f, state.getHeight()/ 2.0f }).zoomTo(z);

std::forward_list<TileID> covering_tiles = tileCover(z, points, reparseOverscaled ? actualZ : z);

covering_tiles.sort([&center](const TileID& a, const TileID& b) {
// Sorts by distance from the box center
return std::fabs(a.x - center.x) + std::fabs(a.y - center.y) <
std::fabs(b.x - center.x) + std::fabs(b.y - center.y);
return std::fabs(a.x - center.column) + std::fabs(a.y - center.row) <
std::fabs(b.x - center.column) + std::fabs(b.y - center.row);
});

return covering_tiles;
Expand Down Expand Up @@ -506,7 +507,7 @@ bool Source::update(MapData& data,
updateTilePtrs();

for (auto& tilePtr : tilePtrs) {
tilePtr->data->redoPlacement(transformState.getAngle(), data.getCollisionDebug());
tilePtr->data->redoPlacement(transformState.getAngle(), transformState.getPitch(), data.getCollisionDebug());
}

updated = data.getAnimationTime();
Expand Down Expand Up @@ -563,7 +564,7 @@ void Source::tileLoadingCompleteCallback(const TileID& normalized_id, const Tran
return;
}

data->redoPlacement(transformState.getAngle(), collisionDebug);
data->redoPlacement(transformState.getAngle(), transformState.getPitch(), collisionDebug);
emitTileLoaded(true);
}

Expand Down
Loading