viewcontrolsselectlistener.java
来自「world wind java sdk 源码」· Java 代码 · 共 524 行 · 第 1/2 页
JAVA
524 行
}
}
protected void updateView(ScreenAnnotation control, String controlType)
{
if (this.wwd == null)
return;
if (!(this.wwd.getView() instanceof OrbitView))
return;
OrbitView view = (OrbitView)this.wwd.getView();
view.stopStateIterators();
view.stopMovement();
if(controlType.equals(AVKey.VIEW_PAN))
{
resetOrbitView(view);
// Go some distance in the control mouse direction
Angle heading = computePanHeading(view, control);
Angle distance = computePanAmount(this.wwd.getModel().getGlobe(), view, control, panStep);
LatLon newViewCenter = LatLon.greatCircleEndPosition(view.getCenterPosition(),
heading, distance);
// Turn around if passing by a pole - TODO: better handling of the pole crossing situation
if (Math.abs(newViewCenter.getLongitude().degrees - view.getCenterPosition().getLongitude().degrees) > 20)
view.setHeading(Angle.POS180.subtract(view.getHeading()));
// Set new center pos
view.setCenterPosition(new Position(newViewCenter, view.getCenterPosition().getElevation()));
}
else if(controlType.equals(AVKey.VIEW_LOOK))
{
setupFirstPersonView(view);
Angle heading = computeLookHeading(view, control, headingStep);
Angle pitch = computeLookPitch(view, control, pitchStep);
// Check whether the view will still point at terrain
Vec4 surfacePoint = computeSurfacePoint(view, heading, pitch);
if (surfacePoint != null)
{
// Change view state
final Position eyePos = view.getEyePosition();// Save current eye position
view.setHeading(heading);
view.setPitch(pitch);
view.setZoom(0);
view.setCenterPosition(eyePos); // Set center at the eye position
}
}
else if (controlType.equals(AVKey.VIEW_ZOOM_IN))
{
resetOrbitView(view);
view.setZoom(computeNewZoom(view, -zoomStep));
}
else if(controlType.equals(AVKey.VIEW_ZOOM_OUT))
{
resetOrbitView(view);
view.setZoom(computeNewZoom(view, zoomStep));
}
else if(controlType.equals(AVKey.VIEW_HEADING_LEFT))
{
resetOrbitView(view);
view.setHeading(view.getHeading().addDegrees(headingStep));
}
else if(controlType.equals(AVKey.VIEW_HEADING_RIGHT))
{
resetOrbitView(view);
view.setHeading(view.getHeading().addDegrees(-headingStep));
}
else if(controlType.equals(AVKey.VIEW_PITCH_UP))
{
resetOrbitView(view);
if (view.getPitch().degrees >= pitchStep)
view.setPitch(view.getPitch().addDegrees(-pitchStep));
}
else if(controlType.equals(AVKey.VIEW_PITCH_DOWN))
{
resetOrbitView(view);
if (view.getPitch().degrees <= 90 - pitchStep)
view.setPitch(view.getPitch().addDegrees(pitchStep));
}
else if(controlType.equals(AVKey.VIEW_FOV_NARROW))
{
if (view.getFieldOfView().degrees / fovStep >= 4)
view.setFieldOfView(view.getFieldOfView().divide(fovStep));
}
else if(controlType.equals(AVKey.VIEW_FOV_WIDE))
{
if (view.getFieldOfView().degrees * fovStep < 120)
view.setFieldOfView(view.getFieldOfView().multiply(fovStep));
}
this.wwd.redraw();
}
protected double computeNewZoom(OrbitView view, double amount)
{
double coeff = 0.05;
double change = coeff * amount;
double logZoom = view.getZoom() != 0 ? Math.log(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);
}
protected Angle computePanHeading(OrbitView view, ScreenAnnotation control)
{
// Compute last pick point 'heading' relative to pan control center
double size = control.getAttributes().getSize().width * control.getAttributes().getScale();
Vec4 center = new Vec4(control.getScreenPoint().x, control.getScreenPoint().y + size / 2, 0);
double px = lastPickPoint.x - center.x;
double py = view.getViewport().getHeight() - lastPickPoint.y - center.y;
Angle heading = view.getHeading().add(Angle.fromRadians(Math.atan2(px, py)));
heading = heading.degrees >= 0 ? heading : heading.addDegrees(360);
return heading;
}
protected Angle computePanAmount(Globe globe, OrbitView view, ScreenAnnotation control, double panStep)
{
// Compute last pick point distance relative to pan control center
double size = control.getAttributes().getSize().width * control.getAttributes().getScale();
Vec4 center = new Vec4(control.getScreenPoint().x, control.getScreenPoint().y + size / 2, 0);
double px = lastPickPoint.x - center.x;
double py = view.getViewport().getHeight() - lastPickPoint.y - center.y;
double pickDistance = Math.sqrt(px * px + py * py);
double pickDistanceFactor = Math.min(pickDistance / 10, 5);
// Compute globe angular distance depending on eye altitude
Position eyePos = view.getEyePosition();
double radius = globe.getRadiusAt(eyePos);
double minValue = 0.5 * (180.0 / (Math.PI * radius)); // Minimum change ~0.5 meters
double maxValue = 1.0; // Maximum change ~1 degree
// Compute an interpolated value between minValue and maxValue, using (eye altitude)/(globe radius) as
// the interpolant. Interpolation is performed on an exponential curve, to keep the value from
// increasing too quickly as eye altitude increases.
double a = eyePos.getElevation() / radius;
a = (a < 0 ? 0 : (a > 1 ? 1 : a));
double expBase = 2.0; // Exponential curve parameter.
double value = minValue + (maxValue - minValue) * ((Math.pow(expBase, a) - 1.0) / (expBase - 1.0));
return Angle.fromDegrees(value * pickDistanceFactor * panStep);
}
protected Angle computeLookHeading(OrbitView view, ScreenAnnotation control, double headingStep)
{
// Compute last pick point 'heading' relative to look control center on x
double size = control.getAttributes().getSize().width * control.getAttributes().getScale();
Vec4 center = new Vec4(control.getScreenPoint().x, control.getScreenPoint().y + size / 2, 0);
double px = lastPickPoint.x - center.x;
double pickDistanceFactor = Math.min(Math.abs(px) / 3000, 5) * Math.signum(px);
// New heading
Angle heading = view.getHeading().add(Angle.fromRadians(headingStep * pickDistanceFactor));
heading = heading.degrees >= 0 ? heading : heading.addDegrees(360);
return heading;
}
protected Angle computeLookPitch(OrbitView view, ScreenAnnotation control, double pitchStep)
{
// Compute last pick point 'pitch' relative to look control center on y
double size = control.getAttributes().getSize().width * control.getAttributes().getScale();
Vec4 center = new Vec4(control.getScreenPoint().x, control.getScreenPoint().y + size / 2, 0);
double py = view.getViewport().getHeight() - lastPickPoint.y - center.y;
double pickDistanceFactor = Math.min(Math.abs(py) / 3000, 5) * Math.signum(py);
// New pitch
Angle pitch = view.getPitch().add(Angle.fromRadians(pitchStep * pickDistanceFactor));
pitch = pitch.degrees >= 0 ? (pitch.degrees <= 90 ? pitch : Angle.fromDegrees(90)) : Angle.ZERO;
return pitch;
}
/**
* Reset the view to an orbit view state if in first person mode (zoom = 0)
*
* @param view the orbit view to reset
*/
protected void resetOrbitView(OrbitView view)
{
if (view.getZoom() > 0) // already in orbit view mode
return;
// Find out where on the terrain the eye is looking at in the viewport center
// TODO: if no terrain is found in the viewport center, iterate toward viewport bottom until it is found
Vec4 centerPoint = computeSurfacePoint(view, view.getHeading(), view.getPitch());
// Reset the orbit view center point heading, pitch and zoom
if (centerPoint != null)
{
Vec4 eyePoint = view.getEyePoint();
// Center pos on terrain surface
Position centerPosition = wwd.getModel().getGlobe().computePositionFromPoint(centerPoint);
// Compute pitch and heading relative to center position
Vec4 normal = wwd.getModel().getGlobe().computeSurfaceNormalAtLocation(centerPosition.getLatitude(),
centerPosition.getLongitude());
Vec4 north = wwd.getModel().getGlobe().computeNorthPointingTangentAtLocation(centerPosition.getLatitude(),
centerPosition.getLongitude());
// Pitch
view.setPitch(Angle.POS180.subtract(view.getForwardVector().angleBetween3(normal)));
// Heading
Vec4 perpendicular = view.getForwardVector().perpendicularTo3(normal);
Angle heading = perpendicular.angleBetween3(north);
double direction = Math.signum(-normal.cross3(north).dot3(perpendicular));
view.setHeading(heading.multiply(direction));
// Zoom
view.setZoom(eyePoint.distanceTo3(centerPoint));
// Center pos
view.setCenterPosition(centerPosition);
}
}
/**
* Setup the view to a first person mode (zoom = 0)
*
* @param view the orbit view to set into a first person view.
*/
protected void setupFirstPersonView(OrbitView view)
{
if (view.getZoom() == 0) // already in first person mode
return;
Vec4 eyePoint = view.getEyePoint();
// Center pos at eye pos
Position centerPosition = wwd.getModel().getGlobe().computePositionFromPoint(eyePoint);
// Compute pitch and heading relative to center position
Vec4 normal = wwd.getModel().getGlobe().computeSurfaceNormalAtLocation(centerPosition.getLatitude(),
centerPosition.getLongitude());
Vec4 north = wwd.getModel().getGlobe().computeNorthPointingTangentAtLocation(centerPosition.getLatitude(),
centerPosition.getLongitude());
// Pitch
view.setPitch(Angle.POS180.subtract(view.getForwardVector().angleBetween3(normal)));
// Heading
Vec4 perpendicular = view.getForwardVector().perpendicularTo3(normal);
Angle heading = perpendicular.angleBetween3(north);
double direction = Math.signum(-normal.cross3(north).dot3(perpendicular));
view.setHeading(heading.multiply(direction));
// Zoom
view.setZoom(0);
// Center pos
view.setCenterPosition(centerPosition);
}
/**
* Find out where on the terrain surface the eye would be looking at
* with the given heading and pitch angles.
*
* @param view the orbit view
* @param heading heading direction clockwise from north.
* @param pitch view pitch angle from the surface normal at the center point.
* @return the terrain surface point the view would be looking at in the viewport center.
*/
protected Vec4 computeSurfacePoint(OrbitView view, Angle heading, Angle pitch)
{
Globe globe = wwd.getModel().getGlobe();
// Compute transform to be applied to north pointing Y so that it would point in the view direction
// Move coordinate system to view center point
Matrix transform = globe.computeTransformToPosition(view.getCenterPosition());
// Rotate so that the north pointing axes Y will point in the look at direction
transform = transform.multiply(Matrix.fromRotationZ(heading.multiply(-1)));
transform = transform.multiply(Matrix.fromRotationX(Angle.NEG90.add(pitch)));
// Compute forward vector
Vec4 forward = Vec4.UNIT_Y.transformBy4(transform);
// Return intersection with terrain
Intersection[] intersections = wwd.getSceneController().getTerrain().intersect(new Line(view.getEyePoint(), forward));
return (intersections != null && intersections.length != 0) ? intersections[0].getIntersectionPoint() : null;
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?