/*
Copyright (C) 2001, 2006 United States Government as represented by
the Administrator of the National Aeronautics and Space Administration.
All Rights Reserved.
*/
package gov.nasa.worldwind.awt;
import gov.nasa.worldwind.WorldWindow;
import gov.nasa.worldwind.avlist.AVKey;
import gov.nasa.worldwind.event.RenderingEvent;
import gov.nasa.worldwind.event.RenderingListener;
import gov.nasa.worldwind.geom.Angle;
import gov.nasa.worldwind.geom.Intersection;
import gov.nasa.worldwind.geom.Line;
import gov.nasa.worldwind.geom.Position;
import gov.nasa.worldwind.globes.Globe;
import gov.nasa.worldwind.pick.PickedObject;
import gov.nasa.worldwind.pick.PickedObjectList;
import gov.nasa.worldwind.view.OrbitView;
import gov.nasa.worldwind.view.ScheduledOrbitViewStateIterator;
import java.awt.*;
import java.awt.event.*;
import java.util.Arrays;
/**
* @author dcollins
* @version $Id: OrbitViewInputBroker.java 5240 2008-04-30 23:56:02Z dcollins $
*/
public class OrbitViewInputBroker
implements KeyListener, MouseListener, MouseMotionListener, MouseWheelListener, FocusListener, RenderingListener
{
private OrbitView view;
private WorldWindow wwd;
private OrbitViewInputSupport orbitViewInputSupport = new OrbitViewInputSupport();
private boolean smoothViewChanges = true;
private boolean lockHeading = true;
// Current mouse state.
private java.awt.Point mousePoint = null;
private Position selectedPosition = null;
private final Integer[] POLLED_KEYS =
{
KeyEvent.VK_LEFT, KeyEvent.VK_RIGHT,
KeyEvent.VK_UP, KeyEvent.VK_DOWN, KeyEvent.VK_PAGE_UP,
KeyEvent.VK_PAGE_DOWN, KeyEvent.VK_ADD, KeyEvent.VK_EQUALS,
KeyEvent.VK_SUBTRACT, KeyEvent.VK_MINUS
};
private KeyPollTimer keyPollTimer = new KeyPollTimer(25, Arrays.asList(POLLED_KEYS),
new ActionListener()
{
public void actionPerformed(ActionEvent actionEvent)
{
if (actionEvent == null)
return;
Object source = actionEvent.getSource();
if (source == null || !(source instanceof Integer))
return;
keyPolled((Integer) source, actionEvent.getModifiers());
}
});
public OrbitViewInputBroker()
{
}
public WorldWindow getWorldWindow()
{
return this.wwd;
}
public void setWorldWindow(WorldWindow newWorldWindow)
{
if (newWorldWindow == this.wwd)
return;
if (this.wwd != null)
{
this.wwd.removeRenderingListener(this);
}
this.wwd = newWorldWindow;
if (this.wwd != null)
{
this.wwd.addRenderingListener(this);
}
if (this.wwd != null && this.wwd.getView() != null && this.wwd.getView() instanceof OrbitView)
this.view = (OrbitView) this.wwd.getView();
else
this.view = null;
this.orbitViewInputSupport.setOrbitView(this.view);
}
public boolean isSmoothViewChanges()
{
return this.smoothViewChanges;
}
public void setSmoothViewChanges(boolean smoothViewChanges)
{
this.smoothViewChanges = smoothViewChanges;
}
public boolean isLockHeading()
{
return this.lockHeading;
}
public void setLockHeading(boolean lockHeading)
{
this.lockHeading = lockHeading;
}
private Point getMousePoint()
{
return this.mousePoint;
}
private void updateMousePoint(MouseEvent event)
{
if (event != null)
{
if (this.wwd instanceof Component)
this.mousePoint = constrainPointToComponentBounds(event.getX(), event.getY(), (Component) this.wwd);
else
this.mousePoint = new Point(event.getX(), event.getY());
}
else
{
this.mousePoint = null;
}
}
private Point constrainPointToComponentBounds(int x, int y, Component c)
{
if (c != null)
{
if (x < 0)
x = 0;
if (y < 0)
y = 0;
if (x > c.getWidth())
x = c.getWidth();
if (y > c.getHeight())
y = c.getHeight();
}
return new Point(x, y);
}
private void updateSelectedPosition()
{
PickedObjectList pickedObjects = this.wwd.getObjectsAtCurrentPosition();
if (pickedObjects != null
&& pickedObjects.getTopPickedObject() != null
&& pickedObjects.getTopPickedObject().isTerrain())
{
this.selectedPosition = pickedObjects.getTopPickedObject().getPosition();
}
else
{
this.selectedPosition = null;
}
}
private void clearSelectedPosition()
{
this.selectedPosition = null;
}
private Position computePositionAtPoint(double mouseX, double mouseY)
{
Position position = null;
if (this.view != null
&& this.wwd != null
&& this.wwd.getModel() != null
&& this.wwd.getModel().getGlobe() != null)
{
Globe globe = this.wwd.getModel().getGlobe();
Line line = this.view.computeRayFromScreenPoint(mouseX, mouseY);
if (line != null)
{
// Attempt to intersect with spheroid of scaled radius.
// This will simulate dragging the selected position more accurately.
double eyeElevation = this.view.getEyePosition().getElevation();
double selectedElevation = this.selectedPosition != null ? this.selectedPosition.getElevation() : 0;
// Intersect with the scaled spheroid, but only when the eye is not inside that spheroid.
if (eyeElevation > selectedElevation)
{
Intersection[] intersection = globe.intersect(line, selectedElevation);
if (intersection != null && intersection.length != 0)
position = globe.computePositionFromPoint(intersection[0].getIntersectionPoint());
}
}
}
return position;
}
public void keyPolled(int keyCode, int modifiers)
{
if (this.wwd == null) // include this test to ensure any derived implementation performs it
return;
if (this.view == null) // include this test to ensure any derived implementation performs it
return;
int slowMask = (modifiers & InputEvent.ALT_DOWN_MASK);
boolean slow = slowMask != 0x0;
if (areModifiersExactly(modifiers, slowMask))
{
if (isLockHeading())
{
double sinHeading = view.getHeading().sin();
double cosHeading = view.getHeading().cos();
double latFactor = 0;
double lonFactor = 0;
if (keyCode == KeyEvent.VK_LEFT)
{
latFactor = sinHeading;
lonFactor = -cosHeading;
}
else if (keyCode == KeyEvent.VK_RIGHT)
{
latFactor = -sinHeading;
lonFactor = cosHeading;
}
else if (keyCode == KeyEvent.VK_UP)
{
latFactor = cosHeading;
lonFactor = sinHeading;
}
else if (keyCode == KeyEvent.VK_DOWN)
{
latFactor = -cosHeading;
lonFactor = -sinHeading;
}
if (latFactor != 0 || lonFactor != 0)
{
Angle latChange = computeLatOrLonChange(latFactor, slow);
Angle lonChange = computeLatOrLonChange(lonFactor, slow);
setCenterLatLon(
this.view.getCenterPosition().getLatitude().add(latChange),
this.view.getCenterPosition().getLongitude().add(lonChange));
return;
}
}
//else
//{
// double forwardAmount = 0;
// double rightAmount = 0;
// if (keyCode == KeyEvent.VK_LEFT)
// rightAmount = -1;
// else if (keyCode == KeyEvent.VK_RIGHT)
// rightAmount = 1;
// else if (keyCode == KeyEvent.VK_UP)
// forwardAmount = 1;
// else if (keyCode == KeyEvent.VK_DOWN)
// forwardAmount = -1;
//
// if (forwardAmount != 0 || rightAmount != 0)
// {
// Globe globe = this.wwd.getModel().getGlobe();
// if (globe != null)
// {
// Angle forwardAngle = this.computeLatOrLonChange(this.view, globe, forwardAmount, slow);
// Angle rightAngle = this.computeLatOrLonChange(this.view, globe, rightAmount, slow);
// Quaternion forwardQuat = this.view.createRotationForward(forwardAngle);
// Quaternion rightQuat = this.view.createRotationRight(rightAngle);
// Quaternion quaternion = forwardQuat.multiply(rightQuat);
// Quaternion rotation = this.computeNewRotation(this.view, quaternion);
// this.setRotation(this.view, rotation);
// return;
// }
// }
//}
}
double headingFactor = 0;
double pitchFactor = 0;
if (areModifiersExactly(modifiers, slowMask))
{
if (keyCode == KeyEvent.VK_PAGE_DOWN)
pitchFactor = 1;
else if (keyCode == KeyEvent.VK_PAGE_UP)
pitchFactor = -1;
}
else if (areModifiersExactly(modifiers, InputEvent.SHIFT_DOWN_MASK | slowMask))
{
if (keyCode == KeyEvent.VK_LEFT)
headingFactor = -1;
else if (keyCode == KeyEvent.VK_RIGHT)
headingFactor = 1;
else if (keyCode == KeyEvent.VK_UP)
pitchFactor = -1;
else if (keyCode == KeyEvent.VK_DOWN)
pitchFactor = 1;
}
if (headingFactor != 0)
{
Angle newHeading = computeNewHeading(4 * headingFactor, slow);
setHeading(newHeading);
return;
}
else if (pitchFactor != 0)
{
Angle newPitch = computeNewPitch(4 * pitchFactor, slow);
setPitch(newPitch);
return;
}
double zoomFactor = 0;
if (areModifiersExactly(modifiers, slowMask))
{
if (keyCode == KeyEvent.VK_ADD ||
keyCode == KeyEvent.VK_EQUALS)
zoomFactor = -1;
else if (keyCode == KeyEvent.VK_SUBTRACT ||
keyCode == KeyEvent.VK_MINUS)
zoomFactor = 1;
}
else if (areModifiersExactly(modifiers, InputEvent.CTRL_DOWN_MASK | slowMask)
|| areModifiersExactly(modifiers, InputEvent.META_DOWN_MASK | slowMask))
{
if (keyCode == KeyEvent.VK_UP)
zoomFactor = -1;
else if (keyCode == KeyEvent.VK_DOWN)
zoomFactor = 1;
}
if (zoomFactor != 0)
{
double newZoom = computeNewZoom(zoomFactor, slow);
setZoom(newZoom);
}
}
public void keyTyped(KeyEvent keyEvent)
{
if (this.wwd == null) // include this test to ensure any derived implementation performs it
return;
if (this.view == null) // include this test to ensure any derived implementation performs it
return;
if (keyEvent == null)
return;
this.keyPollTimer.keyTyped(keyEvent);
}
public void keyPressed(KeyEvent keyEvent)
{
if (this.wwd == null) // include this test to ensure any derived implementation performs it
return;
if (this.view == null) // include this test to ensure any derived implementation performs it
return;
if (keyEvent == null)
return;
this.keyPollTimer.keyPressed(keyEvent);
}
public void keyReleased(KeyEvent keyEvent)
{
if (this.wwd == null) // include this test to ensure any derived implementation performs it
return;
if (this.view == null) // include this test to ensure any derived implementation performs it
return;
if (keyEvent == null)
return;
this.keyPollTimer.keyReleased(keyEvent);
int keyCode = keyEvent.getKeyCode();
if (keyCode == KeyEvent.VK_SPACE)
{
stopViewMovement();
}
else if (keyCode == KeyEvent.VK_N)
{
this.view.applyStateIterator(ScheduledOrbitViewStateIterator.createHeadingIterator(
this.view.getHeading(),
Angle.ZERO)); // Reset heading.
}
else if (keyCode == KeyEvent.VK_R)
{
this.view.applyStateIterator(ScheduledOrbitViewStateIterator.createHeadingPitchIterator(
this.view.getHeading(),
Angle.ZERO, // Reset heading.
this.view.getPitch(),
Angle.ZERO)); // Reset pitch.
}
}
public void mouseClicked(MouseEvent mouseEvent)
{
if (this.wwd == null) // include this test to ensure any derived implementation performs it
return;
if (this.view == null) // include this test to ensure any derived implementation performs it
return;
if (mouseEvent == null)
return;
PickedObjectList pickedObjects = this.wwd.getObjectsAtCurrentPosition();
if (pickedObjects == null
|| pickedObjects.getTopPickedObject() == null
|| !pickedObjects.getTopPickedObject().isTerrain())
return;
PickedObject top = pickedObjects.getTopPickedObject();
Position topPosition = top.getPosition();
if (isLockHeading())
{
this.orbitViewInputSupport.setCenterTarget(null);
// TODO: it's possible to use picked elevation as center elevation, but is this what we want?
Position pos = new Position(topPosition.getLatLon(), this.view.getCenterPosition().getElevation());
setCenterPosition(pos, true, 0.9);
}
//else
//{
// Quaternion quaternion = this.view.createRotationBetweenPositions(
// topPosition,
// new Position(this.view.getLookAtLatitude(), this.view.getLookAtLongitude(), 0));
// Quaternion rotation = this.computeNewRotation(this.view, quaternion);
// this.view.applyStateIterator(OrbitViewInputStateIterator.createRotationIterator(
// rotation, SMOOTHING, DO_COALESCE));
//}
}
public void mousePressed(MouseEvent mouseEvent)
{
if (this.wwd == null) // include this test to ensure any derived implementation performs it
return;
if (this.view == null) // include this test to ensure any derived implementation performs it
return;
if (mouseEvent == null)
return;
updateMousePoint(mouseEvent);
updateSelectedPosition();
}
public void mouseReleased(MouseEvent mouseEvent)
{
if (this.wwd == null) // include this test to ensure any derived implementation performs it
return;
if (this.view == null) // include this test to ensure any derived implementation performs it
return;
if (mouseEvent == null)
return;
updateMousePoint(mouseEvent);
clearSelectedPosition();
}
public void mouseEntered(MouseEvent mouseEvent)
{
if (this.wwd == null) // include this test to ensure any derived implementation performs it
return;
if (this.view == null) // include this test to ensure any derived implementation performs it
return;
}
public void mouseExited(MouseEvent mouseEvent)
{
if (this.wwd == null) // include this test to ensure any derived implementation performs it
return;
if (this.view == null) // include this test to ensure any derived implementation performs it
return;
}
public void mouseDragged(MouseEvent mouseEvent)
{
if (this.wwd == null) // include this test to ensure any derived implementation performs it
return;
if (this.view == null) // include this test to ensure any derived implementation performs it
return;
if (mouseEvent == null)
return;
// Store previous mouse point.
java.awt.Point prevMousePoint = getMousePoint();
// Update mouse point.
updateMousePoint(mouseEvent);
// Store new mouse point.
java.awt.Point curMousePoint = getMousePoint();
// Compute mouse movement.
java.awt.Point mouseMove = null;
if (curMousePoint != null && prevMousePoint != null)
{
mouseMove = new java.awt.Point(
curMousePoint.x - prevMousePoint.x,
curMousePoint.y - prevMousePoint.y);
}
// Compute the current selected position if none exists.
if (this.selectedPosition == null)
this.updateSelectedPosition();
if (areModifiersExactly(mouseEvent, InputEvent.BUTTON1_DOWN_MASK))
{
if (prevMousePoint != null && curMousePoint != null)
{
Position prevPosition = computePositionAtPoint(prevMousePoint.x, prevMousePoint.y);
Position curPosition = computePositionAtPoint(curMousePoint.x, curMousePoint.y);
// Keep selected position under cursor.
if (prevPosition != null && curPosition != null)
{
if (!prevPosition.equals(curPosition))
{
if (isLockHeading())
{
setCenterLatLon(
this.view.getCenterPosition().getLatitude().add(prevPosition.getLatitude()).subtract(curPosition.getLatitude()),
this.view.getCenterPosition().getLongitude().add(prevPosition.getLongitude()).subtract(curPosition.getLongitude()));
}
//else
//{
// Quaternion quaternion = this.view.createRotationBetweenPositions(prevPosition, curPosition);
// if (quaternion != null)
// {
// Quaternion rotation = this.computeNewRotation(this.view, quaternion);
// this.setRotation(this.view, rotation);
// }
//}
}
}
// Cursor is off the globe, simulate globe dragging.
else
{
if (isLockHeading())
{
double sinHeading = this.view.getHeading().sin();
double cosHeading = this.view.getHeading().cos();
double latFactor = (cosHeading * mouseMove.y + sinHeading * mouseMove.x) / 10.0;
double lonFactor = (sinHeading * mouseMove.y - cosHeading * mouseMove.x) / 10.0;
Angle latChange = computeLatOrLonChange(latFactor, false);
Angle lonChange = computeLatOrLonChange(lonFactor, false);
setCenterLatLon(
this.view.getCenterPosition().getLatitude().add(latChange),
this.view.getCenterPosition().getLongitude().add(lonChange));
}
//else
//{
// double forwardFactor = mouseMove.y / 10.0;
// double rightFactor = -mouseMove.x / 10.0;
// Angle forwardAngle = this.computeLatOrLonChange(this.view, globe, forwardFactor, false);
// Angle rightAngle = this.computeLatOrLonChange(this.view, globe, rightFactor, false);
// Quaternion forwardQuat = this.view.createRotationForward(forwardAngle);
// Quaternion rightQuat = this.view.createRotationRight(rightAngle);
// Quaternion quaternion = forwardQuat.multiply(rightQuat);
// Quaternion rotation = this.computeNewRotation(this.view, quaternion);
// this.setRotation(this.view, rotation);
//}
// Cursor went off the globe. Clear the selected position to ensure a new one will be
// computed if the cursor returns to the globe.
clearSelectedPosition();
}
}
}
else if (areModifiersExactly(mouseEvent, InputEvent.BUTTON3_DOWN_MASK)
|| areModifiersExactly(mouseEvent, InputEvent.BUTTON1_DOWN_MASK | InputEvent.CTRL_DOWN_MASK))
{
if (mouseMove != null)
{
if (mouseMove.x != 0)
{
// Switch the direction of heading change depending on whether the cursor is above or below
// the center of the screen.
double headingDirection = 1;
Object source = mouseEvent.getSource();
if (source != null && source instanceof java.awt.Component)
{
java.awt.Component component = (java.awt.Component) source;
if (mouseEvent.getPoint().y < (component.getHeight() / 2))
headingDirection = -1;
}
Angle newHeading = computeNewHeading(headingDirection * mouseMove.x, false);
setHeading(newHeading);
}
if (mouseMove.y != 0)
{
Angle newPitch = computeNewPitch(mouseMove.y, false);
setPitch(newPitch);
}
}
}
else if (areModifiersExactly(mouseEvent, InputEvent.BUTTON2_DOWN_MASK))
{
if (mouseMove != null)
{
if (mouseMove.y != 0)
{
// Reduce the amount of zoom changed by mouse movement.
double scaledMouseY = mouseMove.y / 10d;
double newZoom = computeNewZoom(scaledMouseY, false);
setZoom(newZoom);
}
}
}
}
public void mouseMoved(MouseEvent mouseEvent)
{
if (this.wwd == null) // include this test to ensure any derived implementation performs it
return;
if (this.view == null) // include this test to ensure any derived implementation performs it
return;
if (mouseEvent == null)
return;
updateMousePoint(mouseEvent);
}
public void mouseWheelMoved(MouseWheelEvent mouseWheelEvent)
{
if (this.wwd == null) // include this test to ensure any derived implementation performs it
return;
if (this.view == null) // include this test to ensure any derived implementation performs it
return;
if (mouseWheelEvent == null)
return;
int wheelRotation = mouseWheelEvent.getWheelRotation();
double wheelDirection = Math.signum(wheelRotation);
double newZoom = computeNewZoom(wheelDirection, false);
setZoom(newZoom);
}
public void focusGained(FocusEvent focusEvent)
{
if (this.wwd == null) // include this test to ensure any derived implementation performs it
return;
if (this.view == null) // include this test to ensure any derived implementation performs it
return;
}
public void focusLost(FocusEvent focusEvent)
{
if (this.wwd == null) // include this test to ensure any derived implementation performs it
return;
if (this.view == null) // include this test to ensure any derived implementation performs it
return;
if (focusEvent == null)
return;
stopViewMovement();
this.keyPollTimer.stop();
}
public void stageChanged(RenderingEvent event)
{
if (this.wwd == null) // include this test to ensure any derived implementation performs it
return;
if (this.view == null) // include this test to ensure any derived implementation performs it
return;
if (event == null)
return;
if (event.getStage().equals(RenderingEvent.BEFORE_RENDERING))
{
// Cancel any InputHandler view changes if someone has set a view state iterator.
if (this.view.hasStateIterator())
this.orbitViewInputSupport.clearTargets();
if (this.orbitViewInputSupport.hasTargets())
this.orbitViewInputSupport.moveViewTowardTargets();
}
}
private static boolean areModifiersExactly(InputEvent inputEvent, int mask)
{
return areModifiersExactly(inputEvent.getModifiersEx(), mask);
}
private static boolean areModifiersExactly(int modifiersEx, int mask)
{
return modifiersEx == mask;
}
// ============== View State Changes ======================= //
// ============== View State Changes ======================= //
// ============== View State Changes ======================= //
private void stopViewMovement()
{
if (this.view == null)
return;
this.view.stopMovement();
}
private void stopViewIterators()
{
if (this.view == null)
return;
if (this.view.hasStateIterator())
this.view.stopStateIterators();
}
private void fireViewChangedEvent()
{
if (this.view == null)
return;
this.view.firePropertyChange(AVKey.VIEW, null, this.view);
}
private void setCenterLatLon(Angle latitude, Angle longitude)
{
if (this.view == null)
return;
setCenterPosition(new Position(latitude, longitude, this.view.getCenterPosition().getElevation()));
}
private void setCenterPosition(Position newCenter)
{
if (this.view == null)
return;
setCenterPosition(newCenter, this.smoothViewChanges, 0.4);
}
private void setCenterPosition(Position newCenter, boolean smoothed, double smoothingAmount)
{
if (this.view == null)
return;
// Stop ViewStateIterators, so we are the only one affecting the view.
stopViewIterators();
Position prevTarget = this.orbitViewInputSupport.getCenterTarget();
if (smoothed && prevTarget != null)
{
Position curCenter = this.view.getCenterPosition();
newCenter = new Position(
prevTarget.getLatitude().add(newCenter.getLatitude()).subtract(curCenter.getLatitude()),
prevTarget.getLongitude().add(newCenter.getLongitude()).subtract(curCenter.getLongitude()),
prevTarget.getElevation() + newCenter.getElevation() - curCenter.getElevation());
}
this.orbitViewInputSupport.setCenterSmoothing(smoothed ? smoothingAmount : 0);
this.orbitViewInputSupport.setCenterTarget(newCenter);
fireViewChangedEvent();
}
private void setHeading(Angle newHeading)
{
if (this.view == null)
return;
setHeading(newHeading, this.smoothViewChanges, 0.7);
}
private void setHeading(Angle newHeading, boolean smoothed, double smoothingAmount)
{
if (this.view == null)
return;
// Stop ViewStateIterators, so we are the only one affecting the view.
stopViewIterators();
Angle prevTarget = this.orbitViewInputSupport.getHeadingTarget();
if (smoothed && prevTarget != null)
newHeading = prevTarget.add(newHeading).subtract(this.view.getHeading());
this.orbitViewInputSupport.setHeadingSmoothing(smoothed ? smoothingAmount : 0);
this.orbitViewInputSupport.setHeadingTarget(newHeading);
fireViewChangedEvent();
}
private void setPitch(Angle newPitch)
{
if (this.view == null)
return;
setPitch(newPitch, this.smoothViewChanges, 0.7);
}
private void setPitch(Angle newPitch, boolean smoothed, double smoothingAmount)
{
if (this.view == null)
return;
// Stop ViewStateIterators, so we are the only one affecting the view.
stopViewIterators();
Angle prevTarget = this.orbitViewInputSupport.getPitchTarget();
if (smoothed && prevTarget != null)
newPitch = prevTarget.add(newPitch).subtract(this.view.getPitch());
this.orbitViewInputSupport.setPitchSmoothing(smoothed ? smoothingAmount : 0);
this.orbitViewInputSupport.setPitchTarget(newPitch);
fireViewChangedEvent();
}
private void setZoom(double newZoom)
{
if (this.view == null)
return;
setZoom(newZoom, this.smoothViewChanges, 0.9);
}
private void setZoom(double newZoom, boolean smoothed, double smoothingAmount)
{
if (this.view == null)
return;
// Stop ViewStateIterators, so we are the only one affecting the view.
stopViewIterators();
double prevTarget = this.orbitViewInputSupport.getZoomTarget();
if (smoothed && prevTarget >= 0)
newZoom = computeNewZoomTarget(prevTarget, newZoom, this.view.getZoom());
this.orbitViewInputSupport.setZoomSmoothing(smoothed ? smoothingAmount : 0);
this.orbitViewInputSupport.setZoomTarget(newZoom);
fireViewChangedEvent();
}
private Angle computeLatOrLonChange(double amount, boolean slow)
{
if (this.wwd == null
|| this.wwd.getModel() == null
|| this.wwd.getModel().getGlobe() == null
|| this.view == null
|| this.view.getEyePosition() == null)
{
return Angle.ZERO;
}
Position eyePos = this.view.getEyePosition();
double normAlt = (eyePos.getElevation() / this.wwd.getModel().getGlobe().getRadiusAt(eyePos.getLatLon()));
if (normAlt < 0)
normAlt = 0;
else if (normAlt > 1)
normAlt = 1;
double coeff = (0.0001 * (1 - normAlt)) + (2 * normAlt);
if (slow)
coeff /= 4.0;
return Angle.fromDegrees(coeff * amount);
}
private Angle computeNewHeading(double amount, boolean slow)
{
if (this.view == null)
return Angle.ZERO;
return computeNewHeadingOrPitch(this.view.getHeading(), amount, slow);
}
private Angle computeNewPitch(double amount, boolean slow)
{
if (this.view == null)
return Angle.ZERO;
return computeNewHeadingOrPitch(this.view.getPitch(), amount, slow);
}
private Angle computeNewHeadingOrPitch(Angle value, double amount, boolean slow)
{
double coeff = 1.0/4.0;
if (slow)
coeff /= 4.0;
Angle change = Angle.fromDegrees(coeff * amount);
return value.add(change);
}
private double computeNewZoom(double amount, boolean slow)
{
if (this.view == null)
return 0;
double coeff = 0.05;
if (slow)
coeff /= 4.0;
double change = coeff * amount;
double logZoom = this.view.getZoom() != 0 ? Math.log(this.view.getZoom()) : 0;
// Zoom changes are treated as logarithmic values. This accomplishes two things:
// 1) Zooming is slow near the globe, and fast at great distances.
// 2) Zooming in then immediately zooming out returns the viewer to the same zoom value.
return Math.exp(logZoom + change);
}
private double computeNewZoomTarget(double prevTarget, double newTarget, double curZoom)
{
double lonPrevTarget = prevTarget != 0 ? Math.log(prevTarget) : 0;
double logNewTarget = newTarget != 0 ? Math.log(newTarget) : 0;
double logCurZoom = curZoom != 0 ? Math.log(curZoom) : 0;
return Math.exp(lonPrevTarget + logNewTarget - logCurZoom);
}
//private void setRotation(OrbitView view, Quaternion rotation)
//{
// if (this.isSmoothViewChanges())
// {
// view.applyStateIterator(OrbitViewInputStateIterator.createRotationIterator(
// rotation));
// }
// else
// {
// view.setRotation(rotation);
// this.updateView(view);
// }
//}
//private Quaternion computeNewRotation(OrbitView view, Quaternion amount)
//{
// return view.getRotation().multiply(amount);
//}
}