aboutsummaryrefslogtreecommitdiff
path: root/iosApp/WhirlyGlobeMaplyComponent.xcframework/ios-arm64_x86_64-simulator/WhirlyGlobeMaplyComponent.framework/Headers/WhirlyGlobeViewController.h
blob: ae3c444a020bac55789b6ddc2ef90365544f8357 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
/*
 *  WhirlyGlobeViewController.h
 *  WhirlyGlobeComponent
 *
 *  Created by Steve Gifford on 7/21/12.
 *  Copyright 2011-2022 mousebird consulting
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */

#import <UIKit/UIKit.h>
#import <WhirlyGlobeMaplyComponent/MaplyGlobeRenderController.h>
#import <WhirlyGlobeMaplyComponent/MaplyBaseViewController.h>

@class WGViewControllerLayer;
@class WhirlyGlobeViewController;

/**
    An animation delegate that can be set on a WhirlyGlobeViewController to control the view over time.
    
    Filling out these methods will get you animation callbacks at the proper time to control position, heading, tilt, and height on a frame basis.
    
    You pass the resulting object in to
  */
@protocol WhirlyGlobeViewControllerAnimationDelegate <NSObject>

/**
    This method is called when the animation starts.
    
    At the animation start we collect up the various parameters of the current visual view state and pas them in via the startState.  You probably want to keep track of this for later.
    
    @param viewC The view controller doing the animation.
    
    @param startState The starting point for the visual view animation.  Cache this somewhere for your own interpolation.
    
    @param startTime When the animation starts (e.g. now)
    
    @param endTime When the animation ends.  This is an absolute value.
  */
- (void)globeViewController:(WhirlyGlobeViewController *__nonnull)viewC startState:(WhirlyGlobeViewControllerAnimationState *__nonnull)startState startTime:(NSTimeInterval)startTime endTime:(NSTimeInterval)endTime;

/**
    This method is called at the beginning of every frame draw to position the viewer.
    
    This is the method that does all the work.  You need to fill out the returned WhirlyGlobeViewControllerAnimationState according to whatever interpolation your'e doing based on the currentTime.
    
    @param viewC The view controller doing the animation.
    
    @param currentTime The time for this frame.  Use this rather than calculating the time yourself.
    
    @return The WhirlyGlobeViewControllerAnimationState expressing where you want the viewer to be and where they are looking.
  */
- (nonnull WhirlyGlobeViewControllerAnimationState *)globeViewController:(WhirlyGlobeViewController *__nonnull)viewC stateForTime:(NSTimeInterval)currentTime;

@optional

/**
    This method is called at the end of the animation.
    
    The globe view controller calls this method when the animation is finished.  Do your cleanup here if need be.
    
    @param viewC The globe view controller.
  */
- (void)globeViewControllerDidFinishAnimation:(WhirlyGlobeViewController *__nonnull)viewC;

@end

/**
    A simple animation delegate for moving the globe around.
    
    The animation delegate support provides a lot of flexibility.  This version just provides all the standard fields and interpolates from beginning to end.
  */
@interface WhirlyGlobeViewControllerSimpleAnimationDelegate : NSObject <WhirlyGlobeViewControllerAnimationDelegate>

/// Initialize with an animation state to copy
- (nonnull instancetype)initWithState:(WhirlyGlobeViewControllerAnimationState *__nonnull)endState;

/// Location at the end of the animation
@property (nonatomic) MaplyCoordinateD loc;

/// Heading at the end of the animation
@property (nonatomic) double heading;

/// Height at the end of the animation
@property (nonatomic) double height;

/// Tilt at the end of the animation
@property (nonatomic) double tilt;

/// Roll at the end of the animation
@property (nonatomic) double roll;

/// Globe center at the end of the animation
@property (nonatomic) CGPoint globeCenter;

/// Custom easing
@property (readwrite,copy) ZoomEasingBlock _Nullable zoomEasing;

@end

/** 
    Globe View Controller Delegate protocol for getting back selection and tap events.
    
    Fill out the methods in this protocol and assign yourself as a delegate in the WhirlyGlobeViewController to get selection and tap events.
  */
@protocol WhirlyGlobeViewControllerDelegate <NSObject>

