/* Copyright (C) 2001, 2006 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.geom.*; import gov.nasa.worldwind.util.Logging; import java.lang.reflect.Constructor; import java.util.Arrays; /** * @author dcollins * @version $Id: BasicOrbitViewAnimator.java 4100 2008-01-08 02:49:54Z dcollins $ */ public class BasicOrbitViewAnimator implements OrbitViewAnimator { private boolean stopOnInvalidState = false; private boolean lastStateValid = true; protected BasicOrbitViewAnimator() { } public final void doNextState(double interpolant, OrbitView orbitView, BasicOrbitViewStateIterator stateIterator) { if (orbitView == null) { String message = Logging.getMessage("nullValue.OrbitViewIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } if (stateIterator == null) { String message = Logging.getMessage("nullValue.OrbitViewStateIteratorIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } this.doNextStateImpl(interpolant, orbitView, stateIterator); if (isStopOnInvalidState() && !isLastStateValid()) { stateIterator.stop(); } } protected void doNextStateImpl(double interpolant, OrbitView orbitView, BasicOrbitViewStateIterator stateIterator) { } public final OrbitViewAnimator coalesceWith(OrbitView orbitView, OrbitViewAnimator animator) { if (orbitView == null) { String message = Logging.getMessage("nullValue.OrbitViewIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } if (animator == null) { String message = Logging.getMessage("nullValue.OrbitViewAnimatorIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } OrbitViewAnimator newAnimator = this.coalesceWithImpl(orbitView, animator); if (this.isStopOnInvalidState() || animator.isStopOnInvalidState()) { newAnimator.setStopOnInvalidState(true); } return newAnimator; } protected OrbitViewAnimator coalesceWithImpl(OrbitView orbitView, OrbitViewAnimator animator) { return this; } public void setStopOnInvalidState(boolean stop) { this.stopOnInvalidState = stop; } public boolean isStopOnInvalidState() { return this.stopOnInvalidState; } protected void flagLastStateInvalid() { this.lastStateValid = false; } protected boolean isLastStateValid() { return this.lastStateValid; } // ============== Implementations ======================= // // ============== Implementations ======================= // // ============== Implementations ======================= // public static class AngleAnimator extends BasicOrbitViewAnimator { private final Angle begin; private final Angle end; private final OrbitViewPropertyAccessor.AngleAccessor propertyAccessor; public AngleAnimator( Angle begin, Angle end, OrbitViewPropertyAccessor.AngleAccessor propertyAccessor) { if (begin == null || end == null) { String message = Logging.getMessage("nullValue.AngleIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } if (propertyAccessor == null) { String message = Logging.getMessage("nullValue.OrbitViewPropertyAccessorIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } this.begin = begin; this.end = end; this.propertyAccessor = propertyAccessor; } public final Angle getBegin() { return this.begin; } public final Angle getEnd() { return this.end; } public final OrbitViewPropertyAccessor.AngleAccessor getPropertyAccessor() { return this.propertyAccessor; } protected final void doNextStateImpl(double interpolant, OrbitView orbitView, BasicOrbitViewStateIterator stateIterator) { Angle newValue = this.nextAngle(interpolant, orbitView); if (newValue == null) return; boolean success = this.propertyAccessor.setAngle(orbitView, newValue); if (!success) { flagLastStateInvalid(); } } public Angle nextAngle(double interpolant, OrbitView orbitView) { return Angle.mix( interpolant, this.begin, this.end); } } public static class DoubleAnimator extends BasicOrbitViewAnimator { private final double begin; private final double end; private final OrbitViewPropertyAccessor.DoubleAccessor propertyAccessor; public DoubleAnimator( double begin, double end, OrbitViewPropertyAccessor.DoubleAccessor propertyAccessor) { if (propertyAccessor == null) { String message = Logging.getMessage("nullValue.OrbitViewPropertyAccessorIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } this.begin = begin; this.end = end; this.propertyAccessor = propertyAccessor; } public final Double getBegin() { return this.begin; } public final Double getEnd() { return this.end; } public final OrbitViewPropertyAccessor.DoubleAccessor getPropertyAccessor() { return this.propertyAccessor; } protected final void doNextStateImpl(double interpolant, OrbitView orbitView, BasicOrbitViewStateIterator stateIterator) { Double newValue = this.nextDouble(interpolant, orbitView); if (newValue == null) return; boolean success = this.propertyAccessor.setDouble(orbitView, newValue); if (!success) { flagLastStateInvalid(); } } public Double nextDouble(double interpolant, OrbitView orbitView) { return mix( interpolant, this.begin, this.end); } public static double mix(double amount, double value1, double value2) { if (amount < 0) return value1; else if (amount > 1) return value2; return value1 * (1.0 - amount) + value2 * amount; } } public static class PositionAnimator extends BasicOrbitViewAnimator { private final Position begin; private final Position end; private final OrbitViewPropertyAccessor.PositionAccessor propertyAccessor; public PositionAnimator( Position begin, Position end, OrbitViewPropertyAccessor.PositionAccessor propertyAccessor) { if (begin == null || end == null) { String message = Logging.getMessage("nullValue.PositionIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } if (propertyAccessor == null) { String message = Logging.getMessage("nullValue.OrbitViewPropertyAccessorIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } this.begin = begin; this.end = end; this.propertyAccessor = propertyAccessor; } public final Position getBegin() { return this.begin; } public final Position getEnd() { return this.end; } public final OrbitViewPropertyAccessor.PositionAccessor getPropertyAccessor() { return this.propertyAccessor; } protected final void doNextStateImpl(double interpolant, OrbitView orbitView, BasicOrbitViewStateIterator stateIterator) { Position newValue = this.nextPosition(interpolant, orbitView); if (newValue == null) return; boolean success = this.propertyAccessor.setPosition(orbitView, newValue); if (!success) { flagLastStateInvalid(); } } public Position nextPosition(double interpolant, OrbitView orbitView) { return Position.interpolate( interpolant, this.begin, this.end); } } //public static class QuaternionAnimator extends BasicOrbitViewAnimator //{ // private final Quaternion begin; // private final Quaternion end; // private final OrbitViewPropertyAccessor.QuaternionAccessor propertyAccessor; // // public QuaternionAnimator( // Quaternion begin, Quaternion end, // OrbitViewPropertyAccessor.QuaternionAccessor propertyAccessor) // { // if (begin == null || end == null) // { // String message = Logging.getMessage("nullValue.QuaternionIsNull"); // Logging.logger().severe(message); // throw new IllegalArgumentException(message); // } // if (propertyAccessor == null) // { // String message = Logging.getMessage("nullValue.OrbitViewPropertyAccessorIsNull"); // Logging.logger().severe(message); // throw new IllegalArgumentException(message); // } // // this.begin = begin; // this.end = end; // this.propertyAccessor = propertyAccessor; // } // // public final Quaternion getBegin() // { // return this.begin; // } // // public final Quaternion getEnd() // { // return this.end; // } // // public final OrbitViewPropertyAccessor.QuaternionAccessor getPropertyAccessor() // { // return this.propertyAccessor; // } // // protected final void doNextStateImpl(double interpolant, OrbitView orbitView, BasicOrbitViewStateIterator stateIterator) // { // Quaternion newValue = this.nextQuaternion(interpolant, orbitView); // if (newValue == null) // return; // // boolean success = this.propertyAccessor.setQuaternion(orbitView, newValue); // if (!success) // { // flagLastStateInvalid(); // } // } // // public Quaternion nextQuaternion(double interpolant, OrbitView orbitView) // { // return Quaternion.mix( // interpolant, // this.begin, // this.end); // } //} public static class CompoundAnimator extends BasicOrbitViewAnimator { private OrbitViewAnimator[] animators; public CompoundAnimator(OrbitViewAnimator... animators) { if (animators == null) { String message = Logging.getMessage("nullValue.ArrayIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } int numAnimators = animators.length; this.animators = new OrbitViewAnimator[numAnimators]; System.arraycopy(animators, 0, this.animators, 0, numAnimators); } private CompoundAnimator newInstance(OrbitViewAnimator... animators) { if (animators == null) { String message = Logging.getMessage("nullValue.ArrayIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } CompoundAnimator newCompoundAnimator; try { Class<? extends CompoundAnimator> cls = this.getClass(); Class<? extends OrbitViewAnimator[]> paramCls = animators.getClass(); Constructor<? extends CompoundAnimator> constructor = cls.getConstructor(paramCls); newCompoundAnimator = constructor.newInstance((Object) animators); } catch (Exception e) { String message = Logging.getMessage(""); // TODO Logging.logger().severe(message); throw new IllegalArgumentException(message); } return newCompoundAnimator; } public final Iterable<OrbitViewAnimator> getAnimators() { return Arrays.asList(this.animators); } protected final void doNextStateImpl(double interpolant, OrbitView orbitView, BasicOrbitViewStateIterator stateIterator) { for (OrbitViewAnimator a : animators) { if (a != null) { a.doNextState(interpolant, orbitView, stateIterator); } } } protected final OrbitViewAnimator coalesceWithImpl(OrbitView orbitView, OrbitViewAnimator animator) { if (!(animator instanceof CompoundAnimator)) return this; // Cannot coalesce with different number of internal animators. CompoundAnimator that = (CompoundAnimator) animator; if (this.animators.length != that.animators.length) return this; int numAnimators = this.animators.length; OrbitViewAnimator[] newAnimators = new OrbitViewAnimator[numAnimators]; for (int i = 0; i < numAnimators; i++) { if (this.animators[i] != null && that.animators[i] != null) { newAnimators[i] = this.animators[i].coalesceWith(orbitView, that.animators[i]); } else if (this.animators[i] != null) { newAnimators[i] = this.animators[i]; } } CompoundAnimator newCompoundAnimator = this.newInstance(newAnimators); if (newCompoundAnimator == null) return this; return newCompoundAnimator; } public void setStopOnInvalidState(boolean stop) { super.setStopOnInvalidState(stop); for (OrbitViewAnimator a : animators) { if (a != null) { a.setStopOnInvalidState(stop); } } } } }