[Date Prev][Date Next]
[Chronological]
[Thread]
[Top]
Demo for screen locked renderer.
- To: visad-renderer@ssec.wisc.edu
- Subject: Demo for screen locked renderer.
- From: Jim Koutsovasilis <jimk@bom.gov.au>
- Date: Thu, 22 May 2003 13:51:40 +1000
- User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:0.9.9) Gecko/20020408
Hi everyone,
thanks for you patience in waiting for this email.
It took much longer than I had expected to prepare
the demo, and it also managed to give me a better
understanding of the problem.
I also managed to add a new shadow type
(ShadowScreenLockedSetTypeJ3D.java)
which screen-locks Sets.
Please find attached 3 files:
- ScreenLockedDemo.java
- ScreenLockedRendererJ3D.java
- ShadowScreenLockedSetTypeJ3D.java
You will need to place ScreenLockedRendererJ3D.java and
ShadowScreenLockedSetTypeJ3D.java in your visad/bom
directory, and compile them there.
Before running the demo, please read the javadoc at the
top of ScreenLockedDemo.java. There's a lot to read but
it will help you, and it also includes instructions on how
to run the tests.
To run the program,
> javac ScreenLockedDemo.java
> java ScreenLockedDemo
Look forward to hearing your thoughts on this. I hope
the main javadoc makes sense to you.
Please let me know if you get stuck.
Best regards,
Jim.
---
Jim Koutsovasilis
Bureau of Meteorology, Australia
jimk@bom.gov.au
//
// ScreenLockedRendererJ3D.java
//
/*
VisAD system for interactive analysis and visualization of numerical
data. Copyright (C) 1996 - 2002 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.bom;
// Java
import java.awt.Font;
import java.rmi.RemoteException;
import javax.swing.JFrame;
// VisAD
import visad.ConstantMap;
import visad.DataDisplayLink;
import visad.DataReferenceImpl;
import visad.DelaunayCustom;
import visad.Display;
import visad.FieldImpl;
import visad.FunctionType;
import visad.GraphicsModeControl;
import visad.Gridded2DSet;
import visad.Irregular2DSet;
import visad.RealTupleType;
import visad.RealType;
import visad.Text;
import visad.TextControl;
import visad.TextType;
import visad.TupleType;
import visad.RealTupleType;
import visad.ScalarMap;
import visad.Set;
import visad.SetType;
import visad.ShadowType;
import visad.VisADException;
import visad.java3d.DefaultRendererJ3D;
import visad.java3d.DisplayImplJ3D;
import visad.java3d.DisplayRendererJ3D;
import visad.java3d.MouseBehaviorJ3D;
import visad.java3d.ProjectionControlJ3D;
import visad.java3d.ShadowFunctionTypeJ3D;
import visad.java3d.ShadowSetTypeJ3D;
import visad.java3d.ShadowTupleTypeJ3D;
/**
* This renderer locks text to its initial position on the
* screen.
*
* The render only works if you have a domain tuple of the form:
* (latitude, longitude, text)
* or a function type of the form:
* ((latitude, longitude)->(text))
*/
public class ScreenLockedRendererJ3D extends DefaultRendererJ3D
{
/**
* Default constructor.
*/
public ScreenLockedRendererJ3D()
{
super();
}
/**
* This is used for function types of the form:
* ((latitude, longitude)->(text))
*/
public ShadowType makeShadowFunctionType(FunctionType type,
DataDisplayLink link, ShadowType parent)
throws RemoteException, VisADException
{
return new ShadowScreenLockedFunctionTypeJ3D(type, link, parent);
}
/**
* This is used for tuples of the form:
* (latitude, longitude, text)
*/
public ShadowType makeShadowTupleType(TupleType type, DataDisplayLink link,
ShadowType parent)
throws RemoteException, VisADException
{
return new ShadowScreenLockedTupleTypeJ3D(type, link, parent);
}
public ShadowType makeShadowSetType(SetType type, DataDisplayLink link,
ShadowType parent)
throws RemoteException, VisADException
{
return new ShadowScreenLockedSetTypeJ3D(type, link, parent);
}
/**
* Used for testing.
* Creates a display with a red square and labels at each
* corner of the square. The square rotates, and moves as
* you would expect, but the text is locked to its original
* position on the screen.
*/
public static final void main(String [] args)
throws VisADException, RemoteException
{
final DisplayImplJ3D display = new DisplayImplJ3D("display");
final DisplayRendererJ3D renderer =
(DisplayRendererJ3D) display.getDisplayRenderer();
renderer.setBoxOn(false);
renderer.setBackgroundColor(0.0f, 0.2f, 1.0f);
final GraphicsModeControl gmc =
(GraphicsModeControl) display.getGraphicsModeControl();
gmc.setScaleEnable(false);
gmc.setProjectionPolicy(DisplayImplJ3D.PARALLEL_PROJECTION);
final RealTupleType domainType = new RealTupleType(RealType.Latitude,
RealType.Longitude);
final TextType textType = TextType.getTextType("text");
final FunctionType functionType = new FunctionType(domainType, textType);
// The domain samples make up a square. (clockwise order).
float [][] domainSamples = new float[2][4];
domainSamples[0][0] = 0f;
domainSamples[1][0] = 0f;
domainSamples[0][1] = 10f;
domainSamples[1][1] = 0f;
domainSamples[0][2] = 10f;
domainSamples[1][2] = 10f;
domainSamples[0][3] = 0f;
domainSamples[1][3] = 10f;
// Create the field that will dislay the labels.
final Set domainSet1 = new Gridded2DSet(domainType, domainSamples, 4);
FieldImpl field = new FieldImpl(functionType, domainSet1);
field.setSample(0, new Text(textType, "Screen Locked 1"));
field.setSample(1, new Text(textType, "Screen Locked 2"));
field.setSample(2, new Text(textType, "Screen Locked 3"));
field.setSample(3, new Text(textType, "Screen Locked 4"));
final DataReferenceImpl lockedDataRef = new DataReferenceImpl(
"locked_data_ref");
lockedDataRef.setData(field);
// Created the filled sqaure.
final Gridded2DSet domainSet2 = new Gridded2DSet(domainType,
domainSamples, 4);
final Irregular2DSet filledSet = DelaunayCustom.fill(domainSet2);
final DataReferenceImpl unlockedDataRef = new DataReferenceImpl(
"unlocked_data_ref");
unlockedDataRef.setData(filledSet);
final ScalarMap latMap = new ScalarMap(RealType.Latitude, Display.YAxis);
final ScalarMap lonMap = new ScalarMap(RealType.Longitude, Display.XAxis);
final ScalarMap textMap = new ScalarMap(textType, Display.Text);
display.addMap(latMap);
display.addMap(lonMap);
display.addMap(textMap);
// Center the square in the display.
latMap.setRange(0, 10);
lonMap.setRange(0, 10);
// Center the labels on the corners of the square.
final TextControl textControl = (TextControl) textMap.getControl();
textControl.setCenter(true);
display.addReferences(new ScreenLockedRendererJ3D(), lockedDataRef);
// Color the square red.
display.addReference(unlockedDataRef, new ConstantMap [] {
new ConstantMap(0.0, Display.Green),
new ConstantMap(0.0, Display.Blue)});
// Display the frame.
final JFrame frame = new JFrame("ScreenLockedRendererJ3D");
frame.getContentPane().add(display.getComponent());
frame.setSize(400, 400);
frame.setVisible(true);
}
} // class ScreenLockedRendererJ3D
//
// ShadowScreenLockedSetTypeJ3D.java
//
/*
VisAD system for interactive analysis and visualization of numerical
data. Copyright (C) 1996 - 2002 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.bom;
// Java
import java.rmi.RemoteException;
// VisAD
import visad.ControlEvent;
import visad.ControlListener;
import visad.DataDisplayLink;
import visad.GraphicsModeControl;
import visad.MathType;
import visad.ShadowType;
import visad.VisADException;
import visad.VisADGeometryArray;
import visad.java3d.ShadowSetTypeJ3D;
import visad.java3d.MouseBehaviorJ3D;
import visad.java3d.ProjectionControlJ3D;
import visad.java3d.DisplayImplJ3D;
// Java 3D
import javax.media.j3d.Group;
import javax.media.j3d.TransformGroup;
import javax.media.j3d.Transform3D;
import javax.vecmath.Vector3d;
import javax.vecmath.Matrix3d;
/**
* This renderer locks text to the screen. The display can be
* panned and zoomed, but the text stays locked to its
* initial position.
*/
public class ShadowScreenLockedSetTypeJ3D extends ShadowSetTypeJ3D
{
private TransformGroup transformGroup = null;
private ProjectionControlListener projectionControlListener = null;
public ShadowScreenLockedSetTypeJ3D(MathType type, DataDisplayLink link,
ShadowType parent)
throws RemoteException, VisADException
{
super(type, link, parent);
transformGroup = new TransformGroup();
transformGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
transformGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
transformGroup.setCapability(TransformGroup.ALLOW_CHILDREN_READ);
// Add our listener to the projection control.
DisplayImplJ3D display = (DisplayImplJ3D) getDisplay();
ProjectionControlJ3D control = (ProjectionControlJ3D)
display.getProjectionControl();
projectionControlListener = new ProjectionControlListener();
control.addControlListener(projectionControlListener);
}
/**
* Adds the text to the scene graph hierarchy.
* Create a new transform group and place the text under this
* transform group. This allows us to set the scale, translation
* and rotation of the text independently of the rest of the nodes
* in the scene graph.
*/
public boolean addTextToGroup(Object group, VisADGeometryArray geomArray,
GraphicsModeControl control, float alpha, float [] color)
throws VisADException
{
if (null == transformGroup.getParent()) {
((Group) group).addChild(transformGroup);
}
return super.addTextToGroup(transformGroup, geomArray, control, alpha,
color);
}
/**
* Adds the group to the scene graph hierarchy.
* Create a new transform group and place the text under this
* transform group. This allows us to set the scale, translation
* and rotation of the data independently of the rest of the nodes
* in the scene graph.
*/
public boolean addToGroup(Object group, VisADGeometryArray geomArray,
GraphicsModeControl control, float alpha, float [] color)
throws VisADException
{
if (null == transformGroup.getParent()) {
((Group) group).addChild(transformGroup);
}
return super.addToGroup(transformGroup, geomArray, control, alpha,
color);
}
/**
* When the projection control matrix is changed, this listener
* will undo the scale, translation and rotation of the text
* thus locking it to its initial position on the screen.
*/
private class ProjectionControlListener implements ControlListener
{
private boolean first = true;
private double initialScale;
private double initialXTrans;
private double initialYTrans;
private double initialZTrans;
private double [] rotation = null;
private double [] translation = null;
private double [] scale = null;
/**
* Default constructor.
*/
public ProjectionControlListener()
{
rotation = new double[ 3 ];
translation = new double[ 3 ];
scale = new double[ 1 ];
}
/**
* Undo all scale, translation and rotation transformations.
* @param event contains information about this event
*/
public void controlChanged(ControlEvent event)
{
ProjectionControlJ3D control =
(ProjectionControlJ3D) event.getControl();
double [] projectionControlMatrix = control.getMatrix();
control = null;
MouseBehaviorJ3D.unmake_matrix(rotation, scale, translation,
projectionControlMatrix);
if (first) {
// This is the first time through, so keep a copy
// of our initial scale and translation.
// We assume that there is no rotation.
initialScale = scale[0];
initialXTrans = translation[0];
initialYTrans = translation[1];
initialZTrans = translation[2];
first = false;
projectionControlMatrix = null;
return;
}
Transform3D transform = new Transform3D();
transformGroup.getTransform(transform);
// Get the rotation.
double [][] matrix = new double[4][4];
int k = 0;
for ( int i = 0; i < 4; ++i ) {
for ( int j = 0; j < 4; ++j ) {
matrix[i][j] = projectionControlMatrix[k++];
}
}
projectionControlMatrix = null;
Matrix3d rotationMatrix = new Matrix3d();
rotationMatrix.m00 = matrix[0][0];
rotationMatrix.m01 = matrix[0][1];
rotationMatrix.m02 = matrix[0][2];
rotationMatrix.m10 = matrix[1][0];
rotationMatrix.m11 = matrix[1][1];
rotationMatrix.m12 = matrix[1][2];
rotationMatrix.m20 = matrix[2][0];
rotationMatrix.m21 = matrix[2][1];
rotationMatrix.m22 = matrix[2][2];
matrix = null;
// Undo the rotaion by finding the inverse of the rotation matrix.
rotationMatrix.invert();
rotationMatrix.normalize();
Transform3D rotationTransform = new Transform3D();
rotationTransform.set(rotationMatrix);
// Undo the scaling.
final double newScale = initialScale / scale[0];
// Undo the translation by translating back to our initial location.
Vector3d translationVector = new Vector3d();
translationVector.x = -1 * (translation[0] - initialXTrans) / scale[0];
translationVector.y = -1 * (translation[1] - initialYTrans) / scale[0];
translationVector.z = -1 * (translation[2] - initialZTrans) / scale[0];
Transform3D scaleTranslationTransform = new Transform3D();
scaleTranslationTransform.set(newScale, translationVector );
transform = rotationTransform;
transform.mul( scaleTranslationTransform );
transformGroup.setTransform(transform);
rotationTransform = null;
scaleTranslationTransform = null;
transform = null;
}
} // class ShadowScreenLockedSetTypeJ3D.ProjectionControlListener
}
// ScreenLockedDemo.java
// Java
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.BorderLayout;
import java.rmi.RemoteException;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
// VisAD
import visad.ConstantMap;
import visad.DataReferenceImpl;
import visad.DelaunayCustom;
import visad.Display;
import visad.DisplayImpl;
import visad.FlatField;
import visad.FunctionType;
import visad.GraphicsModeControl;
import visad.Gridded2DDoubleSet;
import visad.Irregular2DSet;
import visad.RealTupleType;
import visad.RealType;
import visad.ScalarMap;
import visad.UnionSet;
import visad.VisADException;
import visad.bom.ScreenLockedRendererJ3D;
import visad.java3d.DefaultRendererJ3D;
import visad.java3d.DisplayImplJ3D;
import visad.java3d.RendererJ3D;
/**
* This demo illustrates the problems I am experiencing with
* the screen locked renderer.
*
* In the process of creating this demo, I learned that a
* Set can be screen-locked by using a ShadowScreenLockedSetTypeJ3D.java
* so I hope you don't mind the addition. ScreenLockedRenderer.java
* also had to change to accommodate this new shadow type.
*
* The demo illustrates the problem I have been having which
* involved a radar rain-rate scale which was locked to the
* screen. When the program started, the scale was locked
* to the lower-left of the screen. When importing some
* radar data, the scale moved to a new location and stayed
* locked to this incorrect position.
*
* I tried to solve this problem a number of ways, and I
* found one. (Incidentally, the method does not work for
* this demo!).
*
* But, there was another problem...
*
* The x/y/z and scale are re-initialised each
* time the shadow type was created, but there was a problem
* when we imported large amounts of radar data and tried
* panning/zooming while the "please wait" message was
* displayed.
*
* When "please wait" is displayed, and the user pans/zooms the
* display, the projection's control's controlChanged() events
* become coarse-grained. ie. there is a big change in the projection control
* matrix between successive firings of controlChanged events.
* So, the scale would move a little and then
* be re-locked to a position near to where it should be, but off by
* quite a few pixels. It would then stay locked to this incorrect position.
*
* That's enough about the radar rain-scale...
* Now to talk about this demo.
*
*
* MathTypes:
* red square: (x,y)
* white cross: (x,y)
* blue triangle: (x,y)
* field: (x,y)->(height)
*
* Locations:
* red square: screen-locked
* white cross: initially centred on red square
* blue triangle: SE of white cross
* field: NE of white cross
*
*
* Test 1
*
* Start the demo
* You will see a white cross displayed over a screen-locked
* red square
* Zoom out a little.
* Pan so that the white cross is in the top left corner of the window
* Click "Add Triangle"
* A blue triangle is displayed near the lower-right corner
* of the white cross, as expected.
* The red square however has moved over to be centred
* under that white cross. It's also resized so that
* fits under the white cross as it did initially.
* Exit
*
*
* Test 2
*
* Start the demo
* You will see a white cross displayed over a screen-locked
* red square
* Click the "Set Range" button.
* This sets the domain ranges (x and y).
* This white cross decreases in size.
* The red square decreases in size, even though it is
* "screen locked"! [alarm bells ring]
* Zoom out a little.
* Pan so that the white cross is in the top left corner of the window
* Click "Add Triangle"
* The blue triangle is displayed near the lower-right corner
* of the white cross, as expected.
* The red square stays screen-locked in the centre of the
* screen.
* Zoom/pan the display
* The red square remains locked to the centre of the screen.
* Exit
*
*
* Test 3
*
* Start the demo
* You will see a white cross displayed over a screen-locked
* red square
* Optional: click "Set Range"
* Zoom out a little.
* Pan so that the white cross is in the top left corner of the window
* Click "Add Field"
* A field is displayed near the top-right of the white cross,
* as expected.
* The red square however has moved over to be centred
* under the white cross again. It's also resized so that it
* fits under the white cross.
*
* Conclusions:
*
* ScalarMap.setRange() is having an effect that I am not
* accounting for.
*
* It seems that setRange() needs to be accounted for, regardless
* of which scalar is involved in the setRange. In "Test 3", visad
* would have done an auto-setRange on the scalar map that maps
* the field's range type to Display.RGB.
*
* Future problems:
*
* Even if we can learn to correctly handle ScalarMap.setRange(),
* there is another problem waiting.
*
* This is the problem that I described earlier regarding the
* re-initialisation of the x/y/z translations and scale. If
* a user is pushing the system hard, and "please wait" is
* displayed, and the display is zoomed/panned, notification of
* changes in the projection control matrix become coarse-grained,
* and re-initialisation is done to the wrong location.
*
* Other:
*
* As an aside, I would like to mention that the projection
* control listeners need to be removed when the shadow is
* destroyed.
*
* Question:
*
* Is it possible to not have to re-initialise the x/y/z translations
* and scale? Perhaps extra logic can be added to ScreenLockedRendererJ3D
* and the ShadowScreenLocked*J3D classes that allow the
* translations and scale to be initialised only once?
*
*/
public final class ScreenLockedDemo
{
private final DisplayImplJ3D display;
private final ScalarMap xMap;
private final ScalarMap yMap;
/**
* Constructor.
*/
public ScreenLockedDemo() throws VisADException, RemoteException
{
display = new DisplayImplJ3D("display");
final GraphicsModeControl gmc =
display.getGraphicsModeControl();
gmc.setScaleEnable(false);
gmc.setProjectionPolicy(DisplayImplJ3D.PARALLEL_PROJECTION);
display.getDisplayRenderer().setBoxOn(false);
final RealType x = RealType.getRealType("x");
final RealType y = RealType.getRealType("y");
xMap = new ScalarMap(x, Display.XAxis);
yMap = new ScalarMap(y, Display.YAxis);
display.addMap(xMap);
display.addMap(yMap);
addScreenLockedSquare(display);
addCross(display);
final JFrame frame = new JFrame("Screen Locked Demo");
final JPanel panel = new JPanel(new BorderLayout());
panel.add(display.getComponent(), BorderLayout.CENTER);
final JPanel buttonsPanel = new JPanel();
final ButtonListener buttonListener = new ButtonListener();
JButton button = new JButton("Add Triangle");
button.addActionListener(buttonListener);
buttonsPanel.add(button);
button = new JButton("Add Field");
button.addActionListener(buttonListener);
buttonsPanel.add(button);
button = new JButton("Set Range");
button.addActionListener(buttonListener);
buttonsPanel.add(button);
panel.add(buttonsPanel, BorderLayout.SOUTH);
frame.getContentPane().add(panel);
frame.setSize(640, 480);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
} // ScreenLockedDemo.ScreenLockedDemo()
/**
* Adds a coloured square to the display, using a screen
* locked renderer.
*/
private static void addScreenLockedSquare(final DisplayImpl display)
throws VisADException, RemoteException
{
final int numSamples = 4;
final double[][]samples = new double[2][numSamples];
samples[0][0] = -10;
samples[1][0] = 10;
samples[0][1] = 10;
samples[1][1] = 10;
samples[0][2] = 10;
samples[1][2] = -10;
samples[0][3] = -10;
samples[1][3] = -10;
final RealTupleType domainType = new RealTupleType(
RealType.getRealType("x"), RealType.getRealType("y"));
final Gridded2DDoubleSet set = new Gridded2DDoubleSet(
domainType, samples, numSamples);
final Irregular2DSet filledSet = DelaunayCustom.fill(set);
final DataReferenceImpl dataRef =
new DataReferenceImpl("square_data_ref");
dataRef.setData(filledSet);
final RendererJ3D renderer = new ScreenLockedRendererJ3D();
final ConstantMap[] maps = new ConstantMap[] {
new ConstantMap(1, Display.Red),
new ConstantMap(0, Display.Green),
new ConstantMap(0, Display.Blue),
new ConstantMap(-0.03, Display.ZAxis)};
display.addReferences(renderer, dataRef, maps);
} // ScreenLockedDemo.addScreenLockedSquare()
/**
* Adds a triangle to the display, using a default renderer.
*/
private static void addTriangle(final DisplayImpl display)
throws VisADException, RemoteException
{
final int numSamples = 3;
final double[][]samples = new double[2][numSamples];
samples[0][0] = 12;
samples[1][0] = -15;
samples[0][1] = 17;
samples[1][1] = -10;
samples[0][2] = 22;
samples[1][2] = -15;
final RealTupleType type = new RealTupleType(
RealType.getRealType("x"), RealType.getRealType("y"));
final Gridded2DDoubleSet set = new Gridded2DDoubleSet(
type, samples, numSamples);
final Irregular2DSet filledSet = DelaunayCustom.fill(set);
final DataReferenceImpl dataRef =
new DataReferenceImpl("triangle_data_ref");
dataRef.setData(filledSet);
final RendererJ3D renderer = new DefaultRendererJ3D();
final ConstantMap[] maps = new ConstantMap[] {
new ConstantMap(0, Display.Red),
new ConstantMap(0, Display.Green),
new ConstantMap(1, Display.Blue),
new ConstantMap(-0.02, Display.ZAxis)};
display.addReferences(renderer, dataRef, maps);
} // ScreenLockedDemo.addTriangle()
/**
* Adds a cross to the dispaly, using a default renderer.
*/
private static void addCross(final DisplayImpl display)
throws VisADException, RemoteException
{
final int numSamples = 2;
final double[][] samples = new double[2][numSamples];
samples[0][0] = -12;
samples[1][0] = 0;
samples[0][1] = 12;
samples[1][1] = 0;
final RealTupleType type = new RealTupleType(
RealType.getRealType("x"), RealType.getRealType("y"));
Gridded2DDoubleSet horizontalSet = new Gridded2DDoubleSet(
type, samples, numSamples);
samples[0][0] = 0;
samples[1][0] = 12;
samples[0][1] = 0;
samples[1][1] = -12;
Gridded2DDoubleSet verticalSet = new Gridded2DDoubleSet(
type, samples, numSamples);
final UnionSet set = new UnionSet(
new Gridded2DDoubleSet[]{
horizontalSet, verticalSet});
final DataReferenceImpl dataRef =
new DataReferenceImpl("lines_data_ref");
dataRef.setData(set);
final ConstantMap[] maps = new ConstantMap[] {
new ConstantMap(2, Display.LineWidth),
new ConstantMap(-0.01, Display.ZAxis)};
display.addReference(dataRef, maps);
} // ScreenLockedDemo.addCross()
/**
* Adds a field to the display.
*/
private static void addField(final DisplayImpl display)
throws VisADException, RemoteException
{
final RealTupleType domainType = new RealTupleType(
RealType.getRealType("x"), RealType.getRealType("y"));
final RealType rangeType = RealType.getRealType("height");
final FunctionType functionType =
new FunctionType(domainType, rangeType);
final FlatField field = FlatField.makeField1(
functionType, 11, 18, 10, 11, 18, 10);
final DataReferenceImpl dataRef =
new DataReferenceImpl("field_data_ref");
dataRef.setData(field);
display.addMap(new ScalarMap(rangeType, Display.RGB));
display.addReference(dataRef);
} // ScreenLockedDemo.addField()
/**
* Listens for button clicks.
*/
private class ButtonListener implements ActionListener
{
/**
* The user has clicked on a button.
*/
public void actionPerformed(ActionEvent event)
{
try {
final String command = event.getActionCommand();
if (command.equals("Add Triangle")) {
addTriangle(display);
} else if (command.equals("Add Field")) {
addField(display);
} else {
xMap.setRange(-20, 20);
yMap.setRange(-20, 20);
}
} catch (VisADException ex) {
System.err.println(ex.getMessage());
ex.printStackTrace();
} catch (RemoteException ex) {
System.err.println(ex.getMessage());
ex.printStackTrace();
}
} // ButtonListener.actionPerformed()
} // class ScreenLockedDemo.ButtonListener
/**
* Used to run the program.
*
* Please read the class javadoc at the top of this file.
*
* @param args arguments are ignored.
*/
public static final void main(String[] args)
throws VisADException, RemoteException
{
new ScreenLockedDemo();
} // ScreenLockedDemo.main()
} // class ScreenLockedDemo