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