@optional
/** 
    Called when the user taps on or near an object.
    
    You're given the object you passed in originally, such as a MaplyScreenMarker.  Most of those objects have userObject properties, which is a good place to stash your own data.
    
    @param viewC The view controller where the user selected something.
    
    @param selectedObj The Maply object they selected.
  */
- (void)globeViewController:(WhirlyGlobeViewController *__nonnull)viewC didSelect:(NSObject *__nonnull)selectedObj;

/** 
    Called when the user taps on or near an object.
    
    This will call back with the closest object it finds near (or on) where the user tapped.
    
    You're given the object you passed in originally, such as a MaplyScreenMarker.
    
    This version is called preferentially if it exists.  Otherwise globeViewController:didSelect: is called if it exists.
    
    @param viewC The view controller where the user selected something.
    
    @param selectedObj The Maply object they selected.
    
    @param coord The location (geographic lon/lat in radians) where the user tapped.
    
    @param screenPt The location on screen where the user tapped.
  */
- (void)globeViewController:(WhirlyGlobeViewController *__nonnull)viewC didSelect:(NSObject *__nonnull)selectedObj atLoc:(MaplyCoordinate)coord onScreen:(CGPoint)screenPt;

/** 
    Called when the user taps on or near one or more objects.  Returns them all.
    
    This method is called when the
    
    @param viewC The view controller where the user selected something.
    
    @param selectedObjs A list of
    
    @param coord The location (geographic lon/lat in radians) where the user tapped.
    
    @param screenPt The location on screen where the user tapped.
  */
- (void)globeViewController:(WhirlyGlobeViewController *__nonnull)viewC allSelect:(NSArray *__nonnull)selectedObjs atLoc:(MaplyCoordinate)coord onScreen:(CGPoint)screenPt;

/** 
    Called when the user taps outside the globe.
  */
- (void)globeViewControllerDidTapOutside:(WhirlyGlobeViewController *__nonnull)viewC;

/** 
    Called when the user taps the globe but doesn't select anything.
    
    @param viewC The view controller where the user selected something.
    
    @param coord The location (geographic lon/lat in radians) where the user tapped.
  */
- (void)globeViewController:(WhirlyGlobeViewController *__nonnull)viewC didTapAt:(MaplyCoordinate)coord;

/** 
    This is an older method called when some layers load.
    
    Certain image layers call this method when they finish loading.  More modern layers don't, so don't rely on this.
  */
- (void)globeViewController:(WhirlyGlobeViewController *__nonnull)viewC layerDidLoad:(WGViewControllerLayer *__nonnull)layer;

/** 
    Called when the globe starts moving.
    
    @param viewC The globe view controller.
    
    @param userMotion Set if this is motion being caused by the user, rather than a call to set location.
    
    This is called when something (probably the user) starts moving the globe.
  */
- (void)globeViewControllerDidStartMoving:(WhirlyGlobeViewController *__nonnull)viewC userMotion:(bool)userMotion;

/** 
    Called when the globe stops moving.
    
    This is called when the globe stops moving.  It passes in the corners of the current viewspace.
    
    @param viewC The globe view controller.
    
    @param userMotion Set if this is motion being caused by the user, rather than a call to set location.
    
    @param corners An array of length 4 containing the corners of the view space (lower left, lower right, upper right, upper left).  If any of those corners does not intersect the globe (think zoomed out), its values are set to MAXFLOAT.
  */
- (void)globeViewController:(WhirlyGlobeViewController *__nonnull)viewC didStopMoving:(MaplyCoordinate *__nonnull)corners userMotion:(bool)userMotion;

/** 
    Called when an animation that knows where it's going to stop start ups.
    
    This is called when we know where the globe will stop.  It passes in the corners of that future viewspace.
    
    @param viewC The globe view controller.
    
    @param corners An array of length 4 containing the corners of the view space (lower left, lower right, upper right, upper left).  If any of those corners does not intersect the globe (think zoomed out), its values are set to MAXFLOAT.
    
    @param userMotion Set if this is motion being caused by the user, rather than a call to set location.
 */
