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