Permalink
Browse files

Merge branch 'develop' of git://github.com/mousebird/WhirlyGlobe into…

… develop
  • Loading branch information...
2 parents 347f2eb + f916fc2 commit f62b36f28487da33501b87196c8db23f4c6e14c8 Juan J. Collas committed Dec 16, 2012
@@ -70,13 +70,28 @@
/// The radius of the earth is 1.0. Height above terrain is relative to that.
@property (nonatomic,assign) float height;
+/// Return the view extents. This is the box the view point is allowed to be within.
+- (void)getViewExtentsLL:(MaplyCoordinate *)ll ur:(MaplyCoordinate *)ur;
+
+/// Set the view extents. This is the box the view point is allowed to be within.
+- (void)setViewExtentsLL:(MaplyCoordinate)ll ur:(MaplyCoordinate)ur;
+
/// Animate to the given position over the given amount of time
-- (void)animateToPosition:(WGCoordinate)newPos time:(NSTimeInterval)howLong;
+- (void)animateToPosition:(MaplyCoordinate)newPos time:(NSTimeInterval)howLong;
/// Set the view to the given position immediately
-- (void)setPosition:(WGCoordinate)newPos;
+- (void)setPosition:(MaplyCoordinate)newPos;
/// Set position and height at the same time
-- (void)setPosition:(WGCoordinate)newPos height:(float)height;
+- (void)setPosition:(MaplyCoordinate)newPos height:(float)height;
+
+/// Get the current position and height
+- (void)getPosition:(WGCoordinate *)pos height:(float *)height;
+
+/// Return the min and max heights above the globe for zooming
+- (void)getZoomLimitsMin:(float *)minHeight max:(float *)maxHeight;
+
+/// Set the min and max heights above the globe for zooming
+- (void)setZoomLimitsMin:(float)minHeight max:(float)maxHeight;
@end
@@ -32,7 +32,7 @@
*/
@interface MaplyInteractionLayer : MaplyBaseInteractionLayer
{
- // The view controller, for various callbacks
+ /// The view controller, for various callbacks
NSObject<MaplyInteractionLayerDelegate> * __weak viewController;
}
@@ -24,21 +24,27 @@
@interface MaplyViewController()
{
- // Custom map scene
+ /// Custom map scene
Maply::MapScene *mapScene;
- // Maply view
+ /// Maply view
MaplyView *mapView;
- // Coordinate system and display adapter
+ /// Coordinate system and display adapter
WhirlyKit::SphericalMercatorDisplayAdapter *coordAdapter;
- // Our own interaction layer for adding and removing things
+ /// Our own interaction layer for adding and removing things
MaplyInteractionLayer *mapInteractLayer;
- // Gesture recognizers
+ /// Gesture recognizers
MaplyTapDelegate *tapDelegate;
MaplyPanDelegate *panDelegate;
MaplyPinchDelegate *pinchDelegate;
+
+ /// Bounding box for the viewer
+ MaplyCoordinate boundLL,boundUR;
+
+ /// Current view animation (kept around so it's not released)
+ NSObject *curAnimation;
}
@end
@@ -39,21 +39,26 @@ void SampleGreatCircle(MaplyCoordinate startPt,MaplyCoordinate endPt,float heigh
Point3f p1 = coordAdapter->localToDisplay(coordAdapter->getCoordSystem()->geographicToLocal(GeoCoord(endPt.x,endPt.y)));
// Note: Dumb approach. Switch to an adaptive sampling
+ bool isFlat = coordAdapter->isFlat();
int numSamples = 300;
for (unsigned int ii=0;ii<=numSamples;ii++)
{
// Sample the point
float t = (ii/(float)numSamples);
Point3f pt = (p1-p0)*t + p0;
// This puts us on the surface of the sphere
- pt.normalize();
+ if (!isFlat)
+ pt.normalize();
// Parabolic curve
float b = 4*height;
float a = -b;
float thisHeight = a*(t*t) + b*t;
- pt *= 1.0+thisHeight;
+ if (isFlat)
+ pt.z() = thisHeight;
+ else
+ pt *= 1.0+thisHeight;
pts.push_back(pt);
}
}
@@ -484,7 +489,10 @@ - (void)addShapesLayerThread:(NSArray *)argArray
{
MaplyCoordinate3d &coord = coords[ii];
Point3f pt = coordAdapter->localToDisplay(coordAdapter->getCoordSystem()->geographicToLocal(GeoCoord(coord.x,coord.y)));
- pt *= (1.0+coord.z);
+ if (coordAdapter->isFlat())
+ pt.z() = coord.z;
+ else
+ pt *= (1.0+coord.z);
newLin.pts.push_back(pt);
}
newLin.lineWidth = lin.lineWidth;
@@ -63,7 +63,7 @@ - (void)dealloc
- (WhirlyKitView *) loadSetup_view
{
- coordAdapter = new SphericalMercatorDisplayAdapter(0.0, GeoCoord(-180.0,-90.0), GeoCoord(180.0,90.0));
+ coordAdapter = new SphericalMercatorDisplayAdapter(0.0, GeoCoord::CoordFromDegrees(-180.0,-90.0), GeoCoord::CoordFromDegrees(180.0,90.0));
mapView = [[MaplyView alloc] initWithCoordAdapater:coordAdapter];
mapView.continuousZoom = true;
@@ -92,7 +92,12 @@ - (void) loadSetup
// Wire up the gesture recognizers
tapDelegate = [MaplyTapDelegate tapDelegateForView:glView mapView:mapView];
panDelegate = [MaplyPanDelegate panDelegateForView:glView mapView:mapView];
+ boundLL = MaplyCoordinateMakeWithDegrees(-180.0,-90.0);
+ boundUR = MaplyCoordinateMakeWithDegrees(180.0,90.0);
+ [self setViewExtentsLL:boundLL ur:boundUR];
pinchDelegate = [MaplyPinchDelegate pinchDelegateForView:glView mapView:mapView];
+ pinchDelegate.minZoom = [mapView minHeightAboveSurface];
+ pinchDelegate.maxZoom = [mapView maxHeightAboveSurface];
}
- (void)viewWillAppear:(BOOL)animated
@@ -120,27 +125,140 @@ - (void)registerForEvents
#pragma mark - Interaction
+/// Return the view extents. This is the box the view point is allowed to be within.
+- (void)getViewExtentsLL:(MaplyCoordinate *)ll ur:(MaplyCoordinate *)ur
+{
+ *ll = boundLL;
+ *ur = boundUR;
+}
+
+/// Set the view extents. This is the box the view point is allowed to be within.
+- (void)setViewExtentsLL:(MaplyCoordinate)ll ur:(MaplyCoordinate)ur
+{
+ CoordSystemDisplayAdapter *adapter = mapView.coordAdapter;
+ CoordSystem *coordSys = adapter->getCoordSystem();
+ boundLL = ll; boundUR = ur;
+
+ // Convert the bounds to a rectangle in local coordinates
+ Point3f bounds3d[4];
+ Point2f bounds[4];
+ bounds3d[0] = adapter->localToDisplay(coordSys->geographicToLocal(GeoCoord(ll.x,ll.y)));
+ bounds3d[1] = adapter->localToDisplay(coordSys->geographicToLocal(GeoCoord(ur.x,ll.y)));
+ bounds3d[2] = adapter->localToDisplay(coordSys->geographicToLocal(GeoCoord(ur.x,ur.y)));
+ bounds3d[3] = adapter->localToDisplay(coordSys->geographicToLocal(GeoCoord(ll.x,ur.y)));
+ for (unsigned int ii=0;ii<4;ii++)
+ bounds[ii] = Point2f(bounds3d[ii].x(),bounds3d[ii].y());
+ [panDelegate setBounds:bounds];
+}
+
// Internal animation handler
-- (void)animateToPoint:(GeoCoord)whereGeo time:(NSTimeInterval)howLong
+- (void)animateToPoint:(Point3f)newLoc time:(NSTimeInterval)howLong
{
- // note: fill this in
+ [mapView cancelAnimation];
+
+ MaplyAnimateViewTranslation *animTrans = [[MaplyAnimateViewTranslation alloc] initWithView:mapView translate:newLoc howLong:howLong];
+ curAnimation = animTrans;
+ mapView.delegate = animTrans;
}
// External facing version of rotateToPoint
- (void)animateToPosition:(MaplyCoordinate)newPos time:(NSTimeInterval)howLong
{
- // Note: fill this in
+ // Snap to the bounds
+ if (newPos.x > boundUR.x) newPos.x = boundUR.x;
+ if (newPos.y > boundUR.y) newPos.y = boundUR.y;
+ if (newPos.x < boundLL.x) newPos.x = boundLL.x;
+ if (newPos.y < boundLL.y) newPos.y = boundLL.y;
+
+ Point3f loc = mapView.coordAdapter->localToDisplay(mapView.coordAdapter->getCoordSystem()->geographicToLocal(GeoCoord(newPos.x,newPos.y)));
+ loc.z() = mapView.loc.z();
+ [self animateToPoint:loc time:howLong];
+}
+
+// This version takes a height as well
+- (void)animateToPosition:(MaplyCoordinate)newPos height:(float)newHeight time:(NSTimeInterval)howLong
+{
+ if (pinchDelegate)
+ {
+ if (newHeight < pinchDelegate.minZoom)
+ newHeight = pinchDelegate.minZoom;
+ if (newHeight > pinchDelegate.maxZoom)
+ newHeight = pinchDelegate.maxZoom;
+ }
+
+ // Snap to the bounds
+ if (newPos.x > boundUR.x) newPos.x = boundUR.x;
+ if (newPos.y > boundUR.y) newPos.y = boundUR.y;
+ if (newPos.x < boundLL.x) newPos.x = boundLL.x;
+ if (newPos.y < boundLL.y) newPos.y = boundLL.y;
+
+ Point3f loc = mapView.coordAdapter->localToDisplay(mapView.coordAdapter->getCoordSystem()->geographicToLocal(GeoCoord(newPos.x,newPos.y)));
+ loc.z() = newHeight;
+
+ [self animateToPoint:loc time:howLong];
}
// External facing set position
- (void)setPosition:(MaplyCoordinate)newPos
{
- // Note: fill this in
+ Point3f loc = mapView.loc;
+ [self setPosition:newPos height:loc.z()];
}
- (void)setPosition:(MaplyCoordinate)newPos height:(float)height
{
- // Note: fill this in
+ [mapView cancelAnimation];
+
+ if (pinchDelegate)
+ {
+ if (height < pinchDelegate.minZoom)
+ height = pinchDelegate.minZoom;
+ if (height > pinchDelegate.maxZoom)
+ height = pinchDelegate.maxZoom;
+ }
+
+ // Snap to the bounds
+ if (newPos.x > boundUR.x) newPos.x = boundUR.x;
+ if (newPos.y > boundUR.y) newPos.y = boundUR.y;
+ if (newPos.x < boundLL.x) newPos.x = boundLL.x;
+ if (newPos.y < boundLL.y) newPos.y = boundLL.y;
+
+ Point3f loc = mapView.coordAdapter->localToDisplay(mapView.coordAdapter->getCoordSystem()->geographicToLocal(GeoCoord(newPos.x,newPos.y)));
+ loc.z() = height;
+ mapView.loc = loc;
+}
+
+- (void)getPosition:(WGCoordinate *)pos height:(float *)height
+{
+ Point3f loc = mapView.loc;
+ GeoCoord geoCoord = mapView.coordAdapter->getCoordSystem()->localToGeographic(loc);
+ pos->x = geoCoord.x(); pos->y = geoCoord.y();
+ *height = loc.z();
+}
+
+/// Return the min and max heights above the globe for zooming
+- (void)getZoomLimitsMin:(float *)minHeight max:(float *)maxHeight
+{
+ if (pinchDelegate)
+ {
+ *minHeight = pinchDelegate.minZoom;
+ *minHeight = pinchDelegate.maxZoom;
+ }
+}
+
+/// Set the min and max heights above the globe for zooming
+- (void)setZoomLimitsMin:(float)minHeight max:(float)maxHeight
+{
+ if (pinchDelegate)
+ {
+ pinchDelegate.minZoom = minHeight;
+ pinchDelegate.maxZoom = maxHeight;
+ Point3f loc = mapView.loc;
+ if (mapView.heightAboveSurface < minHeight)
+ mapView.loc = Point3f(loc.x(),loc.y(),minHeight);
+ if (mapView.heightAboveSurface > maxHeight)
+ mapView.loc = Point3f(loc.x(),loc.y(),maxHeight);
+ }
}
// Called back on the main thread after the interaction thread does the selection
@@ -152,15 +270,15 @@ - (void)handleSelection:(MaplyTapMessage *)msg didSelect:(NSObject *)selectedObj
if (delegate && [delegate respondsToSelector:@selector(maplyViewController:didSelect:)])
[delegate maplyViewController:self didSelect:selectedObj];
} else {
+ MaplyCoordinate coord;
+ coord.x = msg.whereGeo.lon();
+ coord.y = msg.whereGeo.lat();
// The user didn't select anything, let the delegate know.
if (delegate && [delegate respondsToSelector:@selector(maplyViewController:didTapAt:)])
{
- MaplyCoordinate coord;
- coord.x = msg.whereGeo.lon();
- coord.y = msg.whereGeo.lat();
[delegate maplyViewController:self didTapAt:coord];
}
- [self animateToPoint:msg.whereGeo time:1.0];
+ [self animateToPosition:coord time:1.0];
}
}
@@ -1771,7 +1771,7 @@
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
GCC_C_LANGUAGE_STANDARD = c99;
GCC_OPTIMIZATION_LEVEL = 0;
- GCC_SYMBOLS_PRIVATE_EXTERN = YES;
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_THUMB_SUPPORT = YES;
"GCC_THUMB_SUPPORT[arch=armv6]" = NO;
GCC_VERSION = com.apple.compilers.llvmgcc42;
@@ -1794,7 +1794,7 @@
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
GCC_C_LANGUAGE_STANDARD = c99;
- GCC_SYMBOLS_PRIVATE_EXTERN = YES;
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_THUMB_SUPPORT = YES;
"GCC_THUMB_SUPPORT[arch=armv6]" = NO;
GCC_VERSION = com.apple.compilers.llvmgcc42;
@@ -33,9 +33,10 @@
float maxTime;
CFTimeInterval startDate;
WhirlyKit::Point3f org;
+ std::vector<WhirlyKit::Point2f> bounds;
}
/// Initialize with a velocity and negative acceleration (to slow down)
-- (id)initWithView:(MaplyView *)globeView velocity:(float)velocity accel:(float)acceleration dir:(Eigen::Vector3f)dir;
+- (id)initWithView:(MaplyView *)globeView velocity:(float)velocity accel:(float)acceleration dir:(Eigen::Vector3f)dir bounds:(std::vector<WhirlyKit::Point2f> &)bounds;
@end
@@ -19,6 +19,7 @@
*/
#import <Foundation/Foundation.h>
+#import <vector>
#import "MaplyView.h"
@interface MaplyPanDelegate : NSObject <UIGestureRecognizerDelegate>
@@ -33,9 +34,14 @@
/// Viewer location when we started panning
WhirlyKit::Point3f startLoc;
CGPoint lastTouch;
+ /// Boundary quad that we're to stay within
+ std::vector<WhirlyKit::Point2f> bounds;
}
/// Create a pinch gesture and a delegate and wire them up to the given UIView
+ (MaplyPanDelegate *)panDelegateForView:(UIView *)view mapView:(MaplyView *)mapView;
+/// Set the bounding rectangle
+- (void)setBounds:(WhirlyKit::Point2f *)bounds;
+
@end
@@ -23,11 +23,17 @@
@interface MaplyPinchDelegate : NSObject <UIGestureRecognizerDelegate>
{
+ /// Minimum allowable zoom level
+ float minZoom;
+ /// Maximum allowable zoom level
+ float maxZoom;
/// If we're zooming, where we started
float startZ;
MaplyView *mapView;
}
+@property (nonatomic,assign) float minZoom,maxZoom;
+
/// Create a pinch gesture and a delegate and wire them up to the given UIView
+ (MaplyPinchDelegate *)pinchDelegateForView:(UIView *)view mapView:(MaplyView *)mapView;
@@ -65,11 +65,17 @@
/// Height above the plane
- (float)heightAboveSurface;
+/// Minimum valid height above plane
+- (float)minHeightAboveSurface;
+
+/// Maximum valid height above plane
+- (float)maxHeightAboveSurface;
+
/** Given a location on the screen and the screen size, figure out where we touched
the plane. Returns true if we hit and where.
Returns false if we didn't, which can only happened if we're turned away.
*/
-- (bool)pointOnPlaneFromScreen:(CGPoint)pt transform:(const Eigen::Matrix4f *)transform frameSize:(const WhirlyKit::Point2f &)frameSize hit:(WhirlyKit::Point3f *)hit;
+- (bool)pointOnPlaneFromScreen:(CGPoint)pt transform:(const Eigen::Matrix4f *)transform frameSize:(const WhirlyKit::Point2f &)frameSize hit:(WhirlyKit::Point3f *)hit clip:(bool)clip;
/** From a world location in 3D, figure the projection to the screen.
Returns a point within the frame.
Oops, something went wrong.

0 comments on commit f62b36f

Please sign in to comment.