//
// AVControlJ3D.java
//
/*
VisAD system for interactive analysis and visualization of numerical
data. Copyright (C) 1996 - 2017 Bill Hibbard, Curtis Rueden, Tom
Rink, Dave Glowacki, Steve Emmerson, Tom Whittaker, Don Murray, and
Tommy Jasmin.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA
*/
package visad.java3d;
import visad.*;
import javax.media.j3d.*;
import java.util.Vector;
import java.util.Enumeration;
/**
AVControlJ3D is the VisAD abstract superclass for AnimationControlJ3D
and ValueControlJ3D.<P>
*/
public abstract class AVControlJ3D extends Control implements AVControl {
transient Vector switches = new Vector();
private int interval = -1;
public AVControlJ3D(DisplayImplJ3D d) {
super(d);
}
public void addPair(Switch sw, Set se, DataRenderer re) {
switches.addElement(new SwitchSet(sw, se, re));
}
public void addPair(Switch sw, Set se, DataRenderer re, TrajectoryAVHandlerJ3D adptr) {
switches.addElement(new SwitchSet(sw, se, re, adptr));
}
public void nullControl() {
switches.removeAllElements();
super.nullControl();
}
public abstract void init() throws VisADException;
/**
* Sets the time between two steps in the animation set. This value
* is then used to determine the range of acceptable samples to view
* out of each of the renderers associated with the AV_Control
*
* @param interval the time interval in minutes between steps in the
* animation set
*/
public void setInterval(int interval)
{
this.interval = interval;
}
/**
* Method that returns an index in the set that is between the
* lower and upper bounds
*/
private int getIndexForRange(Set set, double lower, double upper)
throws VisADException
{
double [][] values = set.getDoubles(false);
for(int i=0; i<values[0].length; i++) {
if(values[0][i] >= lower && values[0][i] < upper) {
return i;
}
}
return -1;
}
public void selectSwitches(double value, Set animation_set)
throws VisADException {
// check for missing
if (value != value) return;
double[][] fvalues = new double[1][1];
fvalues[0][0] = value;
Enumeration pairs = ((Vector) switches.clone()).elements();
while (pairs.hasMoreElements()) {
SwitchSet ss = (SwitchSet) pairs.nextElement();
Set set = ss.set;
double[][] values = null;
RealTupleType out = ((SetType) set.getType()).getDomain();
if (animation_set != null) {
RealTupleType in =
((SetType) animation_set.getType()).getDomain();
values = CoordinateSystem.transformCoordinates(
out, set.getCoordinateSystem(),
set.getSetUnits(), null /* errors */,
in, animation_set.getCoordinateSystem(),
animation_set.getSetUnits(),
null /* errors */, fvalues);
}
else {
// use RealType for value Unit and CoordinateSystem
// for SelectValue
values = CoordinateSystem.transformCoordinates(
out, set.getCoordinateSystem(),
set.getSetUnits(), null /* errors */,
out, out.getCoordinateSystem(),
out.getDefaultUnits(), null /* errors */,
fvalues);
}
// compute set index from converted value
int [] indices;
// from Luke Matthews of BOM
if(interval == -1) {
//default behaviour
if (set.getLength() == 1) {
indices = new int[] {0};
}
else {
indices = set.doubleToIndex(values);
}
}
else {
double resInSecs = (double)interval*60;
double lower = values[0][0] - (resInSecs/2.0);
double upper = values[0][0] + (resInSecs/2.0);
indices = new int[] {getIndexForRange(set, lower, upper)};
}
if (0 <= indices[0] && indices[0] < ss.swit.numChildren()) {
ss.setWhichChild(indices[0]);
}
else {
ss.setWhichChild(Switch.CHILD_NONE);
}
} // end while (pairs.hasMoreElements())
}
/** clear all 'pairs' in switches that involve re */
public void clearSwitches(DataRenderer re) {
Enumeration pairs = ((Vector) switches.clone()).elements();
while (pairs.hasMoreElements()) {
SwitchSet ss = (SwitchSet) pairs.nextElement();
if (ss.renderer.equals(re)) {
switches.removeElement(ss);
}
}
}
public Vector getSwitches() {
return switches;
}
public boolean equals(Object o)
{
if (!super.equals(o)) {
return false;
}
AVControlJ3D av = (AVControlJ3D )o;
if (switches == null) {
return (av.switches == null);
} else if (av.switches == null) {
// don't assume anything, since it could be a remote control
} else {
if (switches.size() != av.switches.size()) {
return false;
}
for (int i = switches.size() - 1; i > 0; i--) {
if (!switches.elementAt(i).equals(av.switches.elementAt(i))) {
return false;
}
}
}
return true;
}
/** SwitchSet is an inner class of AVControlJ3D for
(Switch, Set, DataRenderer) structures */
protected class SwitchSet extends Object {
Switch swit;
Set set;
DataRenderer renderer;
AVHandler handler;
SwitchSet(Switch sw, Set se, DataRenderer re) {
swit = sw;
set = se;
renderer = re;
}
SwitchSet(Switch sw, Set se, DataRenderer re, AVHandler adptr) {
swit = sw;
set = se;
renderer = re;
handler = adptr;
}
void setWhichChild(int idx) {
if (handler == null) {
swit.setWhichChild(idx);
}
else {
handler.setWhichChild(idx);
}
}
}
}