basicorbitview.java

来自「world wind java sdk 源码」· Java 代码 · 共 917 行 · 第 1/3 页

JAVA
917
字号
/*
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 10301 2009-04-17 20:21:46Z 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.
    protected OrbitViewLimits orbitViewLimits;
    // Model for defining translations between OrbitView coordinates and 3D coordinates.
    private final OrbitViewModel orbitViewModel;
    // Stateless helper classes.
    protected final ViewSupport viewSupport = new ViewSupport();
    protected final OrbitViewCollisionSupport collisionSupport = new OrbitViewCollisionSupport();
    // Properties updated in doApply().
    protected Matrix modelview = Matrix.IDENTITY;
    protected Matrix modelviewInv = Matrix.IDENTITY;
    protected Matrix projection = Matrix.IDENTITY;
    protected java.awt.Rectangle viewport = new java.awt.Rectangle();
    protected Frustum frustum = new Frustum();
    // Properties updated during the most recent call to apply().
    protected DrawContext dc;
    protected Globe globe;
    protected Position lastEyePosition = null;
    protected Vec4 lastEyePoint = null;
    protected Vec4 lastUpVector = null;
    protected Vec4 lastForwardVector = null;
    protected Frustum lastFrustumInModelCoords = null;

    // TODO: make configurable
    protected static final double MINIMUM_NEAR_DISTANCE = 2;
    protected static final double MINIMUM_FAR_DISTANCE = 100;
    protected static final double COLLISION_THRESHOLD = 10;
    protected 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.orbitViewLimits = new BasicOrbitViewLimits();
        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 = normalizedCenterPosition(center);
        this.center = BasicOrbitViewLimits.limitCenterPosition(this.center, this.getOrbitViewLimits());
        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);
        this.heading = BasicOrbitViewLimits.limitHeading(this.heading, this.getOrbitViewLimits());
        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);
        }

        this.pitch = normalizedPitch(pitch);
        this.pitch = BasicOrbitViewLimits.limitPitch(this.pitch, this.getOrbitViewLimits());
        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;
        this.zoom = BasicOrbitViewLimits.limitZoom(this.zoom, this.getOrbitViewLimits());
        resolveCollisionsWithCenterPosition();
    }

    /**
     * Returns the <code>OrbitViewLimits</code> that apply to this <code>OrbitView</code>. Incoming parameters to the
     * methods setCenterPosition, setHeading, setPitch, or setZoom are be limited by the parameters defined in this
     * <code>OrbitViewLimits</code>.
     *
     * @return the <code>OrbitViewLimits</code> that apply to this <code>OrbitView</code>
     */
    public OrbitViewLimits getOrbitViewLimits()
    {
        return this.orbitViewLimits;
    }

    /**
     * Sets the <code>OrbitViewLimits</code> that will apply to this <code>OrbitView</code>. Incoming parameters to the
     * methods setCenterPosition, setHeading, setPitch, or setZoom will be limited by the parameters defined in
     * <code>viewLimits</code>.
     *
     * @param viewLimits the <code>OrbitViewLimits</code> that will apply to this <code>OrbitView</code>.
     * @throws IllegalArgumentException if <code>viewLimits</code> is null.
     */
    public void setOrbitViewLimits(OrbitViewLimits viewLimits)
    {
        if (viewLimits == null)
        {
            String message = Logging.getMessage("nullValue.ViewLimitsIsNull");
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }

        this.orbitViewLimits = viewLimits;
    }

    public OrbitViewModel getOrbitViewModel()
    {
        return this.orbitViewModel;
    }

    public static Position normalizedCenterPosition(Position unnormalizedPosition)
    {
        if (unnormalizedPosition == null)
        {
            String message = Logging.getMessage("nullValue.PositionIsNull");
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }

        return new Position(
                Angle.normalizedLatitude(unnormalizedPosition.getLatitude()),
                Angle.normalizedLongitude(unnormalizedPosition.getLongitude()),
                unnormalizedPosition.getElevation());
    }

    public static Angle normalizedHeading(Angle unnormalizedHeading)
    {
        if (unnormalizedHeading == null)
        {
            String message = Logging.getMessage("nullValue.AngleIsNull");
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }

        double degrees = unnormalizedHeading.degrees;
        double heading = degrees % 360;
        return Angle.fromDegrees(heading > 180 ? heading - 360 : (heading < -180 ? 360 + heading : heading));
    }

    public static Angle normalizedPitch(Angle unnormalizedPitch)
    {
        if (unnormalizedPitch == null)
        {
            String message = Logging.getMessage("nullValue.AngleIsNull");
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }

        // Normalize pitch to the range [-180, 180].
        double degrees = unnormalizedPitch.degrees;
        double pitch = degrees % 360;
        return Angle.fromDegrees(pitch > 180 ? pitch - 360 : (pitch < -180 ? 360 + pitch : pitch));
    }

    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();
        }
    }

    protected 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);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?