/* VisAD Tutorial Copyright (C) 2000-2001 Ugo Taddei */ package tutorial.s6; // Import needed classes import visad.*; import visad.java2d.DisplayImplJ2D; import visad.java2d.DirectManipulationRendererJ2D; import visad.java3d.*; import visad.util.*; import java.rmi.RemoteException; import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.util.Vector; import java.util.Iterator; /** VisAD Tutorial example 6_10 Same as 9_09, but with GUI add-ons Run program with java P6_10 * */ public class P6_10 implements DisplayListener { // Declare variables // The quantities to be displayed in x- and y-axes private RealType easting, northing, altitude, temperature; // lat and lon form a domain2D private RealTupleType domain2D; // (lat, lon, alt) form a domain2D private RealTupleType domain3D; // A Tuple of Reals (a subclass of VisAD Data) // which will hold cursor data. private Real cursorCoords; // and this FlatField will hold the surface private FlatField cubeFF; // The temperature plane private FlatField temperPlane; // The grey plane private Set greyPlane; // The DataReferences from the data to display private DataReferenceImpl cursorDataRef, cubeDataRef; private DataReferenceImpl greyPlaneRef, tPlaneDataRef; private Real nPoints; // data reference for the number of points private DataReference nPointsRef; // The 2D display, and its the maps private DisplayImpl[] displays; private ScalarMap eastMap, northMap, altMap, rgbMap; private ScalarMap rangeX, rangeY, rangeZ; private boolean displaysAreLinked = true; // GUI private JPanel dispPanel; private JPanel guiPanel; public P6_10 (String[] args) throws RemoteException, VisADException { // Create the quantities easting = RealType.getRealType("easting", SI.meter, null); northing = RealType.getRealType("northing", SI.meter, null); altitude = RealType.getRealType("altitude", SI.meter, null); temperature = RealType.getRealType("temperature", SI.kelvin, null); //...the domain2D domain2D = new RealTupleType(easting, northing); // and the domain3D domain3D = new RealTupleType(easting, northing, altitude); // Create the Data: // The cursor double initAltitude = 0.0; cursorCoords = new Real(altitude, initAltitude); // Create the DataReference cursorDataRef = new DataReferenceImpl("cursorDataRef"); // ...and initialize it with the RealTuple cursorDataRef.setData( cursorCoords ); // change tis if you want random samples -> looks very "scientific" ;-) boolean randomSamples = false; // More Data: create a Cube object and get its data Cube cube = new Cube(randomSamples); cubeFF = (FlatField) cube.getData(); cubeDataRef = new DataReferenceImpl("cubeDataRef"); cubeDataRef.setData(cubeFF); // number of points as a real and its reference nPoints = new Real(100.0); nPointsRef = new DataReferenceImpl("nPointsRef"); nPointsRef.setData(nPoints); // Create the white line // with so many points int numberOfPoints = (int) nPoints.getValue(); // we really want to simplify and tak the root of numberOfPoints // this is then the number per dimension: greyPlane = (Set) makePlaneSet(initAltitude, numberOfPoints*numberOfPoints); // Create the line's data ref and set data greyPlaneRef = new DataReferenceImpl("greyPlaneRef"); greyPlaneRef.setData(greyPlane); // Create the temperature plane to be shown on display temperPlane = (FlatField) cubeFF.resample(greyPlane); // create and set data reference tPlaneDataRef = new DataReferenceImpl("tPlaneDataRef"); tPlaneDataRef.setData(temperPlane); CellImpl cell = new CellImpl() { public void doAction() throws RemoteException, VisADException { // get the data object from the reference. We know it's a RealTuple Real lat = (Real) cursorDataRef.getData(); // test if cursor postion (northing) has changed significantly if( Util.isApproximatelyEqual( lat.getValue(), cursorCoords.getValue(), 0.1 ) && Util.isApproximatelyEqual( nPoints.getValue(), ((Real) nPointsRef.getData()).getValue(), 1 ) ){ return; // leave method and thus don't update line } double latValue = lat.getValue(); // make a new line for display 1: will have only 2 points int nOfPoints = 100; greyPlane = (Set) makePlaneSet(latValue, nOfPoints*nOfPoints); // Re-set Data, will update display greyPlaneRef.setData(greyPlane); // now create a larger white line set to compute the temperature line nOfPoints = (int) ((Real) nPointsRef.getData()).getValue(); nOfPoints = (int) Math.sqrt((double)nOfPoints); greyPlane = (Set) makePlaneSet(latValue, nOfPoints*nOfPoints); // function will have this type String funcStr = "( (easting, northing, altitude) -> temperature )"; // create Function (FlatField) and set the data temperPlane = new FlatField( (FunctionType) MathType.stringToType( funcStr ), greyPlane ); temperPlane.setSamples( cubeFF.resample( greyPlane ).getFloats(false), false); // and update ist data reference -> will update display tPlaneDataRef.setData(temperPlane); // assign current cursor position to old cursor position cursorCoords = lat; } }; // link cursor to cell // so that doAction gets called whenever cursor moves cell.addReference(cursorDataRef); cell.addReference(nPointsRef); // create a slider, to show and control northing values VisADSlider latSlider = new VisADSlider(cursorDataRef, -4, 4, 0, northing, "Altitude"); // this slider will control the number of points VisADSlider pointsSlider = new VisADSlider(nPointsRef, 1000, 50000, 1000, RealType.Generic, "Points in Plane"); // Create the Displays and their maps // Two 2D displays displays = new DisplayImpl[2]; for( int i = 0; i<2;i++){ displays[i] = new DisplayImplJ3D("display" + i); } // Get display's graphics mode control draw scales for( int i = 0; i<2;i++){ GraphicsModeControl dispGMC = (GraphicsModeControl) displays[i].getGraphicsModeControl(); dispGMC.setScaleEnable(true); } displays[1].getGraphicsModeControl().setTextureEnable(false); // Create the ScalarMaps eastMap = new ScalarMap( easting, Display.XAxis ); northMap = new ScalarMap( northing, Display.YAxis ); altMap = new ScalarMap( altitude, Display.ZAxis ); rgbMap = new ScalarMap( temperature, Display.RGB ); rangeX = new ScalarMap(easting, Display.SelectRange ); rangeY = new ScalarMap(northing, Display.SelectRange ); rangeZ = new ScalarMap(altitude, Display.SelectRange ); // Add maps to display displays[0].addMap( eastMap ); displays[0].addMap( northMap ); displays[0].addMap( rgbMap ); displays[0].addMap( altMap ); displays[0].addMap( rangeX ); displays[0].addMap( rangeY ); displays[0].addMap( rangeZ ); // Copy those maps and add to second display // but choose only two of the maps displays[1].addMap( (ScalarMap) eastMap.clone() ); displays[1].addMap( (ScalarMap) northMap.clone() ); // set ranges of rgb's and z-axis' maps of 2nd display // so that they math the ranges of 1st display ScalarMap anotherRGBMap = (ScalarMap) rgbMap.clone(); double[] rgbRange = rgbMap.getRange(); anotherRGBMap.setRange(rgbRange[0],rgbRange[1]); displays[1].addMap( anotherRGBMap ); ScalarMap anotherZMap = (ScalarMap) altMap.clone(); anotherZMap.setRange(-4.0, 4.0); displays[1].addMap( anotherZMap ); // Also create constant maps to define cursor size, color, etc... ConstantMap[] cMaps = { new ConstantMap( 1.0f, Display.Red ), new ConstantMap( 1.0f, Display.Green ), new ConstantMap( 1.0f, Display.Blue ), new ConstantMap( -1.0f, Display.XAxis ), new ConstantMap( -1.0f, Display.YAxis ), new ConstantMap( 3.50f, Display.PointSize ) }; // ...and constant maps to make cutting plane grey and transparent ConstantMap[] wLineMaps = { new ConstantMap( 0.75f, Display.Red ), new ConstantMap( 0.75f, Display.Green ), new ConstantMap( 0.75f, Display.Blue ), new ConstantMap( 0.75f, Display.Alpha ) }; // Now Add reference to display // But using a direct manipulation renderer // display 1 displays[0].addReferences( new DirectManipulationRendererJ3D(), cursorDataRef, cMaps ); displays[0].addReference(cubeDataRef); displays[0].addReference(greyPlaneRef, wLineMaps); // display 2 displays[1].addReference(tPlaneDataRef, null); displays[0].addDisplayListener(this); // Create application window, put display into it JFrame jframe = new JFrame("VisAD Tutorial example 6_10"); jframe.getContentPane().setLayout(new BorderLayout()); dispPanel = new JPanel( new GridLayout(1,2) ); dispPanel.add(displays[0].getComponent()); dispPanel.add(displays[1].getComponent()); jframe.getContentPane().add(dispPanel, BorderLayout.CENTER); guiPanel = new JPanel( new GridLayout(1,2) ); guiPanel.add(latSlider); guiPanel.add(pointsSlider); JPanel guiPanel2 = new JPanel( new GridLayout(1,2) ); guiPanel2.add(createRangeSliders()); JPanel pp = new JPanel(); pp.add(createSyncCheck()); pp.add(createSwitchButton()); pp.add(createResetButton()); guiPanel2.add(pp); JPanel southPanel = new JPanel(); southPanel.setLayout(new BoxLayout(southPanel,BoxLayout.Y_AXIS)); southPanel.add(guiPanel); southPanel.add(guiPanel2); jframe.getContentPane().add(southPanel, BorderLayout.SOUTH); // Set window size and make it visible jframe.setSize(600, 400); jframe.setVisible(true); } /**Create a new Gridded3DSet at a given altitude value and from a certain number of points*/ private Set makePlaneSet( double altitudeValue, int pointsPerPlane ) throws VisADException, RemoteException { // arbitrary easting end values of the line float lowVal = -4.0f; float hiVal = 4.0f; float[][] domain2DSamples = new float[3][pointsPerPlane]; int ptsPerDim = (int) Math.sqrt((double)pointsPerPlane); for(int x=0;x Display.ZAxis will not be available anymore // so must explicitely construct a new one if(!twoD){ ScalarMap anotherZMap = (ScalarMap) altMap.clone(); double[] range = altMap.getRange(); anotherZMap.setRange(range[0], range[1]); displays[1].addMap( anotherZMap ); } //re-add the temperature plane reference displays[1].addReference(tPlaneDataRef, null); // add the display to its parent panel dispPanel.add(displays[1].getComponent()); dispPanel.repaint(); // set GMC on GraphicsModeControl dispGMC = (GraphicsModeControl) displays[1].getGraphicsModeControl(); dispGMC.setScaleEnable(true); dispGMC.setTextureEnable(false); } catch (Exception ex) { ex.printStackTrace(); } } /**This function create range sliders and put them in a panel*/ private Component createRangeSliders(){ JPanel p = new JPanel(); p.setLayout(new BoxLayout(p,BoxLayout.Y_AXIS)); try { p.add( new SelectRangeWidget( rangeX ) ); p.add( new SelectRangeWidget( rangeY ) ); p.add( new SelectRangeWidget( rangeZ ) ); } catch (Exception ex) { ex.printStackTrace(); } return p; } /**This function create a check box to linked the displays*/ private JCheckBox createSyncCheck(){ JCheckBox cb = new JCheckBox("Link Displays",true); cb.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { displaysAreLinked = (e.getStateChange() == ItemEvent.SELECTED); } }); return cb; } /**This is the implementation of DisplayListener.displayChanged(DisplayEvent e). * This function sets the position of the left display to match that of the * cube display, but only if the displays are linked by the means of a boolean variable.*/ public void displayChanged(DisplayEvent e) throws VisADException, RemoteException { if (e.getId() == DisplayEvent.FRAME_DONE) { if(displaysAreLinked){ displays[1].getProjectionControl().setMatrix(displays[0].getProjectionControl().getMatrix()); } } } public static void main(String[] args) throws RemoteException, VisADException { P6_10 p = new P6_10(args); } } //end of Visad Tutorial Program 6_09