source: ether_megapoli/trunk/applets/src/gov/noaa/pmel/sgt/GridCartesianRenderer.java @ 174

Last change on this file since 174 was 174, checked in by vmipsl, 13 years ago

Applets _ récupération des sources

File size: 17.8 KB
Line 
1/*
2 * $Id: GridCartesianRenderer.java,v 1.30 2003/08/22 23:02:32 dwd Exp $
3 *
4 * This software is provided by NOAA for full, free and open release.  It is
5 * understood by the recipient/user that NOAA assumes no liability for any
6 * errors contained in the code.  Although this software is released without
7 * conditions or restrictions in its use, it is expected that appropriate
8 * credit be given to its author and to the National Oceanic and Atmospheric
9 * Administration should the software be included by the recipient as an
10 * element in other product development.
11 */
12
13package  gov.noaa.pmel.sgt;
14
15import gov.noaa.pmel.sgt.dm.SGTGrid;
16import gov.noaa.pmel.sgt.dm.SGTData;
17import gov.noaa.pmel.sgt.contour.Contour;
18import gov.noaa.pmel.sgt.contour.ContourLine;
19
20import gov.noaa.pmel.util.GeoDate;
21import gov.noaa.pmel.util.Range2D;
22import gov.noaa.pmel.util.Point2D;
23import gov.noaa.pmel.util.Debug;
24
25import java.awt.Graphics;
26import java.awt.Color;
27import java.awt.Rectangle;
28import java.awt.Font;
29import java.awt.Point;
30import java.awt.FontMetrics;
31import java.util.Enumeration;
32import java.beans.PropertyChangeEvent;
33
34/**
35 * Produces a cartesian plot from a <code>SGTGrid</code> object.
36 *
37 * @author Donald Denbo
38 * @version $Revision: 1.30 $, $Date: 2003/08/22 23:02:32 $
39 * @since 1.0
40 */
41public class GridCartesianRenderer extends CartesianRenderer {
42  /**@shapeType AggregationLink
43   * @label grid
44   * @undirected
45   * @supplierCardinality 1*/
46  private SGTGrid grid_;
47  /**@shapeType AggregationLink
48   * @label attr
49   * @undirected
50   * @supplierCardinality 1*/
51  private GridAttribute attr_ = null;
52
53  /**
54   * @link aggregationByValue
55   * @supplierCardinality 1
56   * @label con
57   */
58  private Contour con_ = null;
59  //
60  private void drawRaster(Graphics g) {
61    int nT, nX, nY, nZ;
62    int[] xp, yp;
63    int i, j;
64    Color color;
65    int xSize, ySize, count;
66    double[] xValues, yValues, gValues;
67    double val;
68    GeoDate[] tValues;
69    //
70    if(grid_.isXTime()) {
71      if(grid_.getTimeArray().length <= 2) return;
72      if(grid_.hasXEdges()) {
73        tValues = grid_.getTimeEdges();
74        xSize = tValues.length;
75        xp = new int[xSize];
76        for(count=0; count < xSize; count++) {
77          xp[count] = cg_.getXUtoD(tValues[count]);
78        }
79      } else {
80        tValues = grid_.getTimeArray();
81        xSize = tValues.length;
82        xp = new int[xSize+1];
83        xp[0] = cg_.getXUtoD(tValues[0].subtract(
84                            (tValues[1].subtract(tValues[0])).divide(2.0)));
85        for(count=1; count < xSize; count++) {
86          xp[count] = cg_.getXUtoD(
87                    (tValues[count-1].add(tValues[count])).divide(2.0));
88        }
89        xp[xSize] = cg_.getXUtoD(tValues[xSize-1].add(
90                    (tValues[xSize-1].subtract(tValues[xSize-2])).divide(2.0)));
91      }
92    } else {
93      if(grid_.getXArray().length <= 2) return;
94      if(grid_.hasXEdges()) {
95        xValues = grid_.getXEdges();
96        xSize = xValues.length;
97        xp = new int[xSize];
98        for(count=0; count < xSize; count++) {
99          xp[count] = cg_.getXUtoD(xValues[count]);
100        }
101      } else {
102        xValues = grid_.getXArray();
103        xSize = xValues.length;
104        xp = new int[xSize+1];
105        xp[0] = cg_.getXUtoD(xValues[0]-(xValues[1]-xValues[0])*0.5);
106        for(count=1; count < xSize; count++) {
107          xp[count] = cg_.getXUtoD((xValues[count-1]+xValues[count])*0.5);
108        }
109        xp[xSize] = cg_.getXUtoD(xValues[xSize-1]+
110                                 (xValues[xSize-1]-xValues[xSize-2])*0.5);
111      }
112    }
113    if(grid_.isYTime()) {
114      if(grid_.getTimeArray().length <= 2) return;
115      if(grid_.hasYEdges()) {
116        tValues = grid_.getTimeEdges();
117        ySize = tValues.length;
118        yp = new int[ySize];
119        for(count=0; count < ySize; count++) {
120          yp[count] = cg_.getYUtoD(tValues[count]);
121        }
122      } else {
123        tValues = grid_.getTimeArray();
124        ySize = tValues.length;
125        yp = new int[ySize+1];
126        yp[0] = cg_.getYUtoD(tValues[0].subtract(
127                          (tValues[1].subtract(tValues[0])).divide(2.0)));
128        for(count=1; count < ySize; count++) {
129          yp[count] = cg_.getYUtoD((tValues[count-1].add(
130                               tValues[count])).divide(2.0));
131        }
132        yp[ySize] = cg_.getYUtoD(tValues[ySize-1].add(
133                     (tValues[ySize-1].subtract(tValues[ySize-2])).divide(2.0)));
134      }
135    } else {
136      if(grid_.getYArray().length <= 2) return;
137      if(grid_.hasYEdges()) {
138        yValues = grid_.getYEdges();
139        ySize = yValues.length;
140        yp = new int[ySize];
141        for(count=0; count < ySize; count++) {
142          yp[count] = cg_.getYUtoD(yValues[count]);
143        }
144      } else {
145        yValues = grid_.getYArray();
146        ySize = yValues.length;
147        yp = new int[ySize+1];
148        yp[0] = cg_.getYUtoD(yValues[0]-(yValues[1]-yValues[0])*0.5);
149        for(count=1; count < ySize; count++) {
150          yp[count] = cg_.getYUtoD((yValues[count-1]+yValues[count])*0.5);
151        }
152        yp[ySize] = cg_.getYUtoD(yValues[ySize-1]+
153                                 (yValues[ySize-1]-yValues[ySize-2])*0.5);
154      }
155    }
156    //
157    // draw raster
158    //
159    gValues = grid_.getZArray();
160    count=0;
161    for(i=0; i < xSize; i++) {
162      for(j=0; j < ySize; j++) {
163        val = gValues[count];
164        if(!Double.isNaN(val)) {
165          color = attr_.getColorMap().getColor(val);
166          g.setColor(color);
167          drawRect(g, xp[i], yp[j], xp[i+1], yp[j+1]);
168        }
169        count++;
170      }
171    }
172  }
173  /**
174   * Get the <code>Attribute</code> associated with
175   * the <code>SGTGrid</code> data.
176   *
177   * @return <code>Attribute</code>
178   */
179  public Attribute getAttribute() {
180    return attr_;
181  }
182  /**
183   * Set the <code>GridAttribute</code> for the renderer.
184   * @since 2.0
185   */
186  public void setAttribute(GridAttribute attr) {
187    if(attr_ != null) attr_.removePropertyChangeListener(this);
188    attr_ = attr;
189    attr_.addPropertyChangeListener(this);
190  }
191  private void drawRect(Graphics g,int x1,int y1,int x2,int y2) {
192    int x, y, width, height;
193    if(x1 < x2) {
194      x = x1;
195      width = x2 - x1;
196    } else {
197      x=x2;
198      width = x1 - x2;
199    }
200    if(y1 < y2) {
201      y = y1;
202      height = y2 - y1;
203    } else {
204      y = y2;
205      height = y1 - y2;
206    }
207    g.fillRect(x, y, width, height);
208  }
209  /**
210   * Default constructor. The <code>GridCartesianRenderer</code> should
211   * be created using the <code>CartesianRenderer.getRenderer</code>
212   * method.
213   *
214   * @see CartesianRenderer#getRenderer
215   * @see Graph
216   **/
217  public GridCartesianRenderer(CartesianGraph cg) {
218    this(cg, null, null);
219  }
220  /**
221   * Construct a <code>GridCartesianRenderer</code>.
222   * The <code>GridCartesianRenderer</code> should
223   * be created using the <code>CartesianRenderer.getRenderer</code>
224   * method.
225   *
226   * @see CartesianRenderer#getRenderer
227   * @see Graph
228   **/
229  public GridCartesianRenderer(CartesianGraph cg, SGTGrid data) {
230    this(cg, data, null);
231  }
232  /**
233   * Construct a <code>GridCartesianRenderer</code>.
234   * The <code>GridCartesianRenderer</code> should
235   * be created using the <code>CartesianRenderer.getRenderer</code>
236   * method.
237   *
238   * @see CartesianRenderer#getRenderer
239   * @see Graph
240   **/
241  public GridCartesianRenderer(CartesianGraph cg, SGTGrid grid, GridAttribute attr) {
242    cg_ = cg;
243    grid_ = grid;
244    attr_ = attr;
245    if(attr_ != null) attr_.addPropertyChangeListener(this);
246  }
247  /**
248   * Render the <code>SGTData</code>. This method should not
249   * be directly called.
250   *
251   * @param g graphics context
252   *
253   * @see Pane#draw
254   */
255  public void draw(Graphics g) {
256    if(cg_.clipping_) {
257      int xmin, xmax, ymin, ymax;
258      int x, y, width, height;
259      if(cg_.xTransform_.isSpace()) {
260        xmin = cg_.getXUtoD(cg_.xClipRange_.start);
261        xmax = cg_.getXUtoD(cg_.xClipRange_.end);
262      } else {
263        xmin = cg_.getXUtoD(cg_.tClipRange_.start);
264        xmax = cg_.getXUtoD(cg_.tClipRange_.end);
265      }
266      if(cg_.yTransform_.isSpace()) {
267        ymin = cg_.getYUtoD(cg_.yClipRange_.start);
268        ymax = cg_.getYUtoD(cg_.yClipRange_.end);
269      } else {
270        ymin = cg_.getYUtoD(cg_.tClipRange_.start);
271        ymax = cg_.getYUtoD(cg_.tClipRange_.end);
272      }
273      if(xmin < xmax) {
274        x = xmin;
275        width = xmax - xmin;
276      } else {
277        x=xmax;
278        width = xmin - xmax;
279      }
280      if(ymin < ymax) {
281        y = ymin;
282        height = ymax - ymin;
283      } else {
284        y = ymax;
285        height = ymin - ymax;
286      }
287      g.setClip(x, y, width, height);
288    }
289    if(attr_.isRaster()) {
290      drawRaster(g);
291    }
292    if(attr_.isAreaFill()) {
293      //
294      // This is a temporary method based on the
295      // PPLUS area fill algorthim
296      //
297      // To be replaced by a area fill method that
298      // uses the ContourLines
299      //
300      double[] x = xArrayP();
301      double[] y = yArrayP();
302      double[] z = grid_.getZArray();
303      int i,j;
304      int nx = x.length;
305      int ny = y.length;
306      double[] xt = new double[5];
307      double[] yt = new double[5];
308      double[] zt = new double[5];
309      for(i=0; i < nx-1; i++) {
310        for(j=0; j < ny-1; j++) {
311          xt[0] = x[i];
312          yt[0] = y[j];
313          zt[0] = z[j + i*ny];
314          //
315          xt[1] = x[i+1];
316          yt[1] = y[j];
317          zt[1] = z[j + (i+1)*ny];
318          //
319          xt[2] = x[i+1];
320          yt[2] = y[j+1];
321          zt[2] = z[j+1 + (i+1)*ny];
322          //
323          xt[3] = xt[0];
324          yt[3] = yt[2];
325          zt[3] = z[j+1 + i*ny];
326          //
327          // repeat first point
328          //
329          xt[4] = xt[0];
330          yt[4] = yt[0];
331          zt[4] = zt[0];
332          //
333          fillSquare(g, xt, yt, zt);
334        }
335      }
336    }
337    if(attr_.isContour()) {
338      double val;
339      String label;
340      Range2D range = computeRange(10);
341      Format format;
342      //        con_ = new Contour(cg_, grid_, range);
343      con_ = new Contour(cg_, grid_, attr_.getContourLevels());
344      ContourLevels clevels = con_.getContourLevels();
345      DefaultContourLineAttribute attr;
346      //
347      // set labels
348      //
349      for(int i=0; i < clevels.size(); i++) {
350        try {
351          val = clevels.getLevel(i);
352          attr = clevels.getDefaultContourLineAttribute(i);
353          if(attr.isAutoLabel()) {
354            if(attr.getLabelFormat().length() <= 0) {
355              format  = new Format(Format.computeFormat(range.start,
356                                                        range.end,
357                                                        attr.getSignificantDigits()));
358            } else {
359              format = new Format(attr.getLabelFormat());
360            }
361            label = format.form(val);
362            attr.setLabelText(label);
363          }
364        } catch (ContourLevelNotFoundException e) {
365          System.out.println(e);
366        }
367      }
368      con_.generateContourLines();
369      con_.generateContourLabels(g);
370      Enumeration elem = con_.elements();
371      ContourLine cl;
372      while(elem.hasMoreElements()) {
373        cl = (ContourLine)elem.nextElement();
374        if(Debug.CONTOUR) {
375          System.out.println(" level = " + cl.getLevel() +
376                             ", length = " + cl.getKmax() +
377                             ", closed = " + cl.isClosed());
378        }
379        cl.draw(g);
380      }
381    }
382    //
383    // reset clip
384    //
385    Rectangle rect = cg_.getLayer().getPane().getBounds();
386    g.setClip(rect);
387  }
388
389  private void fillSquare(Graphics g, double[] x,
390                          double[] y, double[] z) {
391    ContourLevels clevels = attr_.getContourLevels();
392    IndexedColor cmap = (IndexedColor)attr_.getColorMap();
393    int i,j,cindex, npoly, maxindex;
394    double zlev, zlevp1, f;
395    Color col;
396    double[] xpoly = new double[20];
397    double[] ypoly = new double[20];
398    double zmin = Math.min(z[0], z[1]);
399    double zmax = Math.max(z[0], z[1]);
400    for(i=2; i <= 3; i++) {
401      zmin = Math.min(zmin, z[i]);
402      zmax = Math.max(zmax, z[i]);
403    }
404    if(Double.isNaN(zmax)) return;
405    maxindex = clevels.getMaximumIndex();
406    for(cindex=-1; cindex <= maxindex; cindex++) {
407      try {
408        if(cindex == -1) {
409          zlev = -Double.MAX_VALUE;
410        } else {
411          zlev = clevels.getLevel(cindex);
412        }
413        if(cindex == maxindex) {
414          zlevp1 = Double.MAX_VALUE;
415        } else {
416          zlevp1 = clevels.getLevel(cindex+1);
417        }
418      } catch (ContourLevelNotFoundException e) {
419        System.out.println(e);
420        break;
421      }
422      col = cmap.getColorByIndex(cindex+1);
423      if(zmin > zlevp1 || zmax < zlev) continue;
424      if(zmin >= zlev && zmax <= zlevp1) {
425        fillPolygon(g, col, x, y, 4);
426        return;
427      }
428      npoly = -1;
429      for(j=0; j < 4; j++) {  /* sides */
430        if(z[j] < zlev) {
431          //
432          // z[j] is below
433          //
434          if(z[j+1] > zlevp1) {
435            //
436            // z[j+1] is above
437            //
438            npoly=npoly+1;
439            f = (z[j]-zlev)/(z[j]-z[j+1]);
440            xpoly[npoly] = x[j] - f*(x[j]-x[j+1]);
441            ypoly[npoly] = y[j] - f*(y[j]-y[j+1]);
442            //
443            npoly=npoly+1;
444            f = (z[j]-zlevp1)/(z[j]-z[j+1]);
445            xpoly[npoly] = x[j] - f*(x[j]-x[j+1]);
446            ypoly[npoly] = y[j] - f*(y[j]-y[j+1]);
447          } else if(z[j+1] >= zlev &&
448                    z[j+1] <= zlevp1) {
449            //
450            // z[j+1] is inside
451            //
452            npoly=npoly+1;
453            f = (z[j]-zlev)/(z[j]-z[j+1]);
454            xpoly[npoly] = x[j] - f*(x[j]-x[j+1]);
455            ypoly[npoly] = y[j] - f*(y[j]-y[j+1]);
456            //
457            npoly=npoly+1;
458            xpoly[npoly] = x[j+1];
459            ypoly[npoly] = y[j+1];
460          }
461        } else if(z[j] > zlevp1) {
462          //
463          // z[j] is above
464          //
465          if(z[j+1] < zlev) {
466            //
467            // z[j+1] is below
468            //
469            npoly=npoly+1;
470            f = (z[j]-zlevp1)/(z[j]-z[j+1]);
471            xpoly[npoly] = x[j] - f*(x[j]-x[j+1]);
472            ypoly[npoly] = y[j] - f*(y[j]-y[j+1]);
473            //
474            npoly=npoly+1;
475            f = (z[j]-zlev)/(z[j]-z[j+1]);
476            xpoly[npoly] = x[j] - f*(x[j]-x[j+1]);
477            ypoly[npoly] = y[j] - f*(y[j]-y[j+1]);
478          } else if(z[j+1] >= zlev && z[j+1] <= zlevp1) {
479            //
480            // z[j+1] is inside
481            //
482            npoly=npoly+1;
483            f = (z[j]-zlevp1)/(z[j]-z[j+1]);
484            xpoly[npoly] = x[j] - f*(x[j]-x[j+1]);
485            ypoly[npoly] = y[j] - f*(y[j]-y[j+1]);
486            //
487            npoly=npoly+1;
488            xpoly[npoly] = x[j+1];
489            ypoly[npoly] = y[j+1];
490          }
491        } else {
492          //
493          // x[j] is inside
494          //
495          if(z[j+1] > zlevp1) {
496            //
497            // z[j+1] is above
498            //
499            npoly=npoly+1;
500            f = (z[j]-zlevp1)/(z[j]-z[j+1]);
501            xpoly[npoly] = x[j] - f*(x[j]-x[j+1]);
502            ypoly[npoly] = y[j] - f*(y[j]-y[j+1]);
503          } else if(z[j+1] < zlev) {
504            //
505            // z[j+1] is below
506            //
507            npoly=npoly+1;
508            f = (z[j]-zlev)/(z[j]-z[j+1]);
509            xpoly[npoly] = x[j] - f*(x[j]-x[j+1]);
510            ypoly[npoly] = y[j] - f*(y[j]-y[j+1]);
511          } else {
512            //
513            // z[j+1] is inside
514            //
515            npoly=npoly+1;
516            xpoly[npoly] = x[j+1];
517            ypoly[npoly] = y[j+1];
518          }
519        }
520      }
521      fillPolygon(g, col, xpoly, ypoly, npoly+1);
522    }
523  }
524
525  private void fillPolygon(Graphics g, Color c,
526                           double[] x, double[] y,
527                           int npoints) {
528    Layer layer = cg_.getLayer();
529    int[] xt = new int[20];
530    int[] yt = new int[20];
531    g.setColor(c);
532    for(int i=0; i < npoints; i++) {
533      xt[i] = layer.getXPtoD(x[i]);
534      yt[i] = layer.getYPtoD(y[i]);
535    }
536    g.fillPolygon(xt, yt, npoints);
537  }
538
539  private double[] xArrayP() {
540    int i;
541    double[] p;
542    if(grid_.isXTime()) {
543      GeoDate[] t = grid_.getTimeArray();
544      p = new double[t.length];
545      for(i=0; i < t.length; i++) {
546        p[i] = cg_.getXUtoP(t[i]);
547      }
548    } else {
549      double[] x = grid_.getXArray();
550      p = new double[x.length];
551      for(i=0; i < x.length; i++) {
552        p[i] = cg_.getXUtoP(x[i]);
553      }
554    }
555    return p;
556  }
557
558  private double[] yArrayP() {
559    int i;
560    double[] p;
561    if(grid_.isYTime()) {
562      GeoDate[] t = grid_.getTimeArray();
563      p = new double[t.length];
564      for(i=0; i < t.length; i++) {
565        p[i] = cg_.getYUtoP(t[i]);
566      }
567    } else {
568      double[] y = grid_.getYArray();
569      p = new double[y.length];
570      for(i=0; i < y.length; i++) {
571        p[i] = cg_.getYUtoP(y[i]);
572      }
573    }
574    return p;
575  }
576
577  private Range2D computeRange(int levels) {
578    Range2D range;
579    double zmin = Double.POSITIVE_INFINITY;
580    double zmax = Double.NEGATIVE_INFINITY;
581    double[] array = grid_.getZArray();
582    for(int i=0; i < array.length; i++) {
583      if(!Double.isNaN(array[i])) {
584        zmin = Math.min(zmin, array[i]);
585        zmax = Math.max(zmax, array[i]);
586      }
587    }
588    range = Graph.computeRange(zmin, zmax, levels);
589    return range;
590  }
591  /**
592   * Get the <code>SGTGrid</code>.
593   *
594   * @return <code>SGTGrid</code>
595   */
596  public SGTGrid getGrid() {
597    return grid_;
598  }
599  /**
600   * Get the associated <code>CartesianGraph</code> object.
601   * @since 2.0
602   * @return <code>CartesianGraph</code>
603   */
604  public CartesianGraph getCartesianGraph() {
605    return cg_;
606  }
607
608  public void propertyChange(PropertyChangeEvent evt) {
609//      if(Debug.EVENT) {
610//        System.out.println("GridCartesianRenderer: " + evt);
611//        System.out.println("                       " + evt.getPropertyName());
612//      }
613    modified("GridCartesianRenderer: propertyChange(" +
614             evt.getSource().toString() + "[" +
615             evt.getPropertyName() + "]" + ")");
616  }
617  /**
618   * @since 3.0
619   */
620  public SGTData getDataAt(Point pt) {
621    return null;
622  }
623}
Note: See TracBrowser for help on using the repository browser.