Statistics
| Revision:

gvsig-3d / org.gvsig.animation3d / trunk / org.gvsig.animation3d / org.gvsig.animation3d.swing / org.gvsig.animation3d.swing.impl / src / main / java / org / gvsig / animation3d / swing / impl / MultipleFlyToOrbitViewAnimator.java @ 672

History | View | Annotate | Download (7.29 KB)

1
package org.gvsig.animation3d.swing.impl;
2

    
3
import gov.nasa.worldwind.WorldWind;
4
import gov.nasa.worldwind.animation.AngleAnimator;
5
import gov.nasa.worldwind.animation.AnimationSupport;
6
import gov.nasa.worldwind.animation.Animator;
7
import gov.nasa.worldwind.animation.CompoundAnimator;
8
import gov.nasa.worldwind.animation.Interpolator;
9
import gov.nasa.worldwind.animation.PositionAnimator;
10
import gov.nasa.worldwind.animation.ScheduledInterpolator;
11
import gov.nasa.worldwind.geom.Angle;
12
import gov.nasa.worldwind.geom.LatLon;
13
import gov.nasa.worldwind.geom.Position;
14
import gov.nasa.worldwind.globes.Globe;
15
import gov.nasa.worldwind.util.PropertyAccessor;
16
import gov.nasa.worldwind.view.ViewElevationAnimator;
17
import gov.nasa.worldwind.view.ViewPropertyAccessor;
18
import gov.nasa.worldwind.view.orbit.OrbitView;
19
import gov.nasa.worldwind.view.orbit.OrbitViewPropertyAccessor;
20

    
21
import java.util.ArrayList;
22
import java.util.List;
23

    
24
import org.gvsig.animation3d.swing.api.Frame3D;
25

    
26
/**
27
 * @author <a href="mailto:lmarques@disid.com">Lluis Marques</a>
28
 *
29
 */
