Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: graph/DataSet.java


1   package graph;
2   
3   import java.awt.*;
4   import java.applet.*;
5   import java.util.*;
6   import java.lang.*;
7   
8   
9   /*
10  **************************************************************************
11  **
12  **    Class  DataSet
13  **
14  **************************************************************************
15  **    Copyright (C) 1995, 1996 Leigh Brookshaw
16  **
17  **    This program is free software; you can redistribute it and/or modify
18  **    it under the terms of the GNU General Public License as published by
19  **    the Free Software Foundation; either version 2 of the License, or
20  **    (at your option) any later version.
21  **
22  **    This program is distributed in the hope that it will be useful,
23  **    but WITHOUT ANY WARRANTY; without even the implied warranty of
24  **    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25  **    GNU General Public License for more details.
26  **
27  **    You should have received a copy of the GNU General Public License
28  **    along with this program; if not, write to the Free Software
29  **    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30  **************************************************************************
31  **    Modified by Jim Cochrane, last changed in May, 2001
32  **************************************************************************
33  **
34  **    This class is designed to be used in conjunction with 
35  **    the Graph class and Axis class for plotting 2D graphs.
36  **
37  *************************************************************************/
38  
39  
40  /**
41   *  This class is designed to hold the data to be plotted.
42   *  It is to be used in conjunction with the Graph class and Axis 
43   *  class for plotting 2D graphs.
44   *
45   * @version $Revision: 2.31 $, $Date: 2001/05/29 09:36:38 $
46   * @author Leigh Brookshaw 
47   */
48  public class DataSet {
49  
50    public void set_drawer (BasicDrawer d) {
51      _drawer = d;
52    }
53  
54    public void set_dates (String d[]) {
55      dates = d;
56      _drawer.set_dates(d);
57    }
58  
59    public void set_times (String t[]) {
60      times = t;
61      _drawer.set_times(t);
62    }
63  
64    public BasicDrawer drawer() { return _drawer; }
65  
66    // Do dates need to be drawn?
67    public boolean dates_needed() { return _dates_needed; }
68  
69    public void set_dates_needed(boolean b) { _dates_needed = b; }
70  
71    // Number of records in this data set
72    public int count() {
73      return tuple_count;
74    }
75  
76  /*
77  ***********************
78  ** Variables      
79  **********************/
80  
81    /** 
82    *    The Graphics canvas that is driving the whole show.
83    * @see graph.Graph
84    */
85    private Graph g2d_;
86    /**
87    *    The color of the straight line segments
88    */
89    private Color linecolor     = null;
90    /**
91    *    The index of the marker to use at the data points.
92    * @see graph.Markers
93    */
94    private int    marker       = 0;
95    /**
96    *    The marker color
97    */
98    private Color  markercolor  = null;
99    /**
100   *    The scaling factor for the marker. Default value is 1.
101   */
102   private double markerscale  = 1.0;
103   /**
104   *    The Axis object the X data is attached to. From the Axis object
105   *    the scaling for the data can be derived.
106   * @see graph.Axis
107   */
108   private Axis xaxis_;
109   /**
110   *    The Axis object the Y data is attached to.
111   * @see graph.Axis
112   */
113   private Axis yaxis_;
114   /**
115   * The current plottable X maximum of the data. 
116   * This can be very different from
117   * true data X maximum. The data is clipped when plotted.
118   */
119   private double xmax; 
120   /**
121   * The current plottable X minimum of the data. 
122   * This can be very different from
123   * true data X minimum. The data is clipped when plotted.
124   */
125   private double xmin;
126   /**
127   * The current plottable Y maximum of the data. 
128   * This can be very different from
129   * true data Y maximum. The data is clipped when plotted.
130   */
131   private double ymax; 
132   /**
133   * The current plottable Y minimum of the data. 
134   * This can be very different from
135   * true data Y minimum. The data is clipped when plotted.
136   */
137   private double ymin;
138   /**
139   * Boolean to control clipping of the data window.
140   * Default value is <em>true</em>, clip the data window.
141   */
142   private boolean clipping = false;
143 
144 /*
145 *********************
146 ** Constructors
147 ********************/
148 
149   /**
150   *  Instantiate an empty data set.
151   * @precondition
152   *     d != null
153   * @postcondition
154   *     dates_needed() && drawer() == drawer
155   */
156   public DataSet(BasicDrawer d) {
157     if (d  == null) {
158       throw new Error("DataSet constructor: precondition violated");
159     }
160     _drawer = d;
161     data = null;
162     date_drawer = new DateDrawer(d);
163     time_drawer = new TimeDrawer(d);
164     _dates_needed = true;
165     tuple_count = 0;
166   }
167 
168   /**
169   * Instantiate a DataSet with the parsed data.
170   * `d' contains a set of tuples flattened out into array elements -
171   * for example, for a 4-field tuple, d[0..3] are the fields of the
172   # first tuple, d[4..7] are the fields of the second tuple, etc.
173   * The integer n is the number of data Points. This means that the
174   * length of the data array is t*n, where t is the number of fields
175   * in a tuple.
176   * Note: `d' is expected to take y-position (vertical) data only;
177   * x-positions will be calculated based on the position of each
178   * tuple in `d' - from 1 to d.length.
179   * @param d Array containing the (y1,y2,...) data tuples.
180   * @param n Number of tuples in the array.
181   * @param drawer object used to draw the data.
182   * @precondition
183   *     d != null && d.length > 0 && n > 0 && drawer != null
184   * @postcondition
185   *     dates_needed() && drawer() == drawer
186   */
187   public DataSet(double d[], int n, BasicDrawer drawer) throws Error {
188     if ( d  == null || d.length == 0 || n <= 0 || drawer == null ) {
189       throw new Error("DataSet constructor: precondition violated");
190     }
191     int i;
192     _drawer = drawer;
193     date_drawer = new DateDrawer(drawer);
194     time_drawer = new TimeDrawer(drawer);
195     data = d;
196 
197     tuple_count = n;
198     _dates_needed = true;
199   }
200 
201 /*******************
202 ** Public Methods
203 ******************/
204 
205   // x axis
206   public Axis xaxis() { return xaxis_; }
207 
208   // y axis
209   public Axis yaxis() { return yaxis_; }
210 
211   // Color data is to be drawn in - can be null
212   public Color color() { return color_; }
213 
214   // Set the x axis to `a'.
215   public void set_xaxis(Axis a) { xaxis_ = a; }
216 
217   // Set the y axis to `a'.
218   public void set_yaxis(Axis a) { yaxis_ = a; }
219 
220   // Set the color the data is to be drawn in - can be null
221   public void set_color(Color c) { color_ = c; }
222 
223   // Add y1, y2 values for a horizontal line.
224   public void add_hline(DoublePair p) {
225     if (hline_data == null) hline_data = new Vector();
226     hline_data.addElement(p);
227   }
228 
229   // Add x1, x2 values for a vertical line.
230   public void add_vline(DoublePair p) {
231     if (vline_data == null) vline_data = new Vector();
232     vline_data.addElement(p);
233   }
234 
235   public void set_reference_values_needed (boolean b) {
236     _drawer.set_reference_values_needed (b);
237   }
238 
239   /**
240   * Draw the straight line segments and/or the markers at the
241   * data points.
242   * If this data has been attached to an Axis then scale the data
243   * based on the axis maximum/minimum otherwise scale using
244   * the data's maximum/minimum
245   * @param g Graphics state
246   * @param bounds The data window to draw into
247   */
248   public void draw_data(Graphics g, Rectangle bounds) {
249     boolean restore_bounds = false;
250     if (! range_set) range();
251     if ( linecolor != null) g.setColor(linecolor);
252     _drawer.set_data(data);
253     _drawer.set_xaxis(xaxis_);
254     _drawer.set_yaxis(yaxis_);
255     _drawer.set_maxes(xmax, ymax, xmin, ymin);
256     _drawer.set_ranges(xrange, yrange);
257     _drawer.set_clipping(clipping);
258     _drawer.draw_data(g, bounds, hline_data, vline_data, color_);
259   }
260 
261   /**
262   * return the data X maximum.
263   */
264   public double getXmax() {  return dxmax; } 
265   /**
266   * return the data X minimum.
267   */
268   public double getXmin() {  return dxmin; } 
269   /**
270   * return the data Y maximum.
271   */
272   public double getYmax() {  return dymax; } 
273   /**
274   * return the data Y minimum.
275   */
276   public double getYmin() {  return dymin; }
277 
278   /**
279   * Return the number of data points in the DataSet
280   * @return number of (x,y) points.
281   */
282   public int dataPoints() {  return length()/stride(); }
283 
284   /**
285   * get the data point at the parsed index. The first (x,y) pair
286   * is at index 0.
287   * @param index Data point index
288   * @return array containing the (x,y) pair.
289   */
290   public double[] getPoint(int index) {
291     int strd = stride();
292     double point[] = new double[strd];
293     int i = index*strd;
294     if( index < 0 || i > length()-strd ) return null;
295 
296     for(int j=0; j<strd; j++) point[j] = data[i+j];
297 
298     return point;
299   }
300 
301   /**
302   * Return the data point that is closest to the parsed (x,y) position
303   * @param x 
304   * @param y (x,y) position in data space. 
305   * @return array containing the closest data point.
306   */
307   public double[] getClosestPoint(double x, double y) {
308     double point[] = {0.0, 0.0, 0.0};
309     int i;
310     double xdiff, ydiff, dist2;
311     int strd = stride();
312 
313     xdiff = data[0] - x;
314     ydiff = data[1] - y;
315     point[0] = data[0];
316     point[1] = data[1];
317     point[2] = xdiff*xdiff + ydiff*ydiff;
318 
319     for(i=strd; i<length()-1; i+=strd) {
320       xdiff = data[i  ] - x;
321       ydiff = data[i+1] - y;
322       dist2 = xdiff*xdiff + ydiff*ydiff;
323       if(dist2 < point[2]) {
324         point[0] = data[i  ];
325         point[1] = data[i+1];
326         point[2] = dist2;
327       }
328     }
329 
330     return point;
331   }
332 
333   // set g2d to `b'.
334   protected void set_g2d(Graph g) { g2d_ = g; }
335 
336   // The `time_drawer', if there are times; otherwise the `date_drawer',
337   // if there are dates; otherwise null
338   protected TemporalDrawer temporal_drawer() {
339     TemporalDrawer result = null;
340 
341     if (times != null) result = time_drawer;
342     else if (dates != null) result = date_drawer;
343 
344     return result;
345   }
346 
347   /**
348   * Draw times, if they exist; otherwise date dates, if they exist.
349   * Precondition: temporal_drawer() != null implies
350   *    temporal_drawer().main_data_processed()
351   * @param g Graphics context
352   * @param w Data Window
353   */
354   protected void draw_dates(Graphics g, Rectangle w) {
355     TemporalDrawer drawer = temporal_drawer();
356     if (drawer != null && drawer.main_data_processed()) {
357       drawer.set_xaxis(xaxis_);
358       drawer.set_yaxis(yaxis_);
359       drawer.set_maxes(xmax, ymax, xmin, ymin);
360       drawer.set_ranges(xrange, yrange);
361       drawer.set_clipping(clipping);
362       drawer.draw_data(g, w);
363     }
364   }
365 
366   /**
367   * Calculate the range of the data. This modifies dxmin,dxmax,dymin,dymax
368   * and xmin,xmax,ymin,ymax
369   * Precondition: tuple_count has been set
370   */
371   protected void range() {
372     int i;
373     int lnth = length();
374     int stride = stride();
375 
376     if (lnth >= stride ) {
377       dymax = data[0];
378       dymin = dymax;
379       // The range for x follows the data index - starts at 1
380       // and ends at data.length.
381       dxmax = tuple_count;
382       dxmin = 1;
383     } else {
384       dxmin = 0.0;
385       dxmax = 0.0;
386       dymin = 0.0;
387       dymax = 0.0;
388     }
389 
390     // `data' holds only y values - find the largest and smallest.
391     for (i = 0; i < lnth; ++i) {
392       if( dymax < data[i] ) { dymax = data[i]; }
393       else if( dymin > data[i] ) { dymin = data[i]; }
394     }
395     if ( yaxis_ == null) {
396     ymin = dymin;
397     ymax = dymax;
398     }
399     if ( xaxis_ == null) {
400       xmin = dxmin;
401       xmax = dxmax;
402     }
403     range_set = true;
404   }
405 
406 /*
407 *********************
408 ** Protected Variables      
409 **********************/
410 
411   // Main data
412   private double[] data;
413 
414   // Date data
415   protected String[] dates;
416 
417   // Time data
418   protected String[] times;
419 
420   // Color data is to be drawn in - can be null
421   private Color color_;
422 
423   /**
424   * Drawer of price bars - e.g., tic bars or candles
425   */
426   private BasicDrawer _drawer;
427 
428   /**
429   * Drawer of dates
430   */
431   protected DateDrawer date_drawer;
432 
433   /**
434   * Drawer of times
435   */
436   private TimeDrawer time_drawer;
437 
438   /**
439   * The data X maximum. 
440   * Once the data is loaded this will never change.
441   */
442   private double dxmax;
443 
444   /**
445   * The data X minimum. 
446   * Once the data is loaded this will never change.
447   */
448   private double dxmin;
449 
450   /**
451   * The data Y maximum. 
452   * Once the data is loaded this will never change.
453   */
454   private double dymax;
455 
456   /**
457   * The data Y minimum. 
458   * Once the data is loaded this will never change.
459   */
460   private double dymin;
461 
462   // Horizontal, vertical line data
463   private Vector hline_data;
464   private Vector vline_data;
465 
466   /**
467   *    The X range of the clipped data
468   */
469   private double xrange;
470 
471   /**
472   *    The Y range of the clipped data
473   */
474   private double yrange;
475 
476   /**
477   *    The amount to increment the data array when the append method is being
478   *    used.
479   */
480   private int increment = 100;
481 
482   // Has range() been called to set the range?
483   private boolean range_set = false;
484 
485   // Number of tuples in the data
486   private int tuple_count;
487 
488   /**
489   * Number of components in a data tuple - for example, 2 (x, y) for
490   * a simple point
491   * @precondition
492   *    _drawer != null
493   */
494   protected int stride() { return _drawer.drawing_stride(); }
495 
496   protected int length() {
497     int result = 0;
498     if (data != null) result = data.length;
499     return result;
500   }
501 
502   private boolean _dates_needed;
503 }