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