001    /*
002     * $Id: CoverageAnalyzer.java,v 1.5 2012/02/19 17:35:39 davep Exp $
003     *
004     * This file is part of McIDAS-V
005     *
006     * Copyright 2007-2012
007     * Space Science and Engineering Center (SSEC)
008     * University of Wisconsin - Madison
009     * 1225 W. Dayton Street, Madison, WI 53706, USA
010     * https://www.ssec.wisc.edu/mcidas
011     * 
012     * All Rights Reserved
013     * 
014     * McIDAS-V is built on Unidata's IDV and SSEC's VisAD libraries, and
015     * some McIDAS-V source code is based on IDV and VisAD source code.  
016     * 
017     * McIDAS-V is free software; you can redistribute it and/or modify
018     * it under the terms of the GNU Lesser Public License as published by
019     * the Free Software Foundation; either version 3 of the License, or
020     * (at your option) any later version.
021     * 
022     * McIDAS-V is distributed in the hope that it will be useful,
023     * but WITHOUT ANY WARRANTY; without even the implied warranty of
024     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
025     * GNU Lesser Public License for more details.
026     * 
027     * You should have received a copy of the GNU Lesser Public License
028     * along with this program.  If not, see http://www.gnu.org/licenses.
029     */
030    
031    //package jsattrak.coverage;
032    package edu.wisc.ssec.mcidasv.data.adde.sgp4;
033    
034    import edu.wisc.ssec.mcidasv.data.GroundStations;
035    
036    import java.awt.Color;
037    import java.awt.Graphics2D;
038    import java.text.DecimalFormat;
039    import java.text.NumberFormat;
040    import java.util.Hashtable;
041    import java.util.Vector;
042    /*
043    import jsattrak.gui.J2dEarthLabel2;
044    import jsattrak.objects.AbstractSatellite;
045    import jsattrak.objects.GroundStation;
046    import name.gano.astro.GeoFunctions;
047    import name.gano.astro.time.Time;
048    */
049    
050    /**
051     *
052     * @author Shawn
053     */
054    //public class CoverageAnalyzer implements JSatTrakRenderable,JSatTrakTimeDependent
055    public class CoverageAnalyzer
056    {
057        // data arrays
058        private  double[][] coverageCumTime;  // cumulative coverage time array [latPanels x longPanels] in days
059         // in degrees
060        private double[] latPanelMidPoints; // middle point latitude of each division/panel
061        private double[] lonPanelMidPoints; // middle point longitude of each division/panel
062        private double[] latGridPoints; // grid end points for latitude
063        private double[] lonGridPoints; // grid end points for longitude
064       
065        private double minNotZeroVal = 1;  // current maximum and minimum (NOT ZERO) values 
066        private double maxVal = 100;
067        
068        private Time startTime = new Time(); // keep track of start time
069        
070        // color map for data
071        //ColorMap colorMap = new ColorMap();
072        
073        private double lastMJD = -1; // last MJD update time
074        
075        Vector<String> satsUsedInCoverage = new Vector<String>(); // vector of satellites used in Coverage anaylsis
076        
077        // settings ===========
078        // grid sizing >=1
079        private int latPanels = 36; //72;//36; //18// number of divisons along lines of latitude (grid points -1)
080        private int longPanels = 72;  //144;//72; //36 // number of divisions along lines of longitude (grid points -1)
081        
082        // in degrees
083        private double[] latBounds = {-90.0, 90.0}; // minimum,maxium latitude to use in coverage anaylsis
084        private double[] longBounds = {-180.0, 180.0}; // minimum,maxium longitude to use in coverage anaylsis
085        
086        private int alpha = 150; //151; // tranparency of colored panels, 0=can't see it, 255=solid
087        
088        private boolean dynamicUpdating = true; // if dynamic updating from GUI time stepping is enabled
089        private boolean plotCoverageGrid = false; // plot panel grid and center points of panels
090        private double elevationLimit = 15; //15; // elevation limit for ground coverage [degrees] (must be higher for this to count as coverage
091        private NumberFormat colorBarNumberFormat = new DecimalFormat("0.00E0");
092        private boolean showColorBar = true; // Color bar settings
093        private int pixelsFromBottom = 20;
094        private int pixelsFromLeft = 20;
095        private int colorBarLen = 100;
096        private int colorBarHeight = 10;
097        private int colorBarTextSpacing = 5;
098        private // pixels below bar where text is displayed
099        Color colorbarBGcolor = new Color(255, 255, 255, 180);
100        private Color colorBarTextcolor = Color.BLACK;
101        
102        // default constructor
103        public CoverageAnalyzer()
104        {
105            iniParamters();
106        } // constructor
107        
108        /**
109         * Constructor with current time - this will allow coverage to start on next time step
110         * @param currentJulianDate current Julian Date
111         */
112        public CoverageAnalyzer(final Time currentJulianDate)
113        {
114            iniParamters();
115            lastMJD = currentJulianDate.getMJD();
116            startTime.set(currentJulianDate.getCurrentGregorianCalendar().getTimeInMillis());        
117        }
118        
119    //    /**
120    //     * NEEDS TO INCLUDE - SATS INTO VECTOR BEFORE THIS WILL WORK PROPERLY
121    //     * Constructor with current time and current time step - this will allow coverage anaylsis to immediately start
122    //     * @param currentJulianDate current Julian Date
123    //     * @param timeStepDays time step to be used in days
124    //     * @param satHash Hashtable of current satellites
125    //     */
126    //    public CoverageAnalyzer(final Time currentJulianDate, double timeStepDays, final Hashtable<String,AbstractSatellite> satHash)
127    //    {
128    //        iniParamters();
129    //        lastMJD = currentJulianDate.getMJD()-timeStepDays;
130    //        
131    //        performCoverageAnalysis(currentJulianDate, satHash);
132    //    }
133        
134        /**
135         * Clear coverage data and initalizie update time for next simulation step
136         * @param currentJulianDate
137         */
138        public void clearCoverageData(final Time currentJulianDate)
139        {
140            iniParamters();
141            lastMJD = currentJulianDate.getMJD();
142            startTime.set(currentJulianDate.getCurrentGregorianCalendar().getTimeInMillis());
143        }
144        
145        /**
146         * Clears the coverage data and resets last update date
147         */
148        public void clearCoverageData()
149        {
150            iniParamters();
151        }
152        
153        // initalized all parameters (used at class construction to create all arrays, etc)
154        private void iniParamters()
155        {
156            // cumulative time create new array (default 0)
157            coverageCumTime = new double[latPanels][longPanels];
158            // mid points
159            latPanelMidPoints = new double[latPanels];
160            lonPanelMidPoints = new double[longPanels];
161            // grid points
162            latGridPoints = new double[latPanels+1];
163            lonGridPoints = new double[longPanels+1];
164            
165            // calulate grid points, mid points
166            for(int i=0;i<latPanels+1;i++)
167            {
168                latGridPoints[i] = i*(latBounds[1]-latBounds[0])/(latPanels)+latBounds[0];
169                if(i>0)
170                {
171                    latPanelMidPoints[i-1] = (getLatGridPoints()[i]+getLatGridPoints()[i-1])/2.0;
172                }
173            }
174            for(int i=0;i<longPanels+1;i++)
175            {
176                lonGridPoints[i] = i*(longBounds[1]-longBounds[0])/(longPanels)+longBounds[0];
177                if(i>0)
178                {
179                    lonPanelMidPoints[i-1] = (getLonGridPoints()[i]+getLonGridPoints()[i-1])/2.0;
180                }
181            }
182            
183            // clear last mjd update
184            lastMJD = -1;
185            
186        }// iniParamters
187        
188        // test main function
189        public static void main(String[] args)
190        {
191            CoverageAnalyzer ca = new CoverageAnalyzer();
192        } // main
193        
194        
195        /**
196         *  Performa an update of time and data of Coverage Metrics
197         * @param currentJulianDate
198         * @param satHash
199         * @param gsHash
200         */
201    /*
202        @Override
203        public void updateTime(final Time currentJulianDate, final Hashtable<String,AbstractSatellite> satHash, final Hashtable<String,GroundStation> gsHash)
204        {
205            if(!dynamicUpdating)
206            {
207                return; // don't update converage anlysis from JSatTrack GUI
208            }
209            
210            performCoverageAnalysis(currentJulianDate,satHash); // do the analysis
211            
212        } // updateTime
213    */ 
214        // internal function to actually perform the anaylsis - so it can be used by GUI update calls or coverage tool
215        /**
216         * Performs coverage anaylsis with given time and satellite array, this fuction should be called only when directly performing coverage analysis, otherwise call updateTime
217         * @param currentJulianDate
218         * @param satHash
219         */
220        public void performCoverageAnalysis(final Time currentJulianDate, final Hashtable<String,AbstractSatellite> satHash)
221        {
222            // if first time update, save time and quit (only start calc after first time step)
223            if(lastMJD == -1)
224            {
225                lastMJD = currentJulianDate.getMJD();
226                startTime.set(currentJulianDate.getCurrentGregorianCalendar().getTimeInMillis());
227                return;
228            }
229            
230            // check time make sure this time is past when the last time update was 
231            if(currentJulianDate.getMJD() <= lastMJD)
232            {
233                return; // do nothing as this time is later
234            }
235            // calc time diff, and save time
236            double timeDiffDays = currentJulianDate.getMJD() - lastMJD;
237            lastMJD = currentJulianDate.getMJD();
238            
239            // create temp array for time cumlation (so we don't double count sat coverage)
240            // each panel either has access or it doesn't for the current time step -- boolean 
241            boolean[][] tempAcessArray = new boolean[latPanels][longPanels];
242            
243            // === do coverage anaylsis, for each satellite ===
244            for(String satName : satsUsedInCoverage)
245            {
246                // get sat Object
247                AbstractSatellite currentSat = satHash.get(satName);
248                
249                // check to see if satellite is in lat/long AOI coverage box
250                if(currentSat.getLatitude()*180/Math.PI  >= latBounds[0]  && 
251                   currentSat.getLatitude()*180/Math.PI  <= latBounds[1]  &&
252                   currentSat.getLongitude()*180/Math.PI >= longBounds[0] &&
253                   currentSat.getLongitude()*180/Math.PI <= longBounds[1]    )
254                {
255                    
256                    // find closest panel under satellite and the index of that panel
257                    double latPercentile = (currentSat.getLatitude()*180/Math.PI-latBounds[0]) / (latBounds[1]-latBounds[0]);
258                    int latIndex = (int)Math.floor(latPercentile*latPanels);
259                    double longPercentile = (currentSat.getLongitude()*180/Math.PI-longBounds[0]) / (longBounds[1]-longBounds[0]);
260                    int longIndex = (int)Math.floor(longPercentile*longPanels);
261                    
262                    // Coverage assumes sat doesn't have a shaped sensor and it can look straight down (nadir)
263                    // debug for now mark point as access added
264                    double[] aer = new double[3];
265    //                aer = GeoFunctions.calculate_AER(currentJulianDate.getJulianDate(), 
266    //                        new double[]{latPanelMidPoints[latIndex],lonPanelMidPoints[longIndex],0},  // sea level
267    //                        currentSat.getPosMOD());
268    //                
269    //                // see if sat sub-point panel has access (otherwise nothing does)
270    //                if(aer[1] >= elevationLimit)
271    //                {
272    //                    tempAcessArray[latIndex][longIndex] = true; // can't assume access here!
273    //                }
274                    
275                    // Search up=====================================================
276                    // search upwards until no access (careful of lat >90)
277                    int i = latIndex; // includes satellite sub point
278                    double tempElevation2=0; // used in searching to the left and right
279                    do
280                    {
281                        // take care of when i >= latPanels (reflection for longitude index and make lat go down instead of up (and stay at top one iter)
282                        
283                        aer = GeoFunctions.calculate_AER(currentJulianDate.getJulianDate(), 
284                            new double[]{getLatPanelMidPoints()[i],getLonPanelMidPoints()[longIndex],0},  // sea level
285                            currentSat.getTEMEPos());
286                        
287                        if(aer[1] >= elevationLimit)
288                        {
289                            tempAcessArray[i][longIndex] = true;
290                            // search to the left =============================
291                            int j=longIndex-1;
292                            int longSearchCount = 0;
293                            int jWrappedIndex = j; // updated so seach can wrap around map
294                            do
295                            {
296                                // take car of i and j with wrap arounds
297                                if(j < 0)
298                                {
299                                    jWrappedIndex = longPanels + j;
300                                }
301                                else if(j >= longPanels)
302                                {
303                                    jWrappedIndex = j - longPanels;
304                                }
305                                else
306                                {
307                                    jWrappedIndex = j;
308                                }
309                                
310                                tempElevation2 = GeoFunctions.calculate_AER(currentJulianDate.getJulianDate(), 
311                                    new double[]{getLatPanelMidPoints()[i],getLonPanelMidPoints()[jWrappedIndex],0},  // sea level
312                                    currentSat.getTEMEPos())[1];
313                                if(tempElevation2 >= elevationLimit)
314                                {
315                                    tempAcessArray[i][jWrappedIndex] = true;
316                                }
317                                
318                                j--;
319                                longSearchCount++; // make sure we don't get stuck on seaching a row over and over
320                            }while(tempElevation2 >= elevationLimit && longSearchCount < longPanels); 
321                            // search to the left =============================
322                            // search to the Right =============================
323                            j=longIndex+1;
324                            longSearchCount = 0;
325                            jWrappedIndex = j; // updated so seach can wrap around map
326                            do
327                            {
328                                // take car of i and j with wrap arounds
329                                if(j < 0)
330                                {
331                                    jWrappedIndex = longPanels + j;
332                                }
333                                else if(j >= longPanels)
334                                {
335                                    jWrappedIndex = j - longPanels;
336                                }
337                                else
338                                {
339                                    jWrappedIndex = j;
340                                }
341                                
342                                tempElevation2 = GeoFunctions.calculate_AER(currentJulianDate.getJulianDate(), 
343                                    new double[]{getLatPanelMidPoints()[i],getLonPanelMidPoints()[jWrappedIndex],0},  // sea level
344                                    currentSat.getTEMEPos())[1];
345                                if(tempElevation2 >= elevationLimit)
346                                {
347                                    tempAcessArray[i][jWrappedIndex] = true;
348                                }
349                                
350                                j++;
351                                longSearchCount++; // make sure we don't get stuck on seaching a row over and over
352                            }while(tempElevation2 >= elevationLimit && longSearchCount < longPanels); 
353                            // search to the Right =============================
354                            
355                        }
356                        
357                        i++;
358                    }while(aer[1] >= elevationLimit && i < latPanels); // do while - only search up to top of panel
359                    // Search up=====================================================
360                    // Search down=====================================================
361                    // search down until no access (careful of lat >90)
362                    i = latIndex - 1; // includes satellite sub point
363                    tempElevation2 = 0; // used in searching to the left and right
364                    if (i >= 0) // avoid searching down if i is already 0
365                    {
366                        do
367                        {
368                            // take care of when i >= latPanels (reflection for longitude index and make lat go down instead of up (and stay at top one iter)
369                            aer = GeoFunctions.calculate_AER(currentJulianDate.getJulianDate(),
370                                    new double[]
371                                    {
372                                        getLatPanelMidPoints()[i], getLonPanelMidPoints()[longIndex], 0
373                                    
374                                    }, // sea level
375                                    currentSat.getTEMEPos());
376    
377                            if (aer[1] >= elevationLimit)
378                            {
379                                tempAcessArray[i][longIndex] = true;
380                                // search to the left =============================
381                                int j = longIndex - 1;
382                                int longSearchCount = 0;
383                                int jWrappedIndex = j; // updated so seach can wrap around map
384    
385                                do
386                                {
387                                    // take car of i and j with wrap arounds
388                                    if (j < 0)
389                                    {
390                                        jWrappedIndex = longPanels + j;
391                                    }
392                                    else if (j >= longPanels)
393                                    {
394                                        jWrappedIndex = j - longPanels;
395                                    }
396                                    else
397                                    {
398                                        jWrappedIndex = j;
399                                    }
400    
401                                    tempElevation2 = GeoFunctions.calculate_AER(currentJulianDate.getJulianDate(),
402                                            new double[] {getLatPanelMidPoints()[i], getLonPanelMidPoints()[jWrappedIndex], 0}, // sea level
403                                            currentSat.getTEMEPos())[1];
404                                    if (tempElevation2 >= elevationLimit)
405                                    {
406                                        tempAcessArray[i][jWrappedIndex] = true;
407                                    }
408    
409                                    j--;
410                                    longSearchCount++; // make sure we don't get stuck on seaching a row over and over
411                                }while (tempElevation2 >= elevationLimit && longSearchCount < longPanels);
412                                // search to the left =============================
413                                // search to the Right =============================
414                                j = longIndex + 1;
415                                longSearchCount = 0;
416                                jWrappedIndex = j; // updated so seach can wrap around map
417                                do
418                                {
419                                    // take car of i and j with wrap arounds
420                                    if (j < 0)
421                                    {
422                                        jWrappedIndex = longPanels + j;
423                                    }
424                                    else if (j >= longPanels)
425                                    {
426                                        jWrappedIndex = j - longPanels;
427                                    }
428                                    else
429                                    {
430                                        jWrappedIndex = j;
431                                    }
432                                    
433                                    tempElevation2 = GeoFunctions.calculate_AER(currentJulianDate.getJulianDate(),
434                                            new double[]{getLatPanelMidPoints()[i], getLonPanelMidPoints()[jWrappedIndex], 0}, // sea level
435                                            currentSat.getTEMEPos())[1];
436                                    if (tempElevation2 >= elevationLimit)
437                                    {
438                                        tempAcessArray[i][jWrappedIndex] = true;
439                                    }
440    
441                                    j++;
442                                    longSearchCount++; // make sure we don't get stuck on seaching a row over and over
443                                }
444                                while (tempElevation2 >= elevationLimit && longSearchCount < longPanels);
445                            // search to the Right =============================
446    
447                            } // if in elecation limit
448    
449                            i--;
450                        }while (aer[1] >= elevationLimit && i >= 0); // do while
451                    } // if already at 0 no need to search down
452                    // Search down=====================================================
453                    
454                    
455                }// sat is in coverage AOI           
456            } // for each satellite - Coverage anaylsis
457            
458            // merge temp and timecumarray // and update max and min values
459            minNotZeroVal = Double.MAX_VALUE; // really high to start
460            maxVal = -1; // really low to start
461            for(int i=0;i<latPanels;i++) 
462            {
463                for(int j=0;j<longPanels;j++)
464                {
465                    // DEBUG CLEAR VALUE SO ONLY POINTS CURRENTLY IN VIEW SHOW UP
466                    //coverageCumTime[i][j] = 0;
467                    
468                    if(tempAcessArray[i][j])
469                    {
470                        coverageCumTime[i][j] += timeDiffDays;
471                    } // if access at this point
472                    
473                    // update max and min
474                    if(getCoverageCumTime()[i][j] > maxVal)
475                    {
476                        maxVal = getCoverageCumTime()[i][j];
477                    }
478                    if(getCoverageCumTime()[i][j] < minNotZeroVal && getCoverageCumTime()[i][j] > 0)
479                    {
480                       minNotZeroVal =  getCoverageCumTime()[i][j];
481                    }
482                    
483                } // long panels (j)
484            } // lat panels (i) (merge data)
485            
486    
487            
488        } // performCoverageAnalysis
489    /*
490        // draw 2d
491        public void draw2d(Graphics2D g2, J2dEarthLabel2 earthLabel, int totWidth, int totHeight, int imgWidth, int imgHeight, double zoomFac, double cLat, double cLong)
492        {
493            int[] xy = new int[2];
494            int[] xy_old = new int[2];
495            
496            // draw in grid lines for lat and long of coverage area
497            if (plotCoverageGrid)
498            {
499                g2.setColor(new Color(0.0f, 1.0f, 0.0f, 0.2f));
500                for (double lat : getLatGridPoints())
501                {
502                    xy = earthLabel.findXYfromLL(lat, longBounds[0], totWidth, totHeight, imgWidth, imgHeight, zoomFac, cLat, cLong);
503                    xy_old = earthLabel.findXYfromLL(lat, longBounds[1], totWidth, totHeight, imgWidth, imgHeight, zoomFac, cLat, cLong);
504    
505                    g2.drawLine(xy_old[0], xy_old[1], xy[0], xy[1]); // draw a line across the map
506    
507                }
508                g2.setColor(new Color(0.0f, 1.0f, 0.0f, 0.2f));
509                for (double lon : getLonGridPoints())
510                {
511                    xy = earthLabel.findXYfromLL(latBounds[0], lon, totWidth, totHeight, imgWidth, imgHeight, zoomFac, cLat, cLong);
512                    xy_old = earthLabel.findXYfromLL(latBounds[1], lon, totWidth, totHeight, imgWidth, imgHeight, zoomFac, cLat, cLong);
513    
514                    g2.drawLine(xy_old[0], xy_old[1], xy[0], xy[1]); // draw a line across the map
515    
516                }
517                // draw center points
518                g2.setColor(new Color(0.0f, 1.0f, 0.0f, 0.2f));
519                int dotSize = 1;
520                for (double lat : getLatPanelMidPoints())
521                {
522                    for (double lon : getLonPanelMidPoints())
523                    {
524                        xy = earthLabel.findXYfromLL(lat, lon, totWidth, totHeight, imgWidth, imgHeight, zoomFac, cLat, cLong);
525    
526                        g2.drawRect(xy[0] - dotSize / 2, xy[1] - dotSize / 2, dotSize, dotSize);
527                    }
528                }
529            } // graw grid and center points
530            // fill in color scaled panels based on cumulative Coverage time
531            // should combine with above... just use alpha =0.0 when panel is blank
532            int xmax, xmin, ymax, ymin;
533            for(int i=0;i<getLatPanelMidPoints().length;i++)
534            {
535                for(int j=0;j<getLonPanelMidPoints().length;j++)
536                {
537                    xy = earthLabel.findXYfromLL(getLatGridPoints()[i], getLonGridPoints()[j],totWidth,totHeight,imgWidth,imgHeight,zoomFac,cLat,cLong);
538                    xy_old = earthLabel.findXYfromLL(getLatGridPoints()[i+1], getLonGridPoints()[j+1],totWidth,totHeight,imgWidth,imgHeight,zoomFac,cLat,cLong);
539                    
540                    xmax = Math.max(xy[0], xy_old[0]);
541                    xmin = Math.min(xy[0], xy_old[0]);
542                    ymax = Math.max(xy[1], xy_old[1]);
543                    ymin = Math.min(xy[1], xy_old[1]);
544                    
545                    // color based on: coverageCumTime[i][j]
546                    // dummy way for now black or white
547                    if(getCoverageCumTime()[i][j]>0)
548                    {
549                        g2.setColor( colorMap.getColor(getCoverageCumTime()[i][j], minNotZeroVal, maxVal, alpha)  );
550                        g2.fillRect(xmin, ymin, xmax-xmin,ymax-ymin);//xy_old[0]-xy[0], xy_old[1]-xy[1]);
551                    }
552                    else
553                    {
554                        // don't draw anything
555                    }
556                    
557                } // for lon panels
558            } // for lat panels
559            
560            // Draw color bar if wanted!!
561            if(showColorBar)
562            {
563                // colorbar background
564                g2.setColor( colorbarBGcolor );
565                g2.fillRect(pixelsFromLeft-5, totHeight-pixelsFromBottom-colorBarHeight-3, colorBarLen+12+30, colorBarHeight+colorBarTextSpacing+15);
566                
567                // color bar specturm
568                for(int i=0;i<colorBarLen;i++)
569                {
570                    g2.setColor( colorMap.getColor(i, 0, colorBarLen, 255) );
571                    g2.drawLine(pixelsFromLeft+i, totHeight-pixelsFromBottom, pixelsFromLeft+i, totHeight-pixelsFromBottom-colorBarHeight);
572                }
573                
574                // color bar labeling
575                // 0 %
576                int textHeight = 10;
577                g2.setColor( colorBarTextcolor );
578                g2.drawLine(pixelsFromLeft-1, totHeight-pixelsFromBottom+colorBarTextSpacing, pixelsFromLeft-1,totHeight-pixelsFromBottom-colorBarHeight);
579                g2.drawString(colorBarNumberFormat.format(minNotZeroVal*24*60*60) + " sec", pixelsFromLeft-1, totHeight-pixelsFromBottom+colorBarTextSpacing+textHeight);
580                
581                // at 100%
582                g2.setColor( Color.BLACK );
583                g2.drawLine(pixelsFromLeft+colorBarLen, totHeight-pixelsFromBottom+colorBarTextSpacing, pixelsFromLeft+colorBarLen,totHeight-pixelsFromBottom-colorBarHeight);
584                g2.drawString(colorBarNumberFormat.format(maxVal*24*60*60), pixelsFromLeft+colorBarLen, totHeight-pixelsFromBottom+colorBarTextSpacing+textHeight);
585                
586            } // showColorBar
587            
588        } // draw 2d
589        
590        // draw 3d
591        public void draw3d()
592        {
593            
594        } // draw 3d
595    */ 
596        // Settings ==================================
597        
598        public void addSatToCoverageAnaylsis(String satName)
599        {
600            // first check to make sure sat isn't already in list
601            for(String name : satsUsedInCoverage)
602            {
603                if(satName.equalsIgnoreCase(name))
604                {
605                    return; // already in the list
606                }
607            }
608            
609            satsUsedInCoverage.add(satName);
610        } // addSatToCoverageAnaylsis
611        
612        public void clearSatCoverageVector()
613        {
614            satsUsedInCoverage.clear();
615        }
616        
617        public void removeSatFromCoverageAnaylsis(String satName)
618        {
619            // make sure name is in the Vector
620            int i=0; // counter
621            for(String name : satsUsedInCoverage)
622            {
623                if(satName.equalsIgnoreCase(name))
624                {
625                    satsUsedInCoverage.remove(i);
626                    return; // already in the list
627                }
628                i++;
629            }
630        } // removeSatFromCoverageAnaylsis
631        
632        public Vector<String> getSatVector()
633        {
634            return satsUsedInCoverage;
635        }
636        
637        // ======================================================
638    /*
639        public void setColorMap(ColorMap colorMap)
640        {
641            this.colorMap = colorMap;
642        }
643        
644        public ColorMap getColorMap()
645        {
646            return colorMap;
647        }
648    */
649        public int getLatPanels()
650        {
651            return latPanels;
652        }
653    
654        public void setLatPanels(int latPanels)
655        {
656            this.latPanels = latPanels;
657        }
658    
659        public int getLongPanels()
660        {
661            return longPanels;
662        }
663    
664        public void setLongPanels(int longPanels)
665        {
666            this.longPanels = longPanels;
667        }
668    
669        public double[] getLatBounds()
670        {
671            return latBounds;
672        }
673    
674        public void setLatBounds(double[] latBounds)
675        {
676            this.latBounds = latBounds;
677        }
678    
679        public double[] getLongBounds()
680        {
681            return longBounds;
682        }
683    
684        public void setLongBounds(double[] longBounds)
685        {
686            this.longBounds = longBounds;
687        }
688    
689        public int getAlpha()
690        {
691            return alpha;
692        }
693    
694        public void setAlpha(int alpha)
695        {
696            this.alpha = alpha;
697        }
698    
699        public boolean isDynamicUpdating()
700        {
701            return dynamicUpdating;
702        }
703    
704        public void setDynamicUpdating(boolean dynamicUpdating)
705        {
706            this.dynamicUpdating = dynamicUpdating;
707        }
708    
709        public boolean isPlotCoverageGrid()
710        {
711            return plotCoverageGrid;
712        }
713    
714        public void setPlotCoverageGrid(boolean plotCoverageGrid)
715        {
716            this.plotCoverageGrid = plotCoverageGrid;
717        }
718    
719        public double getElevationLimit()
720        {
721            return elevationLimit;
722        }
723    
724        public void setElevationLimit(double elevationLimit)
725        {
726            this.elevationLimit = elevationLimit;
727        }
728    
729        public NumberFormat getColorBarNumberFormat()
730        {
731            return colorBarNumberFormat;
732        }
733    
734        public void setColorBarNumberFormat(NumberFormat colorBarNumberFormat)
735        {
736            this.colorBarNumberFormat = colorBarNumberFormat;
737        }
738    
739        public boolean isShowColorBar()
740        {
741            return showColorBar;
742        }
743    
744        public void setShowColorBar(boolean showColorBar)
745        {
746            this.showColorBar = showColorBar;
747        }
748    
749        public int getPixelsFromBottom()
750        {
751            return pixelsFromBottom;
752        }
753    
754        public void setPixelsFromBottom(int pixelsFromBottom)
755        {
756            this.pixelsFromBottom = pixelsFromBottom;
757        }
758    
759        public int getPixelsFromLeft()
760        {
761            return pixelsFromLeft;
762        }
763    
764        public void setPixelsFromLeft(int pixelsFromLeft)
765        {
766            this.pixelsFromLeft = pixelsFromLeft;
767        }
768    
769        public int getColorBarLen()
770        {
771            return colorBarLen;
772        }
773    
774        public void setColorBarLen(int colorBarLen)
775        {
776            this.colorBarLen = colorBarLen;
777        }
778    
779        public int getColorBarHeight()
780        {
781            return colorBarHeight;
782        }
783    
784        public void setColorBarHeight(int colorBarHeight)
785        {
786            this.colorBarHeight = colorBarHeight;
787        }
788    
789        public int getColorBarTextSpacing()
790        {
791            return colorBarTextSpacing;
792        }
793    
794        public void setColorBarTextSpacing(int colorBarTextSpacing)
795        {
796            this.colorBarTextSpacing = colorBarTextSpacing;
797        }
798    
799        public Color getColorbarBGcolor()
800        {
801            return colorbarBGcolor;
802        }
803    
804        public void setColorbarBGcolor(Color colorbarBGcolor)
805        {
806            this.colorbarBGcolor = colorbarBGcolor;
807        }
808    
809        public Color getColorBarTextcolor()
810        {
811            return colorBarTextcolor;
812        }
813    
814        public void setColorBarTextcolor(Color colorBarTextcolor)
815        {
816            this.colorBarTextcolor = colorBarTextcolor;
817        }
818    
819        public double[][] getCoverageCumTime()
820        {
821            return coverageCumTime;
822        }
823    
824        public double[] getLatPanelMidPoints()
825        {
826            return latPanelMidPoints;
827        }
828    
829        public double[] getLonPanelMidPoints()
830        {
831            return lonPanelMidPoints;
832        }
833    
834        public double[] getLatGridPoints()
835        {
836            return latGridPoints;
837        }
838    
839        public double[] getLonGridPoints()
840        {
841            return lonGridPoints;
842        }
843    /*
844        public Color getColorForIndex(int i, int j)
845        {
846            return colorMap.getColor(getCoverageCumTime()[i][j], minNotZeroVal, maxVal);
847        }
848    */
849        public double getMinNotZeroVal()
850        {
851            return minNotZeroVal;
852        }
853    
854        public double getMaxVal()
855        {
856            return maxVal;
857        }
858        
859        public String getLowerBoundLabel()
860        {
861            return colorBarNumberFormat.format(minNotZeroVal*24*60*60) + " sec";
862        }
863        
864        public String getUpperBoundLabel()
865        {
866            return colorBarNumberFormat.format(maxVal*24*60*60);
867        }
868    
869        public Time getStartTime() {
870            return startTime;
871        }
872    
873        public double getLastMJD() {
874            return lastMJD;
875        }
876        
877    } // CoverageAnalyzer