- (void)globeViewController:(WhirlyGlobeViewController *__nonnull)viewC willStopMoving:(MaplyCoordinate *__nonnull)corners userMotion:(bool)userMotion;

/** 
    Called whenever the viewpoint moves.
    
    This is called whenever the viewpoint moves.  That includes user motion as well as animations.
    
    It may be triggered as often as every frame.  If that's a problem, use the globeViewController:didStopMoving:userMotion: or globeViewController:willStopMoving:userMotion: calls.
    
    @param viewC The globe view controller.
    
    @param corners An array of length 4 containing the corners of the view space (lower left, lower right, upper right, upper left).  If any of those corners does not intersect the globe (think zoomed out), its values are set to MAXFLOAT.
  */
- (void)globeViewController:(WhirlyGlobeViewController *__nonnull)viewC didMove:(MaplyCoordinate *__nonnull)corners;

@end

/** 
    This view controller implements a 3D interactive globe.
    
    This is the main entry point for displaying a globe.  Create one of these, fill it with data and let your users mess around with it.
    
    You can display a variety of features on the globe, including tiled base maps (MaplyQuadImageTilesLayer), vectors (MaplyVectorObject), shapes (MaplyShape), and others.  Check out the add calls in the MaplyBaseViewController for details.
    
    To get selection and tap callbacks, fill out the WhirlyGlobeViewControllerDelegate and assign the delegate.
    
    Most of the functionality is shared with MaplyBaseViewController.  Be sure to look in there first.
 */
@interface WhirlyGlobeViewController : MaplyBaseViewController

/** 
    If set, keep north facing upward on the screen as the user moves around.
    
    Off by default.
  */
@property(nonatomic,assign) bool keepNorthUp;

/** 
    Turn the pan gesture recognizer on and off
 
    On by default.
 */
@property(nonatomic,assign) bool panGesture;

/** 
    Turn the pinch (zoom) gesture recognizer on and off
    
    On by default.
 */
@property(nonatomic,assign) bool pinchGesture;

/**
 Turn the rotate globe functionality for pinch gesture gesture recognizer on and off
 
 On by default.
 */
@property(nonatomic,assign) bool zoomAroundPinch;

/** 
    Turn the rotate gesture recognizer on and off
    
    On by default.
 */
@property(nonatomic,assign) bool rotateGesture;

/** 
    Turn the tilt gesture recognizer on and off
    
    Off by default.
 */
@property(nonatomic,assign) bool tiltGesture;

/** 
    Turn the double tap to zoom gesture recognizer on and off
 
    On by default.
 */
@property(nonatomic,assign) bool doubleTapZoomGesture;

/** 
    Turn the 2 finger tap to zoom out gesture recognizer on and off
 
    On by default.
 */
@property(nonatomic,assign) bool twoFingerTapGesture;

/** 
    Turn on the double tap and drag gesture to zoom in and out.
 
    On by default.
 */
@property(nonatomic,assign) bool doubleTapDragGesture;

/** 
    If set, we use a modified pan gesture recognizer to play nice
        with the scroll view.  For the UIScrollView object, set clipsToBounds,
        pagingEnabled, and delaysContentTouches to YES, and set scrollEnabled
        and canCancelContentTouches to NO.  Add swipe gesture recognizers
        to the scroll view to control paging, and call
        requirePanGestureRecognizerToFailForGesture: for each.
 
    Off by default.
 */
@property(nonatomic,assign) bool inScrollView;


/** 
    If set, we'll automatically move to wherever the user tapped.
    
    When on we'll move the current location to wherever the user tapped if they tapped the globe.  That's true for selection as well.  On by default.
  */
@property(nonatomic,assign) bool autoMoveToTap;

/** 
    Delegate for the selection and tap events.
    
    Fill in the WhirlyGlobeViewControllerDelegate protocol, assign the object here and you'll get selection and tap events.
  */
@property(nonatomic,weak,nullable) NSObject<WhirlyGlobeViewControllerDelegate> *delegate;

/** 
    Current viewer height above terrain.
    
    This is the height from with the viewer is viewing the globe.  Values range from minHeight to maxHeight.  Smaller is closer.  See getZoomLimitsMin:max: for values.  The display units are based on a globe with a radius of 1.0.
 */
