1010import gov .nasa .worldwind .WorldWindow ;
1111import gov .nasa .worldwind .geom .Camera ;
1212import gov .nasa .worldwind .geom .Location ;
13+ import gov .nasa .worldwind .geom .Position ;
1314import gov .nasa .worldwind .gesture .GestureRecognizer ;
1415import gov .nasa .worldwind .gesture .PinchRecognizer ;
1516import gov .nasa .worldwind .gesture .RotationRecognizer ;
1617import gov .nasa .worldwind .util .WWMath ;
1718
1819public class CameraControlFragment extends BasicGlobeFragment {
1920
21+ private static final double COLLISION_THRESHOLD = 20.0 ; // 20m above surface
22+
2023 /**
2124 * Creates a new WorldWindow object with a custom WorldWindowController.
2225 */
@@ -42,7 +45,7 @@ public WorldWindow createWorldWindow() {
4245 * A custom WorldWindController that uses gestures to control the camera directly via the setAsCamera interface
4346 * instead of the default setAsLookAt interface.
4447 */
45- private class CameraController extends BasicWorldWindowController {
48+ private static class CameraController extends BasicWorldWindowController {
4649
4750 protected double beginHeading ;
4851
@@ -189,15 +192,22 @@ protected void gestureDidBegin() {
189192 }
190193
191194 protected void applyLimits (Camera camera ) {
192- double distanceToExtents = this . wwd . distanceToViewGlobeExtents () ;
195+ Position position = camera . position ;
193196
194197 double minAltitude = 100 ;
195- double maxAltitude = distanceToExtents ;
196- camera .position .altitude = WWMath .clamp (camera .position .altitude , minAltitude , maxAltitude );
198+ double maxAltitude = this .wwd .distanceToViewGlobeExtents ();
199+ position .altitude = WWMath .clamp (position .altitude , minAltitude , maxAltitude );
200+
201+ // Check if camera altitude is not under the surface
202+ double elevation = this .wwd .getGlobe ().getElevationAtLocation (position .latitude , position .longitude )
203+ * wwd .getVerticalExaggeration () + COLLISION_THRESHOLD ;
204+ if (elevation > position .altitude ) {
205+ position .altitude = elevation ;
206+ }
197207
198208 // Limit the tilt to between nadir and the horizon (roughly)
199- double r = wwd .getGlobe ().getRadiusAt (camera . position .latitude , camera . position .latitude );
200- double maxTilt = Math .toDegrees (Math .asin (r / (r + camera . position .altitude )));
209+ double r = wwd .getGlobe ().getRadiusAt (position .latitude , position .latitude );
210+ double maxTilt = Math .toDegrees (Math .asin (r / (r + position .altitude )));
201211 double minTilt = 0 ;
202212 camera .tilt = WWMath .clamp (camera .tilt , minTilt , maxTilt );
203213 }
0 commit comments