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 031public class Scene { 032 033 private static double[] BDCurve_Points = 034 { 30.0, 9.0,-30.0,-42.0,-54.0, 035 -64.0,-70.0,-76.0,-80.0,-84.0,-100.0}; 036 037 private static double LARGE_EYE_RADIUS = 38.0; 038 private static double RING_WIDTH = 4.0; 039 private static double MANUAL_EYE_RADIUS = 24.0; 040 private static float[][] IRImageLatitudeArrayLocal = new float[200][200]; 041 private static float[][] IRImageLongitudeArrayLocal = new float[200][200]; 042 private static float[][] IRImageTemperatureArrayLocal = new float[200][200]; 043 private static int IRImageXSize; 044 private static int IRImageYSize; 045 046 public Scene() { 047 IRImageXSize = -1; 048 IRImageYSize = -1; 049 } 050 051 /** 052 * adt_classify in original ADT codebase. 053 * 054 * @param RunFullAnalysis Whether or not a complete scene analysis should 055 * happen. 056 */ 057 public static void DetermineSceneType(boolean RunFullAnalysis) { 058 059 int XInc; 060 int PreviousHistoryEyeSceneID = -1; 061 int PreviousHistoryCloudSceneID = -1; 062 double PreviousHistoryTnoValueMinus12hrs = 0.0; 063 boolean FoundHistoryRecMinus12hrTF = false; 064 double TemperatureValue = -999.0; 065 int LogSpiralAmount = 0; 066 067 int CloudBDCategory = -99; 068 int CloudCWBDCategory = -99; 069 int EyeBDCategory = -99; 070 int CloudBDDifference = -99; 071 int EyeCloudBDCategoryDifference = -99; 072 double TnoInterpValue = -99.9; 073 double CloudBDCategoryFloat = -99.9; 074 double EyeBDCategoryFloat = -99.9; 075 double CloudCWBDCategoryFloat = -99.9; 076 double CloudTemperatureDifference = -99.9; 077 double EyeCloudCWBDCategoryFloatDiff = -99.9; 078 double EyeCloudBDCategoryFloatDiff = -99.9; 079 double CloudBDCategoryFloatDiff = -99.9; 080 double EyeCloudTemperatureDiff2 = -99.9; 081 082 boolean LandFlagTF = Env.LandFlagTF; 083 double InitStrengthValue = Env.InitRawTValue; 084 double RMWSize = Env.RMWSize; 085 086 int EyeFFTValue = History.IRCurrentRecord.eyefft; 087 int CloudFFTValue = History.IRCurrentRecord.cloudfft; 088 double StormLatitude = History.IRCurrentRecord.latitude; 089 double StormLongitude = History.IRCurrentRecord.longitude; 090 double EyeTemperature = History.IRCurrentRecord.eyet; 091 double EyeStdvValue = History.IRCurrentRecord.eyestdv; 092 double CloudCWTemperature = History.IRCurrentRecord.cwcloudt; 093 double CloudTemperature = History.IRCurrentRecord.cloudt; 094 double CloudSymmetryValue = History.IRCurrentRecord.cloudsymave; 095 double CurvedBandBDMaxLatitude = StormLatitude; 096 double CurvedBandBDMaxLongitude = StormLongitude; 097 098 for(XInc=0;XInc<10;XInc++) { 099 /* compute cloud category */ 100 if((CloudTemperature<=BDCurve_Points[XInc])&& 101 (CloudTemperature>BDCurve_Points[XInc+1])) { 102 CloudBDCategory = XInc; 103 TnoInterpValue = (CloudTemperature-BDCurve_Points[CloudBDCategory])/ 104 (BDCurve_Points[CloudBDCategory+1]- 105 BDCurve_Points[CloudBDCategory]); 106 if(CloudBDCategory==0) { 107 TnoInterpValue = 0.0; 108 } 109 CloudBDCategoryFloat = (double)CloudBDCategory+TnoInterpValue; 110 } 111 /* compute eye category */ 112 if((EyeTemperature<=BDCurve_Points[XInc])&& 113 (EyeTemperature>BDCurve_Points[XInc+1])) { 114 EyeBDCategory = XInc; 115 TnoInterpValue = (EyeTemperature-BDCurve_Points[EyeBDCategory])/ 116 (BDCurve_Points[EyeBDCategory+1]- 117 BDCurve_Points[EyeBDCategory]); 118 if(EyeBDCategory==0) { 119 TnoInterpValue = 0.0; 120 } 121 EyeBDCategoryFloat = (double)EyeBDCategory+TnoInterpValue; 122 } 123 /* compute C-W eye category */ 124 if((CloudCWTemperature<=BDCurve_Points[XInc])&& 125 (CloudCWTemperature>BDCurve_Points[XInc+1])) { 126 CloudCWBDCategory = XInc; 127 TnoInterpValue = (CloudCWTemperature-BDCurve_Points[CloudCWBDCategory])/ 128 (BDCurve_Points[CloudCWBDCategory+1]- 129 BDCurve_Points[CloudCWBDCategory]); 130 if(CloudCWBDCategory==0) { 131 TnoInterpValue = 0.0; 132 } 133 CloudCWBDCategoryFloat = (double)CloudCWBDCategory+TnoInterpValue; 134 } 135 } 136 137 /* 138 * System.out.printf("EYE = temp=%f cat=%d part=%f \n",EyeTemperature,EyeBDCategory, 139 * EyeBDCategoryFloat); 140 * System.out.printf("CLD = temp=%f cat=%d part=%f \n",CloudTemperature,CloudBDCategory, 141 * CloudBDCategoryFloat); 142 * System.out.printf("CWT = temp=%f cat=%d part=%f \n",CloudCWTemperature, 143 * CloudCWBDCategory, 144 * CloudCWBDCategoryFloat); 145 */ 146 147 CloudTemperatureDifference = CloudTemperature-CloudCWTemperature; 148 EyeCloudCWBDCategoryFloatDiff = CloudCWBDCategoryFloat-EyeBDCategoryFloat; 149 EyeCloudBDCategoryFloatDiff = CloudBDCategoryFloat-EyeBDCategoryFloat; 150 CloudBDCategoryFloatDiff = CloudBDCategoryFloat-CloudCWBDCategoryFloat; 151 CloudBDDifference = CloudBDCategory-CloudCWBDCategory; 152 EyeCloudBDCategoryDifference = CloudBDCategory-EyeBDCategory; 153 EyeCloudTemperatureDiff2 = EyeTemperature-(Math.min(CloudTemperature,CloudCWTemperature)); 154 155 /* 156 * System.out.printf("BDCategoryDifference=%d\n",BDCategoryDifference); 157 * System.out.printf("EyeCloudBDCategoryDifference=%d\n",EyeCloudBDCategoryDifference); 158 * System.out.printf("CloudBDDifference=%d\n",CloudBDDifference); 159 * System.out.printf("CloudTemperatureDifference=%f\n",CloudTemperatureDifference); 160 * System.out.printf("EyeCloudTemperatureDifference=%f\n",EyeCloudTemperatureDifference); 161 * System.out.printf("EyeCloudCWBDCategoryFloatDiff=%f\n",EyeCloudCWBDCategoryFloatDiff); 162 * System.out.printf("EyeCloudBDCategoryFloatDiff=%f\n",EyeCloudBDCategoryFloatDiff); 163 * System.out.printf("CloudBDCategoryFloatDiff=%f\n",CloudBDCategoryFloatDiff); 164 * System.out.printf("EyeCloudTemperatureDiff2=%f\n",EyeCloudTemperatureDiff2); 165 */ 166 167 int ImageDate = History.IRCurrentRecord.date; 168 int ImageTime = History.IRCurrentRecord.time; 169 170 double CurrentTime = Functions.calctime(ImageDate,ImageTime); 171 /* System.out.printf("current time=%f\n",CurrentTime); */ 172 173 double CurrentTimeMinus12hr = CurrentTime-0.5; 174 boolean FoundEyeSceneTF = false; 175 double MaximumRule9Value = -99.0; 176 int LastRule9Value = 0; 177 double PreviousHistoryTnoValue = MaximumRule9Value; 178 double PreviousValidHistoryTnoValue = PreviousHistoryTnoValue; 179 180 int HistoryFileRecords = History.HistoryNumberOfRecords(); 181 182 if((HistoryFileRecords==0)||(!RunFullAnalysis)) { 183 FoundHistoryRecMinus12hrTF = true; 184 PreviousHistoryEyeSceneID = 3; 185 LastRule9Value = 1; 186 if((CloudCWBDCategoryFloat<3.5)&&(InitStrengthValue<3.5)) { 187 PreviousHistoryCloudSceneID = 3; 188 PreviousHistoryTnoValueMinus12hrs = InitStrengthValue; 189 } else { 190 PreviousHistoryCloudSceneID = 0; 191 PreviousHistoryTnoValueMinus12hrs = Math.max(InitStrengthValue,4.0); 192 } 193 194 } else { 195 FoundHistoryRecMinus12hrTF = false; 196 PreviousHistoryCloudSceneID = 3; 197 198 int RecDate,RecTime,RecLand; 199 int RecEyeScene,RecCloudScene; 200 int RecRule9; 201 double LastValidHistoryRecTime=0.0; 202 double HistoryRecTime; 203 double RecTnoRaw,RecTnoFinal; 204 boolean LandCheckTF; 205 for(XInc=0;XInc<HistoryFileRecords;XInc++) { 206 RecDate = History.HistoryFile[XInc].date; 207 RecTime = History.HistoryFile[XInc].time; 208 RecLand = History.HistoryFile[XInc].land; 209 RecTnoRaw = History.HistoryFile[XInc].Traw; 210 HistoryRecTime = Functions.calctime(RecDate,RecTime); 211 LandCheckTF = true; 212 if(((LandFlagTF)&&(RecLand==1))||(RecTnoRaw<1.0)) { 213 LandCheckTF = false; 214 } 215 if((HistoryRecTime<CurrentTime)&&(LandCheckTF)) { 216 LastValidHistoryRecTime = HistoryRecTime; 217 RecTnoFinal = History.HistoryFile[XInc].Tfinal; 218 RecEyeScene = History.HistoryFile[XInc].eyescene; 219 RecCloudScene = History.HistoryFile[XInc].cloudscene; 220 RecRule9 = History.HistoryFile[XInc].rule9; 221 if((HistoryRecTime>=CurrentTimeMinus12hr)&& 222 (!FoundHistoryRecMinus12hrTF)) { 223 PreviousHistoryTnoValueMinus12hrs = RecTnoFinal; 224 FoundHistoryRecMinus12hrTF = true; 225 } 226 PreviousHistoryTnoValue = RecTnoFinal; 227 PreviousHistoryCloudSceneID = RecCloudScene; 228 PreviousHistoryEyeSceneID = RecEyeScene; 229 if(PreviousHistoryEyeSceneID<=2) { 230 FoundEyeSceneTF = true; 231 } 232 if((PreviousHistoryCloudSceneID==4)&& 233 (PreviousHistoryEyeSceneID==3)) { 234 FoundEyeSceneTF = false; 235 } 236 PreviousValidHistoryTnoValue = PreviousHistoryTnoValue; 237 LastRule9Value = RecRule9; 238 if(PreviousHistoryTnoValue>MaximumRule9Value) { 239 MaximumRule9Value = PreviousHistoryTnoValue; 240 } 241 } else { 242 if(!LandCheckTF) { 243 /* if over land for > 12 hours, turn off FoundEyeSceneTF */ 244 if((HistoryRecTime-LastValidHistoryRecTime)>0.5) { 245 FoundEyeSceneTF = false; 246 PreviousHistoryTnoValue = PreviousValidHistoryTnoValue- 247 (1.0*(HistoryRecTime-LastValidHistoryRecTime)); 248 /* 249 * printf("PreviousValidHistoryTnoValue=%f deltatime=%f 250 * PreviousHistoryTnoValue=%f\n", 251 * PreviousValidHistoryTnoValue, 252 * HistoryRecTime-LastValidHistoryRecTime, 253 * PreviousHistoryTnoValue); 254 */ 255 } 256 } 257 } 258 } 259 /* check for large break in history file */ 260 if(!FoundHistoryRecMinus12hrTF) { 261 PreviousHistoryTnoValueMinus12hrs = PreviousHistoryTnoValue; 262 } 263 } 264 265 /* System.out.printf("FoundHistoryRecMinus12hrTF=%b\n",FoundHistoryRecMinus12hrTF); */ 266 /* System.out.printf("PreviousHistoryTnoValueMinus12hrs=%f\n",PreviousHistoryTnoValueMinus12hrs); */ 267 268 int EyeSceneIDValue; 269 double EyeSceneFactorC = 0.0; 270 double EyeSceneFactorE = 0.0; 271 double EyeSceneFactorA = 1.0-((EyeFFTValue-2)*0.1); 272 double EyeSceneFactorB = -(EyeBDCategoryFloat*0.5); 273 274 if(EyeStdvValue>10.0) { 275 EyeSceneFactorC = 0.50; 276 } 277 double EyeSceneFactorD = (EyeCloudBDCategoryFloatDiff*0.25)+ 278 (EyeCloudCWBDCategoryFloatDiff*0.50); 279 280 /* System.out.printf("EyeSceneFactorD=%f\n",EyeSceneFactorD); */ 281 /* System.out.printf("MaximumRule9Value=%f EyeSceneFactorE=%f\n",MaximumRule9Value,EyeSceneFactorE); */ 282 283 if((FoundHistoryRecMinus12hrTF)&&(PreviousHistoryEyeSceneID<3)&& 284 (MaximumRule9Value>5.0)) { 285 EyeSceneFactorC = EyeSceneFactorC+0.25; /* changed from EyeSceneFactorE */ 286 } 287 /* System.out.printf("EyeSceneFactorE=%f\n",EyeSceneFactorE); */ 288 if(PreviousHistoryTnoValueMinus12hrs<=4.5) { 289 EyeSceneFactorE = Math.max(-1.0,PreviousHistoryTnoValueMinus12hrs-4.5); 290 } 291 292 /* System.out.printf("PreviousHistoryTnoValueMinus12hrs=%f EyeSceneFactorE=%f\n", 293 PreviousHistoryTnoValueMinus12hrs,EyeSceneFactorE); */ 294 295 if((LastRule9Value>0)&&(PreviousHistoryTnoValue<4.0)) { 296 EyeSceneFactorE = EyeSceneFactorE-0.5; 297 } 298 /* System.out.printf("EyeSceneFactorE=%f\n",EyeSceneFactorE); */ 299 double EyeFactorTotal = EyeSceneFactorA+EyeSceneFactorB+EyeSceneFactorC+ 300 EyeSceneFactorD+EyeSceneFactorE; 301 EyeSceneIDValue = 3; /* NO EYE */ 302 if(EyeFactorTotal>=0.50) { 303 EyeSceneIDValue = 0; /* EYE */ 304 } 305 306 /* System.out.printf("EyeFactorTotal= %f EyeSceneIDValue=%d \n",EyeFactorTotal,EyeSceneIDValue); */ 307 308 double EyeCDOSizeValue = 0.0; 309 /* System.out.printf("RMW SIZE=%f\n",RMWSize); */ 310 if(RMWSize>0.0) { 311 /* System.out.printf("Manually Entered RMW Size=%f\n",RMWSize); */ 312 History.IRCurrentRecord.rmw = RMWSize; 313 EyeCDOSizeValue = RMWSize-1.0; /* manually input eye size */ 314 } else { 315 /* System.out.printf("Calculating RMW Size\n"); */ 316 double LocalValue[] = Data.CalcRMW(); 317 double RadiusMaxWind = LocalValue[0]; 318 /* System.out.printf("Calculated RMW Size=%f\n",RadiusMaxWind); */ 319 History.IRCurrentRecord.rmw = RadiusMaxWind; 320 } 321 322 /* LARGE EYE CHECKS */ 323 double LargeEyeRadius = LARGE_EYE_RADIUS; 324 if((EyeSceneIDValue==0)&&(EyeCDOSizeValue>=LargeEyeRadius)) { 325 EyeSceneIDValue = 2; /* large eye */ 326 } 327 328 /* NEW CLOUD SCENE THRESHOLD DETERMINATION */ 329 boolean ShearSceneTF = false; 330 boolean IrregularCDOSceneTF = false; 331 boolean CurvedBandSceneTF = true; 332 boolean CurvedBandBDGrayShadeTF = true; 333 boolean CurvedBandBDBlackWhiteTF = false; 334 boolean EmbeddedCenterCheckTF = false; 335 boolean EmbeddedCenterSceneTF = false; 336 337 double CloudSceneFactorC = 0.0; 338 double CloudSceneFactorD = 0.5; 339 double CloudSceneFactorE = 0.0; 340 double CloudSceneFactorA = CloudCWBDCategoryFloat*0.25; 341 double CloudSceneFactorB = CloudBDCategoryFloat*0.25; 342 if(CloudFFTValue<=2) { 343 CloudSceneFactorC = Math.min(1.50,CloudCWBDCategoryFloat*0.25); 344 } 345 if(PreviousHistoryCloudSceneID>=3) { 346 CloudSceneFactorD = -0.50; 347 } 348 349 /* System.out.printf("CloudCWBDCategoryFloat=%f PreviousHistoryTnoValueMinus12hrs=%f\n", 350 CloudCWBDCategoryFloat,PreviousHistoryTnoValueMinus12hrs); */ 351 352 if(CloudCWBDCategoryFloat>2.0) { 353 if(PreviousHistoryTnoValueMinus12hrs>=2.5) { 354 if(EyeSceneIDValue==0) { 355 CloudSceneFactorE = Math.min(1.00,PreviousHistoryTnoValueMinus12hrs-2.5); 356 } 357 if(PreviousHistoryTnoValueMinus12hrs>=3.5) { 358 CloudSceneFactorE = CloudSceneFactorE+1.00; 359 } 360 } 361 if((FoundHistoryRecMinus12hrTF)&& 362 (FoundEyeSceneTF)) CloudSceneFactorE = CloudSceneFactorE+1.25; 363 } 364 double CloudFactorTotal = CloudSceneFactorA+CloudSceneFactorB+CloudSceneFactorC+ 365 CloudSceneFactorD+CloudSceneFactorE; 366 if(CloudFactorTotal<0.0) { 367 ShearSceneTF = true; /* SHEAR */ 368 } 369 if(CloudFactorTotal>=0.00) { 370 CurvedBandSceneTF = true; /* CURVED BAND (gray) */ 371 } 372 if(CloudFactorTotal>=1.00) { 373 CurvedBandSceneTF = true; /* CURVED BAND (gray) */ 374 /* check for irregular CDO */ 375 if((EyeCloudTemperatureDiff2<0.0)&&(CloudSymmetryValue>40.0)) { 376 IrregularCDOSceneTF = true; /* IRREGULAR CDO */ 377 } 378 } 379 if((CloudFactorTotal>=2.00)&&(CloudFactorTotal<3.00)) { 380 CurvedBandSceneTF = true; /* CURVED BAND (gray) */ 381 /* check for irregular CDO */ 382 if((EyeCloudTemperatureDiff2<0.0)&&(CloudSymmetryValue>30.0)) { 383 IrregularCDOSceneTF = true; /* IRREGULAR CDO */ 384 } 385 if(CloudCWBDCategory>=3) { 386 /* if xcwt>3.0 try black/white CB check */ 387 if((CloudBDDifference>0)&& 388 (CloudTemperatureDifference<-8.0)) { 389 CurvedBandBDGrayShadeTF = false; /* CURVED BAND (b/w) */ 390 CurvedBandBDBlackWhiteTF = true; 391 } 392 /* check for large/ragged eye */ 393 if((EyeSceneIDValue==0)|| 394 ((EyeBDCategoryFloat>1.00)&& 395 (EyeCloudBDCategoryDifference>=2.00))) { 396 CurvedBandSceneTF = false; /* EYE */ 397 } 398 /* check for CDO */ 399 if((CloudBDCategoryFloatDiff<=0.0)&& 400 (EyeCloudCWBDCategoryFloatDiff<1.00)) { 401 CurvedBandSceneTF = false; /* CDO */ 402 } 403 } 404 } 405 if(CloudFactorTotal>=3.00) { 406 CurvedBandSceneTF=false; /* CDO */ 407 /* check for irregular CDO */ 408 if((CloudBDDifference<0)&& 409 (CloudTemperatureDifference>8.0)&&(CloudSymmetryValue>30.0)) { 410 IrregularCDOSceneTF = true; /* IRREGULAR CDO */ 411 CurvedBandSceneTF = true; 412 } 413 } 414 /* EMBEDDED CENTER CHECK */ 415 if((CloudTemperature<CloudCWTemperature)&& 416 (CloudCWTemperature<EyeTemperature)) { 417 EmbeddedCenterCheckTF = true; 418 } 419 if((!CurvedBandSceneTF)&&(EmbeddedCenterCheckTF)) { 420 TemperatureValue=BDCurve_Points[CloudCWBDCategory+1]+273.16; 421 double ReturnValues[] = Scene.adt_logspiral(StormLatitude,StormLongitude,TemperatureValue,1); 422 LogSpiralAmount = (int)ReturnValues[0]; 423 if((LogSpiralAmount>=8)&&(LogSpiralAmount<20)) { 424 EmbeddedCenterSceneTF = true; 425 } 426 427 /* System.out.printf(" EMBDD : CloudCWBDCategory=%d LogSpiralAmount=%d \n", 428 CloudCWBDCategory,LogSpiralAmount); */ 429 430 } 431 432 /* System.out.printf("CloudFactorTotal= %f ShearSceneTF=%b CurvedBandSceneTF=%b CurvedBandBDGrayShadeTF=%b IrregularCDOSceneTF=%b \n", 433 CloudFactorTotal,ShearSceneTF,CurvedBandSceneTF,CurvedBandBDGrayShadeTF,IrregularCDOSceneTF); */ 434 435 /* 436 * System.out.printf("%9s %6d %4.1f %4.1f %2d %2d %5.1f %5.1f %5.2f %5.2f %5.2f %5.2f %5.2f %5.2f %5.2f %2d %2d %4.1f %4.1f %5.2f %5.2f %5.2f %5.2f %5.2f %5.2f %6.2f %7.2f %3.1f \n",ImageDateString,ImageTime, 437 * CloudBDCategoryFloat,CloudCWBDCategoryFloat,CloudFFTValue, 438 * CloudBDDifference,CloudTemperatureDifference,CloudSymmetryValue, 439 * CloudSceneFactorA,CloudSceneFactorB,0.0,CloudSceneFactorC, 440 * CloudSceneFactorD,CloudSceneFactorE,CloudFactorTotal, 441 * EyeFFTValue,EyeCloudBDCategoryDifference,EyeBDCategoryFloat,EyeStdvValue, 442 * EyeSceneFactorA,EyeSceneFactorB,EyeSceneFactorC,EyeSceneFactorD, 443 * EyeSceneFactorE,EyeFactorTotal,StormLatitude,StormLongitude, 444 * PreviousHistoryTnoValue); 445 */ 446 447 /* CLASSIFY CLOUD REGION */ 448 int CurvedBandBDCategory = 0; 449 int CurvedBandBDAmount = 0; 450 int CurvedBandBDMaxAmount = 0; 451 int CloudSceneIDValue = -99; 452 boolean FoundCurvedBandSceneTF = false; 453 double ShearDistance = -99.0; 454 455 /* System.out.printf("CurvedbandsceneTF=%b IrregularCDOTF=%b ShearSceneTF=%b \n",CurvedBandSceneTF,IrregularCDOSceneTF,ShearSceneTF); */ 456 if(CurvedBandSceneTF) { 457 if(ShearSceneTF) { 458 EyeSceneIDValue = 3; /* NO EYE */ 459 CloudSceneIDValue = 4; /* SHEAR */ 460 TemperatureValue = ((BDCurve_Points[2]+BDCurve_Points[3])/2.0)+273.16; 461 ShearDistance = adt_cdoshearcalc(StormLatitude,StormLongitude,TemperatureValue,3); 462 EyeCDOSizeValue = Math.max(4.0,ShearDistance); 463 } 464 else if(IrregularCDOSceneTF) { 465 EyeSceneIDValue = 3; /* NO EYE */ 466 CloudSceneIDValue = 2; /* IRREGULAR CDO */ 467 } 468 else { 469 FoundCurvedBandSceneTF = false; 470 if(CurvedBandBDGrayShadeTF) { 471 /* perform Curved Band analysis */ 472 XInc = 4; /* start with LIGHT GRAY */ 473 while((XInc>=2)&&(!FoundCurvedBandSceneTF)) { 474 TemperatureValue = BDCurve_Points[XInc]+273.16; 475 double ReturnValues[] = Scene.adt_logspiral(StormLatitude,StormLongitude,TemperatureValue,1); 476 LogSpiralAmount = (int)ReturnValues[0]; 477 if((LogSpiralAmount>=8)||(XInc==2)) { 478 /* 10 = .375% -- 10 ==> 9 arcs of 15 degrees */ 479 if(LogSpiralAmount>25) { 480 if(XInc==4) { 481 CurvedBandBDGrayShadeTF = false; 482 CurvedBandBDBlackWhiteTF = true; 483 /* following line to exit out of While statement */ 484 FoundCurvedBandSceneTF = true; 485 } 486 else { 487 XInc = 0; 488 } 489 } 490 else { 491 if((XInc==2)&&(LogSpiralAmount<7)) { 492 /* 7 = .25% -- 10 ==> 6 arcs of 15 degrees */ 493 /* probably shear */ 494 FoundCurvedBandSceneTF = false; 495 CurvedBandBDBlackWhiteTF = false; 496 ShearSceneTF = true; 497 /* gross error check... added 08/15/13 */ 498 if((EyeBDCategoryFloat>1.5)||(CloudBDCategoryFloat>2.5)) { 499 ShearSceneTF = false; 500 IrregularCDOSceneTF = true; 501 } 502 /* following line to exit out of While statement */ 503 XInc--; 504 } 505 else { 506 FoundCurvedBandSceneTF = true; 507 } 508 } 509 } 510 else { 511 XInc--; 512 } 513 } 514 } 515 if(CurvedBandBDBlackWhiteTF) { 516 /* try BLACK and WHITE rings */ 517 FoundCurvedBandSceneTF = false; 518 CurvedBandSceneTF = false; 519 XInc = 6; 520 while((XInc>4)&&(!FoundCurvedBandSceneTF)) { 521 TemperatureValue = BDCurve_Points[XInc]+273.16; 522 double ReturnValues[] = Scene.adt_logspiral(StormLatitude,StormLongitude,TemperatureValue,1); 523 LogSpiralAmount = (int)ReturnValues[0]; 524 if((LogSpiralAmount>=9)&&(LogSpiralAmount<=25)) { 525 FoundCurvedBandSceneTF = true; 526 /* EmbeddedCenterSceneTF = true; needed here? */ 527 } 528 else { 529 XInc--; 530 } 531 } 532 } 533 if(FoundCurvedBandSceneTF) { 534 /* found curved band scenes */ 535 CurvedBandBDCategory = XInc; 536 CurvedBandBDAmount = LogSpiralAmount; 537 EyeSceneIDValue = 3; /* NO EYE */ 538 CloudSceneIDValue = 3; /* CURVED BAND */ 539 /* search for max curved band analysis location w/in 1-degree box */ 540 TemperatureValue = BDCurve_Points[CurvedBandBDCategory]+273.16; 541 boolean CBSearchTF_Global = true; 542 if(CBSearchTF_Global) { /* need global variable here */ 543 double ReturnValues[] = Scene.adt_logspiral(StormLatitude,StormLongitude,TemperatureValue,2); 544 CurvedBandBDMaxAmount = (int)ReturnValues[0]; 545 CurvedBandBDMaxLatitude = ReturnValues[1]; 546 CurvedBandBDMaxLongitude = ReturnValues[2]; 547 /* System.out.printf("max amounts %d %f %f\n",CurvedBandBDMaxAmount,CurvedBandBDMaxLatitude,CurvedBandBDMaxLongitude); */ 548 } 549 } 550 else { 551 /* did not find curved band scenes, mark as non-eye/eye scene */ 552 CloudSceneIDValue = 0; 553 CurvedBandSceneTF = false; 554 EmbeddedCenterSceneTF = false; 555 } 556 } 557 } 558 /* System.out.printf("CurvedbandsceneTF=%b IrregularCDOTF=%b ShearSceneTF=%b EmbeddedCenterTF=%b \n", 559 CurvedBandSceneTF,IrregularCDOSceneTF,ShearSceneTF,EmbeddedCenterSceneTF); */ 560 if(!CurvedBandSceneTF) { 561 if(ShearSceneTF) { 562 /* shear scene */ 563 EyeSceneIDValue = 3; /* NO EYE */ 564 CloudSceneIDValue = 4; /* SHEAR */ 565 TemperatureValue = ((BDCurve_Points[2]+BDCurve_Points[3])/2.0)+273.16; 566 ShearDistance = adt_cdoshearcalc(StormLatitude,StormLongitude,TemperatureValue,3); 567 EyeCDOSizeValue = Math.max(4.0,ShearDistance); 568 } 569 else { 570 CloudSceneIDValue = 0; /* UNIFORM */ 571 if(EmbeddedCenterSceneTF) { 572 CloudSceneIDValue = 1; /* EMBEDDED CENTER */ 573 } 574 /* added 08/15/13 */ 575 if(IrregularCDOSceneTF) { 576 CloudSceneIDValue = 2; /* Irregular CDO */ 577 } 578 /* PINHOLE EYE TEST */ 579 /* 580 * System.out.printf("EyeFactorTotal=%f\n", 581 * "EyeSceneIDValue=%d EyeCloudBDCategoryDifference=%d ", 582 * "EyeFFTValue=%d CloudCWBDCategoryFloat=%f \n", 583 * "CloudSceneIDValue=%d CloudFFTValue=%d ", 584 * "PreviousHistoryTnoValueMinus12hrs=%f\n",EyeFactorTotal, 585 * EyeSceneIDValue,EyeCloudBDCategoryDifference,EyeFFTValue, 586 * CloudCWBDCategoryFloat,CloudSceneIDValue,CloudFFTValue, 587 * PreviousHistoryTnoValueMinus12hrs); 588 */ 589 if((RMWSize>0.0)&&(RMWSize<12.0)) { 590 EyeSceneIDValue = 1; /* PINHOLE EYE CHECK */ 591 } 592 if((EyeFactorTotal>-0.25)&&(EyeFactorTotal<1.50)&& 593 (EyeCloudBDCategoryDifference>=2)&&(EyeFFTValue<=2)&& 594 (CloudCWBDCategoryFloat>6.0)&&(CloudSceneIDValue<=1)&& 595 (CloudFFTValue<=4)&&(PreviousHistoryTnoValueMinus12hrs>=3.5)) { 596 EyeSceneIDValue = 1; /* PINHOLE EYE CHECK */ 597 } 598 } 599 } 600 double CDOSize = -999.0; 601 /* System.out.printf("cloudsceneID=%d eyesceneID=%d\n",CloudSceneIDValue,EyeSceneIDValue); */ 602 if((CloudSceneIDValue<=2)&&(EyeSceneIDValue==3)) { 603 /* for CDO TESTS */ 604 for(XInc=2;XInc<=6;XInc++) { /* DG,MG,LG,B,W */ 605 TemperatureValue = BDCurve_Points[XInc]+273.16; 606 /* System.out.printf("LatitudeValue=%f LongitudeValue=%f TemperatureValue=%f\n",StormLatitude,StormLongitude,TemperatureValue); */ 607 CDOSize = adt_cdoshearcalc(StormLatitude,StormLongitude,TemperatureValue,1); 608 /* System.out.printf("CDO : XInc=%d CDOSize=%f CDOSize/111=%f \n",XInc,CDOSize,CDOSize/111.0); */ 609 if(XInc==2) { 610 EyeCDOSizeValue = CDOSize; 611 } 612 } 613 } 614 615 /* System.out.printf("eyescene=%d cloudscene=%d eyecdosize=%f ringcb=%d ringcbval=%d\n", 616 EyeSceneIDValue,CloudSceneIDValue,EyeCDOSizeValue,CurvedBandBDCategory,CurvedBandBDAmount); */ 617 /* System.out.printf("CBMAX :ringcbval=%d ringcb=%d ringcbval=%d\n",CurvedBandBDMaxAmount,CurvedBandBDCategory,CurvedBandBDAmount); */ 618 619 /* System.out.printf("EyeScene=%d CloudScene=%d EyeCDOSize=%f \n",EyeSceneIDValue,CloudSceneIDValue,EyeCDOSizeValue); */ 620 History.IRCurrentRecord.eyescene = EyeSceneIDValue; 621 History.IRCurrentRecord.cloudscene = CloudSceneIDValue; 622 History.IRCurrentRecord.eyesceneold = -1; 623 History.IRCurrentRecord.cloudsceneold = -1; 624 History.IRCurrentRecord.eyecdosize = EyeCDOSizeValue; 625 History.IRCurrentRecord.ringcb = CurvedBandBDCategory; 626 History.IRCurrentRecord.ringcbval = CurvedBandBDAmount; 627 History.IRCurrentRecord.ringcbvalmax = CurvedBandBDMaxAmount; 628 History.IRCurrentRecord.ringcbvalmaxlat = CurvedBandBDMaxLatitude; 629 History.IRCurrentRecord.ringcbvalmaxlon = CurvedBandBDMaxLongitude; 630 History.IRCurrentRecord.mwscore = Env.MWScore; 631 History.IRCurrentRecord.mwdate = Env.MWJulianDate; 632 History.IRCurrentRecord.mwtime = Env.MWHHMMSSTime; 633 634 } 635 636 /** 637 * Determine storm location using 10^ Log-spiral analysis. 638 * 639 * <p>Algorithm will attempt to match the spiral with the image 640 * pixels at or below the threshold temperature based on 641 * BD-enhancement curve values.</p> 642 * 643 * @param InputLatitude Center latitude of analysis grid 644 * @param InputLongitude Center longitude of analysis grid 645 * @param TemperatureThreshold Temperature threshold value 646 * @param AnalysisTypeIDValue 1=search at single point 647 * 2=search over 2^box 648 * 649 * @return Array of three double values. In order, they 650 * are: 651 * <ol> 652 * <li>SpiralArcLatitude - best latitude location from analysis.</li> 653 * <li>SpiralArcLongitude - best longitude location from analysis.</li> 654 * <li>SpiralArcDistance - number of consecutive arcs through which 655 * spiral passes</li> 656 * </ol> 657 */ 658 public static double[] adt_logspiral(double InputLatitude, 659 double InputLongitude, 660 double TemperatureThreshold, 661 int AnalysisTypeIDValue) 662 { 663 int XInc,YInc,ZInc; 664 int SpiralArcDistance=-99; 665 int SearchLatitudeMaxInteger,SearchLatitudeMinInteger; 666 int SearchLongitudeMaxInteger,SearchLongitudeMinInteger; 667 double SearchLatitudeMaximum,SearchLatitudeMinimum; 668 double SearchLongitudeMaximum,SearchLongitudeMinimum; 669 double SpiralArcLatitude=-999.99; 670 double SpiralArcLongitude=-999.99; 671 float ValidPixelLatitudeArray[] = new float[40000]; 672 float ValidPixelLongitudeArray[] = new float[40000]; 673 float ValidPixelTemperatureArray[] = new float[40000]; 674 675 double ImageResolution = Data.GetCurrentImageResolution(); 676 double DistanceDifferenceMaximumKM=ImageResolution+(ImageResolution/2.0); 677 int IncAddVal=(ImageResolution>RING_WIDTH) ? 1 : ((int)(RING_WIDTH-ImageResolution+1.0)); 678 679 if(AnalysisTypeIDValue==2) { 680 /* search over 2.0 degree box */ 681 SearchLatitudeMaximum = InputLatitude+1.0; 682 SearchLatitudeMinimum = InputLatitude-1.0; 683 SearchLongitudeMaximum = InputLongitude+1.0; 684 SearchLongitudeMinimum = InputLongitude-1.0; 685 SearchLatitudeMaxInteger = (int)(SearchLatitudeMaximum*100.0); 686 SearchLatitudeMinInteger = (int)(SearchLatitudeMinimum*100.0); 687 SearchLongitudeMaxInteger = (int)(SearchLongitudeMaximum*100.0); 688 SearchLongitudeMinInteger = (int)(SearchLongitudeMinimum*100.0); 689 } else { 690 /* search at a single point */ 691 SearchLatitudeMaxInteger = (int)(InputLatitude*100.0); 692 SearchLatitudeMinInteger = (int)(InputLatitude*100.0); 693 SearchLongitudeMaxInteger = (int)(InputLongitude*100.0); 694 SearchLongitudeMinInteger = (int)(InputLongitude*100.0); 695 } 696 697 /* allocate memory, if necessary */ 698 if(IRImageXSize==-1) { 699 IRImageXSize = Data.GetCurrentImageXSize(); 700 IRImageYSize = Data.GetCurrentImageYSize(); 701 IRImageLatitudeArrayLocal = Data.GetCurrentImageLatitudeArray(); 702 IRImageLongitudeArrayLocal = Data.GetCurrentImageLongitudeArray(); 703 IRImageTemperatureArrayLocal = Data.GetCurrentImageTemperatureArray(); 704 } 705 706 /* System.out.printf("temperature threshold=%f\n",TemperatureThreshold); */ 707 /* initialize arrays */ 708 int ValidPointCounter = 0; 709 for(YInc=0;YInc<IRImageYSize;YInc=YInc+IncAddVal) { 710 for(XInc=0;XInc<IRImageXSize;XInc=XInc+IncAddVal) { 711 if(IRImageTemperatureArrayLocal[YInc][XInc]<=TemperatureThreshold) { 712 ValidPixelLatitudeArray[ValidPointCounter] = IRImageLatitudeArrayLocal[YInc][XInc]; 713 ValidPixelLongitudeArray[ValidPointCounter] = IRImageLongitudeArrayLocal[YInc][XInc]; 714 ValidPixelTemperatureArray[ValidPointCounter] = IRImageTemperatureArrayLocal[YInc][XInc]; 715 ValidPointCounter++; 716 } 717 } 718 } 719 /* System.out.printf("Valid Point Counter=%d\n",ValidPointCounter); */ 720 721 int ArcSkipCounter; 722 int ThresholdCounter; 723 int SpiralConsecutiveArcCounter; 724 int SpiralConsecutiveArcMaximum; 725 double SpiralStartMinimumDistance; 726 double SearchIncrementLatitude=0.0; 727 double SearchIncrementLongitude=0.0; 728 double SpiralArcBestRotationAngleValue=0.0; 729 double ArcAngleTheta_Radians; 730 double RadialDistanceKM; 731 double FinalArcAngleTheta,FinalArcAngleThetaPlus180; 732 double RadiansValue=57.29578; /* degree to radians conversion value*/ 733 double SpiralConstantAValue=25.0; /* 10^ log spiral distance constant */ 734 double SpiralConstantBValue=10.0/RadiansValue; /* 10^ log spiral increase */ 735 double LatitudeDifference; 736 double LongitudeDifference; 737 738 for(XInc=SearchLatitudeMinInteger;XInc<=SearchLatitudeMaxInteger;XInc=XInc+20) { 739 SearchIncrementLatitude = (double)XInc/100.0; 740 /* loop through y-axis/lines of analysis grid box */ 741 for(YInc=SearchLongitudeMinInteger;YInc<=SearchLongitudeMaxInteger;YInc=YInc+20) { 742 SearchIncrementLongitude = (double)YInc/100.0; 743 ArcSkipCounter = 0; 744 /* determine distance from each point in box to current location */ 745 if(AnalysisTypeIDValue==2) { 746 SpiralStartMinimumDistance = 12.0; 747 for(ZInc=0;ZInc<ValidPointCounter;ZInc++) { 748 double LocalValue[] = Functions.distance_angle(SearchIncrementLatitude,SearchIncrementLongitude, 749 ValidPixelLatitudeArray[ZInc], 750 ValidPixelLongitudeArray[ZInc],1); 751 double DistanceValue = LocalValue[0]; 752 if(DistanceValue<=SpiralStartMinimumDistance) { 753 /* 754 * if the lat/lon point is too close to cold cloud tops, do 755 * not calculate log spiral at this point. Trying to eliminate 756 * "false" arc locations by forcing the system to use some 757 * of the arc points on the spiral away from the start of 758 * the spiral (were getting "false echos" without this". 759 */ 760 ArcSkipCounter = 1; 761 break; 762 } 763 } 764 } 765 766 int SpiralArcMaximumValue = 0; 767 int SpiralArcMaximumValueRotationFactor = 0; 768 /* 769 * if arc location passes analysis above, 770 * proceed with placement of spiral 771 */ 772 773 if(ArcSkipCounter==0) { 774 /* rotate the arc spiral thru entire revolution at 30^ interval */ 775 for(int RotationFactor=0;RotationFactor<=330;RotationFactor=RotationFactor+30) { 776 SpiralConsecutiveArcCounter = 0; 777 SpiralConsecutiveArcMaximum = 0; 778 779 /* calculate position of each point on spiral from 0 to 540^ */ 780 for(int ArcAngleTheta=0;ArcAngleTheta<=540;ArcAngleTheta=ArcAngleTheta+15) { 781 ArcAngleTheta_Radians = (double)ArcAngleTheta/RadiansValue; 782 RadialDistanceKM = SpiralConstantAValue*Math.exp((SpiralConstantBValue*ArcAngleTheta_Radians)); 783 FinalArcAngleTheta = (double)ArcAngleTheta+(double)RotationFactor; 784 if(SearchIncrementLatitude<0.0) { 785 FinalArcAngleTheta = (double)(-1*ArcAngleTheta)+(double)RotationFactor; 786 } 787 FinalArcAngleThetaPlus180 = FinalArcAngleTheta+180.0; 788 double LocalValue2[] = Functions.distance_angle2(SearchIncrementLatitude,SearchIncrementLongitude, 789 RadialDistanceKM,FinalArcAngleThetaPlus180); 790 double SearchGuessLatitude = LocalValue2[0]; 791 double SearchGuessLongitude = LocalValue2[1]; 792 ThresholdCounter = 0; 793 for(ZInc=0;ZInc<ValidPointCounter;ZInc++) { 794 LatitudeDifference = Math.abs(SearchGuessLatitude- 795 ValidPixelLatitudeArray[ZInc]); 796 LongitudeDifference = Math.abs(SearchGuessLongitude- 797 ValidPixelLongitudeArray[ZInc]); 798 /* 799 * if a point is within 0.1^ latitude/longitude 800 * determine distance 801 */ 802 if((LatitudeDifference<=0.1)&&(LongitudeDifference<=0.1)) { 803 double LocalValue3[] = Functions.distance_angle(SearchGuessLatitude,SearchGuessLongitude, 804 ValidPixelLatitudeArray[ZInc], 805 ValidPixelLongitudeArray[ZInc],1); 806 double DistanceValue3 = LocalValue3[0]; 807 /* 808 * if distance from spiral point is within 6km from an 809 * accepted temperature threshold point, count it 810 */ 811 if(DistanceValue3<=DistanceDifferenceMaximumKM) { 812 ThresholdCounter++; 813 } 814 } 815 } 816 /* 817 * if there are 4 or more threshold points associated 818 * with each spiral point, count within consecutive 819 * spiral point counter 820 */ 821 if(ThresholdCounter>=4) { 822 SpiralConsecutiveArcCounter++; 823 /* 824 * save spiral that has maximum consecutive spiral counts 825 * for each rotation though 360^ at each center location 826 */ 827 if(SpiralConsecutiveArcCounter>SpiralConsecutiveArcMaximum) { 828 SpiralConsecutiveArcMaximum = SpiralConsecutiveArcCounter; 829 } 830 } else { 831 SpiralConsecutiveArcCounter = 0; 832 } 833 /* 834 * if this spiral has the greatest number of consecutive 835 * spiral points, save the location and number of points 836 */ 837 if(SpiralConsecutiveArcMaximum>SpiralArcMaximumValue) { 838 SpiralArcMaximumValue = SpiralConsecutiveArcMaximum; 839 SpiralArcMaximumValueRotationFactor = RotationFactor; 840 } 841 } 842 } /* RotationFactor loop */ 843 if(SpiralArcMaximumValue>SpiralArcDistance) { 844 SpiralArcDistance = SpiralArcMaximumValue; 845 SpiralArcLatitude = SearchIncrementLatitude; 846 SpiralArcLongitude = SearchIncrementLongitude; 847 SpiralArcBestRotationAngleValue = SpiralArcMaximumValueRotationFactor; 848 } 849 } /* ArcSkipCounter if */ 850 } /* YInc loop */ 851 } /* XInc loop */ 852 853 /* load array for best spiral band */ 854 for(int ArcAngleTheta=0;ArcAngleTheta<=540;ArcAngleTheta=ArcAngleTheta+15) { 855 ArcAngleTheta_Radians=(double)ArcAngleTheta/RadiansValue; 856 RadialDistanceKM=SpiralConstantAValue*Math.exp((SpiralConstantBValue*ArcAngleTheta_Radians)); 857 FinalArcAngleTheta=(double)ArcAngleTheta+(double)SpiralArcBestRotationAngleValue; 858 if(SearchIncrementLatitude<0.0) { 859 FinalArcAngleTheta=(double)(-1*ArcAngleTheta)+(double)SpiralArcBestRotationAngleValue; 860 } 861 FinalArcAngleThetaPlus180=FinalArcAngleTheta+180.0; 862 /* load array for external plotting of spiral band */ 863 /* SpiralBandPoints_Global[0][TemporaryCounter]=SearchGuessLatitude; */ 864 /*SpiralBandPoints_Global[1][TemporaryCounter]=SearchGuessLongitude; */ 865 } 866 867 return new double[] { (double)SpiralArcDistance, SpiralArcLatitude, SpiralArcLongitude }; 868 869 } 870 871 /** 872 * Determine eye size or shear distance for a given scene. 873 * 874 * @param InputLatitude Center latitude of analysis grid 875 * @param InputLongitude Center longitude of analysis grid 876 * @param TemperatureThreshold Temperature threshold value to be used 877 * @param AnalysisTypeIDValue Analysis type 878 * (1-cdo size,2-eye size,3-shear distance) 879 * 880 * @return eye/cdo radius or shear distance 881 */ 882 public static double adt_cdoshearcalc(double InputLatitude, 883 double InputLongitude, 884 double TemperatureThreshold, 885 int AnalysisTypeIDValue) 886 { 887 /* maximum distance constant value */ 888 double ANGLEMAXDIFFERENCE=15.0; 889 double RadiusOrShear=-99.0; 890 double Value3=MANUAL_EYE_RADIUS+RING_WIDTH; 891 double PixelLatitudeArray[] = new double[40000]; 892 double PixelLongitudeArray[] = new double[40000]; 893 double PixelTemperatureArray[] = new double[40000]; 894 895 int XInc,YInc,ZInc; 896 int PointCounter=0; 897 int ValidRadiiCounter=4; 898 double DistanceValue,AngleValue; 899 double SymmValue; 900 901 double RadiiLength1=300.0; 902 double RadiiLength2=300.0; 903 double RadiiLength3=300.0; 904 double RadiiLength4=300.0; 905 double MaxDistanceValue=0.0; 906 907 /* allocate memory, if necessary */ 908 if(IRImageXSize==-1) { 909 IRImageXSize = Data.GetCurrentImageXSize(); 910 IRImageYSize = Data.GetCurrentImageYSize(); 911 IRImageLatitudeArrayLocal = Data.GetCurrentImageLatitudeArray(); 912 IRImageLongitudeArrayLocal = Data.GetCurrentImageLongitudeArray(); 913 IRImageTemperatureArrayLocal = Data.GetCurrentImageTemperatureArray(); 914 } 915 916 if(AnalysisTypeIDValue==1) { 917 /* CDO size determination - RETURNS RADIUS */ 918 for(YInc=0;YInc<IRImageYSize;YInc++) { 919 for(XInc=0;XInc<IRImageXSize;XInc++) { 920 if(IRImageTemperatureArrayLocal[YInc][XInc]>TemperatureThreshold) { 921 PixelLatitudeArray[PointCounter] = IRImageLatitudeArrayLocal[YInc][XInc]; 922 PixelLongitudeArray[PointCounter] = IRImageLongitudeArrayLocal[YInc][XInc]; 923 PixelTemperatureArray[PointCounter] = IRImageTemperatureArrayLocal[YInc][XInc]; 924 PointCounter++; 925 } 926 } 927 } 928 929 /* System.out.printf("PointCounter=%d numx*numy=%d\n",PointCounter,IRImageYSize*IRImageXSize); */ 930 if(PointCounter<(IRImageYSize*IRImageXSize)) { 931 for(ZInc=0;ZInc<PointCounter;ZInc++) { 932 double LocalValue[] = Functions.distance_angle(InputLatitude,InputLongitude, 933 PixelLatitudeArray[ZInc],PixelLongitudeArray[ZInc],1); 934 DistanceValue = LocalValue[0]; 935 AngleValue = LocalValue[1]; 936 if(DistanceValue>MaxDistanceValue) MaxDistanceValue=DistanceValue; 937 /* determine size of CDO */ 938 if(DistanceValue>MANUAL_EYE_RADIUS) { 939 if((Math.abs(AngleValue-45.0)<=ANGLEMAXDIFFERENCE)&& 940 (DistanceValue<RadiiLength1)) { 941 RadiiLength1=DistanceValue; 942 } 943 if((Math.abs(AngleValue-135.0)<=ANGLEMAXDIFFERENCE)&& 944 (DistanceValue<RadiiLength2)) { 945 RadiiLength2=DistanceValue; 946 } 947 if((Math.abs(AngleValue-225.0)<=ANGLEMAXDIFFERENCE)&& 948 (DistanceValue<RadiiLength3)) { 949 RadiiLength3=DistanceValue; 950 } 951 if((Math.abs(AngleValue-315.0)<=ANGLEMAXDIFFERENCE)&& 952 (DistanceValue<RadiiLength4)) { 953 RadiiLength4=DistanceValue; 954 } 955 } 956 } 957 958 /* System.out.printf("RadiiLength1=%f RadiiLength2=%fRadiiLength3=%f RadiiLength4=%f\n", 959 RadiiLength1,RadiiLength2,RadiiLength3,RadiiLength4); */ 960 961 if(RadiiLength1<Value3) { 962 ValidRadiiCounter--; 963 } 964 if(RadiiLength2<Value3) { 965 ValidRadiiCounter--; 966 } 967 if(RadiiLength3<Value3) { 968 ValidRadiiCounter--; 969 } 970 if(RadiiLength4<Value3) { 971 ValidRadiiCounter--; 972 } 973 } 974 else { 975 RadiiLength1=0.0; 976 RadiiLength2=0.0; 977 RadiiLength3=0.0; 978 RadiiLength4=0.0; 979 } 980 if(ValidRadiiCounter<3) { 981 RadiusOrShear=0.0; 982 } 983 else { 984 RadiiLength1=Math.min(RadiiLength1,MaxDistanceValue); 985 RadiiLength2=Math.min(RadiiLength2,MaxDistanceValue); 986 RadiiLength3=Math.min(RadiiLength3,MaxDistanceValue); 987 RadiiLength4=Math.min(RadiiLength4,MaxDistanceValue); 988 RadiusOrShear=(RadiiLength1+RadiiLength2+RadiiLength3+RadiiLength4)/4.0; 989 double Value1=RadiiLength1+RadiiLength3; 990 double Value2=RadiiLength2+RadiiLength4; 991 SymmValue=Value1/Value2; 992 SymmValue=Math.max(SymmValue,1.0/SymmValue); 993 } 994 /* System.out.printf("\nPointCounter=%5d RadiiLength1=%5.1f RadiiLength2=%5.1f RadiiLength3=%5.1f RadiiLength4=%5.1f\n", 995 PointCounter, RadiiLength1,RadiiLength2,RadiiLength3,RadiiLength4); */ 996 } 997 998 if(AnalysisTypeIDValue==3) { 999 double ShearDistanceValue=-99.0; 1000 /* need to implement entire odtauto.c library including remapping 1001 RetErr=adt_shearbw(TemperatureValue,LatitudeValue,LongitudeValue, 1002 &ShearDistanceValue); 1003 */ 1004 RadiusOrShear=ShearDistanceValue; 1005 } 1006 1007 return RadiusOrShear; 1008 } 1009}