@property (nonatomic,assign) float height;

/** 
    Tilt in radians.  0 is looking straight down (the default).  PI/2 is looking toward the horizon.
  */
@property(nonatomic,assign) float tilt;

/**
    If set, the globe will be centered to this point on the screen.
 */
@property(nonatomic,assign) CGPoint globeCenter;

/** 
    The current rotation away from north.
    
    If keepNorthUp is set this is always 0.
  */
@property(nonatomic,assign) float heading;

/**
    The current roll around the axis pointed out of the user's nose.
    */
@property (nonatomic,assign) double roll;

/** 
    Returns the closest a viewer is allowed to get to the map surface.
 
    @return FLT_MIN if there's no pinchDelegate set
 */
- (float)getZoomLimitsMin;

/** 
    Returns the farthest away a viewer is allowed to get from the map surface
 
    @return FLT_MIN if there's no pinchDelegate set
 */
- (float)getZoomLimitsMax;

/** 
    Return the zoom limits for the globe.
    
    @param minHeight The closest a viewer is allowed to get to the globe surface.
    
    @param maxHeight The farthest away a viewer is allowed to get from the globe surface.
 */
- (void)getZoomLimitsMin:(float *__nonnull)minHeight max:(float *__nonnull)maxHeight;

/** 
    Set the zoom limits for the globe.
    
    @param minHeight The closest a viewer is allowed to get to the globe surface.
    
    @param maxHeight The farthest away a viewer is allowed to get from the globe surface.
 */
- (void)setZoomLimitsMin:(float)minHeight max:(float)maxHeight;

/** 
    How much we zoom in or out by when the user double taps or two finger taps.
    
    This sets the factor we'll use to zoom in by (e.g. *2.0) when the user double taps.  It also sets how much we zoom out by when the user two finger taps.  This will only have an effect if those gestures are active.
  */
@property (nonatomic) float zoomTapFactor;

/** 
    How long we take to zoom in or out when the user double taps or two finger taps.
    
    This controls the duration of the zoom animation.  You can set it to zero to avoid the animation entirely.
  */
@property (nonatomic) float zoomTapAnimationDuration;

/** 
    Reset the far clipping plane.
    
    This is advanced functionality.  Make sure you actually need to do this before you do it.
    
    The far clipping plane is usually set to something like 4.0.
  */
- (void)setFarClipPlane:(double)farClipPlane;

/** 
    Set the simplified tilt mode.  We'll tilt toward the horizon as the user gets closer to the ground.
    
    This implements a simplified mode for tilting.  As the user gets closer to the ground we tilt more toward the horizon.
    
    @param minHeight The minimum height corresponding to minTilt.
    
    @param maxHeight The height at which to start interoplating tilt.
    
    @param minTilt The most tilt toward the horizon.  Invoked when the user is at minHeight or below.
    
    @param maxTilt The tilt at the maximum height and over.  The tilt will never be less than this, so typically 0.
  */
- (void)setTiltMinHeight:(float)minHeight maxHeight:(float)maxHeight minTilt:(float)minTilt maxTilt:(float)maxTilt;

/// Turn off the varying tilt set up by setTiltMinHeight:maxHeight:minTilt:maxTilt:
- (void)clearTiltHeight;

/** 
    Turn on autorotate to rotate by the given amount every second.
    
    This turns on an auto-rotate mode.  The globe will start rotating after a delay by the given number of degrees per second.  Very pleasant.
    
    @param autoRotateInterval Wait this number of seconds after user interaction to auto rotate.
    
    @param autoRotateDegrees Rotate this number of degrees (not radians) per second.
  */
- (void)setAutoRotateInterval:(float)autoRotateInterval degrees:(float)autoRotateDegrees;

/** 
    Animate to the given position over time.
    
    @param newPos A coordinate in geographic (lon/lat radians)
    
    @param howLong A time interval in seconds.
 */
- (void)animateToPosition:(MaplyCoordinate)newPos time:(NSTimeInterval)howLong;

