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