001/*
002 * This file is part of McIDAS-V
003 *
004 * Copyright 2007-2017
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 http://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 = {
049      "JAN","FEB","MAR","APR","MAY","JUN", "JUL","AUG","SEP","OCT","NOV","DEC"
050   };
051   
052   public Forecasts() {
053   }
054
055   public static double[] ReadForecasts(String ForecastFileName,
056                                        int ForecastFileType,
057                                        double ThresholdTime)
058       throws IOException
059   {
060      String delims = "[, ]+";
061
062      double ReturnLatitudeInterpolation = -999.5;
063      double ReturnLongitudeInterpolation = -999.5;
064      double ReturnCurrentIntensity = -999.5;
065      double CurrentDayValue;
066      int ReturnFlagValue = -1;
067      String TmpStr1;
068      String TmpStr2;
069      String TmpStr3;
070      String TmpStr4;
071      String TmpStr5;
072      String TmpStr6;
073      String TmpStr7;
074      String TmpStr8;
075      String TmpStr9;
076      String TmpStr12;
077      int WindVal;
078      int YearIntVal;
079      int MonthIntVal;
080      int DayIntVal;
081      int HMSTimeIntVal;
082      int FcstTimeIntVal;
083      int JulianDayIntVal;
084      int FcstTimeIntValPrev;
085      int LocVar1,LocVar2;
086      int DayIntValXX;
087      int MonthIntValXX;
088      int YearIntValXX;
089      int JulianDayIntValXX;
090      double TimeArray[] = new double[10];
091      double LatitudeArray[] = new double[10];
092      double LongitudeArray[] = new double[10];
093      double StrengthArray[] = new double[10];
094      double TmpTimeVal2;
095      double NSFactor;
096      double WEFactor;
097
098      ReturnFlagValue = 0;
099      
100      logger.debug("ReadForecasts in...");
101      System.out.printf("Forecast File Name=%s Type=%d\n", ForecastFileName,ForecastFileType);
102      File forecastfile = new File(ForecastFileName);
103      Scanner in = new Scanner(forecastfile);
104
105      int ImageDate = Data.IRData_JulianDate;
106      int ImageTime = Data.IRData_HHMMSSTime;
107      System.out.printf("IMAGE DATE=%d  TIME=%d\n", Data.IRData_JulianDate, Data.IRData_HHMMSSTime);
108      /* int ImageDate = History.IRCurrentRecord.date; */
109      /* int ImageTime = History.IRCurrentRecord.time; */
110      double CurrentTime = Functions.calctime(ImageDate,ImageTime);
111      int XInc=0;
112      int YInc=0;
113      FcstTimeIntValPrev=-1;
114      
115      try {
116
117      /* char aChar = ATCFStormIDString.charAt(2); */
118      if(ForecastFileType==0) {
119         while (in.hasNextLine()) {
120            String forecastRec = in.nextLine();
121            String[] tokens = forecastRec.split(delims);
122            TmpStr1 = tokens[0];
123            TmpStr2 = tokens[1];
124            TmpStr3 = tokens[2];
125            TmpStr4 = tokens[3];
126            TmpStr5 = tokens[4];
127            TmpStr6 = tokens[5];
128            TmpStr7 = tokens[6];
129            TmpStr8 = tokens[7];
130            TmpStr9 = tokens[8];
131            TmpStr12 = tokens[11];
132            WindVal=0;
133            if((TmpStr12.length()>1)&&(TmpStr12.matches("\\d+"))) {
134                WindVal = Integer.parseInt(TmpStr12.substring(0,2)); /* (int)aodt_atoif(TmpStr12,1,2); */
135            }
136            /*
137             * System.out.printf("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",
138             * TmpStr1,TmpStr2,TmpStr3,TmpStr4,TmpStr5,TmpStr6,TmpStr7,TmpStr8,TmpStr9,TmpStr10,TmpStr11,TmpStr12);
139             */
140            if(WindVal==34) {
141               YearIntVal = Integer.parseInt(TmpStr3.substring(0,4));               /* (int)aodt_atoif(TmpStr3,1,4); */
142               MonthIntVal = Integer.parseInt(TmpStr3.substring(4,6));              /* (int)aodt_atoif(TmpStr3,5,6); */
143               DayIntVal = Integer.parseInt(TmpStr3.substring(6,8));                /* (int)aodt_atoif(TmpStr3,7,8); */
144               /* System.out.printf("year=%d month=%d day=%d\n",YearIntVal,MonthIntVal,DayIntVal); */
145               HMSTimeIntVal = 10000*Integer.parseInt(TmpStr3.substring(8,10));     /* 10000*((int)aodt_atoif(TmpStr3,9,10)); */
146               FcstTimeIntVal = 10000*Integer.parseInt(TmpStr6);                    /* 10000*((int)aodt_atoif(TmpStr6,1,strlen(TmpStr6))); */
147               JulianDayIntVal = Functions.idmyyd(DayIntVal,MonthIntVal,YearIntVal);
148               TmpTimeVal2 = Functions.calctime(JulianDayIntVal,HMSTimeIntVal);
149               /* System.out.printf("YInc=%d tmptime=%f\n",YInc,TmpTimeVal2); */
150               if((TmpTimeVal2<CurrentTime)&&
151                  (FcstTimeIntValPrev!=FcstTimeIntVal)&&(YInc<6)) {
152                  LocVar1 = ((int)(FcstTimeIntVal+HMSTimeIntVal))/240000;
153                  LocVar2 = (((int)(FcstTimeIntVal+HMSTimeIntVal))%240000);
154                  TimeArray[YInc] = Functions.calctime(JulianDayIntVal+LocVar1,LocVar2);
155                  NSFactor = (TmpStr7.charAt(TmpStr7.length()-1)=='N') ? 1.0 : -1.0;
156                  WEFactor = (TmpStr8.charAt(TmpStr8.length()-1)=='W') ? 1.0 : -1.0;
157                  LatitudeArray[YInc] = NSFactor*Double.parseDouble(TmpStr7.substring(0,TmpStr7.length()-1))/10.0;           /* (aodt_atoif(TmpStr7,1,strlen(TmpStr7)))/10.0; */
158                  LongitudeArray[YInc] = WEFactor*Double.parseDouble(TmpStr8.substring(0,TmpStr8.length()-1))/10.0;          /* (aodt_atoif(TmpStr8,1,strlen(TmpStr8)))/10.0; */
159                  StrengthArray[YInc] = Double.parseDouble(TmpStr9);                /* aodt_atoif(TmpStr9,1,4); */
160                  YInc++;
161                  FcstTimeIntValPrev = FcstTimeIntVal;
162                  XInc=YInc;
163               }
164            }
165         }
166      } else if(ForecastFileType==1) {  /* NHC */
167         /* read NHC forecast file, quit at EOF */
168         DayIntValXX = 0;
169         MonthIntValXX = 0;
170         YearIntValXX = 0;
171         JulianDayIntValXX = 0;
172         DayIntVal = 0;
173         MonthIntVal = 0;
174         YearIntVal = 0;
175         JulianDayIntVal = 0;
176         boolean NewNHCFormatFlag = false;
177         boolean FoundMonthTF = false;
178         boolean FoundForecast = false;
179         while ((in.hasNextLine())&&(XInc<6)) {
180            String forecastRec = in.nextLine();
181            String[] tokens = forecastRec.split(delims);
182            if(!FoundMonthTF) {
183               if((tokens.length==7)&&(tokens[1].equals("AM")||tokens[1].equals("PM"))) {
184                  /*
185                   * this is reading the header at the top of the forecast file. It
186                   * is done to obtain the current month and year of the forecast so
187                   * that we can check it accurately against the image date/time
188                   */
189                  DayIntValXX = Integer.parseInt(tokens[5].substring(0,2));       /* (int)aodt_atoif(TmpStr6,1,2); */
190                  YearIntValXX = Integer.parseInt(tokens[6].substring(0,4));      /* (int)aodt_atoif(TmpStr7,1,4); */
191                  while((!tokens[4].equals(MonthID_StringX[MonthIntValXX]))&&(MonthIntValXX<12)) {
192                     MonthIntValXX++;
193                  }
194                  JulianDayIntValXX = Functions.idmyyd(DayIntValXX,MonthIntValXX+1,YearIntValXX);
195                  FoundMonthTF = true;
196                  /* System.out.printf("XX julday=%d day=%d month=%d year=%d\n",JulianDayIntValXX,DayIntValXX,MonthIntValXX+1,YearIntValXX); */
197               }
198               MonthIntVal = MonthIntValXX;
199               YearIntVal = YearIntValXX;
200            } else {
201               if((FoundForecast)&&(tokens.length>=6)) {
202                  /* System.out.printf("length=%d\n",tokens.length); */
203                  if(XInc==0) {
204                     if(tokens[0].equals("INITIAL")) {
205                        NewNHCFormatFlag = false;
206                     } else if((tokens[0].equals("INIT"))&&(YearIntVal>=2011)) {
207                        NewNHCFormatFlag = true;
208                     } else {
209                        NewNHCFormatFlag = false;
210                     }
211                     /* System.out.printf("newformatflag=%b\n",NewNHCFormatFlag); */
212                  }
213                  int iadd = (tokens[0].length()==0) ? 1 : 0;
214                  if((NewNHCFormatFlag)||((!NewNHCFormatFlag)&&(XInc==0))) {
215                     TmpStr1 = tokens[0+iadd];
216                     TmpStr2 = tokens[1+iadd];
217                     TmpStr3 = tokens[2+iadd];
218                     TmpStr4 = tokens[3+iadd];
219                     TmpStr5 = tokens[4+iadd];
220                     TmpStr6 = tokens[5+iadd];
221                  } else {
222                     TmpStr1 = tokens[0+iadd];
223                     TmpStr2 = tokens[2+iadd];
224                     TmpStr3 = tokens[3+iadd];
225                     TmpStr4 = tokens[4+iadd];
226                     TmpStr5 = tokens[5+iadd];
227                     TmpStr6 = tokens[6+iadd];
228                  }
229                  /* System.out.printf("1=%s* 1a=%s* 2=%s* 3=%s* 4=%s* 5=%s* 6=%s*\n",TmpStr1,TmpStr1a,TmpStr2,TmpStr3,TmpStr4,TmpStr5,TmpStr6); */
230                  if(TmpStr6.substring(0,2).equals("KT")) {
231                     if(TmpStr2.charAt(7)=='Z') {
232                        DayIntVal = Integer.parseInt(TmpStr2.substring(0,2));              /* ((int)aodt_atoif(TmpStr2,1,7))/10000; */
233                        HMSTimeIntVal = 100*(Integer.parseInt(TmpStr2.substring(3,7)));    /* 100*(((int)aodt_atoif(TmpStr2,1,7))%10000); */
234                        if(DayIntVal<DayIntValXX) {
235                           MonthIntVal++;
236                           if(MonthIntVal==12) {
237                              YearIntVal++;
238                              MonthIntVal = 0;
239                           }
240                           JulianDayIntVal = Functions.idmyyd(DayIntVal,MonthIntVal+1,YearIntVal);
241                        } else {
242                           JulianDayIntVal = JulianDayIntValXX+(DayIntVal-DayIntValXX);
243                        }
244                        TimeArray[XInc] = Functions.calctime(JulianDayIntVal,HMSTimeIntVal);
245                        NSFactor = (TmpStr3.charAt(TmpStr3.length()-1)=='N') ? 1.0 : -1.0;
246                        WEFactor = (TmpStr4.charAt(TmpStr4.length()-1)=='W') ? 1.0 : -1.0;
247                        LatitudeArray[XInc] = NSFactor*Double.parseDouble(TmpStr3.substring(0,TmpStr3.length()-1));
248                        LongitudeArray[XInc] = WEFactor*Double.parseDouble(TmpStr4.substring(0,TmpStr4.length()-1));
249                        StrengthArray[XInc] = Integer.parseInt(TmpStr5);
250                        XInc++;
251                     }
252                  }
253               } else {
254                  if(tokens[0].equals("FORECAST")&&tokens[1].equals("POSITIONS")) FoundForecast = true;
255               }
256            }
257         }
258      } else if(ForecastFileType==2) {
259         /*
260          * read JTWC forecast file, quit at EOF
261          *
262          * o.k... since JTWC does not put the month and year
263          * on their bulletins, they will need to be "made up".
264          * We will assume that the forecast is current and the
265          * month and year from the image is equal to the month
266          * and year of the forecast file.
267          */
268         int[] ReturnValues = Functions.adt_yddmy((int)CurrentTime);
269         DayIntValXX = ReturnValues[0];
270         MonthIntValXX = ReturnValues[1];
271         YearIntValXX = ReturnValues[2];
272         /* System.out.printf("DayIntValXX=%d\n",DayIntValXX); */
273         /* System.out.printf("MonthIntValXX=%d\n",MonthIntValXX); */
274         /* System.out.printf("YearIntValXX=%d\n",YearIntValXX); */
275         int datexxx = 0;
276         int monthxxx = 0;
277         int yearxxx = 0;
278         int DayIntValSub = 0;
279         JulianDayIntVal = 0;
280         while (in.hasNextLine()) {
281            String forecastRec = in.nextLine();
282            String[] tokens = forecastRec.split(delims);
283            if (tokens.length>=5) {
284               int iadd = (tokens[0].length()==0) ? 1 : 0;
285               TmpStr1 = tokens[0+iadd];
286               TmpStr2 = tokens[1+iadd];
287               TmpStr3 = tokens[2+iadd];
288               TmpStr4 = tokens[3+iadd];
289               if(TmpStr2.equals("---")) {
290                  if(XInc==0) {
291                     TmpStr5 = tokens[4+iadd];
292                     /* System.out.printf("XInc=%d : 1=%s* 2=%s* 3=%s* 4=%s* 5=%s* \n",XInc,TmpStr1,TmpStr2,TmpStr3,TmpStr4,TmpStr5); */
293                     DayIntVal = Integer.parseInt(TmpStr1.substring(0,2));
294                     HMSTimeIntVal = 100*Integer.parseInt(TmpStr1.substring(2,6));
295                     /* System.out.printf("dayintval=%d hmstimeintval=%d\n",DayIntVal,HMSTimeIntVal); */
296                     DayIntValSub=DayIntValXX-DayIntVal;
297                     int[] ReturnValues2 = Functions.adt_yddmy(ImageDate);
298                     datexxx = ReturnValues2[0];
299                     monthxxx = ReturnValues2[1];
300                     yearxxx = ReturnValues2[2];
301                     if(DayIntVal==DayIntValXX) {
302                        /*
303                         * dates are the same... probably o.k....
304                         * should check times
305                         */
306                        JulianDayIntVal = (int)CurrentTime;
307                     } else if((DayIntValSub<=2)&&(DayIntValSub>=0)) {
308                        /*
309                         * this is probably o.k too...
310                         * should check times
311                         */
312                        JulianDayIntVal = (int)CurrentTime+(DayIntVal-DayIntValXX);
313                     } else {
314                        /*
315                         * dates are invalid.  Either image date is before
316                         * forecast or is well beyond forecast availability
317                         */
318                        if(DayIntValSub<-27) {
319                           /* System.out.printf("month crossing\n"); */
320                           /* System.out.printf("datexxx=%d\n",datexxx); */
321                           if((datexxx<=2)&&(monthxxx==1)) {
322                              /* System.out.printf("year crossing... image during new year: %d %d\n",yearxxx-1,DayIntVal); */
323                              JulianDayIntVal = Functions.idmyyd(DayIntVal,12,yearxxx-1);
324                           } else {
325                              JulianDayIntVal = Functions.idmyyd(DayIntVal,monthxxx-1,yearxxx);
326                           }
327                           /* System.out.printf("JulianDayIntVal=%d\n",JulianDayIntVal); */
328                        } else {
329                           ReturnFlagValue = -1;
330                        }
331                     }
332                     /* System.out.printf("JulianDayIntVal=%d\n",JulianDayIntVal); */
333                     TimeArray[XInc] = Functions.calctime(JulianDayIntVal,HMSTimeIntVal);
334                     /* System.out.printf("TimeArray[%d]=%f\n",XInc,TimeArray[XInc]); */
335                     NSFactor = (TmpStr4.charAt(TmpStr4.length()-1)=='N') ? 1.0 : -1.0;
336                     WEFactor = (TmpStr5.charAt(TmpStr5.length()-1)=='W') ? 1.0 : -1.0;
337                     LatitudeArray[XInc] = NSFactor*Double.parseDouble(TmpStr4.substring(0,TmpStr4.length()-1));
338                     LongitudeArray[XInc] = WEFactor*Double.parseDouble(TmpStr5.substring(0,TmpStr5.length()-1));
339                  } else {
340                     /* System.out.printf("XInc=%d : 1=%s* 2=%s* 3=%s* 4=%s* \n",XInc,TmpStr1,TmpStr2,TmpStr3,TmpStr4); */
341                     DayIntVal = Integer.parseInt(TmpStr1.substring(0,2));
342                     HMSTimeIntVal = 100*Integer.parseInt(TmpStr1.substring(2,6));
343                     /* System.out.printf("dayintval=%d hmstimeintval=%d\n",DayIntVal,HMSTimeIntVal); */
344                     DayIntValSub = DayIntValXX-DayIntVal;
345                     if(DayIntValSub<-27) {
346                        if((monthxxx-1)==0) {
347                           JulianDayIntVal = Functions.idmyyd(DayIntVal,12,yearxxx-1);
348                        } else {
349                           JulianDayIntVal = Functions.idmyyd(DayIntVal,monthxxx-1,yearxxx);
350                        }
351                     } else {
352                        if(DayIntValSub>27) {
353                           if((monthxxx+1)>12) {
354                              JulianDayIntVal = Functions.idmyyd(DayIntVal,1,yearxxx+1);
355                           } else {
356                              JulianDayIntVal = Functions.idmyyd(DayIntVal,monthxxx+1,yearxxx);
357                           }
358                        } else {
359                           JulianDayIntVal = Functions.idmyyd(DayIntVal,monthxxx,yearxxx);
360                        }
361                     }
362                     /* System.out.printf("JulianDayIntVal=%d\n",JulianDayIntVal); */
363                     TimeArray[XInc] = Functions.calctime(JulianDayIntVal,HMSTimeIntVal);
364                     /* System.out.printf("TimeArray[%d]=%f\n",XInc,TimeArray[XInc]); */
365                     NSFactor = (TmpStr3.charAt(TmpStr3.length()-1)=='N') ? 1.0 : -1.0;
366                     WEFactor = (TmpStr4.charAt(TmpStr4.length()-1)=='W') ? 1.0 : -1.0;
367                     LatitudeArray[XInc] = NSFactor*Double.parseDouble(TmpStr3.substring(0,TmpStr3.length()-1));
368                     LongitudeArray[XInc] = WEFactor*Double.parseDouble(TmpStr4.substring(0,TmpStr4.length()-1));
369                  }
370               }
371               if((TmpStr1.equals("MAX"))&&(TmpStr4.charAt(0)=='-')) {
372                  TmpStr5 = tokens[4+iadd];
373                  if(XInc==0) {
374                     StrengthArray[XInc] = Double.parseDouble(TmpStr5);
375                  }
376                  XInc++;
377               }
378            }
379         }
380      } else if(ForecastFileType==3) {
381         /* generic forecast file input */
382         while (in.hasNextLine()) {
383            String forecastRec = in.nextLine();
384            String[] tokens = forecastRec.split(delims);
385            if(tokens.length>=5) {
386               TmpStr1 = tokens[0];
387               TmpStr2 = tokens[1];
388               TmpStr3 = tokens[2];
389               TmpStr4 = tokens[3];
390               TmpStr5 = tokens[4];
391               TmpStr6 = tokens[5];
392               TmpStr7 = tokens[6];
393               DayIntVal = Integer.parseInt(TmpStr1.substring(0,2));
394               MonthIntVal = Integer.parseInt(TmpStr2.substring(0,2));
395               YearIntVal = Integer.parseInt(TmpStr3.substring(0,4));
396               HMSTimeIntVal = 100*Integer.parseInt(TmpStr4.substring(0,4));
397               JulianDayIntVal = Functions.idmyyd(DayIntVal,MonthIntVal,YearIntVal);
398               TimeArray[XInc] = Functions.calctime(JulianDayIntVal,HMSTimeIntVal);
399               NSFactor = (TmpStr5.charAt(TmpStr5.length()-1)=='N') ? 1.0 : -1.0;
400               WEFactor = (TmpStr6.charAt(TmpStr6.length()-1)=='W') ? 1.0 : -1.0;
401               LatitudeArray[XInc] = NSFactor*Double.parseDouble(TmpStr5.substring(0,TmpStr5.length()-1));
402               LongitudeArray[XInc] = WEFactor*Double.parseDouble(TmpStr6.substring(0,TmpStr6.length()-1));
403               StrengthArray[XInc] = Double.parseDouble(TmpStr5);
404               XInc++;
405            }
406         }
407      } else if(ForecastFileType==4) {
408         String delims4 = "[:+/ ]+";
409         /* RSMC ICAO (FK?? or WT??) forecast file input */
410         /*
411          * Convert the ICAO RSMC bulletin positions from degrees minutes
412          * to degrees and tenths of degrees.
413          * fix courtesy : YanLuo/NOAA 07/22/09 *
414          */
415         int xxx1 = 0;
416         int xxx2 = 0;
417         double LatMultFact = 0.0;
418         double LonMultFact = 0.0;
419         while (in.hasNextLine()) {
420            String forecastRec = in.nextLine();
421            String[] tokens = forecastRec.split(delims4);
422            if(tokens[0].equals("DTG")) {
423               TmpStr1 = tokens[1];
424               /* System.out.printf("TmpStr1=%s*\n",TmpStr1); */
425               DayIntVal = Integer.parseInt(TmpStr1.substring(6,8));
426               MonthIntVal = Integer.parseInt(TmpStr1.substring(4,6));
427               YearIntVal = Integer.parseInt(TmpStr1.substring(0,4));
428               if(tokens.length==2) {
429                  HMSTimeIntVal = 100*Integer.parseInt(TmpStr1.substring(8,12));
430               } else {
431                  TmpStr2 = tokens[2];
432                  HMSTimeIntVal = 100*Integer.parseInt(TmpStr2.substring(0,4));
433               } 
434               JulianDayIntVal = Functions.idmyyd(DayIntVal,MonthIntVal,YearIntVal);
435               TimeArray[XInc] = Functions.calctime(JulianDayIntVal,HMSTimeIntVal);
436               /* System.out.printf("time0=%f  hmstime=%d\n",TimeArray[XInc],HMSTimeIntVal); */
437            } else if(tokens[0].equals("PSN")) {
438                  TmpStr1 = tokens[1];
439                  TmpStr2 = tokens[2];
440                  LatMultFact = (TmpStr1.charAt(0)=='N') ? 1.0 : -1.0;
441                  LonMultFact = (TmpStr2.charAt(0)=='W') ? 1.0 : -1.0;
442                  xxx1 = Integer.parseInt(TmpStr1.substring(1,TmpStr1.length()));
443                  xxx2 = Integer.parseInt(TmpStr2.substring(1,TmpStr2.length()));
444                  /* initial lat/lon */
445                  double LatitudeWhole=((double)xxx1)/100.0;
446                  double LatitudePart=((double)xxx1-(LatitudeWhole*100.0))/60.0;
447                  LatitudeArray[XInc]=LatMultFact*(LatitudeWhole+LatitudePart);
448                  double LongitudeWhole=((double)xxx2)/100.0;
449                  double LongitudePart=((double)xxx2-(LongitudeWhole*100.0))/60.0;
450                  LongitudeArray[XInc]=LonMultFact*(LongitudeWhole+LongitudePart);
451                  XInc++;
452            } else if((tokens[0].equals("MAX"))&&(XInc==0)) {
453                  /* initial lat/lon */
454                  TmpStr1 = tokens[2];
455                  StrengthArray[XInc] = Double.parseDouble(TmpStr1.substring(0,TmpStr1.length()-2));
456            } else if((tokens[0].equals("FCST"))&&(tokens[1].equals("PSN"))) {
457               int numtokens = tokens.length;
458               TmpStr1 = tokens[2];
459               TmpStr2 = tokens[numtokens-2];
460               TmpStr3 = tokens[numtokens-1];
461               /* System.out.printf("1=%s* 2=%s* 3=%s*\n",TmpStr1,TmpStr2,TmpStr3); */
462               LatMultFact = (TmpStr2.charAt(0)=='N') ? 1.0 : -1.0;
463               LonMultFact = (TmpStr3.charAt(0)=='W') ? 1.0 : -1.0;
464               xxx1 = Integer.parseInt(TmpStr2.substring(1,TmpStr2.length()));
465               xxx2 = Integer.parseInt(TmpStr3.substring(1,TmpStr3.length()));
466               int FcstHrAddIntVal = Integer.parseInt(TmpStr1.substring(0,2));
467               /* initial lat/lon */
468               double LatitudeWhole=((double)xxx1)/100.0;
469               double LatitudePart=((double)xxx1-(LatitudeWhole*100.0))/60.0;
470               LatitudeArray[XInc]=LatMultFact*(LatitudeWhole+LatitudePart);
471               double LongitudeWhole=((double)xxx2)/100.0;
472               double LongitudePart=((double)xxx2-(LongitudeWhole*100.0))/60.0;
473               LongitudeArray[XInc]=LonMultFact*(LongitudeWhole+LongitudePart);
474               double FcstHrAddDblVal=((double)FcstHrAddIntVal)/24.0;
475               /* System.out.printf("XInc=%d time0=%f fcsthr=%f\n",XInc,TimeArray[0],FcstHrAddDblVal); */
476               TimeArray[XInc]=TimeArray[0]+FcstHrAddDblVal;
477               XInc++;
478            }
479         } 
480      } else if(ForecastFileType==5) {
481         /* RSMC WTIO30 forecast file input */
482         String delims5 = "[,:/= ]+";
483         while (in.hasNextLine()) {
484            String forecastRec = in.nextLine();
485            String[] tokens = forecastRec.split(delims5);
486            if(tokens[0].equals("2.A")) {
487               TmpStr1 = tokens[2];
488               TmpStr2 = tokens[3];
489               TmpStr3 = tokens[4];
490               TmpStr4 = tokens[6];
491               YearIntVal = Integer.parseInt(TmpStr1);
492               MonthIntVal = Integer.parseInt(TmpStr2);
493               DayIntVal = Integer.parseInt(TmpStr3);
494               HMSTimeIntVal = 100*Integer.parseInt(TmpStr4);
495               JulianDayIntVal = Functions.idmyyd(DayIntVal,MonthIntVal,YearIntVal);
496               TimeArray[XInc] = Functions.calctime(JulianDayIntVal,HMSTimeIntVal);
497               forecastRec = in.nextLine();
498               tokens = forecastRec.split(delims5);
499               if(tokens.length==2) {
500                  TmpStr1 = tokens[0];
501                  TmpStr2 = tokens[1];
502               } else {
503                  /* expecting line like
504                   * WITHIN 20 NM RADIUS OF POINT 22.2S / 50.8E
505                   */
506                  TmpStr1 = tokens[6];
507                  TmpStr2 = tokens[7];
508               }
509               NSFactor = (TmpStr1.charAt(TmpStr1.length()-1)=='N') ? 1.0 : -1.0;
510               WEFactor = (TmpStr2.charAt(TmpStr2.length()-1)=='W') ? 1.0 : -1.0;
511               LatitudeArray[XInc] = NSFactor*Double.parseDouble(TmpStr1.substring(0,TmpStr1.length()-1));
512               LongitudeArray[XInc] = WEFactor*Double.parseDouble(TmpStr2.substring(0,TmpStr2.length()-1));
513            } else if(tokens[0].equals("5.A")) {
514               TmpStr1 = tokens[tokens.length-2];
515               StrengthArray[XInc] = Double.parseDouble(TmpStr1);
516            } else if(tokens[0].equals("1.B")) {
517               XInc=1;
518               forecastRec = in.nextLine();
519               tokens = forecastRec.split(delims5);
520               boolean ICAOValidFcstTF = true;
521               while((ICAOValidFcstTF)&&(XInc<6)) {
522                  TmpStr1 = tokens[1];
523                  TmpStr2 = tokens[2];
524                  TmpStr3 = tokens[3];
525                  TmpStr4 = tokens[4];
526                  TmpStr5 = tokens[6];
527                  TmpStr6 = tokens[7];
528                  TmpStr7 = tokens[10];
529                  YearIntVal = Integer.parseInt(TmpStr1);
530                  MonthIntVal = Integer.parseInt(TmpStr2);
531                  DayIntVal = Integer.parseInt(TmpStr3);
532                  HMSTimeIntVal = 10000*Integer.parseInt(TmpStr4);
533                  JulianDayIntVal = Functions.idmyyd(DayIntVal,MonthIntVal,YearIntVal);
534                  TimeArray[XInc] = Functions.calctime(JulianDayIntVal,HMSTimeIntVal);
535                  NSFactor = (TmpStr5.charAt(TmpStr5.length()-1)=='N') ? 1.0 : -1.0;
536                  WEFactor = (TmpStr6.charAt(TmpStr6.length()-1)=='W') ? 1.0 : -1.0;
537                  LatitudeArray[XInc] = NSFactor*Double.parseDouble(TmpStr5.substring(0,TmpStr5.length()-1));
538                  LongitudeArray[XInc] = WEFactor*Double.parseDouble(TmpStr6.substring(0,TmpStr6.length()-1));
539                  StrengthArray[XInc] = (double)Integer.parseInt(TmpStr7.substring(0,3));
540                  forecastRec = in.nextLine();
541                  tokens = forecastRec.split(delims5);
542                  String TmpStr0 = tokens[0];
543                  if(tokens[0].equals("2.C")) {
544                     ICAOValidFcstTF = false;
545                  } else {
546                     if(TmpStr0.charAt(2)!='H') {
547                        forecastRec = in.nextLine();
548                        ICAOValidFcstTF = false;
549                     }
550                  }
551                  XInc++;
552               }
553            }
554         }
555      } else if(ForecastFileType==6) {
556         /* TCWC AXAU Tech Bulletins file input */
557         String delims6 = "[,:/ ]+";
558         JulianDayIntVal = 0;
559         MonthIntVal = 0;
560         YearIntVal = 0;
561         while (in.hasNextLine()) {
562            String forecastRec = in.nextLine();
563            String[] tokens = forecastRec.split(delims6);
564            if(tokens[0].equals("at")) {
565               /* initial date */
566               TmpStr1 = tokens[1];
567               TmpStr2 = tokens[3];
568               TmpStr3 = tokens[4];
569               TmpStr4 = tokens[5];
570               YearIntVal = Integer.parseInt(TmpStr4);
571               MonthIntVal = Integer.parseInt(TmpStr3);
572               DayIntVal = Integer.parseInt(TmpStr2);
573               /* HMSTimeIntVal = 100*Integer.parseInt(TmpStr1); */
574               JulianDayIntVal = Functions.idmyyd(DayIntVal,MonthIntVal,YearIntVal);
575            }
576            if(tokens[0].equals("Data")) {
577               /* initial time */
578               TmpStr1 = tokens[2];
579               HMSTimeIntVal = 100*Integer.parseInt(TmpStr1);
580               TimeArray[XInc] = Functions.calctime(JulianDayIntVal,HMSTimeIntVal);
581            }
582            if(tokens[0].equals("Latitude")) {
583               /* initial latitude */
584               TmpStr1 = tokens[1];
585               NSFactor = (TmpStr1.charAt(TmpStr1.length()-1)=='N') ? 1.0 : -1.0;
586               LatitudeArray[XInc] = NSFactor*Double.parseDouble(TmpStr1.substring(0,TmpStr1.length()-1));
587            }
588            if(tokens[0].equals("Longitude")) {
589               /* initial longitude */
590               TmpStr1 = tokens[1];
591               WEFactor = (TmpStr1.charAt(TmpStr1.length()-1)=='W') ? 1.0 : -1.0;
592               LongitudeArray[XInc] = WEFactor*Double.parseDouble(TmpStr1.substring(0,TmpStr1.length()-1));
593            }
594            if(tokens[0].equals("Maximum")) {
595               if(tokens[1].equals("10-Minute")) {
596                  /* initial strength */
597                  TmpStr1 = tokens[3];
598                  StrengthArray[XInc] = (double)Integer.parseInt(TmpStr1);
599               }
600            }
601            if(tokens[0].equals("FORECAST")) {
602               XInc=1;
603               forecastRec = in.nextLine();
604               forecastRec = in.nextLine();
605               forecastRec = in.nextLine();
606               tokens = forecastRec.split(delims6);
607               boolean ICAOValidFcstTF = true;
608               while((ICAOValidFcstTF)&&(XInc<6)) {
609                  TmpStr1 = tokens[1];
610                  TmpStr2 = tokens[2];
611                  TmpStr3 = tokens[3];
612                  TmpStr4 = tokens[4];
613                  TmpStr5 = tokens[7];
614                  DayIntVal = Integer.parseInt(TmpStr1);
615                  HMSTimeIntVal = 100*Integer.parseInt(TmpStr2);
616                  JulianDayIntVal = Functions.idmyyd(DayIntVal,MonthIntVal,YearIntVal);
617                  TimeArray[XInc] = Functions.calctime(JulianDayIntVal,HMSTimeIntVal);
618                  NSFactor = (TmpStr3.charAt(TmpStr3.length()-1)=='N') ? 1.0 : -1.0;
619                  WEFactor = (TmpStr4.charAt(TmpStr4.length()-1)=='W') ? 1.0 : -1.0;
620                  LatitudeArray[XInc] = NSFactor*Double.parseDouble(TmpStr3.substring(0,TmpStr3.length()-1));
621                  LongitudeArray[XInc] = WEFactor*Double.parseDouble(TmpStr4.substring(0,TmpStr4.length()-1));
622                  StrengthArray[XInc] = (double)Integer.parseInt(TmpStr5);
623                  if(TimeArray[XInc]<TimeArray[XInc-1]) {
624                     MonthIntVal=MonthIntVal+1;
625                     /* YearIntVal=YearIntVal; */
626                     if(MonthIntVal==13) {
627                        YearIntVal=YearIntVal+1;
628                        MonthIntVal=1;
629                     }
630                     JulianDayIntVal = Functions.idmyyd(DayIntVal,MonthIntVal,YearIntVal);
631                     TimeArray[XInc] = Functions.calctime(JulianDayIntVal,HMSTimeIntVal);
632                  }
633                  forecastRec = in.nextLine();
634                  tokens = forecastRec.split(delims6);
635                  if(tokens[0].equals("REMARKS")) {
636                     ICAOValidFcstTF = false;
637                  }
638                  XInc++;
639               }
640            }
641         }
642      } else if(ForecastFileType==8) {
643         /* BEST - best track b-deck file input */
644         int LastDateValueInt = 1;
645         while (in.hasNextLine()) {
646            String forecastRec = in.nextLine();
647            String[] tokens = forecastRec.split(delims);
648            /* AL, 04, 2010073106,   , BEST,   0,  88N,  329W,  20, 1009, LO,   0,    ,    0,    0,    0,    0, 1011,  180,  75,   0,   0, */
649            if(tokens[3].equals("BEST")) {
650               TmpStr1 = tokens[2];
651               TmpStr2 = tokens[5];
652               TmpStr3 = tokens[6];
653               TmpStr4 = tokens[7];
654               /* System.out.printf("1=%s* 2=%s* 3=%s* 4=%s*\n",TmpStr1,TmpStr2,TmpStr3,TmpStr4); */
655               YearIntVal = Integer.parseInt(TmpStr1.substring(0,4));
656               MonthIntVal = Integer.parseInt(TmpStr1.substring(4,6));
657               DayIntVal = Integer.parseInt(TmpStr1.substring(6,8));
658               HMSTimeIntVal = 10000*Integer.parseInt(TmpStr1.substring(8,10));
659               JulianDayIntVal = Functions.idmyyd(DayIntVal,MonthIntVal,YearIntVal);
660               /* System.out.printf("day=%d month=%d year=%d hms=%d julian=%d \n",DayIntVal,MonthIntVal,YearIntVal,HMSTimeIntVal,JulianDayIntVal); */
661               double TmpTimeVal1 = Functions.calctime(JulianDayIntVal,HMSTimeIntVal);
662               NSFactor = (TmpStr2.charAt(TmpStr2.length()-1)=='N') ? 1.0 : -1.0;
663               WEFactor = (TmpStr3.charAt(TmpStr3.length()-1)=='W') ? 1.0 : -1.0;
664               int CurrentDateValueInt=HMSTimeIntVal;
665               if(CurrentDateValueInt!=LastDateValueInt) {
666               /* System.out.printf("tmptimeval=%f currenttime=%f\n",TmpTimeVal1,CurrentTime); */
667                  if(TmpTimeVal1<CurrentTime) {
668                     TimeArray[0] = TmpTimeVal1;
669                     LatitudeArray[0] = NSFactor*Double.parseDouble(TmpStr2.substring(0,TmpStr2.length()-1))/10.0;
670                     LongitudeArray[0] = WEFactor*Double.parseDouble(TmpStr3.substring(0,TmpStr3.length()-1))/10.0;
671                     StrengthArray[0] = (double)Integer.parseInt(TmpStr4);
672                  } else {
673                     if((TmpTimeVal1>=CurrentTime)&&(XInc<5)) {
674                        XInc++;
675                        TimeArray[XInc] = TmpTimeVal1;
676                        LatitudeArray[XInc] = NSFactor*Double.parseDouble(TmpStr2.substring(0,TmpStr2.length()-1))/10.0;
677                        LongitudeArray[XInc] = WEFactor*Double.parseDouble(TmpStr3.substring(0,TmpStr3.length()-1))/10.0;
678                        StrengthArray[XInc] = (double)Integer.parseInt(TmpStr4);
679                     }
680                  }
681               }
682               LastDateValueInt=CurrentDateValueInt;
683            }
684         }
685      } else if(ForecastFileType==9) {
686         /* HURDAT - best track file input */
687         while (in.hasNextLine()) {
688            String forecastRec = in.nextLine();
689            String[] tokens = forecastRec.split(delims);
690            TmpStr1 = tokens[2];
691            TmpStr2 = tokens[3];
692            TmpStr3 = tokens[4];
693            TmpStr4 = tokens[5];
694            TmpStr5 = tokens[6];
695            TmpStr6 = tokens[7];
696            TmpStr7 = tokens[8];
697            YearIntVal = Integer.parseInt(TmpStr1);
698            MonthIntVal = Integer.parseInt(TmpStr2);
699            DayIntVal = Integer.parseInt(TmpStr3);
700            HMSTimeIntVal=(10000*Integer.parseInt(TmpStr4));
701            JulianDayIntVal = Functions.idmyyd(DayIntVal,MonthIntVal,YearIntVal);
702            double TmpTimeVal1 = Functions.calctime(JulianDayIntVal,HMSTimeIntVal);
703            /* NSFactor = (TmpStr5.charAt(TmpStr5.length()-1)=='N') ? 1.0 : -1.0; */
704            /* WEFactor = (TmpStr6.charAt(TmpStr6.length()-1)=='W') ? 1.0 : -1.0; */
705            NSFactor = 1.0;
706            WEFactor = 1.0;
707            if(TmpTimeVal1<CurrentTime) {
708               TimeArray[0] = TmpTimeVal1;
709               LatitudeArray[0] = NSFactor*Double.parseDouble(TmpStr5.substring(0,TmpStr5.length()-1));
710               LongitudeArray[0] = WEFactor*Double.parseDouble(TmpStr6.substring(0,TmpStr6.length()-1));
711               StrengthArray[0] = (double)Integer.parseInt(TmpStr7);
712            } else {
713               if((TmpTimeVal1>=CurrentTime)&&(XInc<5)) {
714                  XInc++;
715                  TimeArray[XInc] = TmpTimeVal1;
716                  LatitudeArray[XInc] = NSFactor*Double.parseDouble(TmpStr5.substring(0,TmpStr5.length()-1));
717                  LongitudeArray[XInc] = WEFactor*Double.parseDouble(TmpStr6.substring(0,TmpStr6.length()-1));
718                  StrengthArray[XInc] = (double)Integer.parseInt(TmpStr7);
719               }
720            }
721         }
722      } else {
723         ReturnFlagValue = -2;
724      }
725      } catch (Exception e) {
726          System.err.println("Failed to read Forecast file...");
727          in.close();
728          return null;
729      }
730 
731      int ZInc;
732      int MinFcstValue;
733      int LastDateJulianHoldValue = 0;
734      int CurrentYear = 0;
735      double StrengthValue = 0;
736      double LastDateValue = 0;
737      boolean ChangeHemispheresTF = false;
738      boolean YearChangeFlag = false;
739
740      /* System.out.printf("returnflagvalue=%d\n",ReturnFlagValue); */
741      if(ReturnFlagValue>=0) {
742         StrengthValue=StrengthArray[0];
743         MinFcstValue=XInc;
744         /* initialize forecast info array */
745         for(ZInc=0;ZInc<5;ZInc++) {
746            ForecastTimes[ZInc] = 9999999.5;
747            ForecastLatitudes[ZInc] = 999.5;
748            ForecastLongitudes[ZInc] = 999.5;
749         }
750         /* XInc--; */
751         XInc = Math.min(5,XInc);
752         /* System.out.printf("%d  %f %f %f\n",0,TimeArray[0],LatitudeArray[0],LongitudeArray[0]); */
753         LastDateValue = TimeArray[0];
754         ForecastTimes[0] = TimeArray[0];
755         for(ZInc=1;ZInc<XInc;ZInc++) {
756            ForecastTimes[ZInc] = TimeArray[ZInc];
757            if((TimeArray[ZInc]-LastDateValue)>100.0) {
758               /* there has been a year change during the forecast time */
759               if(!YearChangeFlag) {
760                  LastDateJulianHoldValue = (int)LastDateValue;
761                  YearChangeFlag = true;
762               }
763               CurrentYear = ((int)TimeArray[ZInc])/1000;
764               CurrentDayValue = TimeArray[ZInc]-(double)(CurrentYear*1000);
765               TimeArray[ZInc] = (double)((int)LastDateJulianHoldValue+CurrentDayValue);
766               LastDateValue = TimeArray[ZInc];
767            }
768            /* System.out.printf("%d  %f %f %f\n",ZInc,TimeArray[ZInc],LatitudeArray[ZInc],LongitudeArray[ZInc]); */
769            if(Math.abs(LongitudeArray[ZInc]-LongitudeArray[0])>180.0) {
770               /* System.out.printf("changing hemispheres... adjusting longitude\n"); */
771               ChangeHemispheresTF = true;
772               if(LongitudeArray[0]<0) {
773                  LongitudeArray[ZInc] = -360.0+LongitudeArray[ZInc];
774               } else {
775                  LongitudeArray[ZInc] = 360.0+LongitudeArray[ZInc];
776               }
777               /* System.out.printf("%d  %f %f %f\n",ZInc,TimeArray[ZInc],LatitudeArray[ZInc],LongitudeArray[ZInc]); */
778            }
779         }
780         if(YearChangeFlag) {
781            /* System.out.printf("YearChangeFlag=TRUE\n"); */
782            /* System.out.printf("CurrentTime=%f\n",CurrentTime); */
783            /* need to adjust current image time to fit into adjusted date array */
784            if((CurrentTime-TimeArray[0])>100.0) {
785               CurrentYear = ((int)CurrentTime)/1000;
786               CurrentDayValue = CurrentTime-(double)(CurrentYear*1000);
787               CurrentTime = (double)((int)LastDateJulianHoldValue+CurrentDayValue);
788               /* System.out.printf("CurrentTime=%f\n",CurrentTime); */
789            }
790         }
791         if(CurrentTime<TimeArray[0]) {
792            /*
793             * check to see if latest image is only 15 minutes
794             * before current forecast time
795             */
796            if(CurrentTime>(TimeArray[0]-.015)) TimeArray[0] = CurrentTime;
797         }
798 
799         /* determine number of valid forecast times for given image time */
800         YInc = 0;
801         while((TimeArray[YInc]<=CurrentTime)&&(YInc<XInc)) {
802            YInc++;
803         }
804         /* System.out.printf("yinc=%d  xinc=%d  curtime=%f time0=%f threshtime=%f\n",YInc,XInc,CurrentTime,TimeArray[0],ThresholdTime); */
805         if((YInc==0)&&(TimeArray[0]!=CurrentTime)) {
806            /* printf("INVALID FORECAST FILE, IMAGE BEFORE/AFTER FORECAST TIMES\n"); */
807            System.out.printf("%d %f %f %d\n",-1,-99.99,-999.99,99);
808            ReturnFlagValue = -1;
809         }
810         if((YInc==XInc)&&(CurrentTime>=TimeArray[XInc])) {
811            System.out.printf("%d %f %f %d\n",-2,-99.99,-999.99,99);
812            ReturnFlagValue = -1;
813         }
814         if (ReturnFlagValue>=0) {
815            if((CurrentTime-ThresholdTime)>TimeArray[0]) {
816               /* printf("FORECAST FILE MORE THAN 24 HOURS OLD\n"); */
817               System.out.printf("%d %f %f %f\n",-3,-99.99,-999.99,-99.99);
818               ReturnFlagValue = -1;
819            } else {
820               for(ZInc=0;ZInc<=MinFcstValue;ZInc++) {
821                  ForecastLatitudes[ZInc] = LatitudeArray[ZInc];
822                  ForecastLongitudes[ZInc] = LongitudeArray[ZInc];
823               }
824 
825               double InterpLatitude = adt_polint(TimeArray,LatitudeArray,XInc,CurrentTime);
826               double InterpLongitude = adt_polint(TimeArray,LongitudeArray,XInc,CurrentTime);
827 
828               if ((InterpLatitude<=-999.)||(InterpLongitude<=-999.)) {
829                  System.out.printf("%d %f %f %f\n",-4,-99.99,-999.99,-99.99);
830                  ReturnFlagValue = -1;
831               } else {
832                  if(ChangeHemispheresTF) {
833                     if(InterpLongitude>180.0) {
834                       InterpLongitude = -360.0+InterpLongitude;
835                     } else if(InterpLongitude<-180.0) {
836                       InterpLongitude = 360.0+InterpLongitude;
837                     } else {
838                       /* InterpLongitude=InterpLongitude; */
839                     }
840                  }
841                  System.out.printf("%d %f %f %f\n",1,InterpLatitude,InterpLongitude,StrengthValue);
842                  ReturnLatitudeInterpolation = InterpLatitude;
843                  ReturnLongitudeInterpolation = InterpLongitude;
844                  ReturnFlagValue = 0;
845               } /* ReturnFlagValue=-4 */
846            } /* ReturnFlagValue=-3 */
847         } /* ReturnFlagValue=-1/-2 */
848      } /* ReturnFlagValue=-6 */
849
850      in.close();
851
852      ReturnCurrentIntensity = StrengthValue;
853
854      /* McIDAS-V Conversion */
855      ReturnLongitudeInterpolation = -1.0 * ReturnLongitudeInterpolation;
856      logger.debug("ReadForecasts out...");
857      
858      return new double[] {
859         (double)ReturnFlagValue,
860         ReturnLatitudeInterpolation,
861         ReturnLongitudeInterpolation,
862         ReturnCurrentIntensity
863      };
864
865   }
866   
867   /**
868    * Polynomial interpolation scheme program derived from FORTRAN
869    * program POLINT in : Numerical Recipies - The Art of Scientific
870    * Computing, 1986, Press, Flannery, Teukolsky, and Vetterling, Cambridge Press
871    *
872    * @param TimeArrayInput Array containing time values.
873    * @param PositionArrayInput Array containing variable to interpolate.
874    * @param NumberOfPointsInput Number of points in array.
875    * @param CurrentTime Time to interpolate to.
876    *
877    * @return Interpolated position value. Note: if value is {@code -999.5},
878    * it means that the denominator is 0, signifying that there was an
879    * interpolation error.
880    */
881   private static double adt_polint(double[] TimeArrayInput,
882                                    double[] PositionArrayInput,
883                                    int NumberOfPointsInput,
884                                    double CurrentTime)
885   {
886      double PositionValue;
887      double PositionError;
888      double DenominatorValue;
889      double TimeDifferenceValue1;
890      double TimeDifferenceValue2;
891      double TimeValue1;
892      double TimeValue2;
893      double[] LocalArray1 = new double[10];
894      double[] LocalArray2 = new double[10];
895      int XInc;
896      int YInc;
897      int StoreValue = 1;
898
899      TimeDifferenceValue1 = Math.abs(CurrentTime-TimeArrayInput[0]);
900      for(XInc=1;XInc<=NumberOfPointsInput;XInc++) {
901         TimeDifferenceValue2 = Math.abs(CurrentTime-TimeArrayInput[XInc-1]);
902         if(TimeDifferenceValue2<TimeDifferenceValue1) {
903            StoreValue = XInc;
904            TimeDifferenceValue1 = TimeDifferenceValue2;
905         }
906         /* System.out.printf("Xinc-1=%d position array=%f\n",XInc-1,PositionArrayInput[XInc-1]); */
907         LocalArray1[XInc-1] = PositionArrayInput[XInc-1];
908         LocalArray2[XInc-1] = PositionArrayInput[XInc-1];
909      }
910      double PositionValueLocal = PositionArrayInput[StoreValue-1];
911      PositionError = 0.0;
912      StoreValue--;
913      for(YInc=1;YInc<=NumberOfPointsInput-1;YInc++) {
914         for(XInc=1;XInc<=NumberOfPointsInput-YInc;XInc++) {
915            TimeValue1 = TimeArrayInput[XInc-1]-CurrentTime;
916            TimeValue2 = TimeArrayInput[(XInc-1)+YInc]-CurrentTime;
917            PositionValue = LocalArray1[XInc]-LocalArray2[XInc-1];
918            DenominatorValue = TimeValue1-TimeValue2;
919            if(DenominatorValue==0.0) {
920               /* interpolation error - denominator = 0 */
921               return -999.5;                                   /* EXIT */
922            }
923            DenominatorValue = PositionValue/DenominatorValue;
924            LocalArray1[XInc-1] = TimeValue1*DenominatorValue;
925            LocalArray2[XInc-1] = TimeValue2*DenominatorValue;
926            /* System.out.printf("YInc=%d XInc=%d  demon=%f local1=%f local2=%f\n",YInc,XInc,DenominatorValue,LocalArray1[XInc-1],LocalArray2[XInc-1]); */
927         }
928         if((2*StoreValue)<(NumberOfPointsInput-YInc)) {
929            PositionError = LocalArray1[StoreValue];
930         } else {
931            PositionError = LocalArray2[StoreValue-1];
932            StoreValue--;
933         }
934         PositionValueLocal = PositionValueLocal+PositionError;
935      } 
936      /* System.out.printf("interpolated position=%f error=%f\n",PositionValueLocal,PositionError); */
937      double InterpolatedPosition = PositionValueLocal;
938    
939      /*
940       *  NOTE : additional function return point above
941       *  - return -1 if interpolation fails/denominator is zero
942       */
943
944      return InterpolatedPosition;
945
946   }
947
948
949}