[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