/** 
    Animate the given position to the screen position over time.
    
    This is similar to animateToPosition:time: except that it will attempt to match up the screen position and the geographic position.  This is how you offset the location you're looking at.
    
    If it's impossible to move newPos to loc, then nothing happens.
    
    @param newPos The geographic position (lon/lat in radians) to move to.
    
    @param loc The location on the screen where we'd like it to go.
    
    @param howLong How long in seconds to take getting there.
 */
- (bool)animateToPosition:(MaplyCoordinate)newPos onScreen:(CGPoint)loc time:(NSTimeInterval)howLong;

/** 
    Animate to the given position, heading and height over time.
    
    @param newPos A coordinate in geographic (lon/lat radians)
    
    @param newHeight New height to animate to.
    
    @param newHeading New heading to finish on.
    
    @param howLong A time interval in seconds.
 */
- (bool)animateToPosition:(MaplyCoordinate)newPos height:(float)newHeight heading:(float)newHeading time:(NSTimeInterval)howLong;

/** 
    Animate to the given position, heading and height over time.
    
    @param newPos A coordinate in geographic (lon/lat radians) (double precision)
    
    @param newHeight New height to animate to. (double)
    
    @param newHeading New heading to finish on. (double)
    
    @param howLong A time interval in seconds.
 */
- (bool)animateToPositionD:(MaplyCoordinateD)newPos height:(double)newHeight heading:(double)newHeading time:(NSTimeInterval)howLong;

/** 
    Animate to the given position, screen position, heading and height over time.
    
    If it's impossible to move newPos to loc, then nothing happens. 
    
    @param newPos A coordinate in geographic (lon/lat radians)
    
    @param loc The location on the screen where we'd like it to go.
    
    @param newHeight New height to animate to.
    
    @param newHeading New heading to finish on.
    
    @param howLong A time interval in seconds.
 */
- (bool)animateToPosition:(MaplyCoordinate)newPos onScreen:(CGPoint)loc height:(float)newHeight heading:(float)newHeading time:(NSTimeInterval)howLong;

/** 
    Animate with a delegate over time.
    
    Fill in the WhirlyGlobeViewControllerAnimationDelegate and you can control the visual view on a frame by frame basis.  You'll get called back at the appropriate time on the main thread over the time period.
    
    You'll also be called one at the end of the animation to establish the final position.
    
    @param animationDelegate The objects that implements the WhirlyGlobeViewControllerAnimationDelegate protocol.
    
    @param howLong How long the animation will run from the present time.
  */
- (void)animateWithDelegate:(NSObject<WhirlyGlobeViewControllerAnimationDelegate> *__nonnull)animationDelegate time:(NSTimeInterval)howLong;

/** 
    Set the center of the screen to the given position immediately.
    
    @param newPos The geographic position (lon/lat in radians) to move to.
 */
- (void)setPosition:(MaplyCoordinate)newPos;

/** 
    Set the center of the screen and the height offset immediately.
    
    @param newPos The geographic position (lon/lat in radians) to move to.
    
    @param height Height the view point above the globe.
 */
- (void)setPosition:(MaplyCoordinate)newPos height:(float)height;

/** 
    Returns the center of the screen in geographic (lon/lat in radians).
 */
- (MaplyCoordinate)getPosition;

/** 
    Returns the center of the screen in geographic (lon/lat in radians as doubles).
 */
- (MaplyCoordinateD)getPositionD;

/** 
    Returns the current view point's height above the globe.
 */
- (double)getHeight;

/** 
    Set the center of the screen and the height offset immediately.
    
    Set the center and height using double.s
    
    @param newPos The geographic position (lon/lat in radians) to move to.
    
    @param height Height the view point above the globe.
 */
- (void)setPositionD:(MaplyCoordinateD)newPos height:(double)height;

/** 
    Return the current center position and height.
    
    @param pos The center of the screen in geographic (lon/lat in radians).
    
    @param height The current view point's height above the globe.
 */
- (void)getPosition:(MaplyCoordinate *__nonnull)pos height:(float *__nonnull)height;

/** 
    Return the current center position and height in doubles.
    
    @param pos The center of the screen in geographic (lon/lat in radians).
    
    @param height The current view point's height above the globe.
 */
- (void)getPositionD:(MaplyCoordinateD *__nonnull)pos height:(double *__nonnull)height;

