001/*
002 * This file is part of McIDAS-V
003 *
004 * Copyright 2007-2024
005 * Space Science and Engineering Center (SSEC)
006 * University of Wisconsin - Madison
007 * 1225 W. Dayton Street, Madison, WI 53706, USA
008 * https://www.ssec.wisc.edu/mcidas/
009 * 
010 * All Rights Reserved
011 * 
012 * McIDAS-V is built on Unidata's IDV and SSEC's VisAD libraries, and
013 * some McIDAS-V source code is based on IDV and VisAD source code.  
014 * 
015 * McIDAS-V is free software; you can redistribute it and/or modify
016 * it under the terms of the GNU Lesser Public License as published by
017 * the Free Software Foundation; either version 3 of the License, or
018 * (at your option) any later version.
019 * 
020 * McIDAS-V is distributed in the hope that it will be useful,
021 * but WITHOUT ANY WARRANTY; without even the implied warranty of
022 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
023 * GNU Lesser Public License for more details.
024 * 
025 * You should have received a copy of the GNU Lesser Public License
026 * along with this program.  If not, see https://www.gnu.org/licenses/.
027 */
028
029package edu.wisc.ssec.mcidasv.adt;
030
031import java.io.File;
032import java.io.IOException;
033import java.util.Scanner;
034
035import org.slf4j.Logger;
036import org.slf4j.LoggerFactory;
037
038public class Forecasts {
039
040    private static final Logger logger = LoggerFactory.getLogger(Forecasts.class);
041
042    private static double ForecastLatitudes[] = new double[10];
043
044    private static double ForecastLongitudes[] = new double[10];
045
046    private static double ForecastTimes[] = new double[10];
047
048    private static String[] MonthID_StringX = { "JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL",
049            "AUG", "SEP", "OCT", "NOV", "DEC" };
050
051    public Forecasts() {
052    }
053
054    public static double[] ReadForecasts(String ForecastFileName, int ForecastFileType,
055            double ThresholdTime) throws IOException {
056        String delims = "[, ]+";
057
058        double ReturnLatitudeInterpolation = -999.5;
059        double ReturnLongitudeInterpolation = -999.5;
060        double ReturnCurrentIntensity = -999.5;
061        double CurrentDayValue;
062        int ReturnFlagValue = -1;
063        String TmpStr1;
064        String TmpStr2;
065        String TmpStr3;
066        String TmpStr4;
067        String TmpStr5;
068        String TmpStr6;
069        String TmpStr7;
070        String TmpStr8;
071        String TmpStr9;
072        String TmpStr12;
073        int WindVal;
074        int YearIntVal;
075        int MonthIntVal;
076        int DayIntVal;
077        int HMSTimeIntVal;
078        int FcstTimeIntVal;
079        int JulianDayIntVal;
080        int FcstTimeIntValPrev;
081        int LocVar1, LocVar2;
082        int DayIntValXX;
083        int MonthIntValXX;
084        int YearIntValXX;
085        int JulianDayIntValXX;
086        double TimeArray[] = new double[10];
087        double LatitudeArray[] = new double[10];
088        double LongitudeArray[] = new double[10];
089        double StrengthArray[] = new double[10];
090        double TmpTimeVal2;
091        double NSFactor;
092        double WEFactor;
093
094        ReturnFlagValue = 0;
095
096        logger.debug("ReadForecasts in...");
097        System.out.printf("Forecast File Name=%s Type=%d\n", ForecastFileName, ForecastFileType);
098        File forecastfile = new File(ForecastFileName);
099        Scanner in = new Scanner(forecastfile);
100
101        int ImageDate = Data.IRData_JulianDate;
102        int ImageTime = Data.IRData_HHMMSSTime;
103        System.out.printf("IMAGE DATE=%d  TIME=%d\n", Data.IRData_JulianDate,
104                Data.IRData_HHMMSSTime);
105        /* int ImageDate = History.IRCurrentRecord.date; */
106        /* int ImageTime = History.IRCurrentRecord.time; */
107        double CurrentTime = Functions.calctime(ImageDate, ImageTime);
108        int XInc = 0;
109        int YInc = 0;
110        FcstTimeIntValPrev = -1;
111
112        try {
113
114            /* char aChar = ATCFStormIDString.charAt(2); */
115            if (ForecastFileType == 0) {
116                while (in.hasNextLine()) {
117                    String forecastRec = in.nextLine();
118                    String[] tokens = forecastRec.split(delims);
119                    TmpStr1 = tokens[0];
120                    TmpStr2 = tokens[1];
121                    TmpStr3 = tokens[2];
122                    TmpStr4 = tokens[3];
123                    TmpStr5 = tokens[4];
124                    TmpStr6 = tokens[5];
125                    TmpStr7 = tokens[6];
126                    TmpStr8 = tokens[7];
127                    TmpStr9 = tokens[8];
128                    TmpStr12 = tokens[11];
129                    WindVal = 0;
130                    if ((TmpStr12.length() > 1) && (TmpStr12.matches("\\d+"))) {
131                        WindVal = Integer.parseInt(TmpStr12.substring(0, 2)); /*
132                                                                               * (
133                                                                               * int
134                                                                               * )
135                                                                               * aodt_atoif
136                                                                               * (
137                                                                               * TmpStr12
138                                                                               * ,
139                                                                               * 1
140                                                                               * ,
141                                                                               * 2
142                                                                               * )
143                                                                               * ;
144                                                                               */
145                    }
146                    /*
147                     * System.out.printf(
148                     * "1=%s* 2=%s* 3=%s* 4=%s* 5=%s* 6=%s* 7=%s* 8=%s* 9=%s* 10=%s* 11=%s* 12=%s* \n"
149                     * ,
150                     * TmpStr1,TmpStr2,TmpStr3,TmpStr4,TmpStr5,TmpStr6,TmpStr7,
151                     * TmpStr8,TmpStr9,TmpStr10,TmpStr11,TmpStr12);
152                     */
153                    if (WindVal == 34) {
154                        YearIntVal = Integer.parseInt(TmpStr3.substring(0, 4)); /*
155                                                                                 * (
156                                                                                 * int
157                                                                                 * )
158                                                                                 * aodt_atoif
159                                                                                 * (
160                                                                                 * TmpStr3
161                                                                                 * ,
162                                                                                 * 1
163                                                                                 * ,
164                                                                                 * 4
165                                                                                 * )
166                                                                                 * ;
167                                                                                 */
168                        MonthIntVal = Integer.parseInt(TmpStr3.substring(4, 6)); /*
169                                                                                  * (
170                                                                                  * int
171                                                                                  * )
172                                                                                  * aodt_atoif
173                                                                                  * (
174                                                                                  * TmpStr3
175                                                                                  * ,
176                                                                                  * 5
177                                                                                  * ,
178                                                                                  * 6
179                                                                                  * )
180                                                                                  * ;
181                                                                                  */
182                        DayIntVal = Integer.parseInt(TmpStr3.substring(6, 8)); /*
183                                                                                * (
184                                                                                * int
185                                                                                * )
186                                                                                * aodt_atoif
187                                                                                * (
188                                                                                * TmpStr3
189                                                                                * ,
190                                                                                * 7
191                                                                                * ,
192                                                                                * 8
193                                                                                * )
194                                                                                * ;
195                                                                                */
196                        /*
197                         * System.out.printf("year=%d month=%d day=%d\n",YearIntVal
198                         * ,MonthIntVal,DayIntVal);
199                         */
200                        HMSTimeIntVal = 10000 * Integer.parseInt(TmpStr3.substring(8, 10)); /*
201                                                                                             * 10000
202                                                                                             * *
203                                                                                             * (
204                                                                                             * (
205                                                                                             * int
206                                                                                             * )
207                                                                                             * aodt_atoif
208                                                                                             * (
209                                                                                             * TmpStr3
210                                                                                             * ,
211                                                                                             * 9
212                                                                                             * ,
213                                                                                             * 10
214                                                                                             * )
215                                                                                             * )
216                                                                                             * ;
217                                                                                             */
218                        FcstTimeIntVal = 10000 * Integer.parseInt(TmpStr6); /*
219                                                                             * 10000
220                                                                             * *
221                                                                             * (
222                                                                             * (
223                                                                             * int
224                                                                             * )
225                                                                             * aodt_atoif
226                                                                             * (
227                                                                             * TmpStr6
228                                                                             * ,
229                                                                             * 1
230                                                                             * ,
231                                                                             * strlen
232                                                                             * (
233                                                                             * TmpStr6
234                                                                             * )
235                                                                             * )
236                                                                             * )
237                                                                             * ;
238                                                                             */
239                        JulianDayIntVal = Functions.idmyyd(DayIntVal, MonthIntVal, YearIntVal);
240                        TmpTimeVal2 = Functions.calctime(JulianDayIntVal, HMSTimeIntVal);
241                        /*
242                         * System.out.printf("YInc=%d tmptime=%f\n",YInc,TmpTimeVal2
243                         * );
244                         */
245                        if ((TmpTimeVal2 < CurrentTime) && (FcstTimeIntValPrev != FcstTimeIntVal)
246                                && (YInc < 6)) {
247                            LocVar1 = ((int) (FcstTimeIntVal + HMSTimeIntVal)) / 240000;
248                            LocVar2 = (((int) (FcstTimeIntVal + HMSTimeIntVal)) % 240000);
249                            TimeArray[YInc] = Functions
250                                    .calctime(JulianDayIntVal + LocVar1, LocVar2);
251                            NSFactor = (TmpStr7.charAt(TmpStr7.length() - 1) == 'N') ? 1.0 : -1.0;
252                            WEFactor = (TmpStr8.charAt(TmpStr8.length() - 1) == 'W') ? 1.0 : -1.0;
253                            LatitudeArray[YInc] = NSFactor
254                                    * Double.parseDouble(TmpStr7.substring(0, TmpStr7.length() - 1))
255                                    / 10.0; /*
256                                             * (aodt_atoif(TmpStr7,1,strlen(TmpStr7
257                                             * )))/10.0;
258                                             */
259                            LongitudeArray[YInc] = WEFactor
260                                    * Double.parseDouble(TmpStr8.substring(0, TmpStr8.length() - 1))
261                                    / 10.0; /*
262                                             * (aodt_atoif(TmpStr8,1,strlen(TmpStr8
263                                             * )))/10.0;
264                                             */
265                            StrengthArray[YInc] = Double.parseDouble(TmpStr9); /*
266                                                                                * aodt_atoif
267                                                                                * (
268                                                                                * TmpStr9
269                                                                                * ,
270                                                                                * 1
271                                                                                * ,
272                                                                                * 4
273                                                                                * )
274                                                                                * ;
275                                                                                */
276                            YInc++;
277                            FcstTimeIntValPrev = FcstTimeIntVal;
278                            XInc = YInc;
279                        }
280                    }
281                }
282            } else if (ForecastFileType == 1) { /* NHC */
283                /* read NHC forecast file, quit at EOF */
284                DayIntValXX = 0;
285                MonthIntValXX = 0;
286                YearIntValXX = 0;
287                JulianDayIntValXX = 0;
288                DayIntVal = 0;
289                MonthIntVal = 0;
290                YearIntVal = 0;
291                JulianDayIntVal = 0;
292                boolean NewNHCFormatFlag = false;
293                boolean FoundMonthTF = false;
294                boolean FoundForecast = false;
295                while ((in.hasNextLine()) && (XInc < 6)) {
296                    String forecastRec = in.nextLine();
297                    String[] tokens = forecastRec.split(delims);
298                    if (!FoundMonthTF) {
299                        if ((tokens.length == 7)
300                                && (tokens[1].equals("AM") || tokens[1].equals("PM"))) {
301                            /*
302                             * this is reading the header at the top of the
303                             * forecast file. It is done to obtain the current
304                             * month and year of the forecast so that we can
305                             * check it accurately against the image date/time
306                             */
307                            DayIntValXX = Integer.parseInt(tokens[5].substring(0, 2)); /*
308                                                                                        * (
309                                                                                        * int
310                                                                                        * )
311                                                                                        * aodt_atoif
312                                                                                        * (
313                                                                                        * TmpStr6
314                                                                                        * ,
315                                                                                        * 1
316                                                                                        * ,
317                                                                                        * 2
318                                                                                        * )
319                                                                                        * ;
320                                                                                        */
321                            YearIntValXX = Integer.parseInt(tokens[6].substring(0, 4)); /*
322                                                                                         * (
323                                                                                         * int
324                                                                                         * )
325                                                                                         * aodt_atoif
326                                                                                         * (
327                                                                                         * TmpStr7
328                                                                                         * ,
329                                                                                         * 1
330                                                                                         * ,
331                                                                                         * 4
332                                                                                         * )
333                                                                                         * ;
334                                                                                         */
335                            while ((!tokens[4].equals(MonthID_StringX[MonthIntValXX]))
336                                    && (MonthIntValXX < 12)) {
337                                MonthIntValXX++;
338                            }
339                            JulianDayIntValXX = Functions.idmyyd(DayIntValXX, MonthIntValXX + 1,
340                                    YearIntValXX);
341                            FoundMonthTF = true;
342                            /*
343                             * System.out.printf(
344                             * "XX julday=%d day=%d month=%d year=%d\n"
345                             * ,JulianDayIntValXX
346                             * ,DayIntValXX,MonthIntValXX+1,YearIntValXX);
347                             */
348                        }
349                        MonthIntVal = MonthIntValXX;
350                        YearIntVal = YearIntValXX;
351                    } else {
352                        if ((FoundForecast) && (tokens.length >= 6)) {
353                            /* System.out.printf("length=%d\n",tokens.length); */
354                            if (XInc == 0) {
355                                if (tokens[0].equals("INITIAL")) {
356                                    NewNHCFormatFlag = false;
357                                } else if ((tokens[0].equals("INIT")) && (YearIntVal >= 2011)) {
358                                    NewNHCFormatFlag = true;
359                                } else {
360                                    NewNHCFormatFlag = false;
361                                }
362                                /*
363                                 * System.out.printf("newformatflag=%b\n",
364                                 * NewNHCFormatFlag);
365                                 */
366                            }
367                            int iadd = (tokens[0].length() == 0) ? 1 : 0;
368                            if ((NewNHCFormatFlag) || ((!NewNHCFormatFlag) && (XInc == 0))) {
369                                TmpStr1 = tokens[0 + iadd];
370                                TmpStr2 = tokens[1 + iadd];
371                                TmpStr3 = tokens[2 + iadd];
372                                TmpStr4 = tokens[3 + iadd];
373                                TmpStr5 = tokens[4 + iadd];
374                                TmpStr6 = tokens[5 + iadd];
375                            } else {
376                                TmpStr1 = tokens[0 + iadd];
377                                TmpStr2 = tokens[2 + iadd];
378                                TmpStr3 = tokens[3 + iadd];
379                                TmpStr4 = tokens[4 + iadd];
380                                TmpStr5 = tokens[5 + iadd];
381                                TmpStr6 = tokens[6 + iadd];
382                            }
383                            /*
384                             * System.out.printf(
385                             * "1=%s* 1a=%s* 2=%s* 3=%s* 4=%s* 5=%s* 6=%s*\n"
386                             * ,TmpStr1
387                             * ,TmpStr1a,TmpStr2,TmpStr3,TmpStr4,TmpStr5,
388                             * TmpStr6);
389                             */
390                            if (TmpStr6.substring(0, 2).equals("KT")) {
391                                if (TmpStr2.charAt(7) == 'Z') {
392                                    DayIntVal = Integer.parseInt(TmpStr2.substring(0, 2)); /*
393                                                                                            * (
394                                                                                            * (
395                                                                                            * int
396                                                                                            * )
397                                                                                            * aodt_atoif
398                                                                                            * (
399                                                                                            * TmpStr2
400                                                                                            * ,
401                                                                                            * 1
402                                                                                            * ,
403                                                                                            * 7
404                                                                                            * )
405                                                                                            * )
406                                                                                            * /
407                                                                                            * 10000
408                                                                                            * ;
409                                                                                            */
410                                    HMSTimeIntVal = 100 * (Integer
411                                            .parseInt(TmpStr2.substring(3, 7))); /*
412                                                                                  * 100
413                                                                                  * *
414                                                                                  * (
415                                                                                  * (
416                                                                                  * (
417                                                                                  * int
418                                                                                  * )
419                                                                                  * aodt_atoif
420                                                                                  * (
421                                                                                  * TmpStr2
422                                                                                  * ,
423                                                                                  * 1
424                                                                                  * ,
425                                                                                  * 7
426                                                                                  * )
427                                                                                  * )
428                                                                                  * %
429                                                                                  * 10000
430                                                                                  * )
431                                                                                  * ;
432                                                                                  */
433                                    if (DayIntVal < DayIntValXX) {
434                                        MonthIntVal++;
435                                        if (MonthIntVal == 12) {
436                                            YearIntVal++;
437                                            MonthIntVal = 0;
438                                        }
439                                        JulianDayIntVal = Functions.idmyyd(DayIntVal,
440                                                MonthIntVal + 1, YearIntVal);
441                                    } else {
442                                        JulianDayIntVal = JulianDayIntValXX
443                                                + (DayIntVal - DayIntValXX);
444                                    }
445                                    TimeArray[XInc] = Functions.calctime(JulianDayIntVal,
446                                            HMSTimeIntVal);
447                                    NSFactor = (TmpStr3.charAt(TmpStr3.length() - 1) == 'N') ? 1.0
448                                            : -1.0;
449                                    WEFactor = (TmpStr4.charAt(TmpStr4.length() - 1) == 'W') ? 1.0
450                                            : -1.0;
451                                    LatitudeArray[XInc] = NSFactor
452                                            * Double.parseDouble(TmpStr3.substring(0,
453                                                    TmpStr3.length() - 1));
454                                    LongitudeArray[XInc] = WEFactor
455                                            * Double.parseDouble(TmpStr4.substring(0,
456                                                    TmpStr4.length() - 1));
457                                    StrengthArray[XInc] = Integer.parseInt(TmpStr5);
458                                    XInc++;
459                                }
460                            }
461                        } else {
462                            if (tokens[0].equals("FORECAST") && tokens[1].equals("POSITIONS"))
463                                FoundForecast = true;
464                        }
465                    }
466                }
467            } else if (ForecastFileType == 2) {
468                /*
469                 * read JTWC forecast file, quit at EOF
470                 * 
471                 * o.k... since JTWC does not put the month and year on their
472                 * bulletins, they will need to be "made up". We will assume
473                 * that the forecast is current and the month and year from the
474                 * image is equal to the month and year of the forecast file.
475                 */
476                int[] ReturnValues = Functions.adt_yddmy((int) CurrentTime);
477                DayIntValXX = ReturnValues[0];
478                MonthIntValXX = ReturnValues[1];
479                YearIntValXX = ReturnValues[2];
480                /* System.out.printf("DayIntValXX=%d\n",DayIntValXX); */
481                /* System.out.printf("MonthIntValXX=%d\n",MonthIntValXX); */
482                /* System.out.printf("YearIntValXX=%d\n",YearIntValXX); */
483                int datexxx = 0;
484                int monthxxx = 0;
485                int yearxxx = 0;
486                int DayIntValSub = 0;
487                JulianDayIntVal = 0;
488                while (in.hasNextLine()) {
489                    String forecastRec = in.nextLine();
490                    String[] tokens = forecastRec.split(delims);
491                    if (tokens.length >= 5) {
492                        int iadd = (tokens[0].length() == 0) ? 1 : 0;
493                        TmpStr1 = tokens[0 + iadd];
494                        TmpStr2 = tokens[1 + iadd];
495                        TmpStr3 = tokens[2 + iadd];
496                        TmpStr4 = tokens[3 + iadd];
497                        if (TmpStr2.equals("---")) {
498                            if (XInc == 0) {
499                                TmpStr5 = tokens[4 + iadd];
500                                /*
501                                 * System.out.printf(
502                                 * "XInc=%d : 1=%s* 2=%s* 3=%s* 4=%s* 5=%s* \n"
503                                 * ,XInc
504                                 * ,TmpStr1,TmpStr2,TmpStr3,TmpStr4,TmpStr5);
505                                 */
506                                DayIntVal = Integer.parseInt(TmpStr1.substring(0, 2));
507                                HMSTimeIntVal = 100 * Integer.parseInt(TmpStr1.substring(2, 6));
508                                /*
509                                 * System.out.printf(
510                                 * "dayintval=%d hmstimeintval=%d\n"
511                                 * ,DayIntVal,HMSTimeIntVal);
512                                 */
513                                DayIntValSub = DayIntValXX - DayIntVal;
514                                int[] ReturnValues2 = Functions.adt_yddmy(ImageDate);
515                                datexxx = ReturnValues2[0];
516                                monthxxx = ReturnValues2[1];
517                                yearxxx = ReturnValues2[2];
518                                if (DayIntVal == DayIntValXX) {
519                                    /*
520                                     * dates are the same... probably o.k....
521                                     * should check times
522                                     */
523                                    JulianDayIntVal = (int) CurrentTime;
524                                } else if ((DayIntValSub <= 2) && (DayIntValSub >= 0)) {
525                                    /*
526                                     * this is probably o.k too... should check
527                                     * times
528                                     */
529                                    JulianDayIntVal = (int) CurrentTime + (DayIntVal - DayIntValXX);
530                                } else {
531                                    /*
532                                     * dates are invalid. Either image date is
533                                     * before forecast or is well beyond
534                                     * forecast availability
535                                     */
536                                    if (DayIntValSub < -27) {
537                                        /*
538                                         * System.out.printf("month crossing\n");
539                                         */
540                                        /*
541                                         * System.out.printf("datexxx=%d\n",datexxx
542                                         * );
543                                         */
544                                        if ((datexxx <= 2) && (monthxxx == 1)) {
545                                            /*
546                                             * System.out.printf(
547                                             * "year crossing... image during new year: %d %d\n"
548                                             * ,yearxxx-1,DayIntVal);
549                                             */
550                                            JulianDayIntVal = Functions.idmyyd(DayIntVal, 12,
551                                                    yearxxx - 1);
552                                        } else {
553                                            JulianDayIntVal = Functions.idmyyd(DayIntVal,
554                                                    monthxxx - 1, yearxxx);
555                                        }
556                                        /*
557                                         * System.out.printf("JulianDayIntVal=%d\n"
558                                         * ,JulianDayIntVal);
559                                         */
560                                    } else {
561                                        ReturnFlagValue = -1;
562                                    }
563                                }
564                                /*
565                                 * System.out.printf("JulianDayIntVal=%d\n",
566                                 * JulianDayIntVal);
567                                 */
568                                TimeArray[XInc] = Functions
569                                        .calctime(JulianDayIntVal, HMSTimeIntVal);
570                                /*
571                                 * System.out.printf("TimeArray[%d]=%f\n",XInc,
572                                 * TimeArray[XInc]);
573                                 */
574                                NSFactor = (TmpStr4.charAt(TmpStr4.length() - 1) == 'N') ? 1.0
575                                        : -1.0;
576                                WEFactor = (TmpStr5.charAt(TmpStr5.length() - 1) == 'W') ? 1.0
577                                        : -1.0;
578                                LatitudeArray[XInc] = NSFactor
579                                        * Double.parseDouble(TmpStr4.substring(0,
580                                                TmpStr4.length() - 1));
581                                LongitudeArray[XInc] = WEFactor
582                                        * Double.parseDouble(TmpStr5.substring(0,
583                                                TmpStr5.length() - 1));
584                            } else {
585                                /*
586                                 * System.out.printf(
587                                 * "XInc=%d : 1=%s* 2=%s* 3=%s* 4=%s* \n"
588                                 * ,XInc,TmpStr1,TmpStr2,TmpStr3,TmpStr4);
589                                 */
590                                DayIntVal = Integer.parseInt(TmpStr1.substring(0, 2));
591                                HMSTimeIntVal = 100 * Integer.parseInt(TmpStr1.substring(2, 6));
592                                /*
593                                 * System.out.printf(
594                                 * "dayintval=%d hmstimeintval=%d\n"
595                                 * ,DayIntVal,HMSTimeIntVal);
596                                 */
597                                DayIntValSub = DayIntValXX - DayIntVal;
598                                if (DayIntValSub < -27) {
599                                    if ((monthxxx - 1) == 0) {
600                                        JulianDayIntVal = Functions.idmyyd(DayIntVal, 12,
601                                                yearxxx - 1);
602                                    } else {
603                                        JulianDayIntVal = Functions.idmyyd(DayIntVal, monthxxx - 1,
604                                                yearxxx);
605                                    }
606                                } else {
607                                    if (DayIntValSub > 27) {
608                                        if ((monthxxx + 1) > 12) {
609                                            JulianDayIntVal = Functions.idmyyd(DayIntVal, 1,
610                                                    yearxxx + 1);
611                                        } else {
612                                            JulianDayIntVal = Functions.idmyyd(DayIntVal,
613                                                    monthxxx + 1, yearxxx);
614                                        }
615                                    } else {
616                                        JulianDayIntVal = Functions.idmyyd(DayIntVal, monthxxx,
617                                                yearxxx);
618                                    }
619                                }
620                                /*
621                                 * System.out.printf("JulianDayIntVal=%d\n",
622                                 * JulianDayIntVal);
623                                 */
624                                TimeArray[XInc] = Functions
625                                        .calctime(JulianDayIntVal, HMSTimeIntVal);
626                                /*
627                                 * System.out.printf("TimeArray[%d]=%f\n",XInc,
628                                 * TimeArray[XInc]);
629                                 */
630                                NSFactor = (TmpStr3.charAt(TmpStr3.length() - 1) == 'N') ? 1.0
631                                        : -1.0;
632                                WEFactor = (TmpStr4.charAt(TmpStr4.length() - 1) == 'W') ? 1.0
633                                        : -1.0;
634                                LatitudeArray[XInc] = NSFactor
635                                        * Double.parseDouble(TmpStr3.substring(0,
636                                                TmpStr3.length() - 1));
637                                LongitudeArray[XInc] = WEFactor
638                                        * Double.parseDouble(TmpStr4.substring(0,
639                                                TmpStr4.length() - 1));
640                            }
641                        }
642                        if ((TmpStr1.equals("MAX")) && (TmpStr4.charAt(0) == '-')) {
643                            TmpStr5 = tokens[4 + iadd];
644                            if (XInc == 0) {
645                                StrengthArray[XInc] = Double.parseDouble(TmpStr5);
646                            }
647                            XInc++;
648                        }
649                    }
650                }
651            } else if (ForecastFileType == 3) {
652                /* generic forecast file input */
653                while (in.hasNextLine()) {
654                    String forecastRec = in.nextLine();
655                    String[] tokens = forecastRec.split(delims);
656                    if (tokens.length >= 5) {
657                        TmpStr1 = tokens[0];
658                        TmpStr2 = tokens[1];
659                        TmpStr3 = tokens[2];
660                        TmpStr4 = tokens[3];
661                        TmpStr5 = tokens[4];
662                        TmpStr6 = tokens[5];
663                        TmpStr7 = tokens[6];
664                        DayIntVal = Integer.parseInt(TmpStr1.substring(0, 2));
665                        MonthIntVal = Integer.parseInt(TmpStr2.substring(0, 2));
666                        YearIntVal = Integer.parseInt(TmpStr3.substring(0, 4));
667                        HMSTimeIntVal = 100 * Integer.parseInt(TmpStr4.substring(0, 4));
668                        JulianDayIntVal = Functions.idmyyd(DayIntVal, MonthIntVal, YearIntVal);
669                        TimeArray[XInc] = Functions.calctime(JulianDayIntVal, HMSTimeIntVal);
670                        NSFactor = (TmpStr5.charAt(TmpStr5.length() - 1) == 'N') ? 1.0 : -1.0;
671                        WEFactor = (TmpStr6.charAt(TmpStr6.length() - 1) == 'W') ? 1.0 : -1.0;
672                        LatitudeArray[XInc] = NSFactor
673                                * Double.parseDouble(TmpStr5.substring(0, TmpStr5.length() - 1));
674                        LongitudeArray[XInc] = WEFactor
675                                * Double.parseDouble(TmpStr6.substring(0, TmpStr6.length() - 1));
676                        StrengthArray[XInc] = Double.parseDouble(TmpStr5);
677                        XInc++;
678                    }
679                }
680            } else if (ForecastFileType == 4) {
681                String delims4 = "[:+/ ]+";
682                /* RSMC ICAO (FK?? or WT??) forecast file input */
683                /*
684                 * Convert the ICAO RSMC bulletin positions from degrees minutes
685                 * to degrees and tenths of degrees. fix courtesy : YanLuo/NOAA
686                 * 07/22/09 *
687                 */
688                int xxx1 = 0;
689                int xxx2 = 0;
690                double LatMultFact = 0.0;
691                double LonMultFact = 0.0;
692                while (in.hasNextLine()) {
693                    String forecastRec = in.nextLine();
694                    String[] tokens = forecastRec.split(delims4);
695                    if (tokens[0].equals("DTG")) {
696                        TmpStr1 = tokens[1];
697                        /* System.out.printf("TmpStr1=%s*\n",TmpStr1); */
698                        DayIntVal = Integer.parseInt(TmpStr1.substring(6, 8));
699                        MonthIntVal = Integer.parseInt(TmpStr1.substring(4, 6));
700                        YearIntVal = Integer.parseInt(TmpStr1.substring(0, 4));
701                        if (tokens.length == 2) {
702                            HMSTimeIntVal = 100 * Integer.parseInt(TmpStr1.substring(8, 12));
703                        } else {
704                            TmpStr2 = tokens[2];
705                            HMSTimeIntVal = 100 * Integer.parseInt(TmpStr2.substring(0, 4));
706                        }
707                        JulianDayIntVal = Functions.idmyyd(DayIntVal, MonthIntVal, YearIntVal);
708                        TimeArray[XInc] = Functions.calctime(JulianDayIntVal, HMSTimeIntVal);
709                        /*
710                         * System.out.printf("time0=%f  hmstime=%d\n",TimeArray[XInc
711                         * ],HMSTimeIntVal);
712                         */
713                    } else if (tokens[0].equals("PSN")) {
714                        TmpStr1 = tokens[1];
715                        TmpStr2 = tokens[2];
716                        LatMultFact = (TmpStr1.charAt(0) == 'N') ? 1.0 : -1.0;
717                        LonMultFact = (TmpStr2.charAt(0) == 'W') ? 1.0 : -1.0;
718                        xxx1 = Integer.parseInt(TmpStr1.substring(1, TmpStr1.length()));
719                        xxx2 = Integer.parseInt(TmpStr2.substring(1, TmpStr2.length()));
720                        /* initial lat/lon */
721                        double LatitudeWhole = ((double) xxx1) / 100.0;
722                        double LatitudePart = ((double) xxx1 - (LatitudeWhole * 100.0)) / 60.0;
723                        LatitudeArray[XInc] = LatMultFact * (LatitudeWhole + LatitudePart);
724                        double LongitudeWhole = ((double) xxx2) / 100.0;
725                        double LongitudePart = ((double) xxx2 - (LongitudeWhole * 100.0)) / 60.0;
726                        LongitudeArray[XInc] = LonMultFact * (LongitudeWhole + LongitudePart);
727                        XInc++;
728                    } else if ((tokens[0].equals("MAX")) && (XInc == 0)) {
729                        /* initial lat/lon */
730                        TmpStr1 = tokens[2];
731                        StrengthArray[XInc] = Double.parseDouble(TmpStr1.substring(0,
732                                TmpStr1.length() - 2));
733                    } else if ((tokens[0].equals("FCST")) && (tokens[1].equals("PSN"))) {
734                        int numtokens = tokens.length;
735                        TmpStr1 = tokens[2];
736                        TmpStr2 = tokens[numtokens - 2];
737                        TmpStr3 = tokens[numtokens - 1];
738                        /*
739                         * System.out.printf("1=%s* 2=%s* 3=%s*\n",TmpStr1,TmpStr2
740                         * ,TmpStr3);
741                         */
742                        LatMultFact = (TmpStr2.charAt(0) == 'N') ? 1.0 : -1.0;
743                        LonMultFact = (TmpStr3.charAt(0) == 'W') ? 1.0 : -1.0;
744                        xxx1 = Integer.parseInt(TmpStr2.substring(1, TmpStr2.length()));
745                        xxx2 = Integer.parseInt(TmpStr3.substring(1, TmpStr3.length()));
746                        int FcstHrAddIntVal = Integer.parseInt(TmpStr1.substring(0, 2));
747                        /* initial lat/lon */
748                        double LatitudeWhole = ((double) xxx1) / 100.0;
749                        double LatitudePart = ((double) xxx1 - (LatitudeWhole * 100.0)) / 60.0;
750                        LatitudeArray[XInc] = LatMultFact * (LatitudeWhole + LatitudePart);
751                        double LongitudeWhole = ((double) xxx2) / 100.0;
752                        double LongitudePart = ((double) xxx2 - (LongitudeWhole * 100.0)) / 60.0;
753                        LongitudeArray[XInc] = LonMultFact * (LongitudeWhole + LongitudePart);
754                        double FcstHrAddDblVal = ((double) FcstHrAddIntVal) / 24.0;
755                        /*
756                         * System.out.printf("XInc=%d time0=%f fcsthr=%f\n",XInc,
757                         * TimeArray[0],FcstHrAddDblVal);
758                         */
759                        TimeArray[XInc] = TimeArray[0] + FcstHrAddDblVal;
760                        XInc++;
761                    }
762                }
763            } else if (ForecastFileType == 5) {
764                /* RSMC WTIO30 forecast file input */
765                String delims5 = "[,:/= ]+";
766                while (in.hasNextLine()) {
767                    String forecastRec = in.nextLine();
768                    String[] tokens = forecastRec.split(delims5);
769                    if (tokens[0].equals("2.A")) {
770                        TmpStr1 = tokens[2];
771                        TmpStr2 = tokens[3];
772                        TmpStr3 = tokens[4];
773                        TmpStr4 = tokens[6];
774                        YearIntVal = Integer.parseInt(TmpStr1);
775                        MonthIntVal = Integer.parseInt(TmpStr2);
776                        DayIntVal = Integer.parseInt(TmpStr3);
777                        HMSTimeIntVal = 100 * Integer.parseInt(TmpStr4);
778                        JulianDayIntVal = Functions.idmyyd(DayIntVal, MonthIntVal, YearIntVal);
779                        TimeArray[XInc] = Functions.calctime(JulianDayIntVal, HMSTimeIntVal);
780                        forecastRec = in.nextLine();
781                        tokens = forecastRec.split(delims5);
782                        if (tokens.length == 2) {
783                            TmpStr1 = tokens[0];
784                            TmpStr2 = tokens[1];
785                        } else {
786                            /*
787                             * expecting line like WITHIN 20 NM RADIUS OF POINT
788                             * 22.2S / 50.8E
789                             */
790                            TmpStr1 = tokens[6];
791                            TmpStr2 = tokens[7];
792                        }
793                        NSFactor = (TmpStr1.charAt(TmpStr1.length() - 1) == 'N') ? 1.0 : -1.0;
794                        WEFactor = (TmpStr2.charAt(TmpStr2.length() - 1) == 'W') ? 1.0 : -1.0;
795                        LatitudeArray[XInc] = NSFactor
796                                * Double.parseDouble(TmpStr1.substring(0, TmpStr1.length() - 1));
797                        LongitudeArray[XInc] = WEFactor
798                                * Double.parseDouble(TmpStr2.substring(0, TmpStr2.length() - 1));
799                    } else if (tokens[0].equals("5.A")) {
800                        TmpStr1 = tokens[tokens.length - 2];
801                        StrengthArray[XInc] = Double.parseDouble(TmpStr1);
802                    } else if (tokens[0].equals("1.B")) {
803                        XInc = 1;
804                        forecastRec = in.nextLine();
805                        tokens = forecastRec.split(delims5);
806                        boolean ICAOValidFcstTF = true;
807                        while ((ICAOValidFcstTF) && (XInc < 6)) {
808                            TmpStr1 = tokens[1];
809                            TmpStr2 = tokens[2];
810                            TmpStr3 = tokens[3];
811                            TmpStr4 = tokens[4];
812                            TmpStr5 = tokens[6];
813                            TmpStr6 = tokens[7];
814                            TmpStr7 = tokens[10];
815                            YearIntVal = Integer.parseInt(TmpStr1);
816                            MonthIntVal = Integer.parseInt(TmpStr2);
817                            DayIntVal = Integer.parseInt(TmpStr3);
818                            HMSTimeIntVal = 10000 * Integer.parseInt(TmpStr4);
819                            JulianDayIntVal = Functions.idmyyd(DayIntVal, MonthIntVal, YearIntVal);
820                            TimeArray[XInc] = Functions.calctime(JulianDayIntVal, HMSTimeIntVal);
821                            NSFactor = (TmpStr5.charAt(TmpStr5.length() - 1) == 'N') ? 1.0 : -1.0;
822                            WEFactor = (TmpStr6.charAt(TmpStr6.length() - 1) == 'W') ? 1.0 : -1.0;
823                            LatitudeArray[XInc] = NSFactor
824                                    * Double.parseDouble(TmpStr5.substring(0, TmpStr5.length() - 1));
825                            LongitudeArray[XInc] = WEFactor
826                                    * Double.parseDouble(TmpStr6.substring(0, TmpStr6.length() - 1));
827                            StrengthArray[XInc] = (double) Integer
828                                    .parseInt(TmpStr7.substring(0, 3));
829                            forecastRec = in.nextLine();
830                            tokens = forecastRec.split(delims5);
831                            String TmpStr0 = tokens[0];
832                            if (tokens[0].equals("2.C")) {
833                                ICAOValidFcstTF = false;
834                            } else {
835                                if (TmpStr0.charAt(2) != 'H') {
836                                    forecastRec = in.nextLine();
837                                    ICAOValidFcstTF = false;
838                                }
839                            }
840                            XInc++;
841                        }
842                    }
843                }
844            } else if (ForecastFileType == 6) {
845                /* TCWC AXAU Tech Bulletins file input */
846                String delims6 = "[,:/ ]+";
847                JulianDayIntVal = 0;
848                MonthIntVal = 0;
849                YearIntVal = 0;
850                while (in.hasNextLine()) {
851                    String forecastRec = in.nextLine();
852                    String[] tokens = forecastRec.split(delims6);
853                    if (tokens[0].equals("at")) {
854                        /* initial date */
855                        TmpStr1 = tokens[1];
856                        TmpStr2 = tokens[3];
857                        TmpStr3 = tokens[4];
858                        TmpStr4 = tokens[5];
859                        YearIntVal = Integer.parseInt(TmpStr4);
860                        MonthIntVal = Integer.parseInt(TmpStr3);
861                        DayIntVal = Integer.parseInt(TmpStr2);
862                        /* HMSTimeIntVal = 100*Integer.parseInt(TmpStr1); */
863                        JulianDayIntVal = Functions.idmyyd(DayIntVal, MonthIntVal, YearIntVal);
864                    }
865                    if (tokens[0].equals("Data")) {
866                        /* initial time */
867                        TmpStr1 = tokens[2];
868                        HMSTimeIntVal = 100 * Integer.parseInt(TmpStr1);
869                        TimeArray[XInc] = Functions.calctime(JulianDayIntVal, HMSTimeIntVal);
870                    }
871                    if (tokens[0].equals("Latitude")) {
872                        /* initial latitude */
873                        TmpStr1 = tokens[1];
874                        NSFactor = (TmpStr1.charAt(TmpStr1.length() - 1) == 'N') ? 1.0 : -1.0;
875                        LatitudeArray[XInc] = NSFactor
876                                * Double.parseDouble(TmpStr1.substring(0, TmpStr1.length() - 1));
877                    }
878                    if (tokens[0].equals("Longitude")) {
879                        /* initial longitude */
880                        TmpStr1 = tokens[1];
881                        WEFactor = (TmpStr1.charAt(TmpStr1.length() - 1) == 'W') ? 1.0 : -1.0;
882                        LongitudeArray[XInc] = WEFactor
883                                * Double.parseDouble(TmpStr1.substring(0, TmpStr1.length() - 1));
884                    }
885                    if (tokens[0].equals("Maximum")) {
886                        if (tokens[1].equals("10-Minute")) {
887                            /* initial strength */
888                            TmpStr1 = tokens[3];
889                            StrengthArray[XInc] = (double) Integer.parseInt(TmpStr1);
890                        }
891                    }
892                    if (tokens[0].equals("FORECAST")) {
893                        XInc = 1;
894                        forecastRec = in.nextLine();
895                        forecastRec = in.nextLine();
896                        forecastRec = in.nextLine();
897                        tokens = forecastRec.split(delims6);
898                        boolean ICAOValidFcstTF = true;
899                        while ((ICAOValidFcstTF) && (XInc < 6)) {
900                            TmpStr1 = tokens[1];
901                            TmpStr2 = tokens[2];
902                            TmpStr3 = tokens[3];
903                            TmpStr4 = tokens[4];
904                            TmpStr5 = tokens[7];
905                            DayIntVal = Integer.parseInt(TmpStr1);
906                            HMSTimeIntVal = 100 * Integer.parseInt(TmpStr2);
907                            JulianDayIntVal = Functions.idmyyd(DayIntVal, MonthIntVal, YearIntVal);
908                            TimeArray[XInc] = Functions.calctime(JulianDayIntVal, HMSTimeIntVal);
909                            NSFactor = (TmpStr3.charAt(TmpStr3.length() - 1) == 'N') ? 1.0 : -1.0;
910                            WEFactor = (TmpStr4.charAt(TmpStr4.length() - 1) == 'W') ? 1.0 : -1.0;
911                            LatitudeArray[XInc] = NSFactor
912                                    * Double.parseDouble(TmpStr3.substring(0, TmpStr3.length() - 1));
913                            LongitudeArray[XInc] = WEFactor
914                                    * Double.parseDouble(TmpStr4.substring(0, TmpStr4.length() - 1));
915                            StrengthArray[XInc] = (double) Integer.parseInt(TmpStr5);
916                            if (TimeArray[XInc] < TimeArray[XInc - 1]) {
917                                MonthIntVal = MonthIntVal + 1;
918                                /* YearIntVal=YearIntVal; */
919                                if (MonthIntVal == 13) {
920                                    YearIntVal = YearIntVal + 1;
921                                    MonthIntVal = 1;
922                                }
923                                JulianDayIntVal = Functions.idmyyd(DayIntVal, MonthIntVal,
924                                        YearIntVal);
925                                TimeArray[XInc] = Functions
926                                        .calctime(JulianDayIntVal, HMSTimeIntVal);
927                            }
928                            forecastRec = in.nextLine();
929                            tokens = forecastRec.split(delims6);
930                            if (tokens[0].equals("REMARKS")) {
931                                ICAOValidFcstTF = false;
932                            }
933                            XInc++;
934                        }
935                    }
936                }
937            } else if (ForecastFileType == 8) {
938                /* BEST - best track b-deck file input */
939                int LastDateValueInt = 1;
940                while (in.hasNextLine()) {
941                    String forecastRec = in.nextLine();
942                    String[] tokens = forecastRec.split(delims);
943                    /*
944                     * AL, 04, 2010073106, , BEST, 0, 88N, 329W, 20, 1009, LO,
945                     * 0, , 0, 0, 0, 0, 1011, 180, 75, 0, 0,
946                     */
947                    if (tokens[3].equals("BEST")) {
948                        TmpStr1 = tokens[2];
949                        TmpStr2 = tokens[5];
950                        TmpStr3 = tokens[6];
951                        TmpStr4 = tokens[7];
952                        /*
953                         * System.out.printf("1=%s* 2=%s* 3=%s* 4=%s*\n",TmpStr1,
954                         * TmpStr2,TmpStr3,TmpStr4);
955                         */
956                        YearIntVal = Integer.parseInt(TmpStr1.substring(0, 4));
957                        MonthIntVal = Integer.parseInt(TmpStr1.substring(4, 6));
958                        DayIntVal = Integer.parseInt(TmpStr1.substring(6, 8));
959                        HMSTimeIntVal = 10000 * Integer.parseInt(TmpStr1.substring(8, 10));
960                        JulianDayIntVal = Functions.idmyyd(DayIntVal, MonthIntVal, YearIntVal);
961                        /*
962                         * System.out.printf(
963                         * "day=%d month=%d year=%d hms=%d julian=%d \n"
964                         * ,DayIntVal
965                         * ,MonthIntVal,YearIntVal,HMSTimeIntVal,JulianDayIntVal
966                         * );
967                         */
968                        double TmpTimeVal1 = Functions.calctime(JulianDayIntVal, HMSTimeIntVal);
969                        NSFactor = (TmpStr2.charAt(TmpStr2.length() - 1) == 'N') ? 1.0 : -1.0;
970                        WEFactor = (TmpStr3.charAt(TmpStr3.length() - 1) == 'W') ? 1.0 : -1.0;
971                        int CurrentDateValueInt = HMSTimeIntVal;
972                        if (CurrentDateValueInt != LastDateValueInt) {
973                            /*
974                             * System.out.printf("tmptimeval=%f currenttime=%f\n"
975                             * ,TmpTimeVal1,CurrentTime);
976                             */
977                            if (TmpTimeVal1 < CurrentTime) {
978                                TimeArray[0] = TmpTimeVal1;
979                                LatitudeArray[0] = NSFactor
980                                        * Double.parseDouble(TmpStr2.substring(0,
981                                                TmpStr2.length() - 1)) / 10.0;
982                                LongitudeArray[0] = WEFactor
983                                        * Double.parseDouble(TmpStr3.substring(0,
984                                                TmpStr3.length() - 1)) / 10.0;
985                                StrengthArray[0] = (double) Integer.parseInt(TmpStr4);
986                            } else {
987                                if ((TmpTimeVal1 >= CurrentTime) && (XInc < 5)) {
988                                    XInc++;
989                                    TimeArray[XInc] = TmpTimeVal1;
990                                    LatitudeArray[XInc] = NSFactor
991                                            * Double.parseDouble(TmpStr2.substring(0,
992                                                    TmpStr2.length() - 1)) / 10.0;
993                                    LongitudeArray[XInc] = WEFactor
994                                            * Double.parseDouble(TmpStr3.substring(0,
995                                                    TmpStr3.length() - 1)) / 10.0;
996                                    StrengthArray[XInc] = (double) Integer.parseInt(TmpStr4);
997                                }
998                            }
999                        }
1000                        LastDateValueInt = CurrentDateValueInt;
1001                    }
1002                }
1003            } else if (ForecastFileType == 9) {
1004                /* HURDAT - best track file input */
1005                while (in.hasNextLine()) {
1006                    String forecastRec = in.nextLine();
1007                    String[] tokens = forecastRec.split(delims);
1008                    TmpStr1 = tokens[2];
1009                    TmpStr2 = tokens[3];
1010                    TmpStr3 = tokens[4];
1011                    TmpStr4 = tokens[5];
1012                    TmpStr5 = tokens[6];
1013                    TmpStr6 = tokens[7];
1014                    TmpStr7 = tokens[8];
1015                    YearIntVal = Integer.parseInt(TmpStr1);
1016                    MonthIntVal = Integer.parseInt(TmpStr2);
1017                    DayIntVal = Integer.parseInt(TmpStr3);
1018                    HMSTimeIntVal = (10000 * Integer.parseInt(TmpStr4));
1019                    JulianDayIntVal = Functions.idmyyd(DayIntVal, MonthIntVal, YearIntVal);
1020                    double TmpTimeVal1 = Functions.calctime(JulianDayIntVal, HMSTimeIntVal);
1021                    /*
1022                     * NSFactor = (TmpStr5.charAt(TmpStr5.length()-1)=='N') ?
1023                     * 1.0 : -1.0;
1024                     */
1025                    /*
1026                     * WEFactor = (TmpStr6.charAt(TmpStr6.length()-1)=='W') ?
1027                     * 1.0 : -1.0;
1028                     */
1029                    NSFactor = 1.0;
1030                    WEFactor = 1.0;
1031                    if (TmpTimeVal1 < CurrentTime) {
1032                        TimeArray[0] = TmpTimeVal1;
1033                        LatitudeArray[0] = NSFactor
1034                                * Double.parseDouble(TmpStr5.substring(0, TmpStr5.length() - 1));
1035                        LongitudeArray[0] = WEFactor
1036                                * Double.parseDouble(TmpStr6.substring(0, TmpStr6.length() - 1));
1037                        StrengthArray[0] = (double) Integer.parseInt(TmpStr7);
1038                    } else {
1039                        if ((TmpTimeVal1 >= CurrentTime) && (XInc < 5)) {
1040                            XInc++;
1041                            TimeArray[XInc] = TmpTimeVal1;
1042                            LatitudeArray[XInc] = NSFactor
1043                                    * Double.parseDouble(TmpStr5.substring(0, TmpStr5.length() - 1));
1044                            LongitudeArray[XInc] = WEFactor
1045                                    * Double.parseDouble(TmpStr6.substring(0, TmpStr6.length() - 1));
1046                            StrengthArray[XInc] = (double) Integer.parseInt(TmpStr7);
1047                        }
1048                    }
1049                }
1050            } else {
1051                ReturnFlagValue = -2;
1052            }
1053        } catch (Exception e) {
1054            System.err.println("Failed to read Forecast file...");
1055            in.close();
1056            return null;
1057        }
1058
1059        int ZInc;
1060        int MinFcstValue;
1061        int LastDateJulianHoldValue = 0;
1062        int CurrentYear = 0;
1063        double StrengthValue = 0;
1064        double LastDateValue = 0;
1065        boolean ChangeHemispheresTF = false;
1066        boolean YearChangeFlag = false;
1067
1068        /* System.out.printf("returnflagvalue=%d\n",ReturnFlagValue); */
1069        if (ReturnFlagValue >= 0) {
1070            StrengthValue = StrengthArray[0];
1071            MinFcstValue = XInc;
1072            /* initialize forecast info array */
1073            for (ZInc = 0; ZInc < 5; ZInc++) {
1074                ForecastTimes[ZInc] = 9999999.5;
1075                ForecastLatitudes[ZInc] = 999.5;
1076                ForecastLongitudes[ZInc] = 999.5;
1077            }
1078            /* XInc--; */
1079            XInc = Math.min(5, XInc);
1080            /*
1081             * System.out.printf("%d  %f %f %f\n",0,TimeArray[0],LatitudeArray[0]
1082             * ,LongitudeArray[0]);
1083             */
1084            LastDateValue = TimeArray[0];
1085            ForecastTimes[0] = TimeArray[0];
1086            for (ZInc = 1; ZInc < XInc; ZInc++) {
1087                ForecastTimes[ZInc] = TimeArray[ZInc];
1088                if ((TimeArray[ZInc] - LastDateValue) > 100.0) {
1089                    /* there has been a year change during the forecast time */
1090                    if (!YearChangeFlag) {
1091                        LastDateJulianHoldValue = (int) LastDateValue;
1092                        YearChangeFlag = true;
1093                    }
1094                    CurrentYear = ((int) TimeArray[ZInc]) / 1000;
1095                    CurrentDayValue = TimeArray[ZInc] - (double) (CurrentYear * 1000);
1096                    TimeArray[ZInc] = (double) ((int) LastDateJulianHoldValue + CurrentDayValue);
1097                    LastDateValue = TimeArray[ZInc];
1098                }
1099                /*
1100                 * System.out.printf("%d  %f %f %f\n",ZInc,TimeArray[ZInc],
1101                 * LatitudeArray[ZInc],LongitudeArray[ZInc]);
1102                 */
1103                if (Math.abs(LongitudeArray[ZInc] - LongitudeArray[0]) > 180.0) {
1104                    /*
1105                     * System.out.printf(
1106                     * "changing hemispheres... adjusting longitude\n");
1107                     */
1108                    ChangeHemispheresTF = true;
1109                    if (LongitudeArray[0] < 0) {
1110                        LongitudeArray[ZInc] = -360.0 + LongitudeArray[ZInc];
1111                    } else {
1112                        LongitudeArray[ZInc] = 360.0 + LongitudeArray[ZInc];
1113                    }
1114                    /*
1115                     * System.out.printf("%d  %f %f %f\n",ZInc,TimeArray[ZInc],
1116                     * LatitudeArray[ZInc],LongitudeArray[ZInc]);
1117                     */
1118                }
1119            }
1120            if (YearChangeFlag) {
1121                /* System.out.printf("YearChangeFlag=TRUE\n"); */
1122                /* System.out.printf("CurrentTime=%f\n",CurrentTime); */
1123                /*
1124                 * need to adjust current image time to fit into adjusted date
1125                 * array
1126                 */
1127                if ((CurrentTime - TimeArray[0]) > 100.0) {
1128                    CurrentYear = ((int) CurrentTime) / 1000;
1129                    CurrentDayValue = CurrentTime - (double) (CurrentYear * 1000);
1130                    CurrentTime = (double) ((int) LastDateJulianHoldValue + CurrentDayValue);
1131                    /* System.out.printf("CurrentTime=%f\n",CurrentTime); */
1132                }
1133            }
1134            if (CurrentTime < TimeArray[0]) {
1135                /*
1136                 * check to see if latest image is only 15 minutes before
1137                 * current forecast time
1138                 */
1139                if (CurrentTime > (TimeArray[0] - .015))
1140                    TimeArray[0] = CurrentTime;
1141            }
1142
1143            /* determine number of valid forecast times for given image time */
1144            YInc = 0;
1145            while ((TimeArray[YInc] <= CurrentTime) && (YInc < XInc)) {
1146                YInc++;
1147            }
1148            /*
1149             * System.out.printf(
1150             * "yinc=%d  xinc=%d  curtime=%f time0=%f threshtime=%f\n"
1151             * ,YInc,XInc,CurrentTime,TimeArray[0],ThresholdTime);
1152             */
1153            if ((YInc == 0) && (TimeArray[0] != CurrentTime)) {
1154                /*
1155                 * printf(
1156                 * "INVALID FORECAST FILE, IMAGE BEFORE/AFTER FORECAST TIMES\n"
1157                 * );
1158                 */
1159                System.out.printf("%d %f %f %d\n", -1, -99.99, -999.99, 99);
1160                ReturnFlagValue = -1;
1161            }
1162            if ((YInc == XInc) && (CurrentTime >= TimeArray[XInc])) {
1163                System.out.printf("%d %f %f %d\n", -2, -99.99, -999.99, 99);
1164                ReturnFlagValue = -1;
1165            }
1166            if (ReturnFlagValue >= 0) {
1167                if ((CurrentTime - ThresholdTime) > TimeArray[0]) {
1168                    /* printf("FORECAST FILE MORE THAN 24 HOURS OLD\n"); */
1169                    System.out.printf("%d %f %f %f\n", -3, -99.99, -999.99, -99.99);
1170                    ReturnFlagValue = -1;
1171                } else {
1172                    for (ZInc = 0; ZInc <= MinFcstValue; ZInc++) {
1173                        ForecastLatitudes[ZInc] = LatitudeArray[ZInc];
1174                        ForecastLongitudes[ZInc] = LongitudeArray[ZInc];
1175                    }
1176
1177                    double InterpLatitude = adt_polint(TimeArray, LatitudeArray, XInc, CurrentTime);
1178                    double InterpLongitude = adt_polint(TimeArray, LongitudeArray, XInc,
1179                            CurrentTime);
1180
1181                    if ((InterpLatitude <= -999.) || (InterpLongitude <= -999.)) {
1182                        System.out.printf("%d %f %f %f\n", -4, -99.99, -999.99, -99.99);
1183                        ReturnFlagValue = -1;
1184                    } else {
1185                        if (ChangeHemispheresTF) {
1186                            if (InterpLongitude > 180.0) {
1187                                InterpLongitude = -360.0 + InterpLongitude;
1188                            } else if (InterpLongitude < -180.0) {
1189                                InterpLongitude = 360.0 + InterpLongitude;
1190                            } else {
1191                                /* InterpLongitude=InterpLongitude; */
1192                            }
1193                        }
1194                        System.out.printf("%d %f %f %f\n", 1, InterpLatitude, InterpLongitude,
1195                                StrengthValue);
1196                        ReturnLatitudeInterpolation = InterpLatitude;
1197                        ReturnLongitudeInterpolation = InterpLongitude;
1198                        ReturnFlagValue = 0;
1199                    } /* ReturnFlagValue=-4 */
1200                } /* ReturnFlagValue=-3 */
1201            } /* ReturnFlagValue=-1/-2 */
1202        } /* ReturnFlagValue=-6 */
1203
1204        in.close();
1205
1206        ReturnCurrentIntensity = StrengthValue;
1207
1208        /* McIDAS-V Conversion */
1209        ReturnLongitudeInterpolation = -1.0 * ReturnLongitudeInterpolation;
1210        logger.debug("ReadForecasts out...");
1211
1212        return new double[] { (double) ReturnFlagValue, ReturnLatitudeInterpolation,
1213                ReturnLongitudeInterpolation, ReturnCurrentIntensity };
1214
1215    }
1216
1217    /**
1218     * Polynomial interpolation scheme program derived from FORTRAN program
1219     * POLINT in : Numerical Recipies - The Art of Scientific Computing, 1986,
1220     * Press, Flannery, Teukolsky, and Vetterling, Cambridge Press
1221     *
1222     * @param TimeArrayInput
1223     *            Array containing time values.
1224     * @param PositionArrayInput
1225     *            Array containing variable to interpolate.
1226     * @param NumberOfPointsInput
1227     *            Number of points in array.
1228     * @param CurrentTime
1229     *            Time to interpolate to.
1230     *
1231     * @return Interpolated position value. Note: if value is {@code -999.5}, it
1232     *         means that the denominator is 0, signifying that there was an
1233     *         interpolation error.
1234     */
1235    private static double adt_polint(double[] TimeArrayInput, double[] PositionArrayInput,
1236            int NumberOfPointsInput, double CurrentTime) {
1237        double PositionValue;
1238        double PositionError;
1239        double DenominatorValue;
1240        double TimeDifferenceValue1;
1241        double TimeDifferenceValue2;
1242        double TimeValue1;
1243        double TimeValue2;
1244        double[] LocalArray1 = new double[10];
1245        double[] LocalArray2 = new double[10];
1246        int XInc;
1247        int YInc;
1248        int StoreValue = 1;
1249
1250        TimeDifferenceValue1 = Math.abs(CurrentTime - TimeArrayInput[0]);
1251        for (XInc = 1; XInc <= NumberOfPointsInput; XInc++) {
1252            TimeDifferenceValue2 = Math.abs(CurrentTime - TimeArrayInput[XInc - 1]);
1253            if (TimeDifferenceValue2 < TimeDifferenceValue1) {
1254                StoreValue = XInc;
1255                TimeDifferenceValue1 = TimeDifferenceValue2;
1256            }
1257            /*
1258             * System.out.printf("Xinc-1=%d position array=%f\n",XInc-1,
1259             * PositionArrayInput[XInc-1]);
1260             */
1261            LocalArray1[XInc - 1] = PositionArrayInput[XInc - 1];
1262            LocalArray2[XInc - 1] = PositionArrayInput[XInc - 1];
1263        }
1264        double PositionValueLocal = PositionArrayInput[StoreValue - 1];
1265        PositionError = 0.0;
1266        StoreValue--;
1267        for (YInc = 1; YInc <= NumberOfPointsInput - 1; YInc++) {
1268            for (XInc = 1; XInc <= NumberOfPointsInput - YInc; XInc++) {
1269                TimeValue1 = TimeArrayInput[XInc - 1] - CurrentTime;
1270                TimeValue2 = TimeArrayInput[(XInc - 1) + YInc] - CurrentTime;
1271                PositionValue = LocalArray1[XInc] - LocalArray2[XInc - 1];
1272                DenominatorValue = TimeValue1 - TimeValue2;
1273                if (DenominatorValue == 0.0) {
1274                    /* interpolation error - denominator = 0 */
1275                    return -999.5; /* EXIT */
1276                }
1277                DenominatorValue = PositionValue / DenominatorValue;
1278                LocalArray1[XInc - 1] = TimeValue1 * DenominatorValue;
1279                LocalArray2[XInc - 1] = TimeValue2 * DenominatorValue;
1280                /*
1281                 * System.out.printf(
1282                 * "YInc=%d XInc=%d  demon=%f local1=%f local2=%f\n"
1283                 * ,YInc,XInc,DenominatorValue
1284                 * ,LocalArray1[XInc-1],LocalArray2[XInc-1]);
1285                 */
1286            }
1287            if ((2 * StoreValue) < (NumberOfPointsInput - YInc)) {
1288                PositionError = LocalArray1[StoreValue];
1289            } else {
1290                PositionError = LocalArray2[StoreValue - 1];
1291                StoreValue--;
1292            }
1293            PositionValueLocal = PositionValueLocal + PositionError;
1294        }
1295        /*
1296         * System.out.printf("interpolated position=%f error=%f\n",
1297         * PositionValueLocal,PositionError);
1298         */
1299        double InterpolatedPosition = PositionValueLocal;
1300
1301        /*
1302         * NOTE : additional function return point above - return -1 if
1303         * interpolation fails/denominator is zero
1304         */
1305
1306        return InterpolatedPosition;
1307
1308    }
1309
1310}