Hello everybody,
I'm using VisAD to display a 2D time series plot with lots of points (>1000)
and above it moving 'timer bar' that advances from left to right in time. I
found at least 3 possibilities to do this so far, but none of them is doing it
well. Problem is that I need this 'timer bar' to advance smoothly and accurate
even in sub-second resolution. This is ok for let's say around 500 points but
if there more than 1000, the update rate of the display drops to around 1 per
second and less. To make it clear: I'm not moving the 1000 points, they're
fixed, I'm just moving a timer bar consisting of 2 points connected by a line
above the bunch of points.
The first solution I found updates the timer data via a call to setSamples. Far
too slow.
The second one, which I currently use, updates not the data, but the ScalarMap
attached to the timer (via ScalarMap.setRange()). This is much faster than the
first one, but still too slow for lots of underlying points. It seems the
DataRenderer has to redraw all the points, not only the few (2!) that changed.
The third one uses the animation feature of VisAD. I don't know about the speed
yet, because I faced unexpected 'out of memory' errors. If you can't help me
with the speed issue, maybe you can help me with this. The attached file is a
slightly modified P5_02 example. In the current version it works fine, but if
you change the value for ticksPerSecond in line 92 (e.g. to 20 instead of 10),
you'll get (or at least I'll get) a
Exception occurred during event dispatching:
java.lang.OutOfMemoryError
<<no stack trace available>>
Alternatively you can leave the ticksPerSecond at 10 and resize the application
window. Big sizes lead to the same error.
Regards & thanks in advance,
Timo
--
__.__________
|lmo |homas
/*
VisAD Tutorial
Copyright (C) 2000 Ugo Taddei
*/
// Import needed classes
import visad.*;
import visad.java2d.DisplayImplJ2D;
import java.rmi.RemoteException;
import java.awt.*;
import javax.swing.*;
/**
VisAD Tutorial example 5_02
A simple sine curve, but this time animated and with a different MathType.
Use a FieldImpl and Display.Animation
Run program with java P5_02
*
*/
public class TimerTest{
// Declare variables
// The quantities to be displayed in x- and y-axes
private RealType minute, length, amplitude;
// The function amplitude = f(length)
// as ( length -> amplitude )
private FunctionType func_len_amp;
// The ( time -> range )
private FunctionType func_t_range;
// Our Data values for length are represented by the set
private Set lengthSet;
// Time values are given by the set by the set
private Set timeSet;
// The Data class FlatField, which will hold data.
private FlatField amp_len_ff;
// A FieldImpl, which will hold all data.
private FieldImpl timeField;
// The DataReference from the data to display
private DataReferenceImpl data_ref;
// The 2D display, and its the maps
private DisplayImpl display;
private ScalarMap timeAnimMap, timeZMap, lenXMap, ampYMap, ampRGBMap;
public TimerTest (String[] args)
throws RemoteException, VisADException {
// Create the quantities
length = new RealType("some_unit", SI.meter, null);
amplitude = new RealType("time", SI.meter, null);
minute = new RealType("minute", SI.second, null);
// Create the functions
func_len_amp = new FunctionType(length,amplitude);
func_t_range = new FunctionType(minute, func_len_amp );
// Create the sets: one for length and the other for time
int nSamples = 2;
lengthSet = new Linear1DSet(length, -1.0, 1.0, nSamples);
// Time set
int numSeconds = 10;
int ticksPerSecond = 10;
int tSamples = numSeconds * ticksPerSecond;
timeSet = new Integer1DSet(minute, tSamples);
// Values for amplitude are in an array like float[ rangeDim ][ nSamples]
float[][] ampVals = new float[1][nSamples];
// Get the lengthtime values in the domain set to help with the calculations
// "flase" means we don't get a copy from the samples
float[][] lenVals = lengthSet.getSamples( false );
// Create some amplitude values:
// Create a FlatField
amp_len_ff = new FlatField( func_len_amp, lengthSet);
// ...and a FieldImpl
timeField = new FieldImpl( func_t_range, timeSet);
// loop once for all time steps
for(int t=0;t<tSamples;t++){
ampVals[0][0] = (float) t * (1.0f / ticksPerSecond);
ampVals[0][1] = (float) t * (1.0f / ticksPerSecond);
// and initialize it with the samples array
amp_len_ff.setSamples( ampVals );
// set amp_len_ff as the t-th component of the Field
timeField.setSample( t, amp_len_ff );
}
// Create Display and its maps
// A 2D display
display = new DisplayImplJ2D("display1");
// Get display's graphics mode control draw scales
GraphicsModeControl dispGMC = (GraphicsModeControl)
display.getGraphicsModeControl();
dispGMC.setScaleEnable(true);
// Create the ScalarMaps
lenXMap = new ScalarMap( length, Display.YAxis );
ampYMap = new ScalarMap( amplitude, Display.XAxis );
// ampRGBMap = new ScalarMap( amplitude, Display.RGB );
timeAnimMap = new ScalarMap( minute, Display.Animation );
// Add maps to display
display.addMap( lenXMap );
display.addMap( ampYMap );
// display.addMap( ampRGBMap );
display.addMap( timeAnimMap );
// Create a data reference and set the FieldImpl as our data
data_ref = new DataReferenceImpl("amp_len_ref");
data_ref.setData( timeField );
// Add reference to display
display.addReference( data_ref );
// Get AnimationControl from the Animation ScalarMap
AnimationControl ac = (AnimationControl) timeAnimMap.getControl();
// and start animation
ac.setStep(1000 / ticksPerSecond);
ac.setOn( true );
// Create application window, put display into it
JFrame jframe = new JFrame("VisAD Tutorial example 5_02");
jframe.getContentPane().add(display.getComponent());
// Set window size and make it visible
jframe.setSize(300, 300);
jframe.setVisible(true);
}
public static void main(String[] args)
throws RemoteException, VisADException
{
new TimerTest(args);
}
} //end of Visad Tutorial Program 5_02