[Date Prev][Date Next]
[Chronological]
[Thread]
[Top]
Re: Demo for screen locked renderer.
Hello Bill,
thankyou for making those 3 files available on the web site, and
I apologise for taking such a long time to reply to your email....
[I have found some time today to continue working on the Screen
Locked Renderer].
I have modifed ScreenLockedRenderer's main() method and it
works fine (file is attached).
I have also modified ScreenLockedDemo's addScreenLockedSquare()
method, and it also works fine (file is attached).
I would like to do some more testing to see what sort of function
types are and are not supported (eg, ((x, y)->text) instead of
just (text), and shapes?)
In the ScreenLockedRenderer.main() method, the text is placed in
x/y/z space using ConstantMaps. Choosing the correct values for
Display.XAxis and Display.YAxis is a little confusing, but I'm
working on it. It seems like these contant map values need to be
between 0.5 and -0.5 to place the labels where I expect them to be.
In the ScreenLockedDemo.addScreenLockedSquare() method, a
setRange() is done such that the setRange's min/max values are
twice that of the actual min/max values in the Set. This seems to
make the square about the right size.
Is it a coincidence that in the first case my constant maps for x
and y are set to 1/2, whereas in the second case, I do a setRange()
such that the min/max are 2X the real min/max values?
PS. In our majordomo email lists, we configure the "reply to" field
to be the name of the list, meaning that if you reply to a post, the
email-list is the destination (instead of the person who posted).
Thanks,
Jim.
---
Jim Koutsovasilis
Bureau of Meteorology, Australia
jimk@bom.gov.au
Bill Hibbard wrote:
>Hi Jim,
>
>I got to thinking about the complexity of my answers
>yesterday and decided there might be an easier way.
>
>I've put three files on:
>
> ftp://ftp.ssec.wisc.edu/pub/visad-2.0/untested/
>
>for you to experiment with. They are (with brief
>descriptions of the changes):
>
> DisplayRendererJ3D.java:
> add 'OrderedGroup screen_locked'
> add addLockedSceneGraphComponent() method
> that adds BranchGroup to screen_locked instead of non_direct
> add 'TransformGroup locked_trans'
> construct and set in first setTransform3D() call with (t != null)
> screen_locked child of locked_trans and
> locked_trans child of root
>
> DefaultRendererJ3D.java:
> make addSwitch() public
>
> ScreenLockedRendererJ3D.java:
> override addSwitch() to call addLockedSceneGraphComponent()
> instead of addSceneGraphComponent()
>
>The idea is to create another branch of the scene graph
>under screen_locked, which is under a fixed TransformGroup
>named locked_trans that contains the initial value of the
>TransformGroup (trans) of the main scene graph branch
>(under non_direct). Because the TransformGroup is fixed,
>the graphics don't move.
>
>One problem with this approach is that the Data objects to
>be depicted in a screen-locked manner cannot include any
>RealTypes mapped to spatial DisplayRealTypes. They must be
>drawn using ScalarMaps to Text, Shape or Flow (screen-locked
>Flow icons are probably unlikely), and located via ConstantMaps
>to XAxis, YAxis and ZAxis. Using ConstantMaps gets around the
>changing linear mappings in spatial ScalarMaps.
>
>If you are interested in this approach, you'll need to rework
>your ScreenLockedDemo and the main() method in
>ScreenLockedRendererJ3D to conform to this way of doing
>things.
>
>For some reason I don't understand, the red square in
>ScreenLockedDemo looks larger with this approach. It may be
>something about the initial matrix set in trans.
>
>Note in this approach the ShadowScreenLocked*TypeJ3D classes
>are unnecessary.
>
>Please let me know if this approach will make it possible to
>do what you want.
>
>And please let me know if you have any questions or problems.
>
>Cheers,
>Bill
>
>
// 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;
/**
* Demos the ScreenLockedRendererJ3D and its related problems.
*/
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("a"), RealType.getRealType("b"));
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 ScalarMap yMap = new ScalarMap(RealType.getRealType("a"),
Display.YAxis);
final ScalarMap xMap = new ScalarMap(RealType.getRealType("b"),
Display.XAxis);
display.addMap(yMap);
display.addMap(xMap);
yMap.setRange(-20, 20);
xMap.setRange(-20, 20);
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
//
// 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;
// Java3D
import javax.media.j3d.*;
// 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();
}
public void addSwitch(DisplayRendererJ3D displayRenderer,
BranchGroup branch) {
displayRenderer.addLockedSceneGraphComponent(branch);
}
/**
* 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;
// 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);
textMap.setRange(0, 10);
// Center the labels on the corners of the square.
final TextControl textControl = (TextControl) textMap.getControl();
textControl.setCenter(true);
Text text = new Text(textType, "Screen Locked 1");
final DataReferenceImpl lockedDataRef1 = new DataReferenceImpl(
"locked_data_ref");
lockedDataRef1.setData(text);
display.addReferences(new ScreenLockedRendererJ3D(), lockedDataRef1,
new ConstantMap[]{
new ConstantMap(-0.5, Display.XAxis),
new ConstantMap(0.5, Display.YAxis),
new ConstantMap(-0.1, Display.ZAxis)});
text = new Text(textType, "Screen Locked 2");
DataReferenceImpl lockedDataRef2 = new DataReferenceImpl(
"locked_data_ref");
lockedDataRef2.setData(text);
display.addReferences(new ScreenLockedRendererJ3D(), lockedDataRef2,
new ConstantMap[]{
new ConstantMap(0.5, Display.XAxis),
new ConstantMap(-0.5, Display.YAxis),
new ConstantMap(-0.1, Display.ZAxis)});
// Color the square red.
display.addReference(unlockedDataRef, new ConstantMap [] {
new ConstantMap(0.0, Display.Green),
new ConstantMap(0.0, Display.Blue),
new ConstantMap(-0.5, Display.ZAxis)});
// Display the frame.
final JFrame frame = new JFrame("ScreenLockedRendererJ3D");
frame.getContentPane().add(display.getComponent());
frame.setSize(400, 400);
frame.setVisible(true);
}
} // class ScreenLockedRendererJ3D