source: ether_megapoli/trunk/service/implementation/gov2/noaa/pmel/sgt/VectorCartesianRenderer.java @ 192

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

Servlet _ Contour en cours _ package gov2

File size: 13.1 KB
Line 
1/*
2 * $Id: VectorCartesianRenderer.java,v 1.12 2002/06/26 23:18:23 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.SGTVector;
16import gov.noaa.pmel.sgt.dm.SGTData;
17import gov.noaa.pmel.sgt.dm.Collection;
18
19import gov.noaa.pmel.util.GeoDate;
20import gov.noaa.pmel.util.Debug;
21
22import java.awt.Graphics2D;
23import java.awt.BasicStroke;
24import java.awt.Stroke;
25import java.awt.geom.GeneralPath;
26//import java.awt.geom.AffineTransform;
27
28import java.util.Vector;
29import java.util.Enumeration;
30import java.awt.Graphics;
31import java.awt.Event;
32import java.awt.Point;
33import java.awt.Color;
34import java.awt.Rectangle;
35import java.beans.PropertyChangeEvent;
36
37/**
38 * Produces a vector plot.  If
39 * a second data set is specified it must have the same shape as the first.
40 *
41 * @author Donald Denbo
42 * @version $Revision: 1.12 $, $Date: 2002/06/26 23:18:23 $
43 * @since 2.1
44 */
45public class VectorCartesianRenderer extends CartesianRenderer {
46  /**
47   * @link aggregation
48   * @label attr
49   */
50  private VectorAttribute attr_ = null;
51
52  /**
53   * @link aggregation
54   * @label vector
55   */
56  private SGTVector vector_ = null;
57  private Collection collection_ = null;
58  private float slope_;
59  private float xoff_;
60  private float yoff_;
61
62  /**
63   * Get the <code>Attribute</code> associated with the data.
64   */
65  public Attribute getAttribute() {
66    return attr_;
67  }
68
69  private void drawVector(Graphics g, SGTVector vector,
70                          VectorAttribute attr) {
71
72    Layer ly = cg_.getLayer();
73    Graphics2D g2 = (Graphics2D)g;
74    slope_ = (float)ly.getXSlope();
75    xoff_ = (float)ly.getXOffset();
76    yoff_ = (float)ly.getYOffset();
77    GeneralPath gp = null;
78    Stroke savedStroke = g2.getStroke();
79    BasicStroke stroke = new BasicStroke(attr_.getWidth(),
80                                         attr_.getCapStyle(),
81                                         attr_.getMiterStyle(),
82                                         attr_.getMiterLimit());
83    g2.setStroke(stroke);
84    //
85    // a 1 unit lenght vector with a headScale of 1.0 will
86    // create a head barb that is 1.05948 long.  A factor of
87    // 0.94386 is required to remove this effect
88    //
89    float scale = (float)attr_.getVectorScale();
90    float headScale = (float)attr_.getHeadScale()*0.94386f;
91    float fixedScale = (float)(headScale*attr_.getHeadFixedSize());
92    float minSize = (float)attr_.getHeadMinSize();
93    float maxSize = (float)attr_.getHeadMaxSize();
94    double angle = attr_.getOffsetAngle()*0.017453293;
95    float tScale;
96    float[] xp, yp;
97    int[] xtail, ytail;
98    int xdhead, ydhead;
99    int xdtemp, ydtemp;
100    float xphead, yphead;
101    int count, size, nout, idx;
102    double[] xValues, yValues;
103    GeoDate[] xTValues, yTValues;
104    double[] uValues, vValues;
105    float vx, vy, vclen;
106    double vdx, vdy;
107
108    float hx1, hx2;
109    float hy1, hy2;
110    float headX, headY;
111    float orgX, orgY;
112    //
113    // get axes
114    //
115    if(vector.isXTime()) {
116      xTValues = vector.getU().getTimeArray();
117      size = xTValues.length;
118      xp = new float[size];
119      for(count=0; count < size; count++) {
120        xp[count] = (float)cg_.getXUtoP(xTValues[count]);
121      }
122    } else {
123      xValues = vector.getU().getXArray();
124      size = xValues.length;
125      xp = new float[size];
126      for(count=0; count < size; count++) {
127        xp[count] = (float)cg_.getXUtoP(xValues[count]);
128      }
129    }
130    //
131    if(vector.isYTime()) {
132      yTValues = vector.getU().getTimeArray();
133      size = yTValues.length;
134      yp = new float[size];
135      for(count=0; count < size; count++) {
136        yp[count] = (float)cg_.getYUtoP(yTValues[count]);
137      }
138    } else {
139      yValues = vector.getU().getYArray();
140      size = yValues.length;
141      yp = new float[size];
142      for(count=0; count < size; count++) {
143        yp[count] = (float)cg_.getYUtoP(yValues[count]);
144      }
145    }
146    //
147    // get u & v
148    //
149    uValues = vector.getU().getZArray();
150    vValues = vector.getV().getZArray();
151    //
152    xtail = new int[uValues.length];
153    ytail = new int[uValues.length];
154    count = 0;
155//    int nx = xp.length;
156    int ny = yp.length;
157    int idx_ny;
158    for(int i=0; i < xp.length; i++) {
159      idx_ny = i*ny;
160      for(int j=0; j < yp.length; j++) {
161        idx = j + idx_ny;
162        if(Double.isNaN(uValues[idx]) || Double.isNaN(vValues[idx])) continue;
163        orgX = xPtoD(xp[i]);
164        orgY = yPtoD(yp[j]);
165        xtail[count] = (int)orgX;
166        ytail[count] = (int)orgY;
167        vdx = uValues[idx]*scale;
168        vdy = vValues[idx]*scale;
169        if(angle != 0.0) {
170          vx = (float)(vdx*Math.cos(angle)-vdy*Math.sin(angle));
171          vy = (float)(vdy*Math.cos(angle)+vdx*Math.sin(angle));
172        } else {
173          vx = (float)vdx;
174          vy = (float)vdy;
175        }
176        xphead = xp[i] + vx;
177        yphead = yp[j] + vy;
178        //
179        // draw line
180        //
181        gp = new GeneralPath();
182        gp.moveTo(orgX, orgY);
183        headX = xPtoD(xphead);
184        headY = yPtoD(yphead);
185        gp.lineTo(headX, headY);
186        //
187        // draw head
188        //
189        //        if(true) continue;
190        vclen = (float)Math.sqrt((double)(vx*vx+vy*vy));
191        if(vclen == 0.0) {
192          g.drawLine((int)headX, (int)headY, (int)headX, (int)headY);
193        } else {
194          if(attr_.getVectorStyle() != VectorAttribute.NO_HEAD) {
195            if(attr_.getVectorStyle() == VectorAttribute.HEAD) {
196              // unscaled head
197              tScale = fixedScale/vclen;
198              hx1 = xPtoD(xphead + (-vx-0.35f*vy)*tScale);
199              hy1 = yPtoD(yphead + (-vy+0.35f*vx)*tScale);
200              hx2 = xPtoD(xphead + (-vx+0.35f*vy)*tScale);
201              hy2 = yPtoD(yphead + (-vy-0.35f*vx)*tScale);
202              gp.moveTo(hx1, hy1);
203              gp.lineTo(headX, headY);
204              gp.lineTo(hx2, hy2);
205            } else {
206              // scaled head
207              if(vclen >= maxSize) {
208                tScale = maxSize*headScale/vclen;
209              } else if(vclen <= minSize) {
210                tScale = minSize*headScale/vclen;
211              } else {
212                tScale = headScale;
213              }
214              hx1 = xPtoD(xphead + (-vx-0.35f*vy)*tScale);
215              hy1 = yPtoD(yphead + (-vy+0.35f*vx)*tScale);
216              hx2 = xPtoD(xphead + (-vx+0.35f*vy)*tScale);
217              hy2 = yPtoD(yphead + (-vy-0.35f*vx)*tScale);
218              gp.moveTo(hx1, hy1);
219              gp.lineTo(headX, headY);
220              gp.lineTo(hx2, hy2);
221            }
222          }
223        }
224        count++;
225        g2.draw(gp);
226      }
227    }
228    g2.setStroke(savedStroke);
229    //
230    // draw mark
231    //
232    if(attr_.getOriginStyle() == VectorAttribute.MARK) {
233      g.setColor(attr_.getMarkColor());
234      drawMark(g, xtail, ytail, xtail.length, attr_);
235    }
236  }
237
238  private float xPtoD(float xp) {
239    return slope_*xp + xoff_;
240  }
241
242  private float yPtoD(float yp) {
243    return yoff_ - slope_*yp;
244  }
245  /**
246   * Draw a mark at the requested location. This routine is used by
247   * VectorCartesianGraph and VectorKey.
248   *
249   * @param g Graphics object
250   * @param xp horizontal coordinate
251   * @param yp vertical coordinate
252   * @param attr vector attribute
253   * @see VectorKey
254   */
255  protected void drawMark(Graphics g, int[] xp, int[] yp,
256                          int npoints, VectorAttribute attr) {
257    Layer ly = cg_.getLayer();
258
259    PlotMark pm = new PlotMark(attr.getMark());
260    pm.setMarkHeightP(attr.getMarkHeightP());
261
262    for(int i=0; i < npoints; i++) {
263      pm.paintMark(g, ly, xp[i], yp[i]);
264    }
265  }
266
267  /**
268   * Default constructor.
269   *
270   * @see CartesianGraph
271   * @see Graph
272   **/
273  public VectorCartesianRenderer(CartesianGraph cg) {
274    this(cg, (SGTVector)null, null);
275  }
276  /**
277   * Construct a <code>VectorCartesianRenderer</code>. The default
278   * <code>VectorAttribute</code> will be used.
279   *
280   * @param cg the parent <code>CartesianGraph</code>
281   * @param data an <code>SGTVector</code> object
282   *
283   * @see CartesianGraph
284   * @see Graph
285   **/
286  public VectorCartesianRenderer(CartesianGraph cg, SGTVector vector) {
287    this(cg, vector, null);
288    cg_ = cg;
289    vector_ = vector;
290  }
291  /**
292   * Construct a <code>VectorCartesianRenderer</code>.
293   *
294   * @param cg the parent <code>CartesianGraph</code>
295   * @param vector a <code>SGTVector</code>
296   * @param attr the <code>VectorAttribute</code>
297   * @see CartesianGraph
298   * @see Graph
299   **/
300  public VectorCartesianRenderer(CartesianGraph cg,
301                                 SGTVector vector,
302                                 VectorAttribute attr) {
303    cg_ = cg;
304    vector_ = vector;
305    attr_ = attr;
306    if(attr_ != null) attr_.addPropertyChangeListener(this);
307  }
308  /**
309   * Construct a <code>VectorCartesianRenderer</code>.
310   *
311   * @param cg the parent <code>CartesianGraph</code>
312   * @param col a <code>Collection</code> of <code>SGTVector</code> objects
313   * @param attr the <code>VectorAttribute</code>
314   * @see CartesianGraph
315   * @see Graph
316   **/
317  public VectorCartesianRenderer(CartesianGraph cg, Collection col,
318                                 VectorAttribute attr) {
319    cg_ = cg;
320    collection_ = col;
321    attr_ = attr;
322    if(attr_ != null) attr_.addPropertyChangeListener(this);
323  }
324  /**
325   * Render the <code>SGTData</code>. This method should not
326   * be directly called.
327   *
328   * @param g graphics context
329   *
330   * @see Pane#draw
331   */
332  public void draw(Graphics g) {
333    VectorAttribute attr;
334    Object vector;
335
336    if(cg_.clipping_) {
337      int xmin, xmax, ymin, ymax;
338      int x, y, width, height;
339      if(cg_.xTransform_.isSpace()) {
340        xmin = cg_.getXUtoD(cg_.xClipRange_.start);
341        xmax = cg_.getXUtoD(cg_.xClipRange_.end);
342      } else {
343        xmin = cg_.getXUtoD(cg_.tClipRange_.start);
344        xmax = cg_.getXUtoD(cg_.tClipRange_.end);
345      }
346      if(cg_.yTransform_.isSpace()) {
347        ymin = cg_.getYUtoD(cg_.yClipRange_.start);
348        ymax = cg_.getYUtoD(cg_.yClipRange_.end);
349      } else {
350        ymin = cg_.getYUtoD(cg_.tClipRange_.start);
351        ymax = cg_.getYUtoD(cg_.tClipRange_.end);
352      }
353      if(xmin < xmax) {
354        x = xmin;
355        width = xmax - xmin;
356      } else {
357        x=xmax;
358        width = xmin - xmax;
359      }
360      if(ymin < ymax) {
361        y = ymin;
362        height = ymax - ymin;
363      } else {
364        y = ymax;
365        height = ymin - ymax;
366      }
367      g.setClip(x, y, width, height);
368    }
369    if(attr_ == null) {
370      attr = new VectorAttribute(1.0,
371                                 cg_.getPane().getComponent().getForeground());
372    } else {
373      attr = attr_;
374    }
375    g.setColor(attr.getVectorColor());
376    if(collection_ == null) {
377      drawVector(g, vector_, attr);
378    } else {
379      for(Enumeration li = collection_.elements(); li.hasMoreElements();) {
380        vector = li.nextElement();
381        if(vector instanceof SGTVector) {
382          drawVector(g, (SGTVector)vector, attr);
383        }
384      }
385    }
386
387    //
388    // reset clip
389    //
390    Rectangle rect = cg_.getLayer().getPane().getBounds();
391    g.setClip(rect);
392  }
393  /**
394   * Set the <code>VectorAttribute</code>. The line appearance is controlled by
395   * this object.
396   *
397   * @param l <code>VectorAttribute</code>
398   **/
399  public void setVectorAttribute(VectorAttribute l) {
400    if(attr_ != null) attr_.removePropertyChangeListener(this);
401    attr_ = l;
402    if(attr_ != null) attr_.addPropertyChangeListener(this);
403  }
404  /**
405   * Get the <code>VectorAttribute</code>.
406   *
407   * @return <code>VectorAttribute</code>
408   **/
409  public VectorAttribute getVectorAttribute() {
410    return attr_;
411  }
412  /**
413   * Test if a <code>Collection</code> of <code>SGTVector</code>
414   * was using to construct this renderer.
415   *
416   * @return true if <code>Collection</code> was used
417   */
418  public boolean hasCollection() {
419    return (collection_ != null);
420  }
421  /**
422   * Get the <code>Collection</code> of <code>SGTVector</code> objects.
423   *
424   * @return <code>Collection</code>
425   */
426  public Collection getCollection() {
427    return collection_;
428  }
429  /**
430   * Get the <code>SGTVector</code> object.
431   *
432   * @return <code>SGTVector</code>
433   */
434  public SGTVector getVector(){
435    return vector_;
436  }
437  /**
438   * Get the associated <code>CartesianGraph</code> object.
439   *
440   * @return <code>CartesianGraph</code>
441   */
442  public CartesianGraph getCartesianGraph() {
443    return cg_;
444  }
445
446  public void propertyChange(PropertyChangeEvent evt) {
447    //      if(Debug.EVENT) {
448    //        System.out.println("VectorCartesianRenderer: " + evt);
449    //        System.out.println("                       " + evt.getPropertyName());
450    //      }
451    modified("VectorCartesianRenderer: propertyChange(" +
452             evt.getSource().toString() + "[" +
453             evt.getPropertyName() + "]" + ")");
454  }
455  public SGTData getDataAt(Point pt) {
456    return null;
457  }
458}
Note: See TracBrowser for help on using the repository browser.