001/* 002 * To change this template, choose Tools | Templates 003 * and open the template in the editor. 004 */ 005package armyc2.c5isr.JavaTacticalRenderer; 006 007import armyc2.c5isr.JavaLineArray.TacticalLines; 008import armyc2.c5isr.JavaLineArray.arraysupport; 009import armyc2.c5isr.JavaLineArray.lineutility; 010import armyc2.c5isr.JavaLineArray.POINT2; 011import armyc2.c5isr.JavaLineArray.ref; 012import java.util.ArrayList; 013import java.util.HashMap; 014 015import armyc2.c5isr.JavaLineArray.Shape2; 016import java.io.*; 017 018import armyc2.c5isr.RenderMultipoints.clsRenderer; 019import armyc2.c5isr.renderer.utilities.DrawRules; 020import armyc2.c5isr.renderer.utilities.IPointConversion; 021import armyc2.c5isr.renderer.utilities.MSInfo; 022import armyc2.c5isr.renderer.utilities.MSLookup; 023import armyc2.c5isr.renderer.utilities.RendererSettings; 024import armyc2.c5isr.renderer.utilities.RendererUtilities; 025import armyc2.c5isr.renderer.utilities.ErrorLogger; 026import armyc2.c5isr.renderer.utilities.RendererException; 027import armyc2.c5isr.renderer.utilities.Color; 028import armyc2.c5isr.graphics2d.BasicStroke; 029import armyc2.c5isr.graphics2d.BufferedImage; 030import armyc2.c5isr.graphics2d.Graphics2D; 031import armyc2.c5isr.graphics2d.Line2D; 032import armyc2.c5isr.graphics2d.Point2D; 033import armyc2.c5isr.graphics2d.Polygon; 034import armyc2.c5isr.graphics2d.Rectangle2D; 035import armyc2.c5isr.graphics2d.TexturePaint; 036import armyc2.c5isr.renderer.utilities.SymbolID; 037 038/** 039 * A general utility class for the tactical renderer 040* 041 */ 042public final class clsUtility { 043 private static final String _className = "clsUtility"; 044 protected static Point2D POINT2ToPoint2D(POINT2 pt2) { 045 if (pt2 == null) { 046 return null; 047 } 048 049 double x = pt2.x; 050 double y = pt2.y; 051 Point2D pt = new Point2D.Double(x, y); 052 return pt; 053 } 054 /** 055 * returns true if the line segments are all outside the bounds 056 * @param tg the tactical graphic 057 * @param clipBounds the pixels based clip bounds 058 * @return 059 */ 060 public static boolean linesOutsideClipBounds(TGLight tg, 061 Rectangle2D clipBounds) 062 { 063 try 064 { 065 boolean isAutoshape=isAutoshape(tg); 066 if(isAutoshape) 067 return false; 068 069 double xmin=clipBounds.getMinX(); 070 double xmax=clipBounds.getMaxX(); 071 double ymin=clipBounds.getMinY(); 072 double ymax=clipBounds.getMaxY(); 073 int j=0; 074 POINT2 pt0=null,pt1=null; 075 Line2D boundsEdge=null,ptsLine=null; 076 int n=tg.Pixels.size(); 077 //for(j=0;j<tg.Pixels.size()-1;j++) 078 for(j=0;j<n-1;j++) 079 { 080 pt0=tg.Pixels.get(j); 081 pt1=tg.Pixels.get(j+1); 082 083 //if either point is inside the bounds return false 084 if(clipBounds.contains(pt0.x, pt0.y)) 085 return false; 086 if(clipBounds.contains(pt1.x, pt1.y)) 087 return false; 088 089 ptsLine=new Line2D.Double(pt0.x,pt0.y,pt1.x,pt1.y); 090 091 //if the pt0-pt1 line intersects any clip bounds edge then return false 092 boundsEdge=new Line2D.Double(xmin,ymin,xmax,ymin); 093 if(ptsLine.intersectsLine(boundsEdge)) 094 return false; 095 096 boundsEdge=new Line2D.Double(xmax,ymin,xmax,ymax); 097 if(ptsLine.intersectsLine(boundsEdge)) 098 return false; 099 100 boundsEdge=new Line2D.Double(xmax,ymax,xmin,ymax); 101 if(ptsLine.intersectsLine(boundsEdge)) 102 return false; 103 104 boundsEdge=new Line2D.Double(xmin,ymax,xmin,ymin); 105 if(ptsLine.intersectsLine(boundsEdge)) 106 return false; 107 } 108 } 109 catch (Exception exc) 110 { 111 ErrorLogger.LogException(_className ,"linesOutsideClipBounds", 112 new RendererException("Failed inside linesOutsideClipBounds", exc)); 113 } 114 return true; 115 } 116 /** 117 * Returns the minimum client points needed for the symbol 118 * @param lineType line type 119 * @return minimum number of clients required to render the line 120 * @deprecated use MSInfo.getMinPointCount() 121 */ 122 public static int GetMinPoints(int lineType) { 123 int result = -1; 124 switch (lineType) { 125 case TacticalLines.RECTANGULAR: 126 case TacticalLines.CUED_ACQUISITION: 127 case TacticalLines.CIRCULAR: 128 case TacticalLines.PBS_CIRCLE: 129 case TacticalLines.BDZ: 130 case TacticalLines.FSA_CIRCULAR: 131 case TacticalLines.NOTACK: 132 case TacticalLines.FFA_CIRCULAR: 133 case TacticalLines.NFA_CIRCULAR: 134 case TacticalLines.RFA_CIRCULAR: 135 case TacticalLines.ACA_CIRCULAR: 136 case TacticalLines.PAA_CIRCULAR: 137 case TacticalLines.ATI_CIRCULAR: 138 case TacticalLines.CFFZ_CIRCULAR: 139 case TacticalLines.SENSOR_CIRCULAR: 140 case TacticalLines.CENSOR_CIRCULAR: 141 case TacticalLines.DA_CIRCULAR: 142 case TacticalLines.CFZ_CIRCULAR: 143 case TacticalLines.ZOR_CIRCULAR: 144 case TacticalLines.TBA_CIRCULAR: 145 case TacticalLines.TVAR_CIRCULAR: 146 case TacticalLines.KILLBOXBLUE_CIRCULAR: 147 case TacticalLines.KILLBOXPURPLE_CIRCULAR: 148 case TacticalLines.LAUNCH_AREA: 149 case TacticalLines.DEFENDED_AREA_CIRCULAR: 150 case TacticalLines.SHIP_AOI_CIRCULAR: 151 case TacticalLines.PBS_ELLIPSE: 152 case TacticalLines.RANGE_FAN: 153 case TacticalLines.RANGE_FAN_SECTOR: 154 case TacticalLines.RADAR_SEARCH: 155 result = 1; 156 break; 157 case TacticalLines.PAA_RECTANGULAR: 158 case TacticalLines.RECTANGULAR_TARGET: 159 case TacticalLines.FSA_RECTANGULAR: 160 case TacticalLines.SHIP_AOI_RECTANGULAR: 161 case TacticalLines.DEFENDED_AREA_RECTANGULAR: 162 case TacticalLines.FFA_RECTANGULAR: 163 case TacticalLines.RFA_RECTANGULAR: 164 case TacticalLines.NFA_RECTANGULAR: 165 case TacticalLines.ACA_RECTANGULAR: 166 case TacticalLines.ATI_RECTANGULAR: 167 case TacticalLines.CFFZ_RECTANGULAR: 168 case TacticalLines.SENSOR_RECTANGULAR: 169 case TacticalLines.CENSOR_RECTANGULAR: 170 case TacticalLines.DA_RECTANGULAR: 171 case TacticalLines.CFZ_RECTANGULAR: 172 case TacticalLines.ZOR_RECTANGULAR: 173 case TacticalLines.TBA_RECTANGULAR: 174 case TacticalLines.TVAR_RECTANGULAR: 175 case TacticalLines.KILLBOXBLUE_RECTANGULAR: 176 case TacticalLines.KILLBOXPURPLE_RECTANGULAR: 177 result = 2; //was 3 178 break; 179 case TacticalLines.SPTBYFIRE: 180 case TacticalLines.RIP: 181 case TacticalLines.MOBILE_DEFENSE: 182 case TacticalLines.DEMONSTRATE: 183 case TacticalLines.GAP: 184 case TacticalLines.ASLTXING: 185 case TacticalLines.MSDZ: 186 result = 4; 187 break; 188 case TacticalLines.BYPASS: 189 case TacticalLines.BLOCK: 190 case TacticalLines.BREACH: 191 case TacticalLines.CANALIZE: 192 case TacticalLines.CLEAR: 193 case TacticalLines.CONTAIN: 194 case TacticalLines.DELAY: 195 case TacticalLines.DISRUPT: 196 case TacticalLines.PENETRATE: 197 case TacticalLines.RETIRE: 198 case TacticalLines.PURSUIT: 199 case TacticalLines.ENVELOPMENT: 200 case TacticalLines.FPOL: 201 case TacticalLines.RPOL: 202 case TacticalLines.SCREEN: 203 case TacticalLines.COVER: 204 case TacticalLines.GUARD: 205 case TacticalLines.SEIZE: 206 case TacticalLines.EVACUATE: 207 case TacticalLines.WITHDRAW: 208 case TacticalLines.DISENGAGE: 209 case TacticalLines.WDRAWUP: 210 //non task autoshapes 211 case TacticalLines.SARA: 212 case TacticalLines.PDF: 213 case TacticalLines.IL: 214 case TacticalLines.ATKBYFIRE: 215 case TacticalLines.AMBUSH: 216 case TacticalLines.RELEASE: 217 case TacticalLines.HOL: 218 case TacticalLines.BHL: 219 case TacticalLines.MNFLDBLK: 220 case TacticalLines.MNFLDDIS: 221 case TacticalLines.TURN_REVD: 222 case TacticalLines.TURN: 223 case TacticalLines.PLANNED: 224 case TacticalLines.ESR1: 225 case TacticalLines.ESR2: 226 case TacticalLines.ROADBLK: 227 case TacticalLines.EASY: 228 case TacticalLines.BYDIF: 229 case TacticalLines.BYIMP: 230 case TacticalLines.FORDSITE: 231 case TacticalLines.FORDIF: 232 //METOCs 233 case TacticalLines.IFR: 234 case TacticalLines.MVFR: 235 case TacticalLines.TURBULENCE: 236 case TacticalLines.ICING: 237 case TacticalLines.NON_CONVECTIVE: 238 case TacticalLines.CONVECTIVE: 239 case TacticalLines.FROZEN: 240 case TacticalLines.THUNDERSTORMS: 241 case TacticalLines.FOG: 242 case TacticalLines.SAND: 243 case TacticalLines.FREEFORM: 244 case TacticalLines.DEPTH_AREA: 245 case TacticalLines.ISLAND: 246 case TacticalLines.BEACH: 247 case TacticalLines.WATER: 248 case TacticalLines.FISH_TRAPS: 249 case TacticalLines.SWEPT_AREA: 250 case TacticalLines.OIL_RIG_FIELD: 251 case TacticalLines.FOUL_GROUND: 252 case TacticalLines.KELP: 253 case TacticalLines.BEACH_SLOPE_MODERATE: 254 case TacticalLines.BEACH_SLOPE_STEEP: 255 case TacticalLines.ANCHORAGE_AREA: 256 case TacticalLines.TRAINING_AREA: 257 case TacticalLines.FORESHORE_AREA: 258 case TacticalLines.DRYDOCK: 259 case TacticalLines.LOADING_FACILITY_AREA: 260 case TacticalLines.PERCHES: 261 case TacticalLines.UNDERWATER_HAZARD: 262 case TacticalLines.DISCOLORED_WATER: 263 case TacticalLines.BEACH_SLOPE_FLAT: 264 case TacticalLines.BEACH_SLOPE_GENTLE: 265 case TacticalLines.MARITIME_AREA: 266 case TacticalLines.OPERATOR_DEFINED: 267 case TacticalLines.SUBMERGED_CRIB: 268 case TacticalLines.VDR_LEVEL_12: 269 case TacticalLines.VDR_LEVEL_23: 270 case TacticalLines.VDR_LEVEL_34: 271 case TacticalLines.VDR_LEVEL_45: 272 case TacticalLines.VDR_LEVEL_56: 273 case TacticalLines.VDR_LEVEL_67: 274 case TacticalLines.VDR_LEVEL_78: 275 case TacticalLines.VDR_LEVEL_89: 276 case TacticalLines.VDR_LEVEL_910: 277 case TacticalLines.SOLID_ROCK: 278 case TacticalLines.CLAY: 279 case TacticalLines.VERY_COARSE_SAND: 280 case TacticalLines.COARSE_SAND: 281 case TacticalLines.MEDIUM_SAND: 282 case TacticalLines.FINE_SAND: 283 case TacticalLines.VERY_FINE_SAND: 284 case TacticalLines.VERY_FINE_SILT: 285 case TacticalLines.FINE_SILT: 286 case TacticalLines.MEDIUM_SILT: 287 case TacticalLines.COARSE_SILT: 288 case TacticalLines.BOULDERS: 289 case TacticalLines.OYSTER_SHELLS: 290 case TacticalLines.PEBBLES: 291 case TacticalLines.SAND_AND_SHELLS: 292 case TacticalLines.BOTTOM_SEDIMENTS_LAND: 293 case TacticalLines.BOTTOM_SEDIMENTS_NO_DATA: 294 case TacticalLines.BOTTOM_ROUGHNESS_SMOOTH: 295 case TacticalLines.BOTTOM_ROUGHNESS_MODERATE: 296 case TacticalLines.BOTTOM_ROUGHNESS_ROUGH: 297 case TacticalLines.CLUTTER_LOW: 298 case TacticalLines.CLUTTER_MEDIUM: 299 case TacticalLines.CLUTTER_HIGH: 300 case TacticalLines.IMPACT_BURIAL_0: 301 case TacticalLines.IMPACT_BURIAL_10: 302 case TacticalLines.IMPACT_BURIAL_20: 303 case TacticalLines.IMPACT_BURIAL_75: 304 case TacticalLines.IMPACT_BURIAL_100: 305 case TacticalLines.BOTTOM_CATEGORY_A: 306 case TacticalLines.BOTTOM_CATEGORY_B: 307 case TacticalLines.BOTTOM_CATEGORY_C: 308 case TacticalLines.BOTTOM_TYPE_A1: 309 case TacticalLines.BOTTOM_TYPE_A2: 310 case TacticalLines.BOTTOM_TYPE_A3: 311 case TacticalLines.BOTTOM_TYPE_B1: 312 case TacticalLines.BOTTOM_TYPE_B2: 313 case TacticalLines.BOTTOM_TYPE_B3: 314 case TacticalLines.BOTTOM_TYPE_C1: 315 case TacticalLines.BOTTOM_TYPE_C2: 316 case TacticalLines.BOTTOM_TYPE_C3: 317 result = 3; 318 break; 319 case TacticalLines.MRR: 320 case TacticalLines.SL: 321 case TacticalLines.TC: 322 case TacticalLines.SC: 323 case TacticalLines.LLTR: 324 case TacticalLines.DIRATKAIR: 325 case TacticalLines.ABATIS: 326 case TacticalLines.CLUSTER: 327 case TacticalLines.MNFLDFIX: 328 case TacticalLines.FERRY: 329 case TacticalLines.MFLANE: 330 case TacticalLines.RAFT: 331 case TacticalLines.FOXHOLE: 332 case TacticalLines.LINTGT: 333 case TacticalLines.LINTGTS: 334 case TacticalLines.FPF: 335 case TacticalLines.CONVOY: 336 case TacticalLines.HCONVOY: 337 result = 2; 338 break; 339 default: 340 result = 2; 341 break; 342 } 343 if (isClosedPolygon(lineType)) { 344 result = 3; 345 } 346 //add code for change 1 areas 347 return result; 348 } 349 /** 350 * @param linetype line type 351 * @return true if the line is a closed area 352 */ 353 public static boolean isClosedPolygon(int linetype) { 354 boolean result = false; 355 switch (linetype) { 356 case TacticalLines.BBS_AREA: 357 case TacticalLines.BS_BBOX: 358 case TacticalLines.AT: 359 case TacticalLines.DEPICT: 360 case TacticalLines.DZ: 361 case TacticalLines.MINED: 362 case TacticalLines.FENCED: 363 case TacticalLines.UXO: 364 case TacticalLines.ROZ: 365 case TacticalLines.AARROZ: 366 case TacticalLines.UAROZ: 367 case TacticalLines.WEZ: 368 case TacticalLines.FEZ: 369 case TacticalLines.JEZ: 370 case TacticalLines.FAADZ: 371 case TacticalLines.HIDACZ: 372 case TacticalLines.MEZ: 373 case TacticalLines.LOMEZ: 374 case TacticalLines.HIMEZ: 375 case TacticalLines.WFZ_REVD: 376 case TacticalLines.WFZ: 377 case TacticalLines.PNO: 378 case TacticalLines.BATTLE: 379 case TacticalLines.EA: 380 case TacticalLines.EZ: 381 case TacticalLines.LZ: 382 case TacticalLines.PZ: 383 case TacticalLines.GENERAL: 384 case TacticalLines.JTAA: 385 case TacticalLines.SAA: 386 case TacticalLines.SGAA: 387 case TacticalLines.BS_AREA: 388 case TacticalLines.ASSAULT: 389 case TacticalLines.ATKPOS: 390 case TacticalLines.OBJ: 391 case TacticalLines.AO: 392 case TacticalLines.AIRHEAD: 393 case TacticalLines.NAI: 394 case TacticalLines.TAI: 395 case TacticalLines.BASE_CAMP_REVD: 396 case TacticalLines.BASE_CAMP: 397 case TacticalLines.GUERILLA_BASE_REVD: 398 case TacticalLines.GUERILLA_BASE: 399 case TacticalLines.GENERIC_AREA: 400 case TacticalLines.OBSFAREA: 401 case TacticalLines.OBSAREA: 402 case TacticalLines.ZONE: 403 case TacticalLines.STRONG: 404 case TacticalLines.DRCL: 405 case TacticalLines.FSA: 406 case TacticalLines.ACA: 407 case TacticalLines.ASSY: 408 case TacticalLines.BSA: 409 case TacticalLines.NFA: 410 case TacticalLines.RFA: 411 case TacticalLines.FARP: 412 case TacticalLines.AIRFIELD: 413 case TacticalLines.LAA: 414 case TacticalLines.BOMB: 415 case TacticalLines.FFA: 416 case TacticalLines.SMOKE: 417 case TacticalLines.PAA: 418 case TacticalLines.ENCIRCLE: 419 case TacticalLines.DHA_REVD: 420 case TacticalLines.DHA: 421 case TacticalLines.KILL_ZONE: 422 case TacticalLines.EPW: 423 case TacticalLines.RHA: 424 case TacticalLines.DSA: 425 case TacticalLines.CSA: 426 case TacticalLines.RSA: 427 case TacticalLines.FORT_REVD: 428 case TacticalLines.FORT: 429 case TacticalLines.PEN: 430 case TacticalLines.BIO: 431 case TacticalLines.NUC: 432 case TacticalLines.RAD: 433 case TacticalLines.CHEM: 434 case TacticalLines.SERIES: 435 case TacticalLines.ATI: 436 case TacticalLines.TBA: 437 case TacticalLines.TVAR: 438 case TacticalLines.CFFZ: 439 case TacticalLines.CENSOR: 440 case TacticalLines.SENSOR: 441 case TacticalLines.ZOR: 442 case TacticalLines.DA: 443 case TacticalLines.CFZ: 444 case TacticalLines.KILLBOXBLUE: 445 case TacticalLines.KILLBOXPURPLE: 446 //METOCs 447 case TacticalLines.IFR: 448 case TacticalLines.MVFR: 449 case TacticalLines.TURBULENCE: 450 case TacticalLines.ICING: 451 case TacticalLines.NON_CONVECTIVE: 452 case TacticalLines.CONVECTIVE: 453 case TacticalLines.FROZEN: 454 case TacticalLines.THUNDERSTORMS: 455 case TacticalLines.FOG: 456 case TacticalLines.SAND: 457 case TacticalLines.FREEFORM: 458 case TacticalLines.DEPTH_AREA: 459 case TacticalLines.ISLAND: 460 case TacticalLines.BEACH: 461 case TacticalLines.WATER: 462 case TacticalLines.FISH_TRAPS: 463 case TacticalLines.SWEPT_AREA: 464 case TacticalLines.OIL_RIG_FIELD: 465 case TacticalLines.FOUL_GROUND: 466 case TacticalLines.KELP: 467 case TacticalLines.BEACH_SLOPE_MODERATE: 468 case TacticalLines.BEACH_SLOPE_STEEP: 469 case TacticalLines.ANCHORAGE_AREA: 470 case TacticalLines.TRAINING_AREA: 471 case TacticalLines.FORESHORE_AREA: 472 case TacticalLines.DRYDOCK: 473 case TacticalLines.LOADING_FACILITY_AREA: 474 case TacticalLines.PERCHES: 475 case TacticalLines.UNDERWATER_HAZARD: 476 case TacticalLines.DISCOLORED_WATER: 477 case TacticalLines.BEACH_SLOPE_FLAT: 478 case TacticalLines.BEACH_SLOPE_GENTLE: 479 case TacticalLines.MARITIME_AREA: 480 case TacticalLines.OPERATOR_DEFINED: 481 case TacticalLines.SUBMERGED_CRIB: 482 case TacticalLines.VDR_LEVEL_12: 483 case TacticalLines.VDR_LEVEL_23: 484 case TacticalLines.VDR_LEVEL_34: 485 case TacticalLines.VDR_LEVEL_45: 486 case TacticalLines.VDR_LEVEL_56: 487 case TacticalLines.VDR_LEVEL_67: 488 case TacticalLines.VDR_LEVEL_78: 489 case TacticalLines.VDR_LEVEL_89: 490 case TacticalLines.VDR_LEVEL_910: 491 case TacticalLines.SOLID_ROCK: 492 case TacticalLines.CLAY: 493 case TacticalLines.VERY_COARSE_SAND: 494 case TacticalLines.COARSE_SAND: 495 case TacticalLines.MEDIUM_SAND: 496 case TacticalLines.FINE_SAND: 497 case TacticalLines.VERY_FINE_SAND: 498 case TacticalLines.VERY_FINE_SILT: 499 case TacticalLines.FINE_SILT: 500 case TacticalLines.MEDIUM_SILT: 501 case TacticalLines.COARSE_SILT: 502 case TacticalLines.BOULDERS: 503 case TacticalLines.OYSTER_SHELLS: 504 case TacticalLines.PEBBLES: 505 case TacticalLines.SAND_AND_SHELLS: 506 case TacticalLines.BOTTOM_SEDIMENTS_LAND: 507 case TacticalLines.BOTTOM_SEDIMENTS_NO_DATA: 508 case TacticalLines.BOTTOM_ROUGHNESS_SMOOTH: 509 case TacticalLines.BOTTOM_ROUGHNESS_MODERATE: 510 case TacticalLines.BOTTOM_ROUGHNESS_ROUGH: 511 case TacticalLines.CLUTTER_LOW: 512 case TacticalLines.CLUTTER_MEDIUM: 513 case TacticalLines.CLUTTER_HIGH: 514 case TacticalLines.IMPACT_BURIAL_0: 515 case TacticalLines.IMPACT_BURIAL_10: 516 case TacticalLines.IMPACT_BURIAL_20: 517 case TacticalLines.IMPACT_BURIAL_75: 518 case TacticalLines.IMPACT_BURIAL_100: 519 case TacticalLines.BOTTOM_CATEGORY_A: 520 case TacticalLines.BOTTOM_CATEGORY_B: 521 case TacticalLines.BOTTOM_CATEGORY_C: 522 case TacticalLines.BOTTOM_TYPE_A1: 523 case TacticalLines.BOTTOM_TYPE_A2: 524 case TacticalLines.BOTTOM_TYPE_A3: 525 case TacticalLines.BOTTOM_TYPE_B1: 526 case TacticalLines.BOTTOM_TYPE_B2: 527 case TacticalLines.BOTTOM_TYPE_B3: 528 case TacticalLines.BOTTOM_TYPE_C1: 529 case TacticalLines.BOTTOM_TYPE_C2: 530 case TacticalLines.BOTTOM_TYPE_C3: 531 case TacticalLines.TGMF: 532 result = true; 533 break; 534 default: 535 break; 536 } 537 return result; 538 } 539 540 /** 541 * Closes the polygon for areas 542 * @param Pixels the client points 543 */ 544 public static void ClosePolygon(ArrayList<POINT2> Pixels) { 545 try { 546 POINT2 pt0 = Pixels.get(0); 547 POINT2 pt1 = Pixels.get(Pixels.size() - 1); 548 if (pt0.x != pt1.x || pt0.y != pt1.y) { 549 Pixels.add(new POINT2(pt0.x, pt0.y)); 550 } 551 } catch (Exception exc) { 552 ErrorLogger.LogException(_className ,"ClosePolygon", 553 new RendererException("Failed inside ClosePolygon", exc)); 554 } 555 } 556 /** 557 * for change 1 symbol the W/w1 modifiers run too close to the symbol outline 558 * so it shifts the line along the line away from the edge 559 * @param p1 560 * @param p2 561 * @param shift 562 */ 563 protected static void shiftModifiersLeft(POINT2 p1, POINT2 p2, double shift) 564 { 565 try 566 { 567 POINT2 pt1=new POINT2(p1); 568 POINT2 pt2=new POINT2(p2); 569 double dist=lineutility.CalcDistanceDouble(pt1, pt2); 570 if(pt1.x<pt2.x || (pt1.x==pt2.x && pt1.y<pt2.y)) 571 { 572 pt1=lineutility.ExtendAlongLineDouble(pt2, pt1, dist+shift); 573 pt2=lineutility.ExtendAlongLineDouble(pt1, pt2, dist-shift); 574 } 575 else 576 { 577 pt1=lineutility.ExtendAlongLineDouble(pt2, pt1, dist-shift); 578 pt2=lineutility.ExtendAlongLineDouble(pt1, pt2, dist+shift); 579 } 580 p1.x=pt1.x; 581 p1.y=pt1.y; 582 p2.x=pt2.x; 583 p2.y=pt2.y; 584 } 585 catch (Exception exc) { 586 ErrorLogger.LogException(_className ,"shiftModifiersLeft", 587 new RendererException("Failed inside shiftModifiersLeft", exc)); 588 } 589 } 590 /** 591 * Overrides shape properties for symbols based on Mil-Std-2525 592 * @param tg 593 * @param shape 594 */ 595 protected static void ResolveModifierShape(TGLight tg, Shape2 shape) { 596 try { 597 //shape style was set by CELineArray and takes precedence 598 //whenever it is set 599 int shapeStyle = shape.get_Style(); 600 int lineStyle = tg.get_LineStyle(); 601 int lineType = tg.get_LineType(); 602 boolean hasFill=LinesWithFill(lineType); 603 int bolMETOC=clsMETOC.IsWeather(tg.get_SymbolId()); 604 if(bolMETOC>0) 605 return; 606 int fillStyle=0; 607 //for some of these the style must be dashed 608 switch (tg.get_LineType()) { 609 case TacticalLines.NFA: 610 case TacticalLines.NFA_CIRCULAR: 611 case TacticalLines.NFA_RECTANGULAR: 612 case TacticalLines.BIO: 613 case TacticalLines.NUC: 614 case TacticalLines.CHEM: 615 case TacticalLines.RAD: 616 case TacticalLines.WFZ_REVD: 617 case TacticalLines.WFZ: 618 //case TacticalLines.OBSAREA: 619 fillStyle=3; 620 if(tg.get_UseHatchFill()) 621 fillStyle=0; 622 if (shape.getShapeType() == Shape2.SHAPE_TYPE_POLYLINE) { 623 shape.set_Style(tg.get_LineStyle()); 624 shape.setLineColor(tg.get_LineColor()); 625 shape.set_Fillstyle(fillStyle /*GraphicProperties.FILL_TYPE_RIGHT_SLANTS*/);//was 3 626 shape.setFillColor(tg.get_FillColor()); 627 } 628 break; 629 case TacticalLines.OBSAREA: 630 if (shape.getShapeType() == Shape2.SHAPE_TYPE_POLYLINE) { 631 shape.set_Style(tg.get_LineStyle()); 632 shape.setLineColor(tg.get_LineColor()); 633 shape.set_Fillstyle(0 /*GraphicProperties.FILL_TYPE_RIGHT_SLANTS*/); 634 shape.setFillColor(tg.get_FillColor()); 635 } 636 break; 637 case TacticalLines.LAA: 638 fillStyle=2; 639 if(tg.get_UseHatchFill()) 640 fillStyle=0; 641 if (shape.getShapeType() == Shape2.SHAPE_TYPE_POLYLINE) { 642 shape.set_Style(tg.get_LineStyle()); 643 shape.setLineColor(tg.get_LineColor()); 644 shape.set_Fillstyle(fillStyle /*GraphicProperties.FILL_TYPE_LEFT_SLANTS*/);//was 2 645 shape.setFillColor(tg.get_FillColor()); 646 } 647 break; 648 case TacticalLines.DIRATKAIR: 649 case TacticalLines.ATDITCHC: 650 case TacticalLines.ATDITCHM: 651 case TacticalLines.SARA: 652 case TacticalLines.FOLSP: 653 case TacticalLines.FERRY: 654 case TacticalLines.MNFLDFIX: 655 case TacticalLines.TURN_REVD: 656 case TacticalLines.TURN: 657 case TacticalLines.MNFLDDIS: 658 case TacticalLines.EASY: 659 case TacticalLines.BYDIF: 660 case TacticalLines.BYIMP: 661 case TacticalLines.MOBILE_DEFENSE: 662 tg.set_lineCap(BasicStroke.CAP_BUTT); 663 if (shape.getShapeType() == Shape2.SHAPE_TYPE_FILL) { 664 shape.set_Fillstyle(1 /*GraphicProperties.FILL_TYPE_SOLID*/); 665 shape.setFillColor(tg.get_LineColor()); 666 } 667 if (shape.getShapeType() == Shape2.SHAPE_TYPE_POLYLINE) { 668 shape.set_Style(tg.get_LineStyle()); 669 shape.setLineColor(tg.get_LineColor()); 670 } 671 break; 672 case TacticalLines.CLUSTER: 673 case TacticalLines.CATK: 674 case TacticalLines.CATKBYFIRE: 675 case TacticalLines.PLD: 676 case TacticalLines.PLANNED: 677 case TacticalLines.CFL: 678 case TacticalLines.FORDSITE: 679 case TacticalLines.ACOUSTIC_AMB: 680 //any shape for these symbols is dashed 681 if (shape.getShapeType() == Shape2.SHAPE_TYPE_POLYLINE) { 682 shape.set_Style(1 /*GraphicProperties.LINE_TYPE_DASHED*/); 683 shape.setLineColor(tg.get_LineColor()); 684 } 685 break; 686 case TacticalLines.PNO: //always dashed 687 if (shape.getShapeType() == Shape2.SHAPE_TYPE_POLYLINE) { 688 shape.set_Style(1 /*GraphicProperties.LINE_TYPE_DASHED*/); 689 shape.setLineColor(tg.get_LineColor()); 690 shape.setFillColor(tg.get_FillColor()); 691 shape.set_Fillstyle(tg.get_FillStyle()); 692 } 693 break; 694 case TacticalLines.FOLLA: 695 case TacticalLines.ESR1: 696 case TacticalLines.FORDIF: 697 if (shape.getShapeType() == Shape2.SHAPE_TYPE_POLYLINE) { 698 shape.setLineColor(tg.get_LineColor()); 699 if (shapeStyle != lineStyle) { 700 if (shapeStyle != 1 /*GraphicProperties.LINE_TYPE_DASHED*/) { 701 shape.set_Style(lineStyle); 702 } 703 } 704 } 705 break; 706 case TacticalLines.AREA_DEFENSE: 707 if (shape.getShapeType() == Shape2.SHAPE_TYPE_FILL) { 708 shape.set_Fillstyle(tg.get_FillStyle()); 709 shape.setFillColor(tg.get_FillColor()); 710 // If there are 5 points and the first and last are the same this is 711 // a triangle and should be filled with line color 712 POINT2 firstPt = shape.getPoints().get(0); 713 POINT2 lastPt = shape.getPoints().get(shape.getPoints().size() - 1); 714 if (shape.getPoints().size() == 5 && firstPt.x == lastPt.x && firstPt.y == lastPt.y) { 715 shape.set_Fillstyle(1); 716 shape.setFillColor(tg.get_LineColor()); 717 } 718 } 719 if (shape.getShapeType() == Shape2.SHAPE_TYPE_POLYLINE) { 720 shape.setLineColor(tg.get_LineColor()); 721 shape.set_Style(lineStyle); 722 if (hasFill || clsUtility.isClosedPolygon(lineType) || clsUtility.IsChange1Area(lineType)) { 723 shape.set_Fillstyle(tg.get_FillStyle()); 724 shape.setFillColor(tg.get_FillColor()); 725 } 726 } 727 break; 728 case TacticalLines.MOVEMENT_TO_CONTACT: 729 if (shape.getShapeType() == Shape2.SHAPE_TYPE_FILL) { 730 shape.set_Fillstyle(tg.get_FillStyle()); 731 shape.setFillColor(tg.get_FillColor()); 732 // If there are 4 points and the first and last are the same this is 733 // an arrow at the end of a jaggy line and should be filled with line color 734 POINT2 firstPt = shape.getPoints().get(0); 735 POINT2 lastPt = shape.getPoints().get(shape.getPoints().size() - 1); 736 if (shape.getPoints().size() == 4 && firstPt.x == lastPt.x && firstPt.y == lastPt.y) 737 shape.setFillColor(tg.get_LineColor()); 738 } 739 if (shape.getShapeType() == Shape2.SHAPE_TYPE_POLYLINE) { 740 shape.setLineColor(tg.get_LineColor()); 741 shape.set_Style(lineStyle); 742 } 743 break; 744 case TacticalLines.EXPLOIT: 745 // Some shapes have solid lines some have dashed 746 if (shape.getShapeType() == Shape2.SHAPE_TYPE_FILL) { 747 shape.set_Fillstyle(tg.get_FillStyle()); 748 shape.setFillColor(tg.get_FillColor()); 749 } 750 if (shape.getShapeType() == Shape2.SHAPE_TYPE_POLYLINE) { 751 shape.setLineColor(tg.get_LineColor()); 752 if (shapeStyle != 1 /*GraphicProperties.LINE_TYPE_DASHED*/) { 753 shape.set_Style(lineStyle); 754 } 755 } 756 break; 757 default: 758 if (shape.getShapeType() == Shape2.SHAPE_TYPE_FILL) { 759 shape.set_Fillstyle(tg.get_FillStyle()); 760 shape.setFillColor(tg.get_FillColor()); 761 } 762 if (shape.getShapeType() == Shape2.SHAPE_TYPE_POLYLINE) { 763 if (lineType != TacticalLines.LC) { 764 shape.setLineColor(tg.get_LineColor()); 765 } else { 766 SetLCColor(tg, shape); 767 } 768 shape.set_Style(lineStyle); 769 if (hasFill || clsUtility.isClosedPolygon(lineType) || clsUtility.IsChange1Area(lineType)) 770 { 771 switch(lineType) 772 { 773 case TacticalLines.RANGE_FAN: 774 case TacticalLines.RANGE_FAN_SECTOR: 775 case TacticalLines.RADAR_SEARCH: 776 case TacticalLines.BBS_AREA: 777 case TacticalLines.BBS_RECTANGLE: 778 shape.setFillColor(null); 779 break; 780 default: 781 shape.set_Fillstyle(tg.get_FillStyle()); 782 shape.setFillColor(tg.get_FillColor()); 783 break; 784 } 785 } 786 switch(lineType) 787 { 788 case TacticalLines.BS_ELLIPSE: 789 case TacticalLines.BS_RECTANGLE: 790 //case TacticalLines.BBS_RECTANGLE: 791 shape.set_Fillstyle(tg.get_FillStyle()); 792 shape.setFillColor(tg.get_FillColor()); 793 break; 794 case TacticalLines.BBS_RECTANGLE: 795 case TacticalLines.PBS_RECTANGLE: 796 case TacticalLines.PBS_SQUARE: 797 shape.setFillColor(null); 798 break; 799 default: 800 break; 801 } 802 } 803 break; 804 } 805 806 } catch (Exception exc) { 807 ErrorLogger.LogException(_className ,"ResolveModifierShape", 808 new RendererException("Failed inside ResolveModifierShape", exc)); 809 } 810 } 811 public static Color GetOpaqueColor(Color color) 812 { 813 int r=color.getRed(); 814 int g=color.getGreen(); 815 int b=color.getBlue(); 816 return new Color(r,g,b); 817 } 818 /** 819 * These lines allow fill 820 * @param linetype 821 * @return 822 */ 823 public static boolean LinesWithFill(int linetype) 824 { 825 boolean result=false; 826 try 827 { 828 switch(linetype) 829 { 830 case TacticalLines.BS_LINE: 831 case TacticalLines.PAA_RECTANGULAR: 832 case TacticalLines.RECTANGULAR_TARGET: 833 case TacticalLines.CFL: 834 case TacticalLines.TRIP: 835 case TacticalLines.DIRATKAIR: 836 case TacticalLines.BOUNDARY: 837 case TacticalLines.ISOLATE: 838 case TacticalLines.CORDONKNOCK: 839 case TacticalLines.CORDONSEARCH: 840 case TacticalLines.OCCUPY: 841 case TacticalLines.RETAIN: 842 case TacticalLines.SECURE: 843 case TacticalLines.AREA_DEFENSE: 844 case TacticalLines.MOBILE_DEFENSE: 845 case TacticalLines.FLOT: 846 case TacticalLines.LC: 847 case TacticalLines.PL: 848 case TacticalLines.FEBA: 849 case TacticalLines.LL: 850 case TacticalLines.EWL: 851// case TacticalLines.AC: 852// case TacticalLines.SAAFR: 853 case TacticalLines.DIRATKGND: 854 case TacticalLines.DIRATKSPT: 855 case TacticalLines.INFILTRATION: 856 case TacticalLines.FCL: 857 case TacticalLines.HOLD: 858 case TacticalLines.BRDGHD: 859 case TacticalLines.HOLD_GE: 860 case TacticalLines.BRDGHD_GE: 861 case TacticalLines.LOA: 862 case TacticalLines.LOD: 863 case TacticalLines.LDLC: 864 case TacticalLines.RELEASE: 865 case TacticalLines.HOL: 866 case TacticalLines.BHL: 867 case TacticalLines.LINE: 868 case TacticalLines.ABATIS: 869 case TacticalLines.ATDITCH: 870 case TacticalLines.ATWALL: 871 case TacticalLines.SFENCE: 872 case TacticalLines.DFENCE: 873 case TacticalLines.UNSP: 874 case TacticalLines.PLD: 875 case TacticalLines.DOUBLEA: 876 case TacticalLines.LWFENCE: 877 case TacticalLines.HWFENCE: 878 case TacticalLines.SINGLEC: 879 case TacticalLines.DOUBLEC: 880 case TacticalLines.TRIPLE: 881 case TacticalLines.FORTL: 882 case TacticalLines.LINTGT: 883 case TacticalLines.LINTGTS: 884 case TacticalLines.FSCL: 885 case TacticalLines.BCL_REVD: 886 case TacticalLines.BCL: 887 case TacticalLines.ICL: 888 case TacticalLines.IFF_OFF: 889 case TacticalLines.IFF_ON: 890 case TacticalLines.GENERIC_LINE: 891 case TacticalLines.NFL: 892 case TacticalLines.MFP: 893 case TacticalLines.RFL: 894 case TacticalLines.CONVOY: 895 case TacticalLines.HCONVOY: 896 case TacticalLines.MSR: 897 case TacticalLines.MSR_ONEWAY: 898 case TacticalLines.MSR_TWOWAY: 899 case TacticalLines.MSR_ALT: 900 case TacticalLines.ASR: 901 case TacticalLines.ASR_ONEWAY: 902 case TacticalLines.ASR_TWOWAY: 903 case TacticalLines.ASR_ALT: 904 case TacticalLines.ROUTE: 905 case TacticalLines.ROUTE_ONEWAY: 906 case TacticalLines.ROUTE_ALT: 907 result = true; 908 break; 909 default: 910 result = false; 911 break; 912 } 913 } 914 catch(Exception exc) 915 { 916 ErrorLogger.LogException(_className ,"LinesWithFill", 917 new RendererException("Failed inside LinesWithFill", exc)); 918 } 919 return result; 920 } 921 /** 922 * @deprecated 923 * if the line color and fill color are the same or very close then we want to 924 * tweak the fill color a bit to make the line appear distinct from the fill. 925 * @param tg 926 */ 927 public static void tweakFillColor(TGLight tg) 928 { 929 try 930 { 931 if(isSameColor(tg.get_LineColor(),tg.get_FillColor())==false) 932 return; 933 934 Color fillColor=tg.get_FillColor(); 935 int r=fillColor.getRed(),g=fillColor.getGreen(),b=fillColor.getBlue(); 936 int alpha=fillColor.getAlpha(); 937 938 r*=0.9; 939 g*=0.9; 940 b*=0.9; 941 alpha*=0.8; 942 943 fillColor=new Color(r,g,b,alpha); 944 tg.set_FillColor(fillColor); 945 } 946 catch(Exception exc) 947 { 948 ErrorLogger.LogException(_className ,"tweakFillColor", 949 new RendererException("Failed inside tweakFillColor", exc)); 950 } 951 } 952 /** 953 * @deprecated 954 * Test to see if two colors are similar 955 * @param c1 956 * @param c2 957 * @return true is same (or similar) color 958 */ 959 public static Boolean isSameColor(Color c1, Color c2) 960 { 961 try 962 { 963 if(c1==null || c2==null) 964 return true; 965 966 int r1=c1.getRed(),r2=c2.getRed(),g1=c1.getGreen(),g2=c2.getGreen(), 967 b1=c1.getBlue(),b2=c2.getBlue(); 968 969 if(Math.abs(r1-r2)<5) 970 if(Math.abs(g1-g2)<5) 971 if(Math.abs(b1-b2)<5) 972 return true; 973 } 974 catch(Exception exc) 975 { 976 ErrorLogger.LogException(_className ,"isSameColor", 977 new RendererException("Failed inside isSameColor", exc)); 978 } 979 return false; 980 } 981 /** 982 * Customer requested routine for setting the stroke dash pattern 983 * Scales dash length with line width and DPI 984 * @param width 985 * @param style 986 * @param cap 987 * @param join 988 * @return 989 */ 990 public static BasicStroke getLineStroke(int width, int style, int cap, int join) { 991 // Some segments are of length 0.1 because the Java2D renderer adds line caps of 992 // width/2 size to both ends of the segment when "round" is one of BasicStroke.CAP_ROUND 993 // or BasicStroke.CAP_SQUARE. This value is small enough not to affect the 994 // stipple bit pattern calculation for the 3d map and still look good on the 995 // 2d map. 996 997 // NOTE: The dash arrays below do not supportBasisStroke.CAP_BUTT line capping, 998 // although it would be relatively simple to change them such that they would. 999 BasicStroke stroke=null; 1000 try { 1001 final float dashLength = 2 * width; 1002 final float dotLength = 1f; 1003 final float dotSpace = 2 * width; 1004 switch (style) { 1005 case 0://GraphicProperties.LINE_TYPE_SOLID: 1006 stroke = new BasicStroke(width, cap, join); 1007 break; 1008 case 1://GraphicProperties.LINE_TYPE_DASHED: 1009 float[] dash = {dashLength, dashLength}; 1010 stroke = new BasicStroke(width, cap, join, 4f, dash, 0f); 1011 break; 1012 case 2://GraphicProperties.LINE_TYPE_DOTTED: 1013 float[] dot = {dotLength, dotSpace}; 1014 stroke = new BasicStroke(width, cap, join, 4f, dot, 0f); 1015 break; 1016 case 3://GraphicProperties.LINE_TYPE_DASHDOT: 1017 float[] dashdot = {2 * dashLength, dotSpace, dotLength, dotSpace}; 1018 stroke = new BasicStroke(width, cap, join, 4f, dashdot,0f ); 1019 break; 1020 case 4://GraphicProperties.LINE_TYPE_DASHDOTDOT: 1021 float[] dashdotdot = {dashLength, dotSpace, dotLength, dotSpace, dotLength, dotSpace}; 1022 stroke = new BasicStroke(width, cap, join, 4f,dashdotdot, 0f ); 1023 break; 1024 default: 1025 stroke = new BasicStroke(width, cap, join); 1026 break; 1027 } 1028 } catch(Exception exc) { 1029 ErrorLogger.LogException(_className ,"getLineStroke", 1030 new RendererException("Failed inside getLineStroke", exc)); 1031 } 1032 return stroke; 1033 } 1034 /** 1035 * Sets shape properties based on other properties which were set by JavaLineArray 1036 * @param tg tactical graphic 1037 * @param shapes the ShapeInfo array 1038 * @param bi BufferedImage to use for setting shape TexturePaint 1039 */ 1040 public static void SetShapeProperties(TGLight tg, ArrayList<Shape2> shapes, 1041 BufferedImage bi) { 1042 try 1043 { 1044 if (shapes == null) 1045 { 1046 return; 1047 } 1048 1049 int j = 0; 1050 Shape2 shape = null; 1051 BasicStroke stroke = null; 1052 float[] dash = null; 1053 int lineThickness = tg.get_LineThickness(); 1054 int shapeType = -1; 1055 int lineType = tg.get_LineType(); 1056 boolean hasFill=LinesWithFill(lineType); 1057 boolean isChange1Area = clsUtility.IsChange1Area(lineType); 1058 boolean isClosedPolygon = clsUtility.isClosedPolygon(lineType); 1059 //int n=shapes.size(); 1060 //remove air corridors fill shapes if fill is null 1061 if(tg.get_FillColor()==null) 1062 { 1063 switch(tg.get_LineType()) 1064 { 1065 case TacticalLines.AC: 1066 case TacticalLines.SAAFR: 1067 case TacticalLines.MRR: 1068 case TacticalLines.SL: 1069 case TacticalLines.TC: 1070 case TacticalLines.SC: 1071 case TacticalLines.LLTR: 1072 shape=shapes.get(shapes.size()-1); 1073 shapes.clear(); 1074 shapes.add(shape); 1075 break; 1076 case TacticalLines.CATK: 1077 case TacticalLines.AIRAOA: 1078 case TacticalLines.AAAAA: 1079 case TacticalLines.SPT: 1080 case TacticalLines.FRONTAL_ATTACK: 1081 case TacticalLines.TURNING_MOVEMENT: 1082 case TacticalLines.MOVEMENT_TO_CONTACT: 1083 case TacticalLines.MAIN: 1084 case TacticalLines.CATKBYFIRE: //80 1085 ArrayList<Shape2> tempShapes=new ArrayList(); 1086 for(j=0;j<shapes.size();j++) 1087 { 1088 shape=shapes.get(j); 1089 if(shape.getShapeType() != Shape2.SHAPE_TYPE_FILL) 1090 tempShapes.add(shape); 1091 } 1092 shapes=tempShapes; 1093 break; 1094 default: 1095 break; 1096 } 1097 } 1098 for (j = 0; j < shapes.size(); j++) 1099 { 1100 shape = shapes.get(j); 1101 if (shape == null || shape.getShape() == null) { 1102 continue; 1103 } 1104 1105 if (shape.getShapeType() == Shape2.SHAPE_TYPE_FILL) 1106 { 1107 switch(tg.get_LineType()) 1108 { 1109 case TacticalLines.DEPTH_AREA: 1110 break; 1111 default: 1112 shape.setFillColor(tg.get_FillColor()); 1113 break; 1114 } 1115 } 1116 1117 //if(lineType != TacticalLines.LEADING_LINE) 1118 ResolveModifierShape(tg, shape); 1119 if(lineType==TacticalLines.AIRFIELD) 1120 if(j==1) 1121 shape.setFillColor(null); 1122 //diagnostic 1123 if(lineType==TacticalLines.BBS_POINT) 1124 if(j==0) 1125 shape.setLineColor(null); 1126 //end section 1127 1128 shapeType = shape.getShapeType(); 1129 1130 Rectangle2D.Double rect = null; 1131 Graphics2D grid = null; 1132 TexturePaint tp = tg.get_TexturePaint(); 1133 1134 if(lineThickness==0) 1135 lineThickness=1; 1136 //set the shape with the default properties 1137 //the switch statement below will override specific properties as needed 1138 stroke = getLineStroke(lineThickness,shape.get_Style(),tg.get_lineCap(),BasicStroke.JOIN_ROUND); 1139 if(shape.getShapeType()==Shape2.SHAPE_TYPE_FILL) 1140 { 1141 stroke = new BasicStroke(lineThickness, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER); 1142 //shape.setStroke(new BasicStroke(0)); 1143 } 1144 shape.setStroke(stroke); 1145 } // end loop over shapes 1146 if (tg.get_LineType() == TacticalLines.DIRATKAIR) { 1147 // Make arrowhead and bowtie shapes solid even if tg.get_LineStyle() isn't 1148 for (int i = 2; i < shapes.size(); i++) { 1149 Shape2 arrowHeadShape = shapes.get(i); 1150 arrowHeadShape.set_Style(0); 1151 stroke = getLineStroke(lineThickness, 0, tg.get_lineCap(), BasicStroke.JOIN_ROUND); 1152 arrowHeadShape.setStroke(stroke); 1153 } 1154 } else if (tg.get_LineType() == TacticalLines.DIRATKGND || tg.get_LineType() == TacticalLines.DIRATKSPT || tg.get_LineType() == TacticalLines.EXPLOIT || lineType == TacticalLines.INFILTRATION) { 1155 // Make arrowhead shape solid even if tg.get_LineStyle() isn't 1156 Shape2 arrowHeadShape = shapes.get(1); 1157 arrowHeadShape.set_Style(0); 1158 stroke = getLineStroke(lineThickness,0,tg.get_lineCap(),BasicStroke.JOIN_ROUND); 1159 arrowHeadShape.setStroke(stroke); 1160 } else if (tg.get_LineType() == TacticalLines.PDF) { 1161 Shape2 rectShape = shapes.get(1); 1162 rectShape.set_Style(0); 1163 stroke = getLineStroke(lineThickness, 0, tg.get_lineCap(), BasicStroke.JOIN_ROUND); 1164 rectShape.setStroke(stroke); 1165 rectShape.setFillColor(rectShape.getLineColor()); 1166 } 1167 } 1168 catch (Exception exc) { 1169 ErrorLogger.LogException(_className ,"SetShapeProperties", 1170 new RendererException("Failed inside SetShapeProperties", exc)); 1171 } 1172 } 1173 /** 1174 * Returns a boolean indicating whether the line type is a change 1 area 1175 * @param lineType the line type 1176 * @return true if change 1 area 1177 */ 1178 public static boolean IsChange1Area(int lineType) { 1179 try { 1180 switch (lineType) { 1181 case TacticalLines.LAUNCH_AREA: 1182 case TacticalLines.DEFENDED_AREA_CIRCULAR: 1183 case TacticalLines.SHIP_AOI_CIRCULAR: 1184 case TacticalLines.PBS_ELLIPSE: 1185 case TacticalLines.RECTANGULAR: 1186 case TacticalLines.CUED_ACQUISITION: 1187 case TacticalLines.PBS_RECTANGLE: 1188 case TacticalLines.PBS_SQUARE: 1189 case TacticalLines.CIRCULAR: 1190 case TacticalLines.PBS_CIRCLE: 1191 case TacticalLines.BDZ: 1192 case TacticalLines.BBS_POINT: 1193 case TacticalLines.FSA_CIRCULAR: 1194 case TacticalLines.NOTACK: 1195 case TacticalLines.FFA_CIRCULAR: 1196 case TacticalLines.NFA_CIRCULAR: 1197 case TacticalLines.RFA_CIRCULAR: 1198 case TacticalLines.ACA_CIRCULAR: 1199 case TacticalLines.PAA_CIRCULAR: 1200 case TacticalLines.ATI_CIRCULAR: 1201 case TacticalLines.CFFZ_CIRCULAR: 1202 case TacticalLines.SENSOR_CIRCULAR: 1203 case TacticalLines.CENSOR_CIRCULAR: 1204 case TacticalLines.DA_CIRCULAR: 1205 case TacticalLines.CFZ_CIRCULAR: 1206 case TacticalLines.ZOR_CIRCULAR: 1207 case TacticalLines.TBA_CIRCULAR: 1208 case TacticalLines.TVAR_CIRCULAR: 1209 case TacticalLines.KILLBOXBLUE_CIRCULAR: 1210 case TacticalLines.KILLBOXPURPLE_CIRCULAR: 1211 case TacticalLines.RANGE_FAN: 1212 case TacticalLines.RANGE_FAN_FILL: 1213 case TacticalLines.RANGE_FAN_SECTOR: 1214 case TacticalLines.RADAR_SEARCH: 1215 case TacticalLines.PAA_RECTANGULAR: 1216 case TacticalLines.RECTANGULAR_TARGET: 1217 case TacticalLines.FSA_RECTANGULAR: 1218 case TacticalLines.SHIP_AOI_RECTANGULAR: 1219 case TacticalLines.DEFENDED_AREA_RECTANGULAR: 1220 case TacticalLines.FFA_RECTANGULAR: 1221 case TacticalLines.RFA_RECTANGULAR: 1222 case TacticalLines.NFA_RECTANGULAR: 1223 case TacticalLines.ACA_RECTANGULAR: 1224 case TacticalLines.ATI_RECTANGULAR: 1225 case TacticalLines.CFFZ_RECTANGULAR: 1226 case TacticalLines.SENSOR_RECTANGULAR: 1227 case TacticalLines.CENSOR_RECTANGULAR: 1228 case TacticalLines.DA_RECTANGULAR: 1229 case TacticalLines.CFZ_RECTANGULAR: 1230 case TacticalLines.ZOR_RECTANGULAR: 1231 case TacticalLines.TBA_RECTANGULAR: 1232 case TacticalLines.TVAR_RECTANGULAR: 1233 case TacticalLines.KILLBOXBLUE_RECTANGULAR: 1234 case TacticalLines.KILLBOXPURPLE_RECTANGULAR: 1235 return true; 1236 default: 1237 return false; 1238 } 1239 } catch (Exception exc) { 1240 //clsUtility.WriteFile("Error in clsUtility.IsChange1Area"); 1241 ErrorLogger.LogException(_className ,"IsChange1Area", 1242 new RendererException("Failed inside IsChange1Area", exc)); 1243 } 1244 return false; 1245 } 1246 1247 public static void WriteFile(String str) { 1248 try { 1249 BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("Test.txt")); 1250 bufferedWriter.write(str); 1251 //bufferedWriter.newLine(); 1252 //bufferedWriter.write(pointType); 1253 bufferedWriter.close(); 1254 bufferedWriter = null; 1255 } 1256 catch (Exception exc) { 1257 ErrorLogger.LogException(_className ,"WriteFile", 1258 new RendererException("Failed inside WriteFile", exc)); 1259 } 1260 } 1261 1262 /** 1263 * Calculates point where two lines intersect. 1264 * First line defined by pt1, m1. 1265 * Second line defined by pt2, m2. 1266 * result will be written to ptIntersect. 1267 * @param pt1 first line point 1268 * @param m1 slope of first line 1269 * @param pt2 second line point 1270 * @param m2 slope of second line 1271 * @param ptIntersect OUT - intersection point 1272 */ 1273 protected static void CalcIntersectPt(POINT2 pt1, 1274 double m1, 1275 POINT2 pt2, 1276 double m2, 1277 POINT2 ptIntersect) { 1278 try { 1279 if (m1 == m2) { 1280 return; 1281 } 1282 1283 double x1 = pt1.x; 1284 double y1 = pt1.y; 1285 double x2 = pt2.x; 1286 double y2 = pt2.y; 1287 //formula for the intersection of two lines 1288 double dx2 = (double) ((y1 - y2 + m1 * x2 - m1 * x1) / (m2 - m1)); 1289 double x3 = x2 + dx2; 1290 double y3 = (double) (y2 + m2 * dx2); 1291 1292 ptIntersect.x = x3; 1293 ptIntersect.y = y3; 1294 } catch (Exception exc) { 1295 //clsUtility.WriteFile("Error in clsUtility.CalcIntersectPt"); 1296 ErrorLogger.LogException(_className, "CalcIntersectPt", 1297 new RendererException("Failed inside CalcIntersectPt", exc)); 1298 } 1299 } 1300 1301 /** 1302 * Calculates the channel width in pixels for channel types 1303 * @param pixels the client points as 2-tuples x,y in pixels 1304 * @param distanceToChannelPOINT2 OUT - the calculated distance in pixels from the tip of the 1305 * arrowhead to the back of the arrowhead. 1306 * @return the channel width in pixels 1307 */ 1308 protected static int ChannelWidth(double[] pixels, 1309 ref<double[]> distanceToChannelPOINT2) { 1310 int width = 0; 1311 try { 1312 int numPOINT2s = pixels.length / 2; 1313 if (numPOINT2s < 3) { 1314 return 0; 1315 } 1316 1317 POINT2 channelWidthPOINT2 = new POINT2(0, 0); 1318 POINT2 lastSegmentPt1 = new POINT2(0, 0); 1319 POINT2 lastSegmentPt2 = new POINT2(0, 0); 1320 1321 lastSegmentPt1.x = (double) pixels[2 * numPOINT2s - 6]; 1322 lastSegmentPt1.y = (double) pixels[2 * numPOINT2s - 5]; 1323 lastSegmentPt2.x = (double) pixels[2 * numPOINT2s - 4]; 1324 lastSegmentPt2.y = (double) pixels[2 * numPOINT2s - 3]; 1325 channelWidthPOINT2.x = (double) pixels[2 * numPOINT2s - 2]; 1326 channelWidthPOINT2.y = (double) pixels[2 * numPOINT2s - 1]; 1327 1328 ref<double[]> m = new ref(); 1329 double m1 = 0; 1330 //m1.value=new double[1]; 1331 double distance = 0; 1332 POINT2 ptIntersect = new POINT2(0, 0); 1333 //boolean bolVertical = TrueSlope(lastSegmentPt1, lastSegmentPt2, ref m); 1334 boolean bolVertical = lineutility.CalcTrueSlopeDouble2(lastSegmentPt1, lastSegmentPt2, m); 1335 if (bolVertical == true && m.value[0] != 0) { 1336 m1 = -1 / m.value[0]; 1337 CalcIntersectPt(channelWidthPOINT2, m1, lastSegmentPt2, m.value[0], ptIntersect); 1338 distance = lineutility.CalcDistanceDouble(channelWidthPOINT2, ptIntersect); 1339 } 1340 if (bolVertical == true && m.value[0] == 0) //horizontal segment 1341 { 1342 distance = Math.abs(channelWidthPOINT2.y - lastSegmentPt1.y); 1343 } 1344 if (bolVertical == false) //vertical segment 1345 { 1346 distance = Math.abs(channelWidthPOINT2.x - lastSegmentPt1.x); 1347 distanceToChannelPOINT2.value = new double[1]; 1348 distanceToChannelPOINT2.value[0] = distance; 1349 return (int) distance * 4; 1350 } 1351 1352 width = (int) distance * 8; 1353 if (width < 2) { 1354 width = 2; 1355 } 1356 1357 double hypotenuse = lineutility.CalcDistanceDouble(lastSegmentPt2, channelWidthPOINT2); 1358 distanceToChannelPOINT2.value = new double[1]; 1359 distanceToChannelPOINT2.value[0] = Math.sqrt(hypotenuse * hypotenuse - distance * distance); 1360 1361 } catch (Exception exc) { 1362 //clsUtility.WriteFile("Error in clsUtility.ChannelWidth"); 1363 ErrorLogger.LogException(_className, "ChannelWidth", 1364 new RendererException("Failed inside ChannelWidth", exc)); 1365 } 1366 return width; 1367 } 1368 1369 private static boolean InYOrder(POINT2 pt0, 1370 POINT2 pt1, 1371 POINT2 pt2) { 1372 try { 1373 if (pt0.y <= pt1.y && pt1.y <= pt2.y) { 1374 return true; 1375 } 1376 1377 if (pt2.y <= pt1.y && pt1.y <= pt0.y) { 1378 return true; 1379 } 1380 1381 } catch (Exception exc) { 1382 //clsUtility.WriteFile("Error in clsUtility.InYOrder"); 1383 ErrorLogger.LogException(_className, "InYOrder", 1384 new RendererException("Failed inside InYOrder", exc)); 1385 } 1386 return false; 1387 } 1388 /// <summary> 1389 /// tests if POINT2s have successively increasing or decreasing x values. 1390 /// </summary> 1391 /// <param name="pt0"></param> 1392 /// <param name="pt1"></param> 1393 /// <param name="pt2"></param> 1394 /// <returns>true if POINT2s are in X order</returns> 1395 1396 private static boolean InXOrder(POINT2 pt0, 1397 POINT2 pt1, 1398 POINT2 pt2) { 1399 try { 1400 if (pt0.x <= pt1.x && pt1.x <= pt2.x) { 1401 return true; 1402 } 1403 1404 if (pt2.x <= pt1.x && pt1.x <= pt0.x) { 1405 return true; 1406 } 1407 1408 } catch (Exception exc) { 1409 //clsUtility.WriteFile("Error in clsUtility.InXOrder"); 1410 ErrorLogger.LogException(_className, "InXOrder", 1411 new RendererException("Failed inside InXOrder", exc)); 1412 } 1413 return false; 1414 } 1415 1416 /** 1417 * For each sector calculates left azimuth, right azimuth, min radius, max radius 1418 * and stuff H2 with the string delimited result. The function is public, called by JavaRendererServer 1419 * @param tg tactical graphic 1420 */ 1421 public static void GetSectorRadiiFromPoints(TGLight tg) { 1422 try { 1423 if(tg.get_LineType()==TacticalLines.RANGE_FAN_FILL) 1424 return; 1425 POINT2 ptCenter = tg.LatLongs.get(0); 1426 POINT2 ptLeftMin = new POINT2(), ptRightMax = new POINT2(); 1427 int k = 0; 1428 String strLeft = "", strRight = "", strMin = "", strMax = "", temp = ""; 1429 double nLeft = 0, nRight = 0, nMin = 0, nMax = 0; 1430 //if tg.PointCollection has more than one point 1431 //we use the points to calculate left,right,min,max 1432 //and then stuff tg.H2 with the comma delimited string 1433 double dist = 0; 1434 ref<double[]> a12 = new ref(), a21 = new ref(); 1435 int numSectors = 0; 1436 if (tg.LatLongs.size() > 2) { 1437 numSectors = (tg.LatLongs.size() - 2) / 2; 1438 for (k = 0; k < numSectors; k++) { 1439 //get the sector points 1440 ptLeftMin = tg.LatLongs.get(2 * k + 2); 1441 ptRightMax = tg.LatLongs.get(2 * k + 3); 1442 1443 dist = mdlGeodesic.geodesic_distance(ptCenter, ptLeftMin, a12, a21); 1444 nLeft = a12.value[0]; 1445 strLeft = Double.toString(nLeft); 1446 1447 nMin = dist; 1448 strMin = Double.toString(nMin); 1449 1450 dist = mdlGeodesic.geodesic_distance(ptCenter, ptRightMax, a12, a21); 1451 nRight = a12.value[0]; 1452 strRight = Double.toString(nRight); 1453 1454 nMax = dist; 1455 strMax = Double.toString(nMax); 1456 1457 if (k == 0) { 1458 temp = strLeft + "," + strRight + "," + strMin + "," + strMax; 1459 } else { 1460 temp += "," + strLeft + "," + strRight + "," + strMin + "," + strMax; 1461 } 1462 } 1463 if (!temp.equals("")) { 1464 tg.set_LRMM(temp); 1465 } 1466 } 1467 } catch (Exception exc) { 1468 //clsUtility.WriteFile("Error in clsUtility.GetSectorRadiiFromPoints"); 1469 ErrorLogger.LogException(_className, "GetSectorRadiiFromPoints", 1470 new RendererException("Failed inside GetSectorRadiiFromPoints", exc)); 1471 } 1472 } 1473 1474 /** 1475 * Reverses the pixels except for the last point. This is used for 1476 * the axis of advance type routes. The pixels are 2-tuples x,y 1477 * 1478 * @param pixels OUT - Array of client points 1479 */ 1480 protected static void ReorderPixels(double[] pixels) { 1481 try { 1482 double[] tempPixels; 1483 //reverse the pixels 1484 int j; 1485 double x; 1486 double y; 1487 int counter; 1488 int numPoints; 1489 counter = 0; 1490 numPoints = pixels.length / 2; 1491 tempPixels = new double[pixels.length]; 1492 for (j = 0; j < numPoints - 1; j++) { 1493 x = pixels[pixels.length - 2 * j - 4]; 1494 y = pixels[pixels.length - 2 * j - 3]; 1495 tempPixels[counter] = x; 1496 tempPixels[counter + 1] = y; 1497 counter += 2; 1498 } 1499 //put the last pixel point into the last temppixels point 1500 int intPixelSize = pixels.length; 1501 tempPixels[counter] = pixels[intPixelSize - 2]; 1502 tempPixels[counter + 1] = pixels[intPixelSize - 1]; 1503 //stuff the pixels 1504 int n=pixels.length; 1505 //for (j = 0; j < pixels.length; j++) 1506 for (j = 0; j < n; j++) 1507 { 1508 pixels[j] = tempPixels[j]; 1509 } 1510 //tempPixels = null; 1511 } catch (Exception exc) { 1512 ErrorLogger.LogException(_className, "ReorderPixels", 1513 new RendererException("Failed inside ReorderPixels", exc)); 1514 } 1515 } 1516 /** 1517 * do not allow vertical segments for these, move the point x value by 1 pixel 1518 * @param tg tactical graphic 1519 */ 1520 public static void FilterVerticalSegments(TGLight tg) 1521 { 1522 try 1523 { 1524 switch(tg.get_LineType()) 1525 { 1526 case TacticalLines.MAIN: 1527 case TacticalLines.CATK: 1528 case TacticalLines.CATKBYFIRE: 1529 case TacticalLines.AIRAOA: 1530 case TacticalLines.AAAAA: 1531 case TacticalLines.SPT: 1532 case TacticalLines.FRONTAL_ATTACK: 1533 case TacticalLines.TURNING_MOVEMENT: 1534 case TacticalLines.MOVEMENT_TO_CONTACT: 1535 case TacticalLines.LC: 1536 case TacticalLines.UNSP: 1537 case TacticalLines.DFENCE: 1538 case TacticalLines.SFENCE: 1539 case TacticalLines.DOUBLEA: 1540 case TacticalLines.LWFENCE: 1541 case TacticalLines.HWFENCE: 1542 case TacticalLines.BBS_LINE: 1543 case TacticalLines.SINGLEC: 1544 case TacticalLines.DOUBLEC: 1545 case TacticalLines.TRIPLE: 1546 case TacticalLines.MSR_ONEWAY: 1547 case TacticalLines.MSR_TWOWAY: 1548 case TacticalLines.MSR_ALT: 1549 case TacticalLines.ASR_ONEWAY: 1550 case TacticalLines.ASR_TWOWAY: 1551 case TacticalLines.ASR_ALT: 1552 case TacticalLines.ROUTE_ONEWAY: 1553 case TacticalLines.ROUTE_ALT: 1554 case TacticalLines.ATWALL: 1555 break; 1556 default: 1557 return; 1558 } 1559 POINT2 ptCurrent=null; 1560 POINT2 ptLast=null; 1561 int n=tg.Pixels.size(); 1562 //for(int j=1;j<tg.Pixels.size();j++) 1563 for(int j=1;j<n;j++) 1564 { 1565 ptLast=new POINT2(tg.Pixels.get(j-1)); 1566 ptCurrent=new POINT2(tg.Pixels.get(j)); 1567 //if(Math.round(ptCurrent.x)==Math.round(ptLast.x)) 1568 if(Math.abs(ptCurrent.x-ptLast.x)<1) 1569 { 1570 if (ptCurrent.x>=ptLast.x) 1571 ptCurrent.x += 1; 1572 else 1573 ptCurrent.x -= 1; 1574 tg.Pixels.set(j, ptCurrent); 1575 } 1576 } 1577 } 1578 catch(Exception exc) 1579 { 1580 ErrorLogger.LogException("clsUtility", "FilterVerticalSegments", 1581 new RendererException("Failed inside FilterVerticalSegments", exc)); 1582 1583 } 1584 } 1585 /** 1586 * Client utility to calculate the channel points for channel types. 1587 * This code was ported from CJMTK. 1588 * @param arrLocation the client points 1589 * @return the channel point 1590 */ 1591 public static POINT2 ComputeLastPoint(ArrayList<POINT2> arrLocation) { 1592 POINT2 locD = new POINT2(0, 0); 1593 try { 1594 POINT2 locA = arrLocation.get(1); 1595 //Get the first point (b) in pixels. 1596 //var locB:Point=new Point(arrLocation[0].x,arrLocation[0].y); 1597 POINT2 locB = arrLocation.get(0); 1598 1599 //Compute the distance in pixels from (a) to (b). 1600 double dblDx = locB.x - locA.x; 1601 double dblDy = locB.y - locA.y; 1602 1603 //Compute the dblAngle in radians from (a) to (b). 1604 double dblTheta = Math.atan2(-dblDy, dblDx); 1605 1606 //Compute a reasonable intermediate point along the line from (a) to (b). 1607 POINT2 locC = new POINT2(0, 0); 1608 locC.x = (int) (locA.x + 0.85 * dblDx); 1609 locC.y = (int) (locA.y + 0.85 * dblDy); 1610 //Put the last point on the left side of the line from (a) to (b). 1611 double dblAngle = dblTheta + Math.PI / 2.0; 1612 if (dblAngle > Math.PI) { 1613 dblAngle = dblAngle - 2.0 * Math.PI; 1614 } 1615 if (dblAngle < -Math.PI) { 1616 dblAngle = dblAngle + 2.0 * Math.PI; 1617 } 1618 1619 //Set the magnitude of the dblWidth in pixels. Make sure it is at least 15 pixels. 1620 double dblWidth = 30;//was 15 1621 1622 //Compute the last point in pixels. 1623 locD.x = (locC.x + dblWidth * Math.cos(dblAngle)); 1624 locD.y = (locC.y - dblWidth * Math.sin(dblAngle)); 1625 } catch (Exception exc) { 1626 //clsUtility.WriteFile("Error in clsUtility.ComputeLatPoint"); 1627 ErrorLogger.LogException(_className, "ComputeLastPoint", 1628 new RendererException("Failed inside ComputeLastPoint", exc)); 1629 } 1630 return locD; 1631 } 1632 1633 /** 1634 * Called by clsChannelUtility. The segments are used for managing double-backed segments 1635 * for channel types. If the new point is double-backed then the segment at that index will be false. 1636 * 1637 * @param pixels the client points as 2-tuples x,y in pixels 1638 * @param segments OUT - the segments 1639 * @param factor a steepness factor for calculating whether the segment is double-backed 1640 */ 1641 protected static void GetSegments(double[] pixels, 1642 boolean[] segments, 1643 double factor) { 1644 try 1645 { 1646 int j = 0; 1647 ref<double[]> m1 = new ref(); 1648 ref<double[]> m2 = new ref(); 1649 long numPoints = 0; 1650 boolean bolVertical1 = false; 1651 boolean bolVertical2 = false; 1652 1653 POINT2 pt0F = new POINT2(0, 0); 1654 POINT2 pt1F = new POINT2(0, 0); 1655 POINT2 pt2F = new POINT2(0, 0); 1656 1657 segments[0] = true; 1658 1659 numPoints = pixels.length / 2; 1660 for (j = 0; j < numPoints - 2; j++) 1661 { 1662 pt0F.x = (double) pixels[2 * j]; 1663 pt0F.y = (double) pixels[2 * j + 1]; 1664 1665 pt1F.x = (double) pixels[2 * j + 2]; 1666 pt1F.y = (double) pixels[2 * j + 3]; 1667 1668 pt2F.x = (double) pixels[2 * j + 4]; 1669 pt2F.y = (double) pixels[2 * j + 5]; 1670 1671 bolVertical1 = lineutility.CalcTrueSlopeDoubleForRoutes(pt0F, pt1F, m1); 1672 bolVertical2 = lineutility.CalcTrueSlopeDoubleForRoutes(pt1F, pt2F, m2); 1673 1674 segments[j + 1] = true; 1675 if (bolVertical1 == true && bolVertical2 == true) 1676 { 1677 if (Math.abs(Math.atan(m1.value[0]) - Math.atan(m2.value[0])) < 1 / factor && InXOrder(pt0F, pt1F, pt2F) == false) //was 0.1 1678 { 1679 segments[j + 1] = false; 1680 } 1681 } 1682 1683 if ((bolVertical1 == false || Math.abs(m1.value[0]) > factor) && (bolVertical2 == false || Math.abs(m2.value[0]) > factor) && InYOrder(pt0F, pt1F, pt2F) == false) //was 10 1684 { 1685 segments[j + 1] = false; 1686 } 1687 } //end for 1688 //int n=segments.length; 1689 } 1690 catch (Exception exc) 1691 { 1692 //System.out.println(e.getMessage()); 1693 //clsUtility.WriteFile("Error in clsUtility.GetSegments"); 1694 ErrorLogger.LogException(_className, "GetSegments", 1695 new RendererException("Failed inside GetSegments", exc)); 1696 } 1697 } 1698 1699 protected static void GetLCPartitions(double[] pixels, 1700 double LCChannelWith, 1701 ArrayList<P1> partitions, 1702 ArrayList<P1> singleLinePartitions) { 1703 try 1704 { 1705 int numPoints = pixels.length / 2; 1706 POINT2 pt0F = new POINT2(0, 0); 1707 POINT2 pt1F = new POINT2(0, 0); 1708 POINT2 pt2F = new POINT2(0, 0); 1709 1710 P1 nextP = new P1(); 1711 nextP.start = 0; 1712 1713 //used for debugging 1714 double[] angles = new double[numPoints - 1]; 1715 1716 for (int i = 0; i < numPoints - 2; i++) { 1717 pt0F.x = (double) pixels[2 * i]; 1718 pt0F.y = (double) pixels[2 * i + 1]; 1719 1720 pt1F.x = (double) pixels[2 * i + 2]; 1721 pt1F.y = (double) pixels[2 * i + 3]; 1722 1723 pt2F.x = (double) pixels[2 * i + 4]; 1724 pt2F.y = (double) pixels[2 * i + 5]; 1725 1726 double angle1 = Math.atan2(pt1F.y - pt0F.y, pt1F.x - pt0F.x); 1727 double angle2 = Math.atan2(pt1F.y - pt2F.y, pt1F.x - pt2F.x); 1728 double angle = angle1-angle2;// * 180/Math.PI; 1729 double degrees = angle * 180/Math.PI; 1730 if (angle < 0) { 1731 degrees = 360 + degrees; 1732 } 1733 1734 if (degrees > 270) { 1735 boolean angleTooSmall = false; 1736 1737 if (lineutility.CalcDistanceDouble(pt0F, pt1F) < lineutility.CalcDistanceDouble(pt1F, pt2F)) { 1738 POINT2 newPt = lineutility.ExtendAlongLineDouble2(pt1F, pt2F, lineutility.CalcDistanceDouble(pt1F, pt0F)); 1739 if (lineutility.CalcDistanceDouble(pt0F, newPt) < LCChannelWith) 1740 angleTooSmall = true; 1741 } else { 1742 POINT2 newPt = lineutility.ExtendAlongLineDouble2(pt1F, pt0F, lineutility.CalcDistanceDouble(pt1F, pt2F)); 1743 if (lineutility.CalcDistanceDouble(pt2F, newPt) < LCChannelWith) 1744 angleTooSmall = true; 1745 } 1746 if (angleTooSmall) { 1747 // Angle is too small to fit channel, make it a single line partition 1748 nextP.end_Renamed = i - 1; 1749 partitions.add(nextP); 1750 nextP = new P1(); 1751 nextP.start = i; 1752 nextP.end_Renamed=i + 2; 1753 singleLinePartitions.add(nextP); 1754 i++; 1755 nextP = new P1(); 1756 nextP.start = i + 1; 1757 } 1758 } else if(degrees < 90) { 1759 // new Partition 1760 nextP.end_Renamed = i; 1761 partitions.add(nextP); 1762 nextP = new P1(); 1763 nextP.start = i + 1; 1764 } 1765 angles[i] = degrees; 1766 } //end for 1767 nextP.end_Renamed = numPoints - 2; 1768 partitions.add(nextP); 1769 } catch (Exception exc) { 1770 ErrorLogger.LogException(_className, "GetLCPartitions", 1771 new RendererException("Failed inside GetLCPartitions", exc)); 1772 } 1773 } 1774 1775 /** 1776 * Sets the color for the current shape depending on the affiliation 1777 * @param tg 1778 * @param shape 1779 */ 1780 protected static void SetLCColor(TGLight tg, Shape2 shape) { 1781 try { 1782 if (tg.isHostile()) { 1783 if (shape.getLineColor() == Color.RED) { 1784 shape.setLineColor(tg.get_LineColor()); 1785 } else { 1786 shape.setLineColor(Color.RED); 1787 } 1788 } else { 1789 if (shape.getLineColor() != Color.RED) { 1790 shape.setLineColor(tg.get_LineColor()); 1791 } else { 1792 shape.setLineColor(Color.RED); 1793 } 1794 } 1795 1796 } catch (Exception exc) { 1797 //WriteFile("Error in clsUtility.SetLCColor"); 1798 ErrorLogger.LogException(_className, "SetLCColor", 1799 new RendererException("Failed inside SetLCColor", exc)); 1800 } 1801 } 1802 /** 1803 * USAS requires a left-right orientation for ENY, which negates the upper-lower 1804 * orientation we used for Mil-Std-2525 ENY compliance. Therefore we must reverse 1805 * the client points for two of the quadrants 1806 * @param tg tactical graphic 1807 */ 1808 public static void ReverseUSASLCPointsByQuadrant(TGLight tg) 1809 { 1810 try 1811 { 1812 if(tg.Pixels.size()<2) 1813 return; 1814 int quadrant=lineutility.GetQuadrantDouble(tg.Pixels.get(0), tg.Pixels.get(1)); 1815 switch(tg.get_LineType()) 1816 { 1817 case TacticalLines.LC: 1818 if(tg.isHostile()) 1819 { 1820 switch(quadrant) 1821 { 1822 case 2: 1823 case 3: 1824 break; 1825 case 1://reverse the points for these two quadrants 1826 case 4: 1827 int n=tg.Pixels.size(); 1828 ArrayList<POINT2> pts2=(ArrayList<POINT2>)tg.Pixels.clone(); 1829 //for(int j=0;j<tg.Pixels.size();j++) 1830 for(int j=0;j<n;j++) 1831 tg.Pixels.set(j, pts2.get(n-j-1)); 1832 break; 1833 }//end switch quadrant 1834 }//end if 1835 else 1836 { 1837 switch(quadrant) 1838 { 1839 case 1: 1840 case 4: 1841 break; 1842 case 2://reverse the points for these two quadrants 1843 case 3: 1844 int n=tg.Pixels.size(); 1845 ArrayList<POINT2> pts2=(ArrayList<POINT2>)tg.Pixels.clone(); 1846 //for(int j=0;j<tg.Pixels.size();j++) 1847 for(int j=0;j<n;j++) 1848 tg.Pixels.set(j, pts2.get(n-j-1)); 1849 break; 1850 }//end switch quadrant 1851 }//end else 1852 break; 1853 default: 1854 break; 1855 }//end switch linetype 1856 } 1857 catch (Exception exc) { 1858 //WriteFile("Error in clsUtility.SetLCColor"); 1859 ErrorLogger.LogException(_className, "ReverseUSASLCPointsByQuadrant", 1860 new RendererException("Failed inside ReverseUSASLCPointsByQuadrant", exc)); 1861 } 1862 }//end ReverseUSASLCPointsByQuadrant 1863 1864 /** 1865 * use str if tg is null 1866 * @param symbolId Mil=Standard-2525 symbol id 1867 * @return line type 1868 */ 1869 public static int GetLinetypeFromString(String symbolId) 1870 { 1871 try 1872 { 1873 if (symbolId.length() < 16){ 1874 return -1; 1875 } 1876 int symbolSet = SymbolID.getSymbolSet(symbolId); 1877 int entityCode = SymbolID.getEntityCode(symbolId); 1878 int version = SymbolID.getVersion(symbolId); 1879 if (symbolSet == 25) { 1880 return clsRenderer.getCMLineType(version, entityCode); 1881 } else if (symbolSet == 45 || symbolSet == 46) { 1882 return clsMETOC.getWeatherLinetype(version, entityCode); 1883 } 1884 } 1885 catch (Exception exc) { 1886 ErrorLogger.LogException(_className ,"GetLinetypeFromString", 1887 new RendererException("Failed inside GetLinetypeFromString", exc)); 1888 } 1889 return -1; 1890 } 1891 1892 /** 1893 * An auto-shape is a symbol with a fixed number of anchor points 1894 * 1895 * @param tg tactical graphic 1896 * @return true if auto-shape 1897 */ 1898 public static boolean isAutoshape(TGLight tg) { 1899 try { 1900 switch(tg.get_LineType()) 1901 { 1902 case TacticalLines.BBS_RECTANGLE: 1903 case TacticalLines.BS_RECTANGLE: 1904 case TacticalLines.BS_ELLIPSE: 1905 case TacticalLines.PBS_CIRCLE: 1906 case TacticalLines.BS_CROSS: 1907 case TacticalLines.BS_BBOX: 1908 case TacticalLines.BBS_POINT: 1909 return true; 1910 } 1911 MSInfo msInfo = MSLookup.getInstance().getMSLInfo(tg.get_SymbolId()); 1912 if (msInfo == null || IsChange1Area(tg.get_LineType())) { 1913 return false; 1914 } 1915 switch (tg.get_LineType()) { 1916 case TacticalLines.DIRATKAIR: 1917 case TacticalLines.DIRATKGND: 1918 case TacticalLines.DIRATKSPT: 1919 case TacticalLines.INFILTRATION: 1920 // Direction of attack symbols only have two points but can handle more 1921 return false; 1922 default: 1923 break; 1924 } 1925 switch (msInfo.getDrawRule()) { 1926 case DrawRules.LINE26: // Two ways to draw but fixed points 1927 case DrawRules.LINE27: // Two ways to draw but fixed points 1928 case DrawRules.AREA26: // Need same number of points in first half and second half to make two shapes 1929 case DrawRules.CORRIDOR1: // Each point represents an Air Control Point or Communications Checkpoint 1930 return true; 1931 default: 1932 return msInfo.getMaxPointCount() == msInfo.getMinPointCount(); 1933 } 1934 } catch (Exception exc) { 1935 ErrorLogger.LogException(_className, "isAutoshape", 1936 new RendererException("Failed inside isAutoshape", exc)); 1937 } 1938 return false; 1939 } 1940 /** 1941 * Client will send the segment colors within a modifier. 1942 * Format is 0:FFBBBB,4:FFAAAA,... 1943 * For the time being will assume the modifier being used is the H modifier 1944 * @param tg 1945 * @return 1946 */ 1947 public static HashMap<Integer,Color> getMSRSegmentColors(TGLight tg) 1948 { 1949 HashMap<Integer,Color> hMap=null; 1950 try 1951 { 1952 int linetype=tg.get_LineType(); 1953 switch(linetype) 1954 { 1955 case TacticalLines.MSR: 1956 case TacticalLines.ASR: 1957 case TacticalLines.ROUTE: 1958 case TacticalLines.BOUNDARY: 1959 if(tg.get_H()==null || tg.get_H().isEmpty()) 1960 return null; 1961 hMap=new HashMap<Integer,Color>(); 1962 break; 1963 default: 1964 return null; 1965 } 1966 String[]colorStrs=tg.get_H().split(","); 1967 int j=0,numSegs=colorStrs.length; 1968 String segPlusColor=""; 1969 String[]seg=null; 1970 Color color=null; 1971 int index=-1; 1972 for(j=0;j<numSegs;j++) 1973 { 1974 segPlusColor=colorStrs[j]; 1975 if(!segPlusColor.contains(":")) 1976 continue; 1977 seg=segPlusColor.split(":"); 1978 color= RendererUtilities.getColorFromHexString(seg[1]); 1979 index=Integer.parseInt(seg[0]); 1980 hMap.put(index, color); 1981 } 1982 } 1983 catch (Exception exc) 1984 { 1985 ErrorLogger.LogException(_className ,"getMSRSegmentColors", 1986 new RendererException("Failed inside getMSRSegmentColors", exc)); 1987 } 1988 return hMap; 1989 } 1990 public static HashMap<Integer,String> getMSRSegmentColorStrings(TGLight tg) 1991 { 1992 HashMap<Integer,String> hMap=null; 1993 try 1994 { 1995 int linetype = tg.get_LineType(); 1996 switch (linetype) { 1997 case TacticalLines.MSR: 1998 case TacticalLines.ASR: 1999 case TacticalLines.ROUTE: 2000 case TacticalLines.BOUNDARY: 2001 if (tg.get_H() == null || tg.get_H().isEmpty()) 2002 return null; 2003 hMap = new HashMap<>(); 2004 break; 2005 default: 2006 return null; 2007 } 2008 String[] colorStrs = tg.get_H().split(","); 2009 int j = 0; 2010 int numSegs = colorStrs.length; 2011 String segPlusColor = ""; 2012 String[] seg = null; 2013 //Color color = null; 2014 int index = -1; 2015 for (j = 0; j < numSegs; j++) { 2016 segPlusColor = colorStrs[j]; 2017 if (!segPlusColor.contains(":")) 2018 continue; 2019 seg = segPlusColor.split(":"); 2020 //color = armyc2.c5isr.renderer.utilities.SymbolUtilitiesD.getColorFromHexString(seg[1]); 2021 index = Integer.parseInt(seg[0]); 2022 //hMap.put(new Integer(index), color); 2023 hMap.put(new Integer(index), seg[1]); 2024 } 2025 } 2026 catch (Exception exc) 2027 { 2028 ErrorLogger.LogException(_className ,"getMSRSegmentColorStrings", 2029 new RendererException("Failed inside getMSRSegmentColorStrings", exc)); 2030 } 2031 return hMap; 2032 } 2033 /** 2034 * tg.H must be revised for clipped MSR, ASR and Boundary 2035 * This function is called after the pixels were clipped 2036 * @param originalPixels the tactical graphic pixels before clipping 2037 * @param tg 2038 * @deprecated 2039 */ 2040 public static void reviseHModifier(ArrayList<POINT2>originalPixels, 2041 TGLight tg) 2042 { 2043 try 2044 { 2045 //only revise tg.H if it is not null or empty 2046 //and the linetype is bounday, MSR, or ASR 2047 if(tg.get_H()==null || tg.get_H().isEmpty()) 2048 return; 2049 int linetype=tg.get_LineType(); 2050 switch(linetype) 2051 { 2052 case TacticalLines.ASR: 2053 case TacticalLines.MSR: 2054 case TacticalLines.ROUTE: 2055 case TacticalLines.BOUNDARY: 2056 break; 2057 default: 2058 return; 2059 } 2060 int j=0,k=0; 2061 //Line2D line=new Line2D.Double(); 2062 2063 //get the first common point between the original points and tg.Pixels 2064 //if it is n then n segments will have been dropped at the front end of 2065 //the clipped array (from the original pixels) so then we would want to 2066 //set the start index to n for the loop through the original points 2067 int n=-1; 2068 boolean foundPt=false; 2069 int t=originalPixels.size(); 2070 int u=tg.Pixels.size(); 2071 //for(j=0;j<originalPixels.size();j++) 2072 for(j=0;j<t;j++) 2073 { 2074 //for(k=0;k<tg.Pixels.size();k++) 2075 for(k=0;k<u;k++) 2076 { 2077 if(originalPixels.get(j).x==tg.Pixels.get(k).x && originalPixels.get(j).y==tg.Pixels.get(k).y) 2078 { 2079 n=j; 2080 foundPt=true; 2081 break; 2082 } 2083 } 2084 if(foundPt) 2085 break; 2086 } 2087 HashMap<Integer,Color> hmap=getMSRSegmentColors(tg); 2088 //use a 2nd hashmap to store the revised segment numbers, and exisitng Colors 2089 HashMap<Integer,Color> hmap2=new HashMap<Integer,Color>(); 2090 POINT2 segPt0=null,segPt1=null; //the original segments 2091 POINT2 pt0=null,pt1=null; //the clipped segments 2092 Color color=null; 2093 if(n<1) 2094 n=1; 2095 for(Integer key : hmap.keySet()) //keys can begin at 0 2096 { 2097 if(key<n-1) 2098 continue; 2099 if(key+1>originalPixels.size()-1) 2100 break; 2101 color=hmap.get(key); 2102 segPt0=originalPixels.get(key); 2103 segPt1=originalPixels.get(key+1); 2104 u=tg.Pixels.size(); 2105 //for(j=0;j<tg.Pixels.size()-1;j++) 2106 for(j=0;j<u-1;j++) 2107 { 2108 pt0=tg.Pixels.get(j);//clipped pixels 2109 pt1=tg.Pixels.get(j+1); 2110 if(segPt0.x==pt0.x && segPt0.y==pt0.y) 2111 { 2112 hmap2.put(j, color); 2113 break; 2114 } 2115 else if(segPt1.x==pt1.x && segPt1.y==pt1.y) 2116 { 2117 hmap2.put(j, color); 2118 break; 2119 } 2120 else 2121 { 2122 if(pt0.x==segPt1.x && pt0.y==segPt1.y) 2123 continue; 2124 if(pt1.x==segPt0.x && pt1.y==segPt0.y) 2125 continue; 2126 else 2127 { 2128 //if the original segment straddles or clips the clipping area 2129 //then the original segment will contain the clipped segment 2130 double dist0=lineutility.CalcDistanceToLineDouble(segPt0, segPt1, pt0); 2131 double dist1=lineutility.CalcDistanceToLineDouble(segPt0, segPt1, pt1); 2132 Line2D lineOrigPts=new Line2D.Double(segPt0.x,segPt0.y, segPt1.x,segPt1.y); 2133 Rectangle2D rectOrigPts=lineOrigPts.getBounds2D(); 2134 Line2D lineClipPts=new Line2D.Double(pt0.x,pt0.y, pt1.x, pt1.y); 2135 Rectangle2D rectClipPts=lineClipPts.getBounds2D(); 2136 //test if the lines coincide and the clipped segment is within the original segment 2137 if(dist0<1 && dist1<1 && rectOrigPts.contains(rectClipPts)) 2138 { 2139 hmap2.put(j, color); 2140 } 2141 } 2142 } 2143 } 2144 } 2145 if(hmap2.isEmpty()) 2146 { 2147 tg.set_H(""); 2148 return; 2149 } 2150 2151 String h="",temp=""; 2152 for(Integer key : hmap2.keySet()) 2153 { 2154 color=hmap2.get(key); 2155 temp=Integer.toHexString(color.toARGB()); 2156 h+=key.toString()+":"+temp+","; 2157 } 2158 h=h.substring(0, h.length()-1); 2159 tg.set_H(h); 2160 } 2161 catch (Exception exc) { 2162 ErrorLogger.LogException(_className, "reviseHModifer", 2163 new RendererException("Failed inside reviseHModifier", exc)); 2164 } 2165 } 2166 2167 /** 2168 * Adds extra points to LC if there are angles too small to fit the channel 2169 * @param tg 2170 * @param converter 2171 */ 2172 public static void SegmentLCPoints(TGLight tg, IPointConversion converter) { 2173 try { 2174 if (tg.get_LineType() != TacticalLines.LC) 2175 return; 2176 2177 ArrayList<POINT2> points = tg.get_Pixels(); 2178 2179 double LCChannelWith = arraysupport.getScaledSize(40, tg.get_LineThickness(), tg.get_patternScale()); 2180 2181 for (int i = 0; i < points.size() - 2; i++) { 2182 POINT2 ptA = new POINT2(points.get(i).x, points.get(i).y); 2183 POINT2 ptB = new POINT2(points.get(i+1).x, points.get(i+1).y); 2184 POINT2 ptC = new POINT2(points.get(i+2).x, points.get(i+2).y); 2185 2186 double angle1 = Math.atan2(ptB.y - ptA.y, ptB.x - ptA.x); 2187 double angle2 = Math.atan2(ptB.y - ptC.y, ptB.x - ptC.x); 2188 double angle = angle1 - angle2; 2189 double degrees = angle * 180/Math.PI; 2190 2191 if(angle < 0) { 2192 degrees = 360 + degrees; 2193 } 2194 2195 if (degrees > 270) { 2196 // For acute angles where red is the outer line 2197 // Determine shorter segment (BA or BC) 2198 // On longer segment calculate potential new point (newPt) that is length of smaller segment from B 2199 // If distance between smaller segment end point (A or C) and newPt is smaller than the channel width add newPt to points 2200 // In GetLCPartitions() the black line won't be included between the smaller line and newPt since there isn't enough space to fit the channel 2201 if (lineutility.CalcDistanceDouble(ptB, ptA) < lineutility.CalcDistanceDouble(ptB, ptC)) { 2202 // BA is smaller segment 2203 POINT2 newPt = lineutility.ExtendAlongLineDouble2(ptB, ptC, lineutility.CalcDistanceDouble(ptB, ptA)); 2204 if (lineutility.CalcDistanceDouble(ptA, newPt) < LCChannelWith) { 2205 points.add(i + 2, new POINT2(newPt.x, newPt.y)); 2206 i++; 2207 } 2208 } else { 2209 // BC is smaller segment 2210 POINT2 newPt = lineutility.ExtendAlongLineDouble2(ptB, ptA, lineutility.CalcDistanceDouble(ptB, ptC)); 2211 if (lineutility.CalcDistanceDouble(ptC, newPt) < LCChannelWith) { 2212 points.add(i + 1, new POINT2(newPt.x, newPt.y)); 2213 i++; 2214 } 2215 } 2216 } 2217 } 2218 tg.Pixels = points; 2219 tg.LatLongs = armyc2.c5isr.RenderMultipoints.clsUtility.PixelsToLatLong(points, converter); 2220 } catch (Exception exc) { 2221 ErrorLogger.LogException(_className, "segmentLCPoints", 2222 new RendererException("Failed inside segmentLCPoints", exc)); 2223 } 2224 } 2225 /** 2226 * Interpolate pixels for lines with points too close together. 2227 * Drops successive points until the next point is at least 10 pixels from the preceding point 2228 * @param tg 2229 */ 2230 public static void InterpolatePixels(TGLight tg) 2231 { 2232 try 2233 { 2234 if(tg.get_UseLineInterpolation()==false) 2235 return; 2236 2237 int linetype=tg.get_LineType(); 2238 double glyphSize=10; 2239 switch(linetype) 2240 { 2241 case TacticalLines.ATDITCH: 2242 case TacticalLines.ATDITCHC: 2243 glyphSize=25; 2244 break; 2245 case TacticalLines.ATDITCHM: 2246 glyphSize=50; 2247 break; 2248 case TacticalLines.FLOT: 2249 case TacticalLines.LC: 2250 case TacticalLines.FORT_REVD: 2251 case TacticalLines.FORT: 2252 case TacticalLines.FORTL: 2253 case TacticalLines.ENCIRCLE: 2254 case TacticalLines.ZONE: 2255 case TacticalLines.OBSFAREA: 2256 case TacticalLines.OBSAREA: 2257 case TacticalLines.DOUBLEA: 2258 case TacticalLines.LWFENCE: 2259 case TacticalLines.HWFENCE: 2260 case TacticalLines.BBS_LINE: 2261 case TacticalLines.SINGLEC: 2262 case TacticalLines.DOUBLEC: 2263 case TacticalLines.TRIPLE: 2264 case TacticalLines.STRONG: 2265 glyphSize= arraysupport.getScaledSize(30, tg.get_LineThickness(), tg.get_patternScale()); 2266 break; 2267 case TacticalLines.UNSP: 2268 case TacticalLines.LINE: 2269 case TacticalLines.ATWALL: 2270 case TacticalLines.SFENCE: 2271 glyphSize=arraysupport.getScaledSize(40, tg.get_LineThickness(), tg.get_patternScale()); 2272 break; 2273 case TacticalLines.DFENCE: 2274 glyphSize=arraysupport.getScaledSize(50, tg.get_LineThickness(), tg.get_patternScale()); 2275 break; 2276 default: 2277 return; 2278 } 2279 HashMap<Integer,POINT2> hmapPixels=new HashMap<Integer,POINT2>(); 2280 HashMap<Integer,POINT2> hmapGeo=new HashMap<Integer,POINT2>(); 2281 int j=0,currentIndex=0; 2282 double dist=0,dist2=0; 2283 double direction1=0,direction2=0,delta=0; 2284 POINT2 pt0=null,pt1=null,pt2=null; 2285 int n=tg.Pixels.size(); 2286 //for(j=0;j<tg.Pixels.size();j++) 2287 for(j=0;j<n;j++) 2288 { 2289 if(j==0) 2290 { 2291 hmapPixels.put(j, tg.Pixels.get(j)); 2292 hmapGeo.put(j, tg.LatLongs.get(j)); 2293 currentIndex=0; 2294 } 2295 else if(j==tg.Pixels.size()-1) 2296 { 2297 hmapPixels.put(j, tg.Pixels.get(j)); 2298 hmapGeo.put(j, tg.LatLongs.get(j)); 2299 } 2300 else 2301 { 2302 dist=lineutility.CalcDistanceDouble(tg.Pixels.get(currentIndex), tg.Pixels.get(j)); 2303 dist2=lineutility.CalcDistanceDouble(tg.Pixels.get(j), tg.Pixels.get(j+1)); 2304 2305 //change of direction test 2-28-13 2306 pt0=tg.Pixels.get(currentIndex); 2307 pt1=tg.Pixels.get(j); 2308 pt2=tg.Pixels.get(j+1); 2309 direction1=(180/Math.PI)*Math.atan((pt0.y-pt1.y)/(pt0.x-pt1.x)); 2310 direction2=(180/Math.PI)*Math.atan((pt1.y-pt2.y)/(pt1.x-pt2.x)); 2311 delta=Math.abs(direction1-direction2); 2312 if(dist>glyphSize || dist2>glyphSize || delta>20) 2313 { 2314 hmapPixels.put(j, tg.Pixels.get(j)); 2315 hmapGeo.put(j, tg.LatLongs.get(j)); 2316 currentIndex=j; 2317 } 2318 } 2319 } 2320 ArrayList<POINT2>pixels=new ArrayList(); 2321 ArrayList<POINT2>geo=new ArrayList(); 2322 n=tg.Pixels.size(); 2323 //for(j=0;j<tg.Pixels.size();j++) 2324 for(j=0;j<n;j++) 2325 { 2326 if(hmapPixels.containsKey(j)) 2327 pixels.add((POINT2)hmapPixels.get(j)); 2328 if(hmapGeo.containsKey(j)) 2329 geo.add((POINT2)hmapGeo.get(j)); 2330 } 2331 switch(linetype) 2332 { 2333 case TacticalLines.FORT_REVD: 2334 case TacticalLines.FORT: 2335 case TacticalLines.ENCIRCLE: 2336 case TacticalLines.ZONE: 2337 case TacticalLines.OBSFAREA: 2338 case TacticalLines.OBSAREA: 2339 case TacticalLines.STRONG: 2340 if(pixels.size()==2) 2341 { 2342 n=tg.Pixels.size(); 2343 //for(j=0;j<tg.Pixels.size();j++) 2344 for(j=0;j<n;j++) 2345 { 2346 if(hmapPixels.containsKey(j)==false && hmapGeo.containsKey(j)==false) 2347 { 2348 pixels.add(j,tg.Pixels.get(j)); 2349 geo.add(j,tg.LatLongs.get(j)); 2350 break; 2351 } 2352 } 2353 } 2354 break; 2355 default: 2356 break; 2357 } 2358 tg.Pixels=pixels; 2359 tg.LatLongs=geo; 2360 } 2361 catch (Exception exc) { 2362 ErrorLogger.LogException(_className, "InterpolatePixels", 2363 new RendererException("Failed inside InterpolatePixels", exc)); 2364 } 2365 } 2366 /** 2367 * construct a line segment outside the polygon corresponding to some index 2368 * @param tg 2369 * @param index 2370 * @param dist 2371 * @return 2372 */ 2373 protected static Line2D getExtendedLine(TGLight tg, 2374 int index, 2375 double dist) 2376 { 2377 Line2D line=null; 2378 try 2379 { 2380 Polygon polygon=new Polygon(); 2381 int j=0; 2382 int n=tg.Pixels.size(); 2383 //for(j=0;j<tg.Pixels.size();j++) 2384 for(j=0;j<n;j++) 2385 { 2386 polygon.addPoint((int)tg.Pixels.get(j).x, (int)tg.Pixels.get(j).y); 2387 } 2388 POINT2 pt0=null; 2389 POINT2 pt1=null; 2390 if(tg.Pixels.size()>3) 2391 { 2392 pt0=tg.Pixels.get(index); 2393 pt1=tg.Pixels.get(index+1); 2394 } 2395 else 2396 { 2397 pt0=tg.Pixels.get(1); 2398 pt1=tg.Pixels.get(2); 2399 } 2400 2401 POINT2 ptExtend=null; 2402 int extend=-1; 2403 POINT2 midPt=lineutility.MidPointDouble(pt0, pt1,0); 2404 double slope=Math.abs(pt1.y-pt0.y)/(pt1.x-pt0.x); 2405 if(slope<=1) 2406 { 2407 ptExtend=lineutility.ExtendDirectedLine(pt0, pt1, midPt, lineutility.extend_above, 2); 2408 if(polygon.contains(ptExtend.x,ptExtend.y)) 2409 extend=lineutility.extend_below; 2410 else 2411 extend=lineutility.extend_above; 2412 } 2413 else 2414 { 2415 ptExtend=lineutility.ExtendDirectedLine(pt0, pt1, midPt, lineutility.extend_left, 2); 2416 if(polygon.contains(ptExtend.x,ptExtend.y)) 2417 extend=lineutility.extend_right; 2418 else 2419 extend=lineutility.extend_left; 2420 2421 } 2422 POINT2 pt3=null; 2423 POINT2 pt4=null; 2424 pt3=lineutility.ExtendDirectedLine(pt0, pt1, pt0, extend, dist); 2425 pt4=lineutility.ExtendDirectedLine(pt0, pt1, pt1, extend, dist); 2426 line=new Line2D.Double(pt3.x, pt3.y, pt4.x, pt4.y); 2427 } 2428 catch (Exception exc) { 2429 ErrorLogger.LogException(_className, "getExtendedLine", 2430 new RendererException("Failed inside getExtendedLine", exc)); 2431 } 2432 return line; 2433 } 2434 2435}//end clsUtility