NOTICE: This version of the NSF Unidata web site (archive.unidata.ucar.edu) is no longer being updated.
Current content can be found at unidata.ucar.edu.
To learn about what's going on, see About the Archive Site.
Thanks for your quick response. I'm sorry, though- but I'm still confused. I think perhaps I did not make it clear what I want to do. I just want to take example P2_03 on the visAD tutorial page: http://www.ssec.wisc.edu/~billh/tutorial/s2/Section2.html and draw the sample points as bars instead of dots. The top of each bar would be at the y (height) value of the point and the bottom of each bar would be at y = 0. All I meant about the "midpoint" stuff was that if barwidth = 1 then 0.5 of the bar would be to the left of the x (time) position and 0.5 of the bar would be to the right of the x position. In other words, the upper left corner of each bar would be at coordinate (x - 0.5, y) and the lower right corner of the bar shape would be at (x + 0.5, 0). In this case, I don't think we need the third RealType ("dif") in your example. Right? I also didn't understand the section of code where you set up the shapes. Why do you have to generate the Linear1DSet of samples when you already have all the sample data you need? Which leads to a more general question- is VisAD not a good program for plotting/charting discrete data? Is it much better suited for continuous functions? Anyway, here is my modified version of example P2_03 as I attempt to draw the points as bars. The only section that's different from the one on the web page is the "set up shapes" section (and the fact that I made the heightMap range start at 0 instead of -10, which shouldn't matter much). I guess my biggest problem is that I don't know how to get the bar shapes to draw. I know I'm missing code to do that, but I'm not quite sure what it should be. I don't even understand how the example in the tutorial knew to draw dots as opposed to a line connecting the points in the previous tutorial example. Any help is greatly appreciated! Here is my code, followed by your prev. email for reference. You may want to just scroll down to my "set up shapes" section. THANK YOU!! /* VisAD Tutorial Copyright (C) 2000 Ugo Taddei */ // Import needed classes import visad.*; import visad.java2d.DisplayImplJ2D; import java.rmi.RemoteException; import java.awt.*; import javax.swing.*; /** VisAD Tutorial example 2_03 Data are organized as MathType ( index -> ( time, height ) ) and represent some points from the parabola of the previous example Data are indexed (time, height) points and get depicted as such. Run program with java P2_03 */ public class P2_03Bar{ // Declare variables // The quantities to be displayed in x- and y-axes: time and height, respectively // Our index is alos a RealType private RealType time, height, index; // A Tuple, to pack time and height together private RealTupleType t_h_tuple; // The function ( time(i), height(i) ), where i = index, // represented by ( index -> ( time, height) ) // ( time, height) are a Tuple, so we have a FunctionType // from index to a tuple private FunctionType func_i_tuple; // Our Data values, the points, are now indexed by the Set private Set index_set; // The Data class FlatField, which will hold time and height data. // time data are implicitely given by the Set time_set private FlatField vals_ff; // The DataReference from the data to display private DataReferenceImpl data_ref; // The 2D display, and its the maps private DisplayImpl display; private ScalarMap timeMap, heightMap; public P2_03Bar (String []args) throws RemoteException, VisADException { // Create the quantities // x and y are measured in SI meters // Use RealType(String name, Unit u, Set set), set is null time = new RealType("time", SI.second, null); height = new RealType("height", SI.meter, null); // Organize time and height in a Tuple t_h_tuple = new RealTupleType( time, height); // Index has no unit, just a name index = new RealType("index"); // Create a FunctionType ( index -> ( time, height) ) // Use FunctionType(MathType domain, MathType range) func_i_tuple = new FunctionType( index, t_h_tuple); // Create the x_set, with 5 values, but this time using a // Integer1DSet(MathType type, int length) index_set = new Integer1DSet(index, 5); // These are our actual data values for time and height // Note that these values correspond to the parabola of the // previous examples. The y (height) values are the same, but the x (time) // are now given given. float[][] point_vals = new float[][]{{-3.0f, -1.5f, 0.0f, 1.5f, 3.0f,}, {0.0f, 33.75f, 45.0f, 33.75f, 0.0f,} }; // Create a FlatField, that is the Data class for the samples // Use FlatField(FunctionType type, Set domain_set) vals_ff = new FlatField( func_i_tuple, index_set); // and put the height values above in it vals_ff.setSamples( point_vals ); // Create Display and its maps // A 2D display display = new DisplayImplJ2D("display1"); // Get display's graphics mode control and draw scales GraphicsModeControl dispGMC = (GraphicsModeControl) display.getGraphicsModeControl(); dispGMC.setScaleEnable(true); // Create the ScalarMaps: quantity time is to be displayed along XAxis // and height along YAxis // Use ScalarMap(ScalarType scalar, DisplayRealType display_scalar) timeMap = new ScalarMap( time, Display.XAxis ); heightMap = new ScalarMap( height, Display.YAxis ); // Add maps to display display.addMap( timeMap ); display.addMap( heightMap ); // Scale heightMap. This will scale the y-axis, because heightMap has DisplayRealType YAXIS // We simply choose the range from -4 to 4 for the x-axis // and -10.0 to 50.0 for timeMap.setRange( -4.0, 4.0); heightMap.setRange( 0.0, 50.0); // Create a data reference and set the FlatField as our data data_ref = new DataReferenceImpl("data_ref"); data_ref.setData( vals_ff ); ///////////////////// set up shapes ///////////////////// // can't do this- get class cast exception because it's not a // ShapeControl, it's a visad.java2d.ProjectionControlJ2D. // So how do I get the control? //ShapeControl control = (ShapeControl) heightMap.getControl(); float barWidth = 1f; int nPts = point_vals[1].length; VisADQuadArray[] shapes = new VisADQuadArray[nPts]; for (int i=0; i<nPts; i++) { shapes[i] = new VisADQuadArray(); shapes[i].vertexCount = 4; float hw = 0.5f * barWidth; float x = point_vals[0][i]; float y = point_vals[1][i]; shapes[i].coordinates = new float[] {x - hw, y, 0.0f, x + hw, y, 0.0f, x + hw, y, 0.0f, x - hw, y, 0.0f}; } // how do I draw these shapes? Do I just call this once I get // a valid ShapeControl object? : // control.setShapes(shape) ///////////////////// end set up shapes ///////////////////// // Add reference to display display.addReference( data_ref ); // Create application window, put display into it JFrame jframe = new JFrame("VisAD Tutorial example 2_03Bar"); jframe.getContentPane().add(display.getComponent()); // Set window size and make it visible jframe.setSize(300, 300); jframe.setVisible(true); } public static void main(String[] args) throws RemoteException, VisADException { new P2_03Bar(args); } } //end of Visad Tutorial example 2_03 "From: Bill Hibbard " wrote: > > Hi Jen, > > > Hi. I am new to VisAD but it seems really great. Problem is, it's so > > powerful that I'm having trouble figuring out the simple stuff. I've > > been looking at the (very helpful) tutorial at: > > > > http://www.ssec.wisc.edu/~billh/tutorial/s2/Section2.html > > > > I want to do a plot similar to the one in example P2_03 or P2_04, but > > insead of points to represent the data I would like bars. I want to make > > a bar graph, where the bottom of each bar is at a certain point on the x > > axis (in this example, maybe the midpoint of each bar would be at its > > corresponding x value) and the top of each bar is at the height of the > > corresponding y value. Do I have to make a VisADQuadArray for every bar > > I want or is there a simpler solution? Does anybody have/know of a > > simple Bar Chart example in 2d or 3d using VisAD? > > You can probably do this using ScalarMaps to Display.Shape. > Say you have a FlatField 'field' with MathType > (index -> (mid, top)) and you want the midpoint of bars at > mid values and tops of bars at top values. > > You can probably do this using ScalarMaps to Display.Shape. > Say you have a FlatField 'field' with MathType > (index -> (mid, top)) and you want the midpoint of bars at > mid values and tops of bars at top values. Then do > something like: > > // create new_field with (top - mid) values > RealType dif = new RealType("dif"); > RealTupleType range = new RealTupleType(mid, top, dif); > FunctionType new_func = new FunctionType(index, range); > Set set = field.getDomainSet(); > int length = set.getLength(); > float[][] old_values = field.getFloats(); > float[][] new_values = new float[3][length]; > new_values[0] = old_values[0]; > new_values[1] = old_values[1]; > float min_mid = Float.MAXIMUM_VALUE; > float max_mid = Float.MINIMUM_VALUE; > float max_dif = Float.MINIMUM_VALUE; > for (int i=0; i<length; i++) { > if (new_values[0][i] < min_mid) min_mid = new_values[0][i]; > if (new_values[0][i] > max_mid) max_mid = new_values[0][i]; > new_values[2][i] = new_values[1][i] - new_values[0][i]; > if (new_values[2][i] > max_mid) max_mid = new_values[2][i]; > } > FlatField new_field = new FlatField(new_func, set); > new_field.setSamples(new_values); > > // some tuning values for display > float dif_resolution = ...; // desired resolution of dif values > int ndifs = 1 + (int) (max_dif / dif_resolution); // # of dif samples > float width = ...; // width of bar (e.g., 0.02f) > > // set up Scalarmaps for display > display.addMap(new ScalarMap(index, Display.XAxis)); > ScalarMap mid_map = new ScalarMap(mid, Display.YAxis); > display.addMap(mid_map); > mid_map.setRange(min_mid, max_mid); > display.addMap(new ScalarMap(mid, Display.YAxis)); > ScalarMap dif_map = new ScalarMap(dif, Display.Shape); > display.addMap(dif_map); > > // set up shapes > ShapeControl control = (ShapeControl) dif_map.getControl(); > Linear1DSet dif_set = new Linear1DSet(dif, 0.0, max_dif, ndifs); > float[][] difs = dif_set.getSamples(); > VisADQuadArray[] dif_shapes = new VisADQuadArray[ndifs]; > for (int i=0; i<ndifs; i++) { > dif_shapes[i] = new VisADQuadArray(); > dif_shapes[i].vertexCount = 4; > float hw = 0.5f * width; > float hh = 0.5f * difs[0][i] * (2.0f / (max_mid - min_mid)); > dif_shapes[i].coordinates = new float[] > {hw, hh, 0.0f, -hw, hh, 0.0f, -hw, -hh, 0.0f, hw, -hh, 0.0f}; > } > control.setShapeSet(dif_set); > control.setShapes(dif_shapes); > > I haven't tested this, so it may have bugs, but its the general > idea. > > Cheers, > Bill > ---------------------------------------------------------- > Bill Hibbard, SSEC, 1225 W. Dayton St., Madison, WI 53706 > hibbard@xxxxxxxxxxxxxxxxx 608-263-4427 fax: 608-263-6738 > http://www.ssec.wisc.edu/~billh/vis.html
visad
archives: