protected void applyLimits(Camera camera) { double distanceToExtents = this.wwd.distanceToViewGlobeExtents(); double minAltitude = 100; double maxAltitude = distanceToExtents; camera.altitude = WWMath.clamp(camera.altitude, minAltitude, maxAltitude); // Limit the tilt to between nadir and the horizon (roughly) double r = wwd.getGlobe().getRadiusAt(camera.latitude, camera.latitude); double maxTilt = Math.toDegrees(Math.asin(r / (r + camera.altitude))); double minTilt = 0; camera.tilt = WWMath.clamp(camera.tilt, minTilt, maxTilt); } }
@Override protected void gestureDidBegin() { if (this.activeGestures++ == 0) { this.wwd.getNavigator().getAsCamera(this.wwd.getGlobe(), this.beginCamera); this.camera.set(this.beginCamera); } }
protected void gestureDidBegin() { if (this.activeGestures++ == 0) { this.wwd.getNavigator().getAsLookAt(this.wwd.getGlobe(), this.beginLookAt); this.lookAt.set(this.beginLookAt); } }
/** * Converts a screen point to the geographic coordinates on the globe. * * @param screenX X coordinate * @param screenY Y coordinate * @param result Pre-allocated Position receives the geographic coordinates * * @return true if the screen point could be converted; false if the screen point is not on the globe */ public boolean screenPointToGroundPosition(float screenX, float screenY, Position result) { if (this.wwd.rayThroughScreenPoint(screenX, screenY, ray)) { Globe globe = wwd.getGlobe(); if (globe.intersect(ray, this.pickPoint)) { globe.cartesianToGeographic(pickPoint.x, this.pickPoint.y, this.pickPoint.z, result); return true; } } return false; } }
/** * Converts a screen point to the geographic coordinates on the globe. * * @param screenX X coordinate * @param screenY Y coordinate * @param result Pre-allocated Position receives the geographic coordinates * * @return true if the screen point could be converted; false if the screen point is not on the globe */ public boolean screenPointToGroundPosition(float screenX, float screenY, Position result) { if (this.wwd.rayThroughScreenPoint(screenX, screenY, ray)) { Globe globe = wwd.getGlobe(); if (globe.intersect(ray, this.pickPoint)) { globe.cartesianToGeographic(pickPoint.x, this.pickPoint.y, this.pickPoint.z, result); return true; } } return false; }
protected void positionView(WorldWindow wwd) { LookAt lookAt = new LookAt().set(46.230, -122.190, 500, WorldWind.ABSOLUTE, 1.5e4 /*range*/, 45.0 /*heading*/, 70.0 /*tilt*/, 0 /*roll*/); wwd.getNavigator().setAsLookAt(this.getWorldWindow().getGlobe(), lookAt); } }
@Override public void run() { this.wwd.getNavigator().setAsCamera(this.wwd.getGlobe(), this.camera); this.wwd.requestRedraw(); pool.release(this.reset()); } }
protected void positionView(WorldWindow wwd) { Position mtRainier = new Position(46.852886, -121.760374, 4392.0); Position eye = new Position(46.912, -121.527, 2000.0); // Compute heading and distance from peak to eye Globe globe = wwd.getGlobe(); double heading = eye.greatCircleAzimuth(mtRainier); double distanceRadians = mtRainier.greatCircleDistance(eye); double distance = distanceRadians * globe.getRadiusAt(mtRainier.latitude, mtRainier.longitude); // Compute camera settings double altitude = eye.altitude - mtRainier.altitude; double range = Math.sqrt(altitude * altitude + distance * distance); double tilt = Math.toDegrees(Math.atan(distance / eye.altitude)); // Apply the new view Camera camera = new Camera(); camera.set(eye.latitude, eye.longitude, eye.altitude, WorldWind.ABSOLUTE, heading, tilt, 0.0 /*roll*/); wwd.getNavigator().setAsCamera(globe, camera); } }
@Override public void onNavigatorEvent(WorldWindow wwd, NavigatorEvent event) { long currentTime = System.currentTimeMillis(); long elapsedTime = currentTime - lastEventTime; int eventAction = event.getAction(); boolean receivedUserInput = (eventAction == WorldWind.NAVIGATOR_MOVED && event.getLastInputEvent() != null); // Update the status overlay views whenever the navigator stops moving, // and also it is moving but at an (arbitrary) maximum refresh rate of 20 Hz. if (eventAction == WorldWind.NAVIGATOR_STOPPED || elapsedTime > 50) { // Get the current navigator state to apply to the overlays event.getNavigator().getAsLookAt(wwd.getGlobe(), lookAt); event.getNavigator().getAsCamera(wwd.getGlobe(), camera); // Update the overlays updateOverlayContents(lookAt, camera); updateOverlayColor(eventAction); lastEventTime = currentTime; } // Show the crosshairs while the user is gesturing and fade them out after the user stops if (receivedUserInput) { showCrosshairs(); } else { fadeCrosshairs(); } } };
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setAboutBoxTitle("About the " + this.getResources().getText(R.string.title_placemarks_milstd2525)); setAboutBoxText("Demonstrates how to add MilStd2525C Symbols to a RenderableLayer."); // Create a TextView to show the MIL-STD-2525 renderer's initialization status this.statusText = new TextView(this); this.statusText.setTextColor(android.graphics.Color.YELLOW); FrameLayout globeLayout = (FrameLayout) findViewById(R.id.globe); globeLayout.addView(this.statusText); // Set the camera to look at the area where the symbols will be displayed. Position pos = new Position(32.4520, 63.44553, 0); LookAt lookAt = new LookAt().set(pos.latitude, pos.longitude, pos.altitude, WorldWind.ABSOLUTE, 1e5 /*range*/, 0 /*heading*/, 45 /*tilt*/, 0 /*roll*/); this.getWorldWindow().getNavigator().setAsLookAt(this.getWorldWindow().getGlobe(), lookAt); // The MIL-STD-2525 rendering library takes time initialize, we'll perform this task via the // AsyncTask's background thread and then load the symbols in its post execute handler. new InitializeSymbolsTask().execute(); }
/** * Creates a new WorldWindow object with a custom WorldWindowController. */ @Override public WorldWindow createWorldWindow() { // Let the super class (BasicGlobeFragment) do the creation WorldWindow wwd = super.createWorldWindow(); // Override the default "look at" gesture behavior with a camera centric gesture controller wwd.setWorldWindowController(new CameraController()); // Create a camera position above KOXR airport, Oxnard, CA Camera camera = new Camera(); camera.set(34.2, -119.2, 10000, WorldWind.ABSOLUTE, 90, // Looking east 70, // Lookup up from nadir 0); // No roll // Apply the new camera position Globe globe = wwd.getGlobe(); wwd.getNavigator().setAsCamera(globe, camera); return wwd; }
protected void handlePinch(GestureRecognizer recognizer) { int state = recognizer.getState(); float scale = ((PinchRecognizer) recognizer).getScale(); if (state == WorldWind.BEGAN) { this.gestureDidBegin(); } else if (state == WorldWind.CHANGED) { if (scale != 0) { // Apply the change in scale to the navigator, relative to when the gesture began. this.lookAt.range = this.beginLookAt.range / scale; this.applyLimits(this.lookAt); this.wwd.getNavigator().setAsLookAt(this.wwd.getGlobe(), this.lookAt); this.wwd.requestRedraw(); } } else if (state == WorldWind.ENDED || state == WorldWind.CANCELLED) { this.gestureDidEnd(); } }
protected void handleRotate(GestureRecognizer recognizer) { int state = recognizer.getState(); float rotation = ((RotationRecognizer) recognizer).getRotation(); if (state == WorldWind.BEGAN) { this.gestureDidBegin(); this.lastRotation = 0; } else if (state == WorldWind.CHANGED) { // Apply the change in rotation to the navigator, relative to the navigator's current values. double headingDegrees = this.lastRotation - rotation; this.lookAt.heading = WWMath.normalizeAngle360(this.lookAt.heading + headingDegrees); this.lastRotation = rotation; this.wwd.getNavigator().setAsLookAt(this.wwd.getGlobe(), this.lookAt); this.wwd.requestRedraw(); } else if (state == WorldWind.ENDED || state == WorldWind.CANCELLED) { this.gestureDidEnd(); } }
@Override protected void handleRotate(GestureRecognizer recognizer) { int state = recognizer.getState(); float rotation = ((RotationRecognizer) recognizer).getRotation(); if (state == WorldWind.BEGAN) { this.gestureDidBegin(); this.lastRotation = 0; } else if (state == WorldWind.CHANGED) { // Apply the change in rotation to the navigator, relative to the navigator's current values. double headingDegrees = this.lastRotation - rotation; this.camera.heading = WWMath.normalizeAngle360(this.camera.heading + headingDegrees); this.lastRotation = rotation; this.wwd.getNavigator().setAsCamera(this.wwd.getGlobe(), this.camera); this.wwd.requestRedraw(); } else if (state == WorldWind.ENDED || state == WorldWind.CANCELLED) { this.gestureDidEnd(); } }
@Override protected void handlePinch(GestureRecognizer recognizer) { int state = recognizer.getState(); float scale = ((PinchRecognizer) recognizer).getScale(); if (state == WorldWind.BEGAN) { this.gestureDidBegin(); } else if (state == WorldWind.CHANGED) { if (scale != 0) { // Apply the change in scale to the navigator, relative to when the gesture began. scale = ((scale - 1) * 0.1f) + 1; // dampen the scale factor this.camera.altitude = this.camera.altitude * scale; this.applyLimits(this.camera); this.wwd.getNavigator().setAsCamera(this.wwd.getGlobe(), this.camera); this.wwd.requestRedraw(); } } else if (state == WorldWind.ENDED || state == WorldWind.CANCELLED) { this.gestureDidEnd(); } }
/** * Creates a new WorldWindow (GLSurfaceView) object. */ public WorldWindow createWorldWindow() { // Create the WorldWindow (a GLSurfaceView) which displays the globe. this.wwd = new WorldWindow(getContext()); // Setup the WorldWindow's layers. this.wwd.getLayers().addLayer(new BackgroundLayer()); this.wwd.getLayers().addLayer(new BlueMarbleLandsatLayer()); // Setup the WorldWindow's elevation coverages. this.wwd.getGlobe().getElevationModel().addCoverage(new BasicElevationCoverage()); return this.wwd; }
@Override public void run() { this.wwd.getNavigator().getAsCamera(this.wwd.getGlobe(), this.beginCamera); this.beginPos.set(this.beginCamera.latitude, this.beginCamera.longitude, this.beginCamera.altitude); for (int i = 0; i < this.steps; i++) { double amount = (double) i / (double) (this.steps - 1); this.beginPos.interpolateAlongPath(this.endPos, WorldWind.GREAT_CIRCLE, amount, this.curPos); this.curCamera.latitude = this.curPos.latitude; this.curCamera.longitude = this.curPos.longitude; this.curCamera.altitude = this.curPos.altitude; this.curCamera.heading = WWMath.interpolateAngle360(amount, this.beginCamera.heading, this.endCamera.heading); this.curCamera.tilt = WWMath.interpolateAngle180(amount, this.beginCamera.tilt, this.endCamera.tilt); this.curCamera.roll = WWMath.interpolateAngle180(amount, this.beginCamera.roll, this.endCamera.roll); Runnable setCommand = SetCameraCommand.obtain(this.wwd, this.curCamera); runOnActivityThread(setCommand); sleepQuietly(FRAME_INTERVAL); } } }
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Establish the activity content setContentView(this.layoutResourceId); setAboutBoxTitle("About the " + this.getResources().getText(R.string.title_basic_globe)); setAboutBoxText("Demonstrates how to construct a WorldWindow with a few layers.\n" + "The globe uses the default navigation gestures: \n" + " - one-finger pan moves the camera,\n" + " - two-finger pinch-zoom adjusts the range to the look at position, \n" + " - two-finger rotate arcs the camera horizontally around the look at position,\n" + " - three-finger tilt arcs the camera vertically around the look at position."); // Create the WorldWindow (a GLSurfaceView) which displays the globe. this.wwd = new WorldWindow(this); // Add the WorldWindow view object to the layout that was reserved for the globe. FrameLayout globeLayout = (FrameLayout) findViewById(R.id.globe); globeLayout.addView(this.wwd); // Setup the WorldWindow's layers. this.wwd.getLayers().addLayer(new BackgroundLayer()); this.wwd.getLayers().addLayer(new BlueMarbleLandsatLayer()); this.wwd.getLayers().addLayer(new AtmosphereLayer()); // Setup the WorldWindow's elevation coverages. this.wwd.getGlobe().getElevationModel().addCoverage(new BasicElevationCoverage()); }
protected void handleTilt(GestureRecognizer recognizer) { int state = recognizer.getState(); float dx = recognizer.getTranslationX(); float dy = recognizer.getTranslationY(); if (state == WorldWind.BEGAN) { this.gestureDidBegin(); this.lastRotation = 0; } else if (state == WorldWind.CHANGED) { // Apply the change in tilt to the navigator, relative to when the gesture began. double headingDegrees = 180 * dx / this.wwd.getWidth(); double tiltDegrees = -180 * dy / this.wwd.getHeight(); this.lookAt.heading = WWMath.normalizeAngle360(this.beginLookAt.heading + headingDegrees); this.lookAt.tilt = this.beginLookAt.tilt + tiltDegrees; this.applyLimits(this.lookAt); this.wwd.getNavigator().setAsLookAt(this.wwd.getGlobe(), this.lookAt); this.wwd.requestRedraw(); } else if (state == WorldWind.ENDED || state == WorldWind.CANCELLED) { this.gestureDidEnd(); } }
@Override protected void handleTilt(GestureRecognizer recognizer) { int state = recognizer.getState(); float dx = recognizer.getTranslationX(); float dy = recognizer.getTranslationY(); if (state == WorldWind.BEGAN) { this.gestureDidBegin(); this.lastRotation = 0; } else if (state == WorldWind.CHANGED) { // Apply the change in tilt to the navigator, relative to when the gesture began. double headingDegrees = 180 * dx / this.wwd.getWidth(); double tiltDegrees = -180 * dy / this.wwd.getHeight(); this.camera.heading = WWMath.normalizeAngle360(this.beginCamera.heading + headingDegrees); this.camera.tilt = this.beginCamera.tilt + tiltDegrees; this.applyLimits(camera); this.wwd.getNavigator().setAsCamera(this.wwd.getGlobe(), this.camera); this.wwd.requestRedraw(); } else if (state == WorldWind.ENDED || state == WorldWind.CANCELLED) { this.gestureDidEnd(); } }