globeannotation.java
来自「world wind java sdk 源码」· Java 代码 · 共 357 行
JAVA
357 行
/*
Copyright (C) 2001, 2006, 2007 United States Government
as represented by the Administrator of the
National Aeronautics and Space Administration.
All Rights Reserved.
*/
package gov.nasa.worldwind.render;
import gov.nasa.worldwind.*;
import gov.nasa.worldwind.geom.*;
import gov.nasa.worldwind.util.*;
import javax.media.opengl.GL;
import java.awt.*;
/**
* Represent a text label attached to a Position on the globe and its rendering attributes.
* @author Patrick Murris
* @version $Id: GlobeAnnotation.java 10542 2009-04-27 17:28:30Z dcollins $
* @see AbstractAnnotation
* @see AnnotationAttributes
*/
public class GlobeAnnotation extends AbstractAnnotation implements Locatable, Movable
{
private Position position;
/**
* Creates a <code>GlobeAnnotation</code> with the given text, at the given globe <code>Position</code>.
* @param text the annotation text.
* @param position the annotation <code>Position</code>.
*/
public GlobeAnnotation(String text, Position position)
{
this.init(text, position, null, null);
}
/**
* Creates a <code>GlobeAnnotation</code> with the given text, at the given globe <code>Position</code>.
* Specifiy the <code>Font</code> to be used.
* @param text the annotation text.
* @param position the annotation <code>Position</code>.
* @param font the <code>Font</code> to use.
*/
public GlobeAnnotation(String text, Position position, Font font)
{
this.init(text, position, font, null);
}
/**
* Creates a <code>GlobeAnnotation</code> with the given text, at the given globe <code>Position</code>.
* Specifiy the <code>Font</code> and text <code>Color</code> to be used.
* @param text the annotation text.
* @param position the annotation <code>Position</code>.
* @param font the <code>Font</code> to use.
* @param textColor the text <code>Color</code>.
*/
public GlobeAnnotation(String text, Position position, Font font, Color textColor)
{
this.init(text, position, font, textColor);
}
/**
* Creates a <code>GlobeAnnotation</code> with the given text, at the given globe <code>Position</code>.
* Specify the default {@link AnnotationAttributes} set.
* @param text the annotation text.
* @param position the annotation <code>Position</code>.
* @param defaults the default {@link AnnotationAttributes} set.
*/
public GlobeAnnotation(String text, Position position, AnnotationAttributes defaults)
{
if (text == null)
{
String message = Logging.getMessage("nullValue.StringIsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
if (position == null)
{
String message = Logging.getMessage("nullValue.PositionIsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
if (defaults == null)
{
String message = Logging.getMessage("nullValue.AnnotationAttributesIsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
this.setText(text);
this.position = position;
this.getAttributes().setDefaults(defaults);
}
private void init(String text, Position position, Font font, Color textColor)
{
if (text == null)
{
String message = Logging.getMessage("nullValue.StringIsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
if (position == null)
{
String message = Logging.getMessage("nullValue.PositionIsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
this.setText(text);
this.position = position;
this.getAttributes().setFont(font);
this.getAttributes().setTextColor(textColor);
}
public Position getPosition()
{
return this.position;
}
public void setPosition(Position position)
{
this.position = position;
}
public void move(Position position)
{
if (position == null)
{
String msg = Logging.getMessage("nullValue.PositionIsNull");
Logging.logger().severe(msg);
throw new IllegalArgumentException(msg);
}
this.position = this.position.add(position);
}
public void moveTo(Position position)
{
if (position == null)
{
String msg = Logging.getMessage("nullValue.PositionIsNull");
Logging.logger().severe(msg);
throw new IllegalArgumentException(msg);
}
this.position = position;
}
public Position getReferencePosition()
{
return this.position;
}
//**************************************************************//
//******************** Rendering *****************************//
//**************************************************************//
protected void doRenderNow(DrawContext dc)
{
if (dc.isPickingMode() && this.getPickSupport() == null)
return;
Vec4 point = dc.getAnnotationRenderer().getAnnotationDrawPoint(dc, this);
if (point == null)
return;
if (dc.getView().getFrustumInModelCoordinates().getNear().distanceTo(point) < 0)
return;
Vec4 screenPoint = dc.getView().project(point);
if (screenPoint == null)
return;
java.awt.Dimension size = this.getPreferredSize(dc);
Position pos = dc.getGlobe().computePositionFromPoint(point);
// Determine scale and opacity factors based on distance from eye vs the distance to the look at point.
double lookAtDistance = this.computeLookAtDistance(dc);
double eyeDistance = dc.getView().getEyePoint().distanceTo3(point);
double distanceFactor = Math.sqrt(lookAtDistance / eyeDistance);
double scale = WWMath.clamp(distanceFactor,
this.attributes.getDistanceMinScale(), this.attributes.getDistanceMaxScale());
double opacity = WWMath.clamp(distanceFactor,
this.attributes.getDistanceMinOpacity(), 1);
this.setDepthFunc(dc, screenPoint);
this.drawTopLevelAnnotation(dc, (int) screenPoint.x, (int) screenPoint.y, size.width, size.height, scale,
opacity, pos);
}
protected double computeLookAtDistance(DrawContext dc)
{
// TODO: cache lookAtDistance for one frame cycle
View view = dc.getView();
// Get point in the middle of the screen
Position groundPos = view.computePositionFromScreenPoint(
view.getViewport().getCenterX(), view.getViewport().getCenterY());
// Return eye altitude if no point found
if (groundPos == null)
{
return view.getEyePosition().getElevation();
}
// Compute distance from eye to the position in the middle of the screen
return view.getEyePoint().distanceTo3(dc.getGlobe().computePointFromPosition(groundPos));
}
protected void setDepthFunc(DrawContext dc, Vec4 screenPoint)
{
GL gl = dc.getGL();
Position eyePos = dc.getView().getEyePosition();
if (eyePos == null)
{
gl.glDepthFunc(GL.GL_ALWAYS);
return;
}
double altitude = eyePos.getElevation();
if (altitude < (dc.getGlobe().getMaxElevation() * dc.getVerticalExaggeration()))
{
double depth = screenPoint.z - (8d * 0.00048875809d);
depth = depth < 0d ? 0d : (depth > 1d ? 1d : depth);
gl.glDepthFunc(GL.GL_LESS);
gl.glDepthRange(depth, depth);
}
else if (screenPoint.z >= 1d)
{
gl.glDepthFunc(GL.GL_EQUAL);
gl.glDepthRange(1d, 1d);
}
else
{
gl.glDepthFunc(GL.GL_ALWAYS);
}
}
//**************************************************************//
//******************** Restorable State **********************//
//**************************************************************//
/**
* Returns an XML state document String describing the public attributes of this GlobeAnnotation.
*
* @return XML state document string describing this GlobeAnnotation.
*/
public String getRestorableState()
{
RestorableSupport restorableSupport = null;
// Try to parse the superclass' xml state document, if it defined one.
String superStateInXml = super.getRestorableState();
if (superStateInXml != null)
{
try
{
restorableSupport = RestorableSupport.parse(superStateInXml);
}
catch (Exception e)
{
// Parsing the document specified by the superclass failed.
String message = Logging.getMessage("generic.ExceptionAttemptingToParseStateXml", superStateInXml);
Logging.logger().severe(message);
}
}
// Create our own state document from scratch.
if (restorableSupport == null)
restorableSupport = RestorableSupport.newRestorableSupport();
// Creating a new RestorableSupport failed. RestorableSupport logged the problem, so just return null.
if (restorableSupport == null)
return null;
// Save the position property only if all parts (latitude, longitude, and elevation) can be saved.
// We will not save a partial position (for example, just the elevation).
if (this.position != null
&& this.position.getLatitude() != null
&& this.position.getLongitude() != null)
{
RestorableSupport.StateObject positionStateObj = restorableSupport.addStateObject("position");
if (positionStateObj != null)
{
restorableSupport.addStateValueAsDouble(positionStateObj, "latitude",
this.position.getLatitude().degrees);
restorableSupport.addStateValueAsDouble(positionStateObj, "longitude",
this.position.getLongitude().degrees);
restorableSupport.addStateValueAsDouble(positionStateObj, "elevation",
this.position.getElevation());
}
}
return restorableSupport.getStateAsXml();
}
/**
* Restores publicly settable attribute values found in the specified XML state document String. The
* document specified by <code>stateInXml</code> must be a well formed XML document String, or this will throw an
* IllegalArgumentException. Unknown structures in <code>stateInXml</code> are benign, because they will
* simply be ignored.
*
* @param stateInXml an XML document String describing a GlobeAnnotation.
* @throws IllegalArgumentException If <code>stateInXml</code> is null, or if <code>stateInXml</code> is not
* a well formed XML document String.
*/
public void restoreState(String stateInXml)
{
if (stateInXml == null)
{
String message = Logging.getMessage("nullValue.StringIsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
// Allow the superclass to restore it's state.
try
{
super.restoreState(stateInXml);
}
catch (Exception e)
{
// Superclass will log the exception.
}
RestorableSupport restorableSupport;
try
{
restorableSupport = 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);
}
// Restore the position property only if all parts are available.
// We will not restore a partial position (for example, just the latitude).
RestorableSupport.StateObject positionStateObj = restorableSupport.getStateObject("position");
if (positionStateObj != null)
{
Double latitudeState = restorableSupport.getStateValueAsDouble(positionStateObj, "latitude");
Double longitudeState = restorableSupport.getStateValueAsDouble(positionStateObj, "longitude");
Double elevationState = restorableSupport.getStateValueAsDouble(positionStateObj, "elevation");
if (latitudeState != null && elevationState != null)
setPosition(Position.fromDegrees(latitudeState, longitudeState, elevationState));
}
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?