30
public class MultipleFlyToOrbitViewAnimator extends CompoundAnimator {
31

    
32
    private List<Frame3D> frames;
33
    private int index;
34
    private OrbitView orbitView;
35

    
36
    /**
37
     * @param orbitView
38
     * @param frames
39
     */
40
    public MultipleFlyToOrbitViewAnimator(OrbitView orbitView, List<Frame3D> frames) {
41
        super(new ScheduledInterpolator(10000));
42
        this.orbitView = orbitView;
43
        this.frames = frames;
44
        this.index = 0;
45
        setFrame(frames.get(index));
46
    }
47

    
48
    @Override
49
    protected void setImpl(double interpolant) {
50
        boolean allStopped = true;
51
        for (Animator a : animators) {
52
            if (a != null) {
53
                if (a.hasNext()) {
54
                    allStopped = false;
55
                    a.set(interpolant);
56
                }
57
            }
58
        }
59
        if (allStopped && index >= frames.size()) {
60
            this.stop();
61
        } else if (allStopped && index < frames.size() - 1) {
62
            index++;
63
            Frame3D frame = frames.get(index);
64
            setFrame(frame);
65
        }
66
    }
67

    
68
    private void setFrame(Frame3D frame) {
69
        double latitude = frame.getPosition().getY();
70
        double longitude = frame.getPosition().getX();
71
        Position newCenterPos =
72
            new Position(LatLon.fromDegrees(latitude, longitude), orbitView.getGlobe()
73
                .getElevation(Angle.fromDegreesLatitude(latitude),
74
                    Angle.fromDegreesLongitude(longitude))
75
                + frame.getElevation());
76
        Angle newHeading = Angle.fromDegrees(frame.getHeading());
77
        Angle newPitch = Angle.fromDegrees(frame.getPitch());
78

    
79
        long timeToMove =
80
            AnimationSupport.getScaledTimeMillisecs(orbitView.getEyePosition(), newCenterPos, 4000,
81
                14000);
82

    
83
        interpolator = new ScheduledInterpolator(timeToMove);
84

    
85
        animators =
86
            createAnimators(orbitView, orbitView.getCenterPosition(), newCenterPos,
87
                orbitView.getHeading(), newHeading, orbitView.getPitch(), newPitch,
88
                orbitView.getZoom(), frame.getZoom(), timeToMove,
89
                WorldWind.ABSOLUTE);
90
    }
91

    
92
    private Animator[] createAnimators(OrbitView orbitView, Position beginCenterPos,
93
        Position endCenterPos, Angle beginHeading, Angle endHeading, Angle beginPitch,
94
        Angle endPitch, double beginZoom, double endZoom, long timeToMove, int altitudeMode) {
95

    
96
        OnSurfacePositionAnimator centerAnimator =
97
            new OnSurfacePositionAnimator(orbitView.getGlobe(), new ScheduledInterpolator(
98
                timeToMove), beginCenterPos, endCenterPos,
99
                OrbitViewPropertyAccessor.createCenterPositionAccessor(orbitView), altitudeMode);
100
        
101
        // Create an elevation animator with ABSOLUTE altitude mode because the
102
        // OrbitView altitude mode applies to the
103
        // center position, not the zoom.
104
        ViewElevationAnimator zoomAnimator =
105
            new ViewElevationAnimator(orbitView.getGlobe(), beginZoom, endZoom, beginCenterPos,
106
                endCenterPos, WorldWind.ABSOLUTE,
107
                OrbitViewPropertyAccessor.createZoomAccessor(orbitView));
108
        
109
        centerAnimator.useMidZoom = zoomAnimator.getUseMidZoom();
110

    
111
        AngleAnimator headingAnimator =
112
            new AngleAnimator(new ScheduledInterpolator(timeToMove), beginHeading, endHeading,
113
                ViewPropertyAccessor.createHeadingAccessor(orbitView));
114

    
115
        AngleAnimator pitchAnimator =
116
            new AngleAnimator(new ScheduledInterpolator(timeToMove), beginPitch, endPitch,
117
                ViewPropertyAccessor.createPitchAccessor(orbitView));
118

    
119
        List<Animator> animators = new ArrayList<Animator>();
120
        animators.add(centerAnimator);
121
        animators.add(zoomAnimator);
122
        animators.add(headingAnimator);
123
        animators.add(pitchAnimator);
124

    
125
        return animators.toArray(new Animator[0]);
126
    }
127

    
128
    protected static class OnSurfacePositionAnimator extends PositionAnimator {
129

    
130
        Globe globe;
131
        int altitudeMode;
132
        boolean useMidZoom = true;
133

    
134
        public OnSurfacePositionAnimator(Globe globe, Interpolator interpolator, Position begin,
135
            Position end, PropertyAccessor.PositionAccessor propertyAccessor, int altitudeMode) {
136
            super(interpolator, begin, end, propertyAccessor);
137
            this.globe = globe;
138
            this.altitudeMode = altitudeMode;
139
        }
140

    
141
        @Override
142
        protected Position nextPosition(double interpolant) {
143
            final int MAX_SMOOTHING = 1;
144

    
145
            final double CENTER_START = this.useMidZoom ? 0.2 : 0.0;
146
            final double CENTER_STOP = this.useMidZoom ? 0.8 : 0.8;
147
            double latLonInterpolant =
148
                AnimationSupport.basicInterpolant(interpolant, CENTER_START, CENTER_STOP,
149
                    MAX_SMOOTHING);
150

    
151
            // Invoke the standard next position functionality.
152
            Position pos = super.nextPosition(latLonInterpolant);
153

    
154
            // Check the altitude mode. If the altitude mode depends on the
155
            // surface elevation we will reevaluate the
156
            // end position altitude. When the animation starts we may not have
157
            // accurate elevation data available for
158
            // the end position, so recalculating the elevation as we go ensures
159
            // that the animation will end at the
160
            // correct altitude.
161
            double endElevation = 0.0;
162
            boolean overrideEndElevation = false;
163

    
164
            if (this.altitudeMode == WorldWind.CLAMP_TO_GROUND) {
165
                overrideEndElevation = true;
166
                endElevation =
167
                    this.globe.getElevation(getEnd().getLatitude(), getEnd().getLongitude());
168
            } else if (this.altitudeMode == WorldWind.RELATIVE_TO_GROUND) {
169
                overrideEndElevation = true;
170
                endElevation =
171
                    this.globe.getElevation(getEnd().getLatitude(), getEnd().getLongitude())
172
                        + getEnd().getAltitude();
173
            }
174

    
175
            if (overrideEndElevation) {
176
                LatLon ll = pos; // Use interpolated lat/lon.
177
                double e1 = getBegin().getElevation();
178
                pos =
179
                    new Position(ll, (1 - latLonInterpolant) * e1 + latLonInterpolant
180
                        * endElevation);
181
            }
182

    
183
            return pos;
184
        }
185
    }
186
}