/** 
    Set the viewing state all at once
    
    This sets the position, tilt, height, screen position and heading all at once.
  */
- (void)setViewState:(WhirlyGlobeViewControllerAnimationState *__nonnull)viewState;

/** 
    Make a WhirlyGlobeViewControllerAnimationState object from the current view state.
    
    This returns the current view parameters in a single WhirlyGlobeViewControllerAnimationState.
  */
- (nullable WhirlyGlobeViewControllerAnimationState *)getViewState;

/** 
    Return a view state looking at the given location.
    
    Creates a view state that looks at the given location, taking tilt and heading into account.
    
    @param coord The location the user will be looking at.
    
    @param tilt Tilt off of vertical.
    
    @param heading Heading calculated from due north.
    
    @param alt Altitude of the point the user will be looking at (0, is a good value).
    
    @param range How far the user will be from the location they're looking at.
    
    @return The view state encapsulating the user location.  Will be nil if the parameters weren't valid.
  */
- (nullable WhirlyGlobeViewControllerAnimationState *)viewStateForLookAt:(MaplyCoordinate)coord tilt:(float)tilt heading:(float)heading altitude:(float)alt range:(float)range;

/** 
    Apply viewing constraints to the given view state.
    
    This applies active viewing constraints, such as min and max height and calculated tilt, if it's on to the given view state. This is particularly useful when controlled tilt is on.
  */
- (void)applyConstraintsToViewState:(WhirlyGlobeViewControllerAnimationState *__nonnull)viewState;

/** 
    Find a selectable object at or near the given location.
    
    This runs immediately and looks for a Maply object at the given location.  It differs from the WhirlyGlobeViewControllerDelegate in that it doesn't require user interaction.
    
    @param screenPt The location on screen where we're looking for an object.
    
    @return Returns a Maply object such as MaplyScreenLabel or MaplyShape or nil if it failed to find anything.
  */
- (nullable id)findObjectAtLocation:(CGPoint)screenPt;

/** 
    Return a location on the screen for a given geographic coordinate or CGPointZero if it's not on the screen.
 
    @param geoCoord Point on the earth in lat/lon radians you want a screen position for.
 
    @return the point or CGPointZero
 */
- (CGPoint)screenPointFromGeo:(MaplyCoordinate)geoCoord;

/** 
    Return a location on the screen for a given geographic coordinate or false if it's not on the screen.
    
    @param geoCoord Point on the earth in lat/lon radians you want a screen position for.
    
    @param screenPt Location on the screen.
    
    @return True if the geo coord was on the screen, false otherwise.
  */
- (bool)screenPointFromGeo:(MaplyCoordinate)geoCoord screenPt:(CGPoint *__nonnull)screenPt;

/** 
    Calculate a geo coordinate from a point on the screen.
    
    @param screenPt Location on the screen.
    
    @param geoCoord Point on the earth in lat/lon radians.
    
    @return True if the point was on the globe, false otherwise.
  */
- (bool)geoPointFromScreen:(CGPoint)screenPt geoCoord:(MaplyCoordinate *__nonnull)geoCoord;

/**
    Calculate a geo coordinate from a point on the screen.
    
    @param screenPt Location on the screen.
    
    @return The corresponding MaplyCoordinate wrapped in an NSValue  if the point was on the globe, nil otherwise.
  */
- (nullable NSValue *)geoPointFromScreen:(CGPoint)screenPt;

/** 
    Calculate a geocentric coordinate from a point on the screen.
 
    @param screenPt Location on the screen.
 
    @return An array of 3 NSNumber (with doubles). If the point wasn't on the globe, returns nil
 */
- (nullable NSArray *)geocPointFromScreen:(CGPoint)screenPt;

/** 
    Calculate a geocentric coordinate from a point on the screen.
    
    @param screenPt Location on the screen.
    
    @param retCoords An array of 3 doubles.  The geocentric coordinate will be returned here.
    
    @return True if the point was on the globe, false otherwise.
 */
- (bool)geocPointFromScreen:(CGPoint)screenPt geocCoord:(double *__nonnull)retCoords;

