/* 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 javax.swing.*; import java.util.Vector; /** VisAD Tutorial example 6_09 Direct Manipulation of a line Resample surface into a line with MathType (easting -> temperature ) Use Gridded1DSet for line and two VisADSliders to control northing and number of points Run program with java P6_09 * */ public class P6_09{ // 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; public P6_09 (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 ); // More Data: create a Cube object and get its data Cube cube = new Cube(); 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, 8, 5000, 50, 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 ); // Add maps to display displays[0].addMap( eastMap ); displays[0].addMap( northMap ); displays[0].addMap( rgbMap ); displays[0].addMap( altMap ); // 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); // Create application window, put display into it JFrame jframe = new JFrame("VisAD Tutorial example 6_09"); jframe.getContentPane().setLayout(new BorderLayout()); JPanel dispPanel = new JPanel( new GridLayout(1,2) ); dispPanel.add(displays[0].getComponent()); dispPanel.add(displays[1].getComponent()); jframe.getContentPane().add(dispPanel, BorderLayout.CENTER); dispPanel = new JPanel( new GridLayout(1,2) ); dispPanel.add(latSlider); dispPanel.add(pointsSlider); jframe.getContentPane().add(dispPanel, BorderLayout.SOUTH); // Set window size and make it visible jframe.setSize(600, 300); 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