source: ether_statistics/service/implementation/gov/noaa/pmel/sgt/contour/Contour.java @ 569

Last change on this file since 569 was 569, checked in by vmipsl, 12 years ago

Nouveau projet

File size: 24.8 KB
Line 
1/*
2 * $Id: Contour.java,v 1.15 2001/08/03 22:50:12 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.contour;
14
15import gov.noaa.pmel.sgt.CartesianGraph;
16import gov.noaa.pmel.sgt.ContourLineAttribute;
17import gov.noaa.pmel.sgt.DefaultContourLineAttribute;
18import gov.noaa.pmel.sgt.SGLabel;
19import gov.noaa.pmel.sgt.LayerNotFoundException;
20import gov.noaa.pmel.sgt.ContourLevels;
21import gov.noaa.pmel.sgt.ContourLevelNotFoundException;
22
23import gov.noaa.pmel.sgt.dm.SGTGrid;
24
25import gov.noaa.pmel.util.Range2D;
26import gov.noaa.pmel.util.Point2D;
27import gov.noaa.pmel.util.GeoDate;
28import gov.noaa.pmel.util.Debug;
29
30import java.awt.Graphics;
31import java.awt.Color;
32import java.awt.Font;
33import java.awt.FontMetrics;
34
35import java.util.Vector;
36import java.util.Enumeration;
37import java.beans.PropertyChangeListener;
38import java.beans.PropertyChangeEvent;
39
40/**
41 * Contour constructs a set of <code>ContourLine</code> objects based on
42 * the <code>ContourLevels</code>, <code>SGTGrid</code>, and mask
43 * supplied. Used by
44 * <code>GridCartesianRenderer</code> for <code>GridAttribute</code>
45 * types of CONTOUR.
46 *
47 * @author D. W. Denbo
48 * @version $Revision: 1.15 $, $Date: 2001/08/03 22:50:12 $
49 * @since 2.0
50 * @see ContourLine
51 * @see ContourLevels
52 * @see gov.noaa.pmel.sgt.GridCartesianRenderer
53 * @see gov.noaa.pmel.sgt.GridAttribute
54 * @see ContourLineAttribute
55 * @see DefaultContourLineAttribute
56 */
57public class Contour implements PropertyChangeListener {
58  /**
59   * @label grid
60   */
61  private SGTGrid grid_;
62  /**
63   * A non-zero mask value will cause a point to be excluded.
64   * @label mask
65   */
66  private SGTGrid mask_;
67  private CartesianGraph cg_;
68  /**
69   * @label contourLevels
70   */
71  private ContourLevels contourLevels_;
72  private double zmin_;
73  private double zmax_;
74  private boolean upToDate_;
75  private GeoDate tref_ = null;
76  private boolean xTime_ = false;
77  private boolean yTime_ = false;
78  private double[] px_;
79  private double[] py_;
80  private double[] z_;
81  private double[] xx_;
82  private double[] yy_;
83  private double[] zz_;
84  private boolean[] used_;
85  private int[] kabov_;
86  private int[] isin_ = {0, 1, 0, -1};
87  private double weezee_;
88  private int nx_;
89  private int ny_;
90
91  /**
92   * @associates <oiref:gov.noaa.pmel.sgt.contour.ContourLine:oiref>
93   * @link aggregation
94   * @supplierCardinality 1..*
95   * @label contourLines
96   */
97  private Vector contourLines_;
98
99  /**
100   * @link aggregationByValue
101   * @supplierCardinality 1
102   * @label sides
103   */
104  private Sides sides_;
105
106  /**
107   * @link aggregationByValue
108   * @supplierCardinality 1
109   * @label gridFlag
110   */
111  private GridFlag gridFlag_;
112  //
113  private static double DSLAB = 2.0;
114  private static double SLAB1F = 0.4;
115  /**
116   * Construct a <code>Contour</code> object using a range to define
117   * the <code>ContourLevels</code>.
118   */
119  public Contour(CartesianGraph cg, SGTGrid grid, Range2D range) {
120    cg_ = cg;
121    grid_ = grid;
122    contourLevels_ = ContourLevels.getDefault(range);
123    init();
124    upToDate_ = false;
125  }
126  /**
127   * Construct a <code>Contour</code> object using an array of levels to define
128   * the <code>ContourLevels</code>.
129   */
130  public Contour(CartesianGraph cg, SGTGrid grid, double[] levels) {
131    cg_ = cg;
132    grid_ = grid;
133    contourLevels_ = ContourLevels.getDefault(levels);
134    init();
135    upToDate_ = false;
136  }
137
138  /**
139   * Construct a <code>Contour</code> object using a
140   * <code>ContourLevels</code> object.
141   */
142  public Contour(CartesianGraph cg, SGTGrid grid, ContourLevels conLevels) {
143    cg_ = cg;
144    grid_ = grid;
145    contourLevels_ = conLevels;
146    contourLevels_.addPropertyChangeListener(this);
147    init();
148    upToDate_ = false;
149  }
150  /**
151   * Get a reference to the <code>ContourLevels</code> object.
152   */
153  public ContourLevels getContourLevels() {
154    return contourLevels_;
155  }
156  /**
157   * Set a <code>SGTGrid</code> object to be used to mask the data
158   * grid.  The Z values are used to determine the masking, values of
159   * NaN and non-zero are set as MISSING.
160   */
161  public void setMask(SGTGrid mask) {
162    if(mask_ == null || !mask_.equals(mask)) upToDate_ = false;
163    mask_ = mask;
164  }
165  /**
166   * Get the mask.
167   */
168  public SGTGrid getMask() {
169    return mask_;
170  }
171  /**
172   * Return the <code>Enumeration</code> of a <code>Vector</code>
173   * containing the <code>ContourLine</code> objects.
174   */
175  public Enumeration elements() {
176    if(!upToDate_) generateContourLines();
177    return contourLines_.elements();
178  }
179  /**
180   * Reponds to changes in the <code>ContourLevels</code> object.
181   */
182  public void propertyChange(PropertyChangeEvent event) {
183  }
184
185  private void init() {
186    GeoDate[] ttemp;
187    if(grid_.isXTime()) {
188      xTime_ = true;
189      ttemp = grid_.getTimeArray();
190      tref_ = ttemp[0];
191      px_ = getTimeOffsetArray(ttemp, tref_);
192      nx_ = grid_.getTSize();
193    } else {
194      px_ = grid_.getXArray();
195      nx_ = grid_.getXSize();
196    }
197    if(grid_.isYTime()) {
198      yTime_ = true;
199      ttemp = grid_.getTimeArray();
200      tref_ = ttemp[0];
201      py_ = getTimeOffsetArray(ttemp, tref_);
202      ny_ = grid_.getTSize();
203    } else {
204      py_ = grid_.getYArray();
205      ny_ = grid_.getYSize();
206    }
207    if(Debug.CONTOUR) {
208      System.out.println("nx_ = " + nx_ + ", ny_ = " + ny_);
209    }
210    /**
211     *   side definitions
212     *   ________
213     *  |   2    |
214     *  |        |
215     * 3|        |1
216     *  |        |
217     *  |________|
218     *      0
219     */
220    sides_ = new Sides(nx_, ny_);
221    //
222    // make the corner arrays index from 0 to 3
223    //
224    xx_ = new double[4];
225    yy_ = new double[4];
226    zz_ = new double[4];
227    used_ = new boolean[4];
228    kabov_ = new int[4];
229    z_ = grid_.getZArray();
230  }
231
232  private double[] getTimeOffsetArray(GeoDate[] tarray, GeoDate tref) {
233    double[] array = new double[tarray.length];
234    for(int i=0; i < tarray.length; i++) {
235      array[i] = tarray[i].offset(tref);
236    }
237    return array;
238  }
239
240  private GeoDate[] getTimeArray(double[] array, GeoDate tref) {
241    GeoDate[] tarray = new GeoDate[array.length];
242    for(int i=0; i < array.length; i++) {
243      tarray[i] = new GeoDate(tref);
244      tarray[i].increment(array[i], GeoDate.DAYS);
245    }
246    return tarray;
247  }
248  /**
249   * Given the current <code>ContourLevels</code>, mask, and
250   * <code>SGTGrid</code> generate the <code>ContourLine</code>s.
251   */
252  public void generateContourLines() {
253    double zrange;
254    double zc;
255    int kabij, kabip1, kabjp1;
256    int used0, used3;
257    int ll;
258    int i=0;
259    int j=0;
260    int ii, jj;
261    ContourLine cl;
262    int lin, k, kmax, nseg;
263    boolean reversed;
264    double xt, yt, frac;
265    double flm1, flp1;
266    int lp1, lp2, lm1;
267    int kda, kdb;
268    int exit;
269
270    if(upToDate_) return;
271
272    contourLines_ = new Vector();
273    upToDate_ = true;
274    computeMinMax();
275    //
276    // compute a small non-zero value for testing
277    //
278    zrange = (zmax_ - zmin_)*1.1;
279    if(zrange <= 0.0) return;
280    weezee_ = zrange*0.0002;
281    //
282    // loop over all contour levels
283    //
284    Enumeration lenum = contourLevels_.levelElements();
285    while(lenum.hasMoreElements()) {
286      //
287      // initialize for level
288      //
289      zc = ((Double)lenum.nextElement()).doubleValue();
290      if(Debug.CONTOUR) {
291                                System.out.println("zc = " + zc);
292      }
293      if(zc <= zmin_ || zc >= zmax_) continue;
294      sides_.clear();
295      if(mask_ != null) {
296        gridFlag_ = new GridFlag(grid_, mask_, zc);
297      } else {
298        gridFlag_ = new GridFlag(grid_, zc);
299      }
300      for(ii=0; ii < nx_; ii++) {    /* 1001 */
301      loop1000:
302        for(jj=0; jj < ny_; jj++) {  /* 1000 */
303          i = ii;
304          j = jj;
305          kabij = gridFlag_.getValue(i, j);
306          if(i < nx_-1) {
307            kabip1 = gridFlag_.getValue(i+1, j);
308          } else {
309            kabip1 = 10;
310          }
311          if(j < ny_-1) {
312            kabjp1 = gridFlag_.getValue(i, j+1);
313          } else {
314            kabjp1 = 10;
315          }
316          used0 = sides_.getSide(i, j, 0);
317          used3 = sides_.getSide(i, j, 3);
318          ll=0;   /*  bottom side */
319          if(kabij + kabip1 + used0 == 0) {
320            computeCorners(i, j, zc);
321          } else if(kabij + kabjp1 + used3 == 0) {
322            ll=3;  /*  left side */
323            computeCorners(i, j, zc);
324          } else {
325            continue;
326          }
327          //
328          // setup for new contour line
329          //
330          lin = ll;
331          k = 0;
332          nseg = 1;
333          reversed = false;
334          cl = new ContourLine();
335          try {
336            cl.setAttributes(contourLevels_.getDefaultContourLineAttribute(), 
337                             contourLevels_.getContourLineAttribute(zc));
338          } catch (ContourLevelNotFoundException e) {
339            System.out.println(e);
340          }
341          cl.setLevel(zc);
342          cl.setCartesianGraph(cg_);
343          cl.setTime(tref_, xTime_, yTime_);
344          contourLines_.addElement(cl);  /* add to list */
345          cl.addPoint(0.0, 0.0);  /* dummy k=1 point */
346          //
347          // Given entrance to square(i,j) on side lin,
348          // record the entrance point x(k), y(k).
349          // Set lin to used
350          //
351          //    lin    lp1    lp2    lm1
352          //   _________________________
353          //     0      1      2      3
354          //     1      2      3      0
355          //     2      3      0      1
356          //     3      0      1      2
357          //
358        loop350:
359          while(true) {  /* 350 */
360            lp1 = lin + 1 - ((lin+1)/4)*4;
361            lp2 = lp1 + 1 - ((lp1+1)/4)*4;
362            lm1 = lp2 + 1 - ((lp2+1)/4)*4;
363            if(!reversed) {
364              k = k + 1;
365              frac = (zc - zz_[lin])/(zz_[lp1] - zz_[lin]);
366              xt = xx_[lin] + (xx_[lp1] - xx_[lin])*frac;
367              yt = yy_[lin] + (yy_[lp1] - yy_[lin])*frac;
368              cl.addPoint(xt, yt);
369              sides_.setSideUsed(i, j, lin, true);
370            }
371            //
372            // See if an exit exists on side l-1, l+1, or l+2.
373            // If so choose the one closest to side l. If the
374            // exit already used terminate x,y.
375            //
376            reversed = false;
377            exit = lm1;
378            if(kabov_[lin] + kabov_[lm1] == 0) {
379              if(kabov_[lp1] + kabov_[lp2] == 0) {
380                flm1 = (zc - zz_[lin])/(zz_[lm1] - zc);
381                flp1 = (zc - zz_[lp1])/(zz_[lp2] - zc);
382                if(!(used_[lp1] ||
383                     (flm1 <= flp1 && !used_[lm1]))) {
384                  exit = lp1;
385                }
386              }
387            } else {
388              if(kabov_[lp1] + kabov_[lp2] == 0) {
389                exit = lp1;
390              } else {
391                exit = lp2;
392                if(kabov_[lp2] + kabov_[lm1] != 0) { /* 470 */
393                  if(kabov_[lp2] + kabov_[lm1] <= 15) {
394                    kda = lin;
395                    kdb = lp2;
396                    if(kabov_[lp2] > 5) {
397                      kda = lm1;
398                      kdb = lp1;
399                    }
400                    k = k + 1;
401                    frac = (zc - zz_[kda])/(zz_[kdb] - zz_[kda]);
402                    xt = xx_[kda] + (xx_[kdb] - xx_[kda])*frac;
403                    yt = yy_[kda] + (yy_[kdb] - yy_[kda])*frac;
404                    cl.addPoint(xt, yt);
405                  }
406                  if(nseg > 1) {
407                    kmax = k;
408                    //
409                    //       pt(1) = pt(2)
410                    //  pt(kmax+1) = pt(kmax)
411                    //
412                    cl.setElementAt((Point2D.Double)cl.elementAt(1), 0);
413                    cl.addPoint((Point2D.Double)cl.elementAt(k));
414                    cl.setClosed(false);
415                    cl.setKmax(kmax);
416                    continue loop1000;
417                  }
418                  reversed = true;
419                  nseg = 2;
420                  cl.reverseElements(k);
421                  i=ii;
422                  j=jj;
423                  exit = ll;
424                  //
425                  // Find square entered by present exit.
426                  //
427                  //    exit    i     j     lin
428                  //   _________________________
429                  //     0      i    j-1     2
430                  //     1     i+1    j      3
431                  //     2      i    j+1     0
432                  //     3     i-1    j      1
433                  //
434                  i = i + isin_[exit];
435                  j = j + isin_[3-exit];
436                  lin = exit + 2 - ((exit+2)/4)*4;
437                  computeCorners(i, j, zc);
438                  continue loop350;
439                }
440              }
441            }
442            if(used_[exit]) {
443              kmax = k + 1;
444              //
445              //     pt(kmax) = pt(2)
446              //        pt(1) = pt(k)
447              //   pt(kmax+1) = pt(3)
448              //
449              cl.addPoint((Point2D.Double)cl.elementAt(1));
450              cl.setElementAt((Point2D.Double)cl.elementAt(k), 0);
451              cl.addPoint((Point2D.Double)cl.elementAt(2));
452              cl.setClosed(true);
453              cl.setKmax(kmax);
454              continue loop1000;
455            }
456            i = i + isin_[exit];
457            j = j + isin_[3-exit];
458            lin = exit + 2 - ((exit+2)/4)*4;
459            computeCorners(i, j, zc);
460          } /* 350 */
461        } /* 1000 */
462      } /* 1001 */
463    } /* levels */
464  }
465
466  private void computeCorners(int i, int j, double zc) {
467    int jl, lp1, il;
468    boolean[] used = {false, false, false, false};
469    //
470    // Get xx,yy,zz,kabov for each corner and
471    // used for each side.
472    //
473    //   lcorner     il    jl    lp1
474    //      0        i     j      1
475    //      1       i+1    j      2
476    //      2       i+1   j+1     3
477    //      3        i    j+1     0
478    //
479    //
480    // lcorner definitions:
481    // (i,j+1) __________ (i+1,j+1)
482    //        |    2     |
483    //        |          |
484    //       3|          |1
485    //        |          |
486    //        |__________|
487    //  (i,j)      0      (i+1,j)
488    //
489    for(int lcorner=0; lcorner < 4; lcorner++) { /* 620 */
490      jl = j + lcorner/2;
491      lp1 = lcorner + 1 - ((lcorner+1)/4)*4;
492      il = i + lp1/2;
493      zz_[lcorner] = Double.NaN;
494      kabov_[lcorner] = 10;
495      if(((il+1)*(nx_-il) > 0) && ((jl+1)*(ny_-jl) > 0) &&
496         (!gridFlag_.isMissing(il, jl))) {
497        used[lcorner] = sides_.isSideUsed(i, j, lcorner);
498        zz_[lcorner] = setZ(z(il, jl), zc);
499        if(zz_[lcorner] < zc) {
500          kabov_[lcorner] = -1;
501        } else {
502          kabov_[lcorner] = 1;
503        }
504      }
505      xx_[lcorner] = px_[Math.max(0,Math.min(il,nx_-1))];
506      yy_[lcorner] = py_[Math.max(0,Math.min(jl,ny_-1))];
507    } /* 620 */
508    used_[0] = used[0];
509    used_[1] = used[1];
510    used_[2] = used[2];
511    used_[3] = used[3];
512  }
513
514  private double z(int i, int j) {
515    return z_[j + i*ny_];
516  }
517
518  private double setZ(double z, double zc) {
519    double diff = z - zc;
520    if(Math.abs(diff) < weezee_) {
521      return zc + weezee_ * (diff>0.0?1.0:-1.0);
522    } else {
523      return z;
524    }
525  }
526
527  private void computeMinMax() {
528    double[] grid = grid_.getZArray();
529    double[] mask = null;
530    boolean haveMask = mask_ != null;
531    if(haveMask) mask = mask_.getZArray();
532
533    zmin_ = Double.POSITIVE_INFINITY;
534    zmax_ = Double.NEGATIVE_INFINITY;
535
536    for(int i=0; i < grid.length; i++) {
537      if(!Double.isNaN(grid[i]) &&
538         !(haveMask && (mask[i] == 0.0))) {
539        zmin_ = Math.min(zmin_, grid[i]);
540        zmax_ = Math.max(zmax_, grid[i]);
541      }
542    }
543  }
544  /**
545   * Given the computed <code>ContourLine</code>s and the
546   * <code>ContourLineAttribute</code> generate the contour labels.
547   * Must be only invoked after generateConourLines().
548   */
549  public void generateContourLabels(Graphics g) {
550    int i, j, k, kk, km1, kp1;
551    int nx, ny;
552    double dx, dy, dzdx, dzdy, dzdg;
553    GeoDate tref = null;
554    GeoDate time;
555    double[] x, y, z, s;
556    double dxx, dyy, smax;
557    double space = 0.0;
558    double ark = 1.0;
559    boolean roomFound;
560    double slab1, stest;
561    double width, hgt;
562    double xa, xb, ya, yb, aa, bb, cc, zxy;
563    double xendl, yendl;
564    //    double xst, yst, xstp, ystp;
565    double xlab, ylab, hhgt, angle;
566    SGLabel label;
567    double[] px, py;
568    boolean xIncreasing, yIncreasing;
569    double dlev, cspace;
570    Enumeration elem = contourLines_.elements();
571    ContourLine cl;
572    while(elem.hasMoreElements()) {
573      cl = (ContourLine)elem.nextElement();
574      int kmax = cl.getKmax();
575      int lev = contourLevels_.getIndex(cl.getLevel());
576      if(Debug.CONTOUR) {
577        //      System.out.println("drawLabelContourLine: lev = " + lev +
578        //                       ", level = " + cl.getLevel());
579      }
580      DefaultContourLineAttribute cattr = cl.getDefaultContourLineAttribute();
581      cattr.setContourLineAttribute(cl.getContourLineAttribute());
582      if(kmax <= 1 || !cattr.isLabelEnabled()) continue;
583      //
584      // create SGLabel at a dummy location and no rotation
585      //
586      label = new SGLabel("CLevel", 
587                          cattr.getLabelText(), 
588                          cattr.getLabelHeightP(), 
589                          new Point2D.Double(0.0,0.0), 
590                          SGLabel.BOTTOM, 
591                          SGLabel.LEFT);
592      if(cattr.getLabelFont() != null) label.setFont(cattr.getLabelFont());
593      label.setColor(cattr.getLabelColor());
594      label.setLayer(cg_.getLayer());
595      //
596      // compute hgt and width from font
597      //
598      int swidth = (int)label.getStringWidth(g);
599      int sheight = (int)label.getStringHeight(g);
600      width = cg_.getLayer().getXDtoP(swidth) - cg_.getLayer().getXDtoP(0);
601      //
602      hgt = cg_.getLayer().getYDtoP(0) - cg_.getLayer().getYDtoP(sheight);
603      //
604      hhgt = hgt*0.5;
605      width = width + hhgt;
606      if(Debug.CONTOUR) {
607        //      System.out.println("drawLabeledContourLine: hhgt,width = " +
608        //                       hhgt + ", " + width);
609      }
610      //
611      px = xArrayP();
612      py = yArrayP();
613      z = grid_.getZArray();
614      xIncreasing = px[0] < px[1];
615      yIncreasing = py[0] < py[1];
616      nx = px.length;
617      ny = py.length;
618      //
619      x = new double[kmax+1];
620      y = new double[kmax+1];
621      s = new double[kmax+1];
622      if(cl.isXTime() || cl.isYTime()) {
623        tref = cl.getReferenceTime();
624      }
625      s[1] = 0.0;
626      //
627      // convert ContourLine to physical units
628      //
629      x = cl.getXArrayP();
630      y = cl.getYArrayP();
631      //
632      // compute s[k]
633      //
634      for(k=2; k <= kmax; k++) {
635        dxx = x[k] - x[k-1];
636        dyy = y[k] - y[k-1];
637        s[k] = s[k-1] + Math.sqrt(dxx*dxx+dyy*dyy);
638      }
639      smax = s[kmax];
640      slab1 = smax*SLAB1F;
641      stest = Math.max(0.0, DSLAB - slab1);
642      k=1;
643      //
644      // check conditions for labelling
645      //
646      while(k < kmax) { /* 755 */
647        km1 = Math.max(k-1, 1);
648        stest = stest + s[k] - s[km1];
649        //
650        // Test if there is enough room for a label
651        //
652        if(stest < DSLAB || (smax - s[k]) <= 2.0*width) {
653          //      drawLineSegment(g, x[k], y[k], x[k+1], y[k+1]);
654          k=k+1;
655          continue;
656        }
657        kp1 = k + 1;
658        //
659        // gradient test
660        //
661        if(lev != 0) {
662          try {
663            dlev = Math.abs(contourLevels_.getLevel(lev) - 
664                            contourLevels_.getLevel(lev-1));
665            if(xIncreasing) {
666              for(i=0; i < nx-1; i++) {
667                if(x[k] >= px[i] && x[k] <= px[i+1]) break;
668              }
669            } else {
670              for(i=0; i < nx-1; i++) {
671                if(x[k] <= px[i] && x[k] >= px[i+1]) break;
672              }
673            }
674            if(yIncreasing) {
675              for(j=0; j < ny-1; j++) {
676                if(y[k] >= py[j] && y[k] <= py[j+1]) break;
677              }
678            } else {
679              for(j=0; j < ny-1; j++) {
680                if(y[k] <= py[j] && y[k] >= py[j+1]) break;
681              }
682            }
683            i = Math.min(i, nx-2);
684            j = Math.min(j, ny-2);
685            dx = px[i+1] - px[i];
686            dy = py[j+1] - py[j];
687            if(Double.isNaN(z[j+(i+1)*ny])) {
688              dzdx = 0.0;
689            } else {
690              dzdx = (z[j+(i+1)*ny] - z[j+i*ny])/dx;
691            }
692            if(Double.isNaN(z[j+1+i*ny])) {
693              dzdy = 0.0;
694            } else {
695              dzdy = (z[j+1+i*ny] - z[j+i*ny])/dy;
696            }
697            //
698            // dzdg = sqrt(dzdx*dzdx+dzdy*dzdy)
699            //
700            // replace with less prone to overflow
701            // calculation
702            //
703            dzdg = Math.abs(dzdx) + Math.abs(dzdy);
704            if(dzdg != 0.0) {
705              cspace = dlev/dzdg;
706              //
707              // is there room for label height?
708              // (was 0.75)
709              if(cspace < hgt*1.0) {
710                //              drawLineSegment(g, x[k], y[k], x[k+1], y[k+1]);
711                k=k+1;
712                continue;
713              }
714            }
715          } catch (ContourLevelNotFoundException e) {
716            System.out.println(e);
717          }
718        }
719        //
720        // test line arc
721        //
722        roomFound = false;
723        for(kk=kp1; kk <= kmax; kk++) {
724          dxx = x[kk] - x[k];
725          dyy = y[kk] - y[k];
726          space = Math.sqrt(dxx*dxx + dyy*dyy);
727          ark = s[kk] - s[k];
728          if(space >= width) { 
729            roomFound = true;
730            break;
731          }
732        }
733        if(space/ark < 0.80 || !roomFound) {
734          //      drawLineSegment(g, x[k], y[k], x[k+1], y[k+1]);
735          k=k+1;
736          continue;
737        } else {
738          //
739          // add label to contour line
740          //
741          cl.addLabel(k, (SGLabel)label.copy(), hgt, width);
742          //
743          // draw the label
744          //
745          stest = 0.0;   /* 810 */
746//        xa = x[kk-1] - x[k];
747//        xb = x[kk] - x[kk-1];
748//        ya = y[kk-1] - y[k];
749//        yb = y[kk] - y[kk-1];
750//        aa = xb*xb + yb*yb;
751//        bb = xa*xb + ya*yb;
752//        cc = xa*xa + ya*ya - width*width;
753//        zxy = (-bb + Math.sqrt(bb*bb - aa*cc))/aa;
754//        dxx = xa + xb*zxy;
755//        dyy = ya + yb*zxy;
756//        xendl = x[k] + dxx;
757//        yendl = y[k] + dyy;
758//        //
759//        // compute label angle
760//        //
761//        angle = 90.0;
762//        if(dyy < 0.0) angle = -90.0;
763//        if(dxx != 0.0) {
764//          angle = Math.atan(dyy/dxx)*180.0/Math.PI;
765//        }
766//        //
767//        // compute label position
768//        //
769//        if(dxx >= 0) {
770//          xlab = x[k] + hhgt*(0.5*dxx + dyy)/width;
771//          ylab = y[k] + hhgt*(0.5*dyy - dxx)/width;
772//        } else {
773//          xlab = xendl - hhgt*(0.5*dxx + dyy)/width;
774//          ylab = yendl - hhgt*(0.5*dyy - dxx)/width;
775//        }
776//        label.setAngle(angle);
777//        label.setLocationP(new Point2D.Double(xlab, ylab));
778//        try {
779//          label.draw(g);
780//          //    drawRotatedRectangle(g, angle, xlab, ylab, width-hhgt, hgt);
781//        } catch (LayerNotFoundException e) {
782//          System.out.println(e);
783//        }
784//        drawLineSegment(g, xendl, yendl, x[kk], y[kk]);
785          k = kk;
786        }
787      }
788    }
789  }
790
791  private void drawRotatedRectangle(Graphics g,
792                                    double angle,
793                                    double x0, double y0,
794                                    double width, double height) {
795    double sinthta = Math.sin(angle*Math.PI/180.0);
796    double costhta = Math.cos(angle*Math.PI/180.0);
797    double[] x, y;
798    double xp, yp;
799    int[] xd, yd;
800    double xorig, yorig;
801    x = new double[4];
802    y = new double[4];
803    xd = new int[5];
804    yd = new int[5];
805    xorig = x0;
806    yorig = y0;
807    x[0] = x0;
808    y[0] = y0;
809    x[1] = x[0] + width;
810    y[1] = y[0];
811    x[2] = x[1];
812    y[2] = y[0] + height;
813    x[3] = x[0];
814    y[3] = y[2];
815    for(int i=0; i < 4; i++) {
816      xp = (x[i]-xorig)*costhta - (y[i]-yorig)*sinthta + xorig;
817      yp = (y[i]-yorig)*costhta + (x[i]-xorig)*sinthta + yorig;
818      xd[i] = cg_.getLayer().getXPtoD(xp);
819      yd[i] = cg_.getLayer().getYPtoD(yp);
820    }
821    xd[4] = xd[0];
822    yd[4] = yd[0];
823    g.setColor(Color.blue);
824    g.drawPolyline(xd, yd, 5);
825    g.setColor(Color.black);
826  }
827
828//    private void drawLineSegment(Graphics g, double x0, double y0,
829//                             double x1, double y1) { /* 900 */
830//      int xd0, yd0, xd1, yd1;
831//      xd0 = cg_.getLayer().getXPtoD(x0);
832//      yd0 = cg_.getLayer().getYPtoD(y0);
833//      xd1 = cg_.getLayer().getXPtoD(x1);
834//      yd1 = cg_.getLayer().getYPtoD(y1);
835//      g.drawLine(xd0, yd0, xd1, yd1);
836//    }
837
838  private double[] xArrayP() {
839    int i;
840    double[] p;
841    if(grid_.isXTime()) {
842      GeoDate[] t = grid_.getTimeArray();
843      p = new double[t.length];
844      for(i=0; i < t.length; i++) {
845        p[i] = cg_.getXUtoP(t[i]);
846      }
847    } else {
848      double[] x = grid_.getXArray();
849      p = new double[x.length];
850      for(i=0; i < x.length; i++) {
851        p[i] = cg_.getXUtoP(x[i]);
852      }
853    }
854    return p;
855  }
856
857  private double[] yArrayP() {
858    int i;
859    double[] p;
860    if(grid_.isYTime()) {
861      GeoDate[] t = grid_.getTimeArray();
862      p = new double[t.length];
863      for(i=0; i < t.length; i++) {
864        p[i] = cg_.getYUtoP(t[i]);
865      }
866    } else {
867      double[] y = grid_.getYArray();
868      p = new double[y.length];
869      for(i=0; i < y.length; i++) {
870        p[i] = cg_.getYUtoP(y[i]);
871      }
872    }
873    return p;
874  }
875
876//    private void drawContourLine(Graphics g, ContourLine cl) {
877//      GeoDate tref, time;
878//      Point2D.Double[] pt;
879//      int i;
880//      //    int size = cl.size();
881//      int size = cl.getKmax() + 1;
882//      if(size <= 3) return;
883//      int[] xp = new int[size];
884//      int[] yp = new int[size];
885//      pt = new Point2D.Double[size];
886//      for(i=0; i < size; i++) {
887//        pt[i] = (Point2D.Double)cl.elementAt(i);
888//      }
889//      if(cl.isXTime()) {
890//        tref = cl.getReferenceTime();
891//        for(i=0; i < size; i++) {
892//      time = (new GeoDate(tref)).increment(pt[i].x, GeoDate.DAYS);
893//      xp[i] = cg_.getXUtoD(time);
894//        }
895//      } else {
896//        for(i=0; i < size; i++) {
897//      xp[i] = cg_.getXUtoD(pt[i].x);
898//        }
899//      }
900//      if(cl.isYTime()) {
901//        tref = cl.getReferenceTime();
902//        for(i=0; i < size; i++) {
903//      time = (new GeoDate(tref)).increment(pt[i].y, GeoDate.DAYS);
904//      yp[i] = cg_.getYUtoD(time);
905//        }
906//      } else {
907//        for(i=0; i < size; i++) {
908//      yp[i] = cg_.getYUtoD(pt[i].y);
909//        }
910//      }
911//      g.drawPolyline(xp, yp, size);
912//    }
913}
Note: See TracBrowser for help on using the repository browser.