/**
    Calculate a size in meters by projecting the two screen points onto the globe.
    Return -1, -1 if the points weren't on the globe.
  */
- (CGSize)realWorldSizeFromScreenPt0:(CGPoint)pt0 pt1:(CGPoint)pt1;

/** 
    Find a height that shows the given bounding box.
    
    This method will search for a height that shows the given bounding box within the view.  The search is inefficient, so don't call this a lot.
    
    @param bbox The bounding box (in radians) we're trying to view.
    
    @param pos The position the viewer will be at.
 */
- (float)findHeightToViewBounds:(MaplyBoundingBox)bbox pos:(MaplyCoordinate)pos;

/**
    Find a height that shows the given bounding box.
    This method will search for a height that shows the given bounding box within the view.  The search is inefficient, so don't call this a lot.

    This version takes a margin to add around the outside of the area.  Positive margins increase the screen area considered, making the
    given area larger.  Negative margins make the specified area smaller.

    @param bbox The bounding box (in radians) we're trying to view.
    @param pos Where the view will be looking.
    @param marginX Horizontal boundary around the area
    @param marginY Vertical boundary around the area
 */
- (float)findHeightToViewBounds:(MaplyBoundingBox)bbox
                            pos:(MaplyCoordinate)pos
                        marginX:(double)marginX
                        marginY:(double)marginY;

/**
    Find a height that shows the given bounding box.
    This method will search for a height that shows the given bounding box within the view.  The search is inefficient, so don't call this a lot.

    This version takes a margin to add around the outside of the area.  Positive margins increase the screen area considered, making the
    given area larger.  Negative margins make the specified area smaller.
 
    This version attempts to place the given bounds within a rectangle other than the whole view frame.
    Note that this doesn't work well when the bounds are very large.

    @param bbox The bounding box (in radians) we're trying to view.
    @param pos Where the view will be looking.
    @param frame The screen area to consider.
    @param newPos (out,optional) The center location needed to place \c pos at the center of \c frame
    @param marginX Horizontal boundary around the area
    @param marginY Vertical boundary around the area
 */
- (float)findHeightToViewBounds:(MaplyBoundingBox)bbox
                            pos:(MaplyCoordinate)pos
                          frame:(CGRect)frame
                         newPos:(MaplyCoordinate *_Nullable)newPos
                        marginX:(double)marginX
                        marginY:(double)marginY;

/**
 
    Return the extents of the current view.
 
    When we're dealing with a globe the corners could be outside of the globe, in this case kMaplyNullBoundingBox is returned.
 
    @return Returns the bounding box if exists a bounding bbox for the current view, otherwise returns kMaplyNullBoundingBox.
 */
- (MaplyBoundingBox)getCurrentExtents;

/**
 
    Return the extents of the current view.
 
    When we're dealing with a globe the corners could be outside of the globe, in this case false is returned.
 
    @param bbox The bbox will be returned here.
 
    @return Returns true if exists a bounding bbox for the current view, otherwise returns false
 */
- (bool)getCurrentExtents:(MaplyBoundingBox *__nonnull)bbox;

/**
  
    From the current view figure out a usable geo bounding box.
  
    This is similar to the WhirlyGlobeViewControllerDelegate methods and getCurrentExtents except that it goes a little deeper.  It starts with the four corners of the screen and then tries to take tilt and orientation into account.  Ideally it produces a bounding box that covers everything the user is looking at as opposed to where the four corners are.
 
    @param bboxes The bounding boxes to fill in.  Pass in two.
 
    @param visualBoxes If set, we'll build bounding boxes you can display.  If not set, we'll build a single bounding box usable for math.
  */
- (int)getUsableGeoBoundsForView:(MaplyBoundingBox *__nonnull)bboxes visual:(bool)visualBoxes;

/**
 
    Make a gesture recognizer's success depend on the pan gesture
      recognizer's failure.
 
    When using the globe view within a scroll view, add swipe gesture
      recognizers to the scroll view to control paging, and call this method
      for each.  See also the inScrollView property and its comment.
 
    @param other The other, subordinate gesture recognizer.
 */
- (void)requirePanGestureRecognizerToFailForGesture:(UIGestureRecognizer *__nullable)other;

@end