/*
Copyright (C) 2001, 2007 United States Government as represented by
the Administrator of the National Aeronautics and Space Administration.
All Rights Reserved.
*/
package gov.nasa.worldwind.view;
import gov.nasa.worldwind.Configuration;
import gov.nasa.worldwind.avlist.AVKey;
import gov.nasa.worldwind.geom.*;
import gov.nasa.worldwind.globes.Globe;
import gov.nasa.worldwind.render.DrawContext;
import gov.nasa.worldwind.util.Logging;
import gov.nasa.worldwind.util.RestorableSupport;
import javax.media.opengl.GL;
/**
* @author dcollins
* @version $Id: BasicOrbitView.java 5276 2008-05-02 04:33:57Z dcollins $
*/
public class BasicOrbitView extends AbstractView implements OrbitView
{
private Position center = Position.ZERO;
private Angle heading = Angle.ZERO;
private Angle pitch = Angle.ZERO;
private double zoom;
private Angle fieldOfView = Angle.fromDegrees(45);
private double nearClipDistance = -1; // Default to auto-configure.
private double farClipDistance = -1; // Default to auto-configure.
// Model for defining translations between OrbitView coordinates and 3D coordinates.
private final OrbitViewModel orbitViewModel;
// Stateless helper classes.
private final ViewSupport viewSupport = new ViewSupport();
private final OrbitViewCollisionSupport collisionSupport = new OrbitViewCollisionSupport();
// Properties updated in doApply().
private Matrix modelview = Matrix.IDENTITY;
private Matrix modelviewInv = Matrix.IDENTITY;
private Matrix projection = Matrix.IDENTITY;
private java.awt.Rectangle viewport = new java.awt.Rectangle();
private Frustum frustum = new Frustum();
// Properties updated during the most recent call to apply().
private DrawContext dc;
private Globe globe;
private Position lastEyePosition = null;
private Vec4 lastEyePoint = null;
private Vec4 lastUpVector = null;
private Vec4 lastForwardVector = null;
private Frustum lastFrustumInModelCoords = null;
// TODO: make configurable
private static final double MINIMUM_NEAR_DISTANCE = 2;
private static final double MINIMUM_FAR_DISTANCE = 100;
private static final double COLLISION_THRESHOLD = 10;
private static final int COLLISION_NUM_ITERATIONS = 4;
public BasicOrbitView()
{
this(new BasicOrbitViewModel());
}
public BasicOrbitView(OrbitViewModel orbitViewModel)
{
if (orbitViewModel == null)
{
String message = Logging.getMessage("nullValue.OrbitViewModelIsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
this.orbitViewModel = orbitViewModel;
this.collisionSupport.setCollisionThreshold(COLLISION_THRESHOLD);
this.collisionSupport.setNumIterations(COLLISION_NUM_ITERATIONS);
loadConfigurationValues();
}
private void loadConfigurationValues()
{
Double initLat = Configuration.getDoubleValue(AVKey.INITIAL_LATITUDE);
Double initLon = Configuration.getDoubleValue(AVKey.INITIAL_LONGITUDE);
double initElev = this.center.getElevation();
// Set center latitude and longitude. Do not change center elevation.
if (initLat != null && initLon != null)
setCenterPosition(Position.fromDegrees(initLat, initLon, initElev));
// Set only center latitude. Do not change center longitude or center elevation.
else if (initLat != null)
setCenterPosition(Position.fromDegrees(initLat, this.center.getLongitude().degrees, initElev));
// Set only center longitude. Do not center latitude or center elevation.
else if (initLon != null)
setCenterPosition(Position.fromDegrees(this.center.getLatitude().degrees, initLon, initElev));
Double initHeading = Configuration.getDoubleValue(AVKey.INITIAL_HEADING);
if (initHeading != null)
setHeading(Angle.fromDegrees(initHeading));
Double initPitch = Configuration.getDoubleValue(AVKey.INITIAL_PITCH);
if (initPitch != null)
setPitch(Angle.fromDegrees(initPitch));
Double initAltitude = Configuration.getDoubleValue(AVKey.INITIAL_ALTITUDE);
if (initAltitude != null)
setZoom(initAltitude);
Double initFov = Configuration.getDoubleValue(AVKey.FOV);
if (initFov != null)
setFieldOfView(Angle.fromDegrees(initFov));
}
public Position getCenterPosition()
{
return this.center;
}
public void setCenterPosition(Position center)
{
if (center == null)
{
String message = Logging.getMessage("nullValue.PositionIsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
if (center.getLatitude().degrees < -90 || center.getLatitude().degrees > 90)
{
String message = Logging.getMessage("generic.LatitudeOutOfRange", center.getLatitude());
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
this.center = normalizedPosition(center);
resolveCollisionsWithCenterPosition();
}
public Angle getHeading()
{
return this.heading;
}
public void setHeading(Angle heading)
{
if (heading == null)
{
String message = Logging.getMessage("nullValue.AngleIsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
this.heading = normalizedHeading(heading);
resolveCollisionsWithPitch();
}
public Angle getPitch()
{
return this.pitch;
}
public void setPitch(Angle pitch)
{
if (pitch == null)
{
String message = Logging.getMessage("nullValue.AngleIsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
if (pitch.degrees > 90 || pitch.degrees < 0)
{
String message = Logging.getMessage("generic.AngleOutOfRange", pitch);
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
this.pitch = pitch;
resolveCollisionsWithPitch();
}
public double getZoom()
{
return this.zoom;
}
public void setZoom(double zoom)
{
if (zoom < 0)
{
String message = Logging.getMessage("generic.ArgumentOutOfRange", zoom);
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
this.zoom = zoom;
resolveCollisionsWithCenterPosition();
}
public OrbitViewModel getOrbitViewModel()
{
return this.orbitViewModel;
}
private static Position normalizedPosition(Position position)
{
if (position == null)
{
String message = Logging.getMessage("nullValue.PositionIsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
return new Position(
Angle.normalizedLatitude(position.getLatitude()),
Angle.normalizedLongitude(position.getLongitude()),
position.getElevation());
}
private static Angle normalizedHeading(Angle unnormalizedAngle)
{
if (unnormalizedAngle == null)
{
String message = Logging.getMessage("nullValue.AngleIsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
double degrees = unnormalizedAngle.degrees;
double heading = degrees % 360;
return Angle.fromDegrees(heading > 180 ? heading - 360 : (heading < -180 ? 360 + heading : heading));
}
private void resolveCollisionsWithCenterPosition()
{
if (this.dc == null)
return;
if (!isDetectCollisions())
return;
// Compute the near distance corresponding to the current set of values.
double nearDistance = this.nearClipDistance > 0 ? this.nearClipDistance : getAutoNearClipDistance();
// If there is no collision, 'newCenterPosition' will be null. Otherwise it will contain a value
// that will resolve the collision.
Position newCenter = this.collisionSupport.computeCenterPositionToResolveCollision(this, nearDistance, this.dc);
if (newCenter != null && newCenter.getLatitude().degrees >= -90 && newCenter.getLongitude().degrees <= 90)
{
this.center = newCenter;
flagHadCollisions();
}
}
private void resolveCollisionsWithPitch()
{
if (this.dc == null)
return;
if (!isDetectCollisions())
return;
// Compute the near distance corresponding to the current set of values.
double nearDistance = this.nearClipDistance > 0 ? this.nearClipDistance : getAutoNearClipDistance();
// If there is no collision, 'newPitch' will be null. Otherwise it will contain a value
// that will resolve the collision.
Angle newPitch = this.collisionSupport.computePitchToResolveCollision(this, nearDistance, this.dc);
if (newPitch != null && newPitch.degrees <= 90 && newPitch.degrees >= 0)
{
this.pitch = newPitch;
flagHadCollisions();
}
}
public boolean canFocusOnViewportCenter()
{
return this.dc != null
&& this.dc.getViewportCenterPosition() != null
&& this.globe != null;
}
public void focusOnViewportCenter()
{
if (this.dc == null)
{
String message = Logging.getMessage("nullValue.DrawContextIsNull");
Logging.logger().severe(message);
throw new IllegalStateException(message);
}
if (this.globe == null)
{
String message = Logging.getMessage("nullValue.DrawingContextGlobeIsNull");
Logging.logger().severe(message);
throw new IllegalStateException(message);
}
Position viewportCenterPos = this.dc.getViewportCenterPosition();
if (viewportCenterPos == null)
{
String message = Logging.getMessage("nullValue.DrawingContextViewportCenterIsNull");
Logging.logger().severe(message);
throw new IllegalStateException(message);
}
// We want the actual "geometric point" here, which must be adjusted for vertical exaggeration.
Vec4 viewportCenterPoint = this.globe.computePointFromPosition(
viewportCenterPos.getLatitude(), viewportCenterPos.getLongitude(),
this.globe.getElevation(viewportCenterPos.getLatitude(), viewportCenterPos.getLongitude())
* dc.getVerticalExaggeration());
if (viewportCenterPoint != null)
{
Matrix modelview = this.orbitViewModel.computeTransformMatrix(this.globe,
this.center, this.heading, this.pitch, this.zoom);
if (modelview != null)
{
Matrix modelviewInv = modelview.getInverse();
if (modelviewInv != null)
{
// The change in focus must happen seamlessly; we can't move the eye or the forward vector
// (only the center position and zoom should change). Therefore we pick a point along the
// forward vector, and *near* the viewportCenterPoint, but not necessarily at the
// viewportCenterPoint itself.
Vec4 eyePoint = Vec4.UNIT_W.transformBy4(modelviewInv);
Vec4 forward = Vec4.UNIT_NEGATIVE_Z.transformBy4(modelviewInv);
double distance = eyePoint.distanceTo3(viewportCenterPoint);
Vec4 newCenterPoint = Vec4.fromLine3(eyePoint, distance, forward);
OrbitViewModel.ModelCoordinates modelCoords = this.orbitViewModel.computeModelCoordinates(
this.globe, modelview, newCenterPoint);
if (validateModelCoordinates(modelCoords))
{
setModelCoordinates(modelCoords);
}
}
}
}
}
public void stopMovementOnCenter()
{
firePropertyChange(CENTER_STOPPED, null, null);
}
public Position getEyePosition()
{
if (this.lastEyePosition == null)
this.lastEyePosition = computeEyePositionFromModelview();
return this.lastEyePosition;
}
public void setEyePosition(Position eyePosition)
{
if (eyePosition == null)
{
String message = Logging.getMessage("nullValue.PositionIsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
LatLon latlon = eyePosition.getLatLon();
double elevation = eyePosition.getElevation();
// Set the center lat/lon to the eye lat/lon. Set the center elevation to zero if the eye elevation is >= 0.
// Set the center elevation to the eye elevation if the eye elevation is < 0.
this.center = new Position(latlon, elevation >= 0 ? 0 : elevation);
this.heading = Angle.ZERO;
this.pitch = Angle.ZERO;
// If the eye elevation is >= 0, zoom gets the eye elevation. If the eye elevation < 0, zoom gets 0.
this.zoom = elevation >= 0 ? elevation : 0;
resolveCollisionsWithCenterPosition();
}
public Position getCurrentEyePosition()
{
if (this.globe != null)
{
Matrix modelview = this.orbitViewModel.computeTransformMatrix(this.globe, this.center,
this.heading, this.pitch, this.zoom);
if (modelview != null)
{
Matrix modelviewInv = modelview.getInverse();
if (modelviewInv != null)
{
Vec4 eyePoint = Vec4.UNIT_W.transformBy4(modelviewInv);
return this.globe.computePositionFromPoint(eyePoint);
}
}
}
return Position.ZERO;
}
public void setOrientation(Position eyePosition, Position centerPosition)
{
if (eyePosition == null || centerPosition == null)
{
String message = Logging.getMessage("nullValue.PositionIsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
if (this.globe == null)
{
String message = Logging.getMessage("nullValue.DrawingContextGlobeIsNull");
Logging.logger().severe(message);
throw new IllegalStateException(message);
}
Vec4 newEyePoint = this.globe.computePointFromPosition(eyePosition);
Vec4 newCenterPoint = this.globe.computePointFromPosition(centerPosition);
if (newEyePoint == null || newCenterPoint == null)
{
String message = Logging.getMessage("View.ErrorSettingOrientation", eyePosition, centerPosition);
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
// If eye lat/lon != center lat/lon, then the surface normal at the center point will be a good value
// for the up direction.
Vec4 up = this.globe.computeSurfaceNormalAtPoint(newCenterPoint);
// Otherwise, estimate the up direction by using the *current* heading with the new center position.
Vec4 forward = newCenterPoint.subtract3(newEyePoint).normalize3();
if (forward.cross3(up).getLength3() < 0.001)
{
Matrix modelview = this.orbitViewModel.computeTransformMatrix(
this.globe, centerPosition, this.heading, Angle.ZERO, 1);
if (modelview != null)
{
Matrix modelviewInv = modelview.getInverse();
if (modelviewInv != null)
{
up = Vec4.UNIT_Y.transformBy4(modelviewInv);
}
}
}
if (up == null)
{
String message = Logging.getMessage("View.ErrorSettingOrientation", eyePosition, centerPosition);
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
OrbitViewModel.ModelCoordinates modelCoords = this.orbitViewModel.computeModelCoordinates(
this.globe, newEyePoint, newCenterPoint, up);
if (!validateModelCoordinates(modelCoords))
{
String message = Logging.getMessage("View.ErrorSettingOrientation", eyePosition, centerPosition);
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
setModelCoordinates(modelCoords);
}
public Vec4 getEyePoint()
{
if (this.lastEyePoint == null)
this.lastEyePoint = Vec4.UNIT_W.transformBy4(this.modelviewInv);
return this.lastEyePoint;
}
public Vec4 getCurrentEyePoint()
{
if (this.globe != null)
{
Matrix modelview = this.orbitViewModel.computeTransformMatrix(this.globe, this.center,
this.heading, this.pitch, this.zoom);
if (modelview != null)
{
Matrix modelviewInv = modelview.getInverse();
if (modelviewInv != null)
{
return Vec4.UNIT_W.transformBy4(modelviewInv);
}
}
}
return Vec4.ZERO;
}
public Vec4 getUpVector()
{
if (this.lastUpVector == null)
this.lastUpVector = Vec4.UNIT_Y.transformBy4(this.modelviewInv);
return this.lastUpVector;
}
public Vec4 getForwardVector()
{
if (this.lastForwardVector == null)
this.lastForwardVector = Vec4.UNIT_NEGATIVE_Z.transformBy4(this.modelviewInv);
return this.lastForwardVector;
}
public Matrix getModelviewMatrix()
{
return this.modelview;
}
public Angle getFieldOfView()
{
return this.fieldOfView;
}
public void setFieldOfView(Angle fieldOfView)
{
if (fieldOfView == null)
{
String message = Logging.getMessage("nullValue.AngleIsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
this.fieldOfView = fieldOfView;
}
public double getNearClipDistance()
{
return this.nearClipDistance;
}
public void setNearClipDistance(double distance)
{
this.nearClipDistance = distance;
}
public double getFarClipDistance()
{
return this.farClipDistance;
}
public void setFarClipDistance(double distance)
{
this.farClipDistance = distance;
}
public double getAutoNearClipDistance()
{
Position eyePos = getCurrentEyePosition();
return computeNearDistance(eyePos);
}
public double getAutoFarClipDistance()
{
Position eyePos = getCurrentEyePosition();
return computeFarDistance(eyePos);
}
private double computeNearDistance(Position eyePosition)
{
double near = 0;
if (eyePosition != null && this.dc != null)
{
double elevation = this.viewSupport.computeElevationAboveSurface(this.dc, eyePosition);
double tanHalfFov = this.fieldOfView.tanHalfAngle();
near = elevation / (2 * Math.sqrt(2 * tanHalfFov * tanHalfFov + 1));
}
return near < MINIMUM_NEAR_DISTANCE ? MINIMUM_NEAR_DISTANCE : near;
}
private double computeFarDistance(Position eyePosition)
{
double far = 0;
if (eyePosition != null)
{
far = computeHorizonDistance(eyePosition);
}
return far < MINIMUM_FAR_DISTANCE ? MINIMUM_FAR_DISTANCE : far;
}
public java.awt.Rectangle getViewport()
{
// java.awt.Rectangle is mutable, so we defensively copy the viewport.
return new java.awt.Rectangle(this.viewport);
}
public Frustum getFrustum()
{
return this.frustum;
}
public Frustum getFrustumInModelCoordinates()
{
if (this.lastFrustumInModelCoords == null)
{
Matrix modelviewTranspose = this.modelview.getTranspose();
if (modelviewTranspose != null)
this.lastFrustumInModelCoords = this.frustum.transformBy(modelviewTranspose);
else
this.lastFrustumInModelCoords = this.frustum;
}
return this.lastFrustumInModelCoords;
}
public Matrix getProjectionMatrix()
{
return this.projection;
}
protected void doApply(DrawContext dc)
{
if (dc == null)
{
String message = Logging.getMessage("nullValue.DrawContextIsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
if (dc.getGL() == null)
{
String message = Logging.getMessage("nullValue.DrawingContextGLIsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
if (dc.getGlobe() == null)
{
String message = Logging.getMessage("nullValue.DrawingContextGlobeIsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
// Update DrawContext and Globe references.
this.dc = dc;
this.globe = this.dc.getGlobe();
//========== modelview matrix state ==========//
// Compute the current modelview matrix.
this.modelview = this.orbitViewModel.computeTransformMatrix(this.globe, this.center,
this.heading, this.pitch, this.zoom);
if (this.modelview == null)
this.modelview = Matrix.IDENTITY;
// Compute the current inverse-modelview matrix.
this.modelviewInv = this.modelview.getInverse();
if (this.modelviewInv == null)
this.modelviewInv = Matrix.IDENTITY;
//========== projection matrix state ==========//
// Get the current OpenGL viewport state.
int[] viewportArray = new int[4];
this.dc.getGL().glGetIntegerv(GL.GL_VIEWPORT, viewportArray, 0);
this.viewport = new java.awt.Rectangle(viewportArray[0], viewportArray[1], viewportArray[2], viewportArray[3]);
// Compute the current clip plane distances.
double nearDistance = this.nearClipDistance > 0 ? this.nearClipDistance : getAutoNearClipDistance();
double farDistance = this.farClipDistance > 0 ? this.farClipDistance : getAutoFarClipDistance();
// Compute the current projection matrix.
this.projection = Matrix.fromPerspective(this.fieldOfView,
this.viewport.getWidth(), this.viewport.getHeight(),
nearDistance, farDistance);
// Compute the current frustum.
this.frustum = Frustum.fromPerspective(this.fieldOfView,
(int) this.viewport.getWidth(), (int) this.viewport.getHeight(),
nearDistance, farDistance);
//========== load GL matrix state ==========//
this.viewSupport.loadGLViewState(dc, this.modelview, this.projection);
//========== after apply (GL matrix state) ==========//
afterDoApply();
}
protected void afterDoApply()
{
// Clear cached computations.
this.lastEyePosition = null;
this.lastEyePoint = null;
this.lastUpVector = null;
this.lastForwardVector = null;
this.lastFrustumInModelCoords = null;
}
public Vec4 project(Vec4 modelPoint)
{
if (modelPoint == null)
{
String message = Logging.getMessage("nullValue.Vec4IsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
return this.viewSupport.project(modelPoint, this.modelview, this.projection, this.viewport);
}
public Vec4 unProject(Vec4 windowPoint)
{
if (windowPoint == null)
{
String message = Logging.getMessage("nullValue.Vec4IsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
return this.viewSupport.unProject(windowPoint, this.modelview, this.projection, this.viewport);
}
public Line computeRayFromScreenPoint(double x, double y)
{
return this.viewSupport.computeRayFromScreenPoint(x, y, this.modelview, this.projection, this.viewport);
}
public Position computePositionFromScreenPoint(double x, double y)
{
if (this.globe != null)
{
Line ray = computeRayFromScreenPoint(x, y);
if (ray != null)
return this.globe.getIntersectionPosition(ray);
}
return null;
}
public double computePixelSizeAtDistance(double distance)
{
return this.viewSupport.computePixelSizeAtDistance(distance, this.fieldOfView, this.viewport);
}
public double computeHorizonDistance()
{
double horizon = 0;
Position eyePos = computeEyePositionFromModelview();
if (eyePos != null)
{
horizon = computeHorizonDistance(eyePos);
}
return horizon;
}
private double computeHorizonDistance(Position eyePosition)
{
if (this.globe != null && eyePosition != null)
{
double elevation = eyePosition.getElevation();
double elevationAboveSurface = this.viewSupport.computeElevationAboveSurface(this.dc, eyePosition);
return this.viewSupport.computeHorizonDistance(this.globe, Math.max(elevation, elevationAboveSurface));
}
return 0;
}
private Position computeEyePositionFromModelview()
{
if (this.globe != null)
{
Vec4 eyePoint = Vec4.UNIT_W.transformBy4(this.modelviewInv);
return this.globe.computePositionFromPoint(eyePoint);
}
return Position.ZERO;
}
private void setModelCoordinates(OrbitViewModel.ModelCoordinates modelCoords)
{
if (modelCoords != null)
{
if (modelCoords.getCenterPosition() != null)
this.center = normalizedPosition(modelCoords.getCenterPosition());
if (modelCoords.getHeading() != null)
this.heading = normalizedHeading(modelCoords.getHeading());
if (modelCoords.getPitch() != null)
this.pitch = modelCoords.getPitch();
this.zoom = modelCoords.getZoom();
}
}
private boolean validateModelCoordinates(OrbitViewModel.ModelCoordinates modelCoords)
{
return (modelCoords != null
&& modelCoords.getCenterPosition() != null
&& modelCoords.getCenterPosition().getLatitude().degrees >= -90
&& modelCoords.getCenterPosition().getLatitude().degrees <= 90
&& modelCoords.getHeading() != null
&& modelCoords.getPitch() != null
&& modelCoords.getPitch().degrees >= 0
&& modelCoords.getPitch().degrees <= 90
&& modelCoords.getZoom() >= 0);
}
public String getRestorableState()
{
RestorableSupport rs = RestorableSupport.newRestorableSupport();
// Creating a new RestorableSupport failed. RestorableSupport logged the problem, so just return null.
if (rs == null)
return null;
rs.addStateValueAsBoolean("detectCollisions", isDetectCollisions());
if (this.fieldOfView != null)
rs.addStateValueAsDouble("fieldOfView", this.fieldOfView.degrees);
if (this.nearClipDistance > 0)
rs.addStateValueAsDouble("nearClipDistance", this.nearClipDistance);
if (this.farClipDistance > 0)
rs.addStateValueAsDouble("farClipDistance", this.farClipDistance);
if (this.center != null)
{
RestorableSupport.StateObject so = rs.addStateObject("center");
if (so != null)
{
rs.addStateValueAsDouble(so, "latitude", this.center.getLatitude().degrees);
rs.addStateValueAsDouble(so, "longitude", this.center.getLongitude().degrees);
rs.addStateValueAsDouble(so, "elevation", this.center.getElevation());
}
}
if (this.heading != null)
rs.addStateValueAsDouble("heading", this.heading.degrees);
if (this.pitch != null)
rs.addStateValueAsDouble("pitch", this.pitch.degrees);
rs.addStateValueAsDouble("zoom", this.zoom);
return rs.getStateAsXml();
}
public void restoreState(String stateInXml)
{
if (stateInXml == null)
{
String message = Logging.getMessage("nullValue.StringIsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
RestorableSupport rs;
try
{
rs = RestorableSupport.parse(stateInXml);
}
catch (Exception e)
{
// Parsing the document specified by stateInXml failed.
String message = Logging.getMessage("generic.ExceptionAttemptingToParseStateXml", stateInXml);
Logging.logger().severe(message);
throw new IllegalArgumentException(message, e);
}
Boolean b = rs.getStateValueAsBoolean("detectCollisions");
if (b != null)
setDetectCollisions(b);
// Restore the center property only if all parts are available.
// We will not restore a partial center (for example, just latitude).
RestorableSupport.StateObject so = rs.getStateObject("center");
if (so != null)
{
Double lat = rs.getStateValueAsDouble(so, "latitude");
Double lon = rs.getStateValueAsDouble(so, "longitude");
Double ele = rs.getStateValueAsDouble(so, "elevation");
if (lat != null && lon != null)
setCenterPosition(Position.fromDegrees(lat, lon, (ele != null ? ele : 0)));
}
Double d = rs.getStateValueAsDouble("heading");
if (d != null)
setHeading(Angle.fromDegrees(d));
d = rs.getStateValueAsDouble("pitch");
if (d != null)
setPitch(Angle.fromDegrees(d));
d = rs.getStateValueAsDouble("zoom");
if (d != null)
setZoom(d);
d = rs.getStateValueAsDouble("fieldOfView");
if (d != null)
setFieldOfView(Angle.fromDegrees(d));
d = rs.getStateValueAsDouble("nearClipDistance");
if (d != null)
setNearClipDistance(d);
d = rs.getStateValueAsDouble("farClipDistance");
if (d != null)
setFarClipDistance(d);
}
}