001package armyc2.c5isr.JavaTacticalRenderer; 002 003import static armyc2.c5isr.JavaTacticalRenderer.clsUtility.GetLinetypeFromString; 004 005import android.graphics.Bitmap; 006 007import java.util.ArrayList; 008import java.util.HashMap; 009import java.util.Map; 010 011import armyc2.c5isr.JavaLineArray.Channels; 012import armyc2.c5isr.JavaLineArray.POINT2; 013import armyc2.c5isr.JavaLineArray.Shape2; 014import armyc2.c5isr.JavaLineArray.TacticalLines; 015import armyc2.c5isr.JavaLineArray.arraysupport; 016import armyc2.c5isr.JavaLineArray.lineutility; 017import armyc2.c5isr.graphics2d.AffineTransform; 018import armyc2.c5isr.graphics2d.BasicStroke; 019import armyc2.c5isr.graphics2d.BufferedImage; 020import armyc2.c5isr.graphics2d.Font; 021import armyc2.c5isr.graphics2d.FontMetrics; 022import armyc2.c5isr.graphics2d.FontRenderContext; 023import armyc2.c5isr.graphics2d.Graphics2D; 024import armyc2.c5isr.graphics2d.Line2D; 025import armyc2.c5isr.graphics2d.PathIterator; 026import armyc2.c5isr.graphics2d.Point; 027import armyc2.c5isr.graphics2d.Point2D; 028import armyc2.c5isr.graphics2d.Polygon; 029import armyc2.c5isr.graphics2d.Rectangle2D; 030import armyc2.c5isr.graphics2d.Shape; 031import armyc2.c5isr.graphics2d.TextLayout; 032import armyc2.c5isr.renderer.SinglePointRenderer; 033import armyc2.c5isr.renderer.utilities.Color; 034import armyc2.c5isr.renderer.utilities.EntityCode; 035import armyc2.c5isr.renderer.utilities.ErrorLogger; 036import armyc2.c5isr.renderer.utilities.IPointConversion; 037import armyc2.c5isr.renderer.utilities.ImageInfo; 038import armyc2.c5isr.renderer.utilities.MilStdAttributes; 039import armyc2.c5isr.renderer.utilities.RendererException; 040import armyc2.c5isr.renderer.utilities.RendererSettings; 041import armyc2.c5isr.renderer.utilities.RendererUtilities; 042import armyc2.c5isr.renderer.utilities.ShapeInfo; 043import armyc2.c5isr.renderer.utilities.SymbolID; 044 045/** 046 * This class handles everything having to do with text for a 047 * tactical graphic. Note: labels are handled the same as text modifiers. 048 * 049 */ 050public class Modifier2 { 051 private POINT2[] textPath; 052 private String textID; 053 private String featureID; 054 private String text; 055 056 private Bitmap image; 057 private int iteration; 058 private int justify; 059 private int type; 060 private double lineFactor; 061 private static final String _className = "Modifier2"; 062 @Deprecated 063 private boolean isIntegral = false; 064 private boolean fitsMBR = true; 065 066 Modifier2() { 067 textPath = new POINT2[2]; 068 } 069 070 private static final int toEnd = 1; // Put next to pt0 on opposite side of line 071 private static final int aboveMiddle = 2; //use both points 072 private static final int area = 3; //use one point 073 private static final int screen = 4; //use one point, screen, cover, guard points 074 private static final int aboveEnd = 5; // Put next to pt0 on line 075 private static final int aboveMiddlePerpendicular = 6; //use both points 076 private static final int aboveStartInside = 7; //place at the start inside the shape 077 private static final int aboveEndInside = 8; //place at the end inside the shape 078 private static final int areaImage = 9; //use one point 079 private static double fillAlphaCanObscureText = 50d; 080 081 private static boolean DoublesBack(POINT2 pt0, POINT2 pt1, POINT2 pt2) { 082 boolean result = true; 083 try { 084 double theta1 = Math.atan2(pt2.y - pt1.y, pt2.x - pt1.x); 085 double theta0 = Math.atan2(pt0.y - pt1.y, pt0.x - pt1.x); 086 double beta = Math.abs(theta0 - theta1); 087 if (beta > 0.1) { 088 result = false; 089 } 090 091 } catch (Exception exc) { 092 ErrorLogger.LogException(_className, "DoublesBack", 093 new RendererException("Failed inside DoublesBack", exc)); 094 } 095 return result; 096 } 097 098 /** 099 * Returns a generic label for the symbol per Mil-Std-2525 100 * 101 * @param tg 102 * @return 103 */ 104 private static String GetCenterLabel(TGLight tg) { 105 String label = ""; 106 try { 107 switch (tg.get_LineType()) { 108 case TacticalLines.SHIP_AOI_RECTANGULAR: 109 case TacticalLines.SHIP_AOI_CIRCULAR: 110 label = "AOI"; 111 break; 112 case TacticalLines.DEFENDED_AREA_RECTANGULAR: 113 case TacticalLines.DEFENDED_AREA_CIRCULAR: 114 label = "DA"; 115 break; 116 case TacticalLines.NOTACK: 117 label = "N"; 118 break; 119 case TacticalLines.LAUNCH_AREA: 120 label = "LA"; 121 break; 122 case TacticalLines.SL: 123 label = "SL"; 124 break; 125 case TacticalLines.TC: 126 label = "TC"; 127 break; 128 case TacticalLines.AARROZ: 129 label = "AARROZ"; 130 break; 131 case TacticalLines.UAROZ: 132 label = "UAROZ"; 133 break; 134 case TacticalLines.WEZ: 135 label = "WEZ"; 136 break; 137 case TacticalLines.FEZ: 138 label = "FEZ"; 139 break; 140 case TacticalLines.JEZ: 141 label = "JEZ"; 142 break; 143 case TacticalLines.IFF_OFF: 144 label = "IFF OFF"; 145 break; 146 case TacticalLines.IFF_ON: 147 label = "IFF ON"; 148 break; 149 case TacticalLines.BCL_REVD: 150 case TacticalLines.BCL: 151 label = "BCL"; 152 break; 153 case TacticalLines.ICL: 154 label = "ICL"; 155 break; 156 case TacticalLines.FEBA: 157 label = "FEBA"; 158 break; 159 case TacticalLines.BDZ: 160 label = "BDZ"; 161 break; 162 case TacticalLines.JTAA: 163 label = "JTAA"; 164 break; 165 case TacticalLines.SAA: 166 label = "SAA"; 167 break; 168 case TacticalLines.SGAA: 169 label = "SGAA"; 170 break; 171 case TacticalLines.ASSAULT: 172 label = "ASLT"; 173 break; 174 case TacticalLines.SAAFR: 175 label = "SAAFR"; 176 break; 177 case TacticalLines.AC: 178 label = "AC"; 179 break; 180 case TacticalLines.SECURE: 181 case TacticalLines.SEIZE: 182 label = "S"; 183 break; 184 case TacticalLines.RETAIN: 185 label = "R"; 186 break; 187 case TacticalLines.PENETRATE: 188 label = "P"; 189 break; 190 case TacticalLines.OCCUPY: 191 label = "O"; 192 break; 193 case TacticalLines.ISOLATE: 194 label = "I"; 195 break; 196 case TacticalLines.FIX: 197 label = "F"; 198 break; 199 case TacticalLines.DISRUPT: 200 label = "D"; 201 break; 202 case TacticalLines.CANALIZE: 203 case TacticalLines.CLEAR: 204 label = "C"; 205 break; 206 case TacticalLines.BREACH: 207 case TacticalLines.BYPASS: 208 label = "B"; 209 break; 210 case TacticalLines.CORDONKNOCK: 211 label = "C/K"; 212 break; 213 case TacticalLines.CORDONSEARCH: 214 label = "C/S"; 215 break; 216 case TacticalLines.UXO: 217 label = "UXO"; 218 break; 219 case TacticalLines.RETIRE: 220 label = "R"; 221 break; 222 case TacticalLines.FPOL: 223 label = "P(F)"; 224 break; 225 case TacticalLines.RPOL: 226 label = "P(R)"; 227 break; 228 case TacticalLines.BRDGHD: 229 case TacticalLines.BRDGHD_GE: 230 if (SymbolID.getVersion(tg.get_SymbolId()) >= SymbolID.Version_2525E) 231 label = "BL"; 232 else 233 label = "B"; 234 break; 235 case TacticalLines.HOLD: 236 case TacticalLines.HOLD_GE: 237 //label="HOLDING LINE"; 238 label = "HL"; 239 break; 240 case TacticalLines.PL: 241 label = "PL"; 242 break; 243 case TacticalLines.LL: 244 label = "LL"; 245 break; 246 case TacticalLines.EWL: 247 label = "EWL"; 248 break; 249 case TacticalLines.SCREEN: 250 label = "S"; 251 break; 252 case TacticalLines.COVER: 253 label = "C"; 254 break; 255 case TacticalLines.GUARD: 256 label = "G"; 257 break; 258 case TacticalLines.RIP: 259 label = "RIP"; 260 break; 261 case TacticalLines.WITHDRAW: 262 label = "W"; 263 break; 264 case TacticalLines.WDRAWUP: 265 label = "WP"; 266 break; 267 case TacticalLines.CATK: 268 case TacticalLines.CATKBYFIRE: 269 label = "CATK"; 270 break; 271 case TacticalLines.FLOT: 272 label = "FLOT"; 273 break; 274 case TacticalLines.LC: 275 label = "LC"; 276 break; 277 case TacticalLines.ASSY: 278 label = "AA"; 279 break; 280 case TacticalLines.EA: 281 label = "EA"; 282 break; 283 case TacticalLines.DZ: 284 label = "DZ"; 285 break; 286 case TacticalLines.EZ: 287 label = "EZ"; 288 break; 289 case TacticalLines.LZ: 290 label = "LZ"; 291 break; 292 case TacticalLines.LAA: 293 label = "LAA"; 294 break; 295 case TacticalLines.PZ: 296 label = "PZ"; 297 break; 298 case TacticalLines.MRR: 299 label = "MRR"; 300 break; 301 case TacticalLines.SC: 302 label = "SC"; 303 break; 304 case TacticalLines.LLTR: 305 label = "LLTR"; 306 break; 307 case TacticalLines.ROZ: 308 label = "ROZ"; 309 break; 310 case TacticalLines.FAADZ: 311 label = "SHORADEZ"; 312 break; 313 case TacticalLines.HIDACZ: 314 label = "HIDACZ"; 315 break; 316 case TacticalLines.MEZ: 317 label = "MEZ"; 318 break; 319 case TacticalLines.LOMEZ: 320 label = "LOMEZ"; 321 break; 322 case TacticalLines.HIMEZ: 323 label = "HIMEZ"; 324 break; 325 case TacticalLines.WFZ: 326 label = "WFZ"; 327 break; 328 case TacticalLines.MINED: 329 case TacticalLines.FENCED: 330 label = "M"; 331 break; 332 case TacticalLines.PNO: 333 label = "(P)"; 334 break; 335 case TacticalLines.OBJ: 336 label = "OBJ"; 337 break; 338 case TacticalLines.NAI: 339 label = "NAI"; 340 break; 341 case TacticalLines.TAI: 342 label = "TAI"; 343 break; 344 case TacticalLines.BASE_CAMP_REVD: 345 case TacticalLines.BASE_CAMP: 346 label = "BC"; 347 break; 348 case TacticalLines.GUERILLA_BASE_REVD: 349 case TacticalLines.GUERILLA_BASE: 350 label = "GB"; 351 break; 352 case TacticalLines.LINTGTS: 353 label = "SMOKE"; 354 break; 355 case TacticalLines.FPF: 356 label = "FPF"; 357 break; 358 case TacticalLines.ATKPOS: 359 label = "ATK"; 360 break; 361 case TacticalLines.FCL: 362 label = "FCL"; 363 break; 364 case TacticalLines.LOA: 365 label = "LOA"; 366 break; 367 case TacticalLines.LOD: 368 label = "LD"; 369 break; 370 case TacticalLines.PLD: 371 label = "PLD"; 372 break; 373 case TacticalLines.DELAY: 374 label = "D"; 375 break; 376 case TacticalLines.RELEASE: 377 label = "RL"; 378 break; 379 case TacticalLines.HOL: 380 label = "HOL"; 381 break; 382 case TacticalLines.BHL: 383 label = "BHL"; 384 break; 385 case TacticalLines.SMOKE: 386 label = "SMOKE"; 387 break; 388 case TacticalLines.NFL: 389 label = "NFL"; 390 break; 391 case TacticalLines.MFP: 392 label = "MFP"; 393 break; 394 case TacticalLines.FSCL: 395 label = "FSCL"; 396 break; 397 case TacticalLines.CFL: 398 label = "CFL"; 399 break; 400 case TacticalLines.RFL: 401 label = "RFL"; 402 break; 403 case TacticalLines.AO: 404 label = "AO"; 405 break; 406 case TacticalLines.BOMB: 407 label = "BOMB"; 408 break; 409 case TacticalLines.TGMF: 410 label = "TGMF"; 411 break; 412 case TacticalLines.FSA: 413 label = "FSA"; 414 break; 415 case TacticalLines.FSA_CIRCULAR: 416 case TacticalLines.FSA_RECTANGULAR: 417 label = "FSA"; 418 break; 419 case TacticalLines.ACA: 420 case TacticalLines.ACA_CIRCULAR: 421 case TacticalLines.ACA_RECTANGULAR: 422 label = "ACA"; 423 break; 424 case TacticalLines.FFA: 425 case TacticalLines.FFA_CIRCULAR: 426 case TacticalLines.FFA_RECTANGULAR: 427 label = "FFA"; 428 break; 429 case TacticalLines.NFA: 430 case TacticalLines.NFA_CIRCULAR: 431 case TacticalLines.NFA_RECTANGULAR: 432 label = "NFA"; 433 break; 434 case TacticalLines.RFA: 435 case TacticalLines.RFA_CIRCULAR: 436 case TacticalLines.RFA_RECTANGULAR: 437 label = "RFA"; 438 break; 439 case TacticalLines.ATI: 440 case TacticalLines.ATI_CIRCULAR: 441 case TacticalLines.ATI_RECTANGULAR: 442 label = "ATI ZONE"; 443 break; 444 case TacticalLines.PAA: 445 case TacticalLines.PAA_CIRCULAR: 446 case TacticalLines.PAA_RECTANGULAR: 447 label = "PAA"; 448 break; 449 case TacticalLines.CFFZ: 450 case TacticalLines.CFFZ_CIRCULAR: 451 case TacticalLines.CFFZ_RECTANGULAR: 452 label = "CFF ZONE"; 453 break; 454 case TacticalLines.CFZ: 455 case TacticalLines.CFZ_CIRCULAR: 456 case TacticalLines.CFZ_RECTANGULAR: 457 label = "CF ZONE"; 458 break; 459 case TacticalLines.SENSOR: 460 case TacticalLines.SENSOR_CIRCULAR: 461 case TacticalLines.SENSOR_RECTANGULAR: 462 label = "SENSOR ZONE"; 463 break; 464 case TacticalLines.CENSOR: 465 case TacticalLines.CENSOR_CIRCULAR: 466 case TacticalLines.CENSOR_RECTANGULAR: 467 label = "CENSOR ZONE"; 468 break; 469 case TacticalLines.DA: 470 case TacticalLines.DA_CIRCULAR: 471 case TacticalLines.DA_RECTANGULAR: 472 label = "DA"; 473 break; 474 case TacticalLines.ZOR: 475 case TacticalLines.ZOR_CIRCULAR: 476 case TacticalLines.ZOR_RECTANGULAR: 477 label = "ZOR"; 478 break; 479 case TacticalLines.TBA: 480 case TacticalLines.TBA_CIRCULAR: 481 case TacticalLines.TBA_RECTANGULAR: 482 label = "TBA"; 483 break; 484 case TacticalLines.TVAR: 485 case TacticalLines.TVAR_CIRCULAR: 486 case TacticalLines.TVAR_RECTANGULAR: 487 label = "TVAR"; 488 break; 489 case TacticalLines.KILLBOXBLUE: 490 case TacticalLines.KILLBOXBLUE_CIRCULAR: 491 case TacticalLines.KILLBOXBLUE_RECTANGULAR: 492 label = "BKB"; 493 break; 494 case TacticalLines.KILLBOXPURPLE: 495 case TacticalLines.KILLBOXPURPLE_CIRCULAR: 496 case TacticalLines.KILLBOXPURPLE_RECTANGULAR: 497 label = "PKB"; 498 break; 499 case TacticalLines.MSR: 500 case TacticalLines.MSR_ONEWAY: 501 case TacticalLines.MSR_TWOWAY: 502 case TacticalLines.MSR_ALT: 503 label = "MSR"; 504 break; 505 case TacticalLines.ASR: 506 case TacticalLines.ASR_ONEWAY: 507 case TacticalLines.ASR_TWOWAY: 508 case TacticalLines.ASR_ALT: 509 label = "ASR"; 510 break; 511 case TacticalLines.ROUTE: 512 case TacticalLines.ROUTE_ONEWAY: 513 case TacticalLines.ROUTE_ALT: 514 label = "ROUTE"; 515 break; 516 case TacticalLines.LDLC: 517 label = "LD/LC"; 518 break; 519 case TacticalLines.AIRHEAD: 520 label = "AIRHEAD LINE"; 521 break; 522 case TacticalLines.BLOCK: 523 case TacticalLines.BEARING: 524 label = "B"; 525 break; 526 case TacticalLines.BEARING_J: 527 label = "J"; 528 break; 529 case TacticalLines.BEARING_RDF: 530 label = "RDF"; 531 break; 532 case TacticalLines.ELECTRO: 533 label = "E"; 534 break; 535 case TacticalLines.BEARING_EW: 536 label = "EW"; 537 break; 538 case TacticalLines.ACOUSTIC: 539 case TacticalLines.ACOUSTIC_AMB: 540 label = "A"; 541 break; 542 case TacticalLines.TORPEDO: 543 label = "T"; 544 break; 545 case TacticalLines.OPTICAL: 546 label = "O"; 547 break; 548 case TacticalLines.DHA: 549 label = "DHA"; 550 break; 551 case TacticalLines.FARP: 552 label = "FARP"; 553 break; 554 case TacticalLines.BSA: 555 label = "BSA"; 556 break; 557 case TacticalLines.DSA: 558 label = "DSA"; 559 break; 560 case TacticalLines.CSA: 561 label = "CSA"; 562 break; 563 case TacticalLines.RSA: 564 label = "RSA"; 565 break; 566 case TacticalLines.CONTAIN: 567 label = "C"; 568 break; 569 case TacticalLines.OBSFAREA: 570 label = "FREE"; 571 break; 572 default: 573 break; 574 } 575 } catch (Exception exc) { 576 //clsUtility.WriteFile("Error in Modifier2.GetCenterLabel"); 577 ErrorLogger.LogException(_className, "GetCenterLabel", 578 new RendererException("Failed inside GetCenterLabel", exc)); 579 } 580 return label; 581 } 582 //non CPOF clients using best fit need these accessors 583 584 public POINT2[] get_TextPath() { 585 return textPath; 586 } 587 588 protected void set_TextPath(POINT2[] value) { 589 textPath = value; 590 } 591 592 @Deprecated 593 protected void set_IsIntegral(boolean value) { 594 isIntegral = value; 595 } 596 597 @Deprecated 598 protected boolean get_IsIntegral() { 599 return isIntegral; 600 } 601 602 private static void AddOffsetModifier(TGLight tg, 603 String text, 604 int type, 605 double lineFactor, 606 int startIndex, 607 int endIndex, 608 double spaces, 609 String rightOrLeft) { 610 if (rightOrLeft == null || tg.Pixels == null || tg.Pixels.size() < 2 || endIndex >= tg.Pixels.size()) { 611 return; 612 } 613 614 POINT2 pt0 = tg.Pixels.get(startIndex); 615 POINT2 pt1 = tg.Pixels.get(endIndex); 616 if (rightOrLeft.equals("left")) { 617 pt0.x -= spaces; 618 pt1.x -= spaces; 619 } else { 620 pt0.x += spaces; 621 pt1.x += spaces; 622 } 623 AddModifier2(tg, text, type, lineFactor, pt0, pt1, false); 624 } 625 626 /** 627 * 628 * @param tg 629 * @param text 630 * @param type 631 * @param lineFactor 632 * @param ptStart 633 * @param ptEnd 634 */ 635 private static void AddModifier(TGLight tg, 636 String text, 637 int type, 638 double lineFactor, 639 POINT2 ptStart, 640 POINT2 ptEnd) { 641 if (tg.Pixels == null || tg.Pixels.size() < 2) { 642 return; 643 } 644 AddModifier2(tg, text, type, lineFactor, ptStart, ptEnd, false); 645 } 646 647 private static void AddModifier2(TGLight tg, 648 String text, 649 int type, 650 double lineFactor, 651 POINT2 pt0, 652 POINT2 pt1, 653 boolean isIntegral) { 654 AddModifier2(tg, text, type, lineFactor, pt0, pt1, isIntegral, null); 655 } 656 657 private static void AddModifier2(TGLight tg, 658 String text, 659 int type, 660 double lineFactor, 661 POINT2 pt0, 662 POINT2 pt1, 663 boolean isIntegral, 664 String modifierType) { 665 try { 666 if (text == null || text.equals("")) { 667 return; 668 } 669 670 Modifier2 modifier = new Modifier2(); 671 modifier.set_IsIntegral(isIntegral); 672 modifier.text = text; 673 modifier.type = type; 674 modifier.lineFactor = lineFactor; 675 modifier.textPath[0] = pt0; 676 modifier.textPath[1] = pt1; 677 modifier.textID = modifierType; 678 tg.modifiers.add(modifier); 679 } catch (Exception exc) { 680 ErrorLogger.LogException(_className, "AddModifier", 681 new RendererException("Failed inside AddModifier", exc)); 682 } 683 } 684 685 private static void AddIntegralModifier(TGLight tg, 686 String text, 687 int type, 688 double lineFactor, 689 int startIndex, 690 int endIndex) { 691 AddIntegralModifier(tg, text, type, lineFactor, startIndex, endIndex, true); 692 } 693 694 private static void AddIntegralModifier(TGLight tg, 695 String text, 696 int type, 697 double lineFactor, 698 int startIndex, 699 int endIndex, 700 Boolean isIntegral) { 701 AddIntegralModifier(tg, text, type, lineFactor, startIndex, endIndex, isIntegral, null); 702 } 703 704 private static void AddIntegralModifier(TGLight tg, 705 String text, 706 int type, 707 double lineFactor, 708 int startIndex, 709 int endIndex, 710 Boolean isIntegral, 711 String modifierType) { 712 if (tg.Pixels == null || tg.Pixels.isEmpty() || endIndex >= tg.Pixels.size()) { 713 return; 714 } 715 AddIntegralAreaModifier(tg, text, type, lineFactor, tg.Pixels.get(startIndex), tg.Pixels.get(endIndex), isIntegral, modifierType); 716 } 717 718 /** 719 * Creates and adds center modifiers for generic areas 720 * 721 * @param tg 722 * @param text 723 * @param type 724 * @param lineFactor 725 * @param pt0 726 * @param pt1 727 */ 728 private static void AddAreaModifier(TGLight tg, 729 String text, 730 int type, 731 double lineFactor, 732 POINT2 pt0, 733 POINT2 pt1) { 734 AddIntegralAreaModifier(tg, text, type, lineFactor, pt0, pt1, true); 735 } 736 737 /** 738 * sets modifier.textId to the modifier type, e.g. label, T, T1, etc. 739 * 740 * @param tg 741 * @param text 742 * @param type 743 * @param lineFactor 744 * @param pt0 745 * @param pt1 746 * @param modifierType 747 */ 748 private static void AddAreaModifier(TGLight tg, 749 String text, 750 int type, 751 double lineFactor, 752 POINT2 pt0, 753 POINT2 pt1, 754 String modifierType) { 755 AddIntegralAreaModifier(tg, text, type, lineFactor, pt0, pt1, true, modifierType); 756 } 757 758 private static void AddIntegralAreaModifier(TGLight tg, 759 String text, 760 int type, 761 double lineFactor, 762 POINT2 pt0, 763 POINT2 pt1, 764 Boolean isIntegral) { 765 AddIntegralAreaModifier(tg,text,type,lineFactor,pt0, pt1, isIntegral, null); 766 } 767 768 private static void AddIntegralAreaModifier(TGLight tg, 769 Bitmap image, 770 int type, 771 double lineFactor, 772 POINT2 pt0, 773 POINT2 pt1, 774 Boolean isIntegral) { 775 try { 776 if (image == null || image.equals("")) { 777 return; 778 } 779 780 Modifier2 modifier = new Modifier2(); 781 modifier.set_IsIntegral(isIntegral); 782 modifier.image = image; 783 if (image == null || image.equals("")) { 784 return; 785 } 786 787 if (pt0 == null || pt1 == null) { 788 return; 789 } 790 791 modifier.type = type; 792 modifier.lineFactor = lineFactor; 793 modifier.textPath[0] = pt0; 794 modifier.textPath[1] = pt1; 795 tg.modifiers.add(modifier); 796 } catch (Exception exc) { 797 ErrorLogger.LogException(_className, "AddAreaModifier", 798 new RendererException("Failed inside AddAreaModifier", exc)); 799 } 800 } 801 802 private static void AddIntegralAreaModifier(TGLight tg, 803 String text, 804 int type, 805 double lineFactor, 806 POINT2 pt0, 807 POINT2 pt1, 808 Boolean isIntegral, 809 String modifierType) { 810 if (pt0 == null || pt1 == null) { 811 return; 812 } 813 AddModifier2(tg, text, type, lineFactor, pt0, pt1, isIntegral, modifierType); 814 } 815 816 /** 817 * Returns symbol MBR. Assumes points have been initialized with value of 818 * 0th point 819 * 820 * @param tg the tactical graphic object 821 * @param ptUl OUT - MBR upper left 822 * @param ptUr OUT - MBR upper right 823 * @param ptLr OUT - MBR lower right 824 * @param ptLl OUT - MBR lower left 825 */ 826 public static void GetMBR(TGLight tg, 827 POINT2 ptUl, 828 POINT2 ptUr, 829 POINT2 ptLr, 830 POINT2 ptLl) { 831 try { 832 int j = 0; 833 double x = 0; 834 double y = 0; 835 ptUl.x = tg.Pixels.get(0).x; 836 ptUl.y = tg.Pixels.get(0).y; 837 ptUr.x = tg.Pixels.get(0).x; 838 ptUr.y = tg.Pixels.get(0).y; 839 ptLl.x = tg.Pixels.get(0).x; 840 ptLl.y = tg.Pixels.get(0).y; 841 ptLr.x = tg.Pixels.get(0).x; 842 ptLr.y = tg.Pixels.get(0).y; 843 int n = tg.Pixels.size(); 844 //for (j = 1; j < tg.Pixels.size(); j++) 845 for (j = 1; j < n; j++) { 846 x = tg.Pixels.get(j).x; 847 y = tg.Pixels.get(j).y; 848 if (x < ptLl.x) { 849 ptLl.x = x; 850 ptUl.x = x; 851 } 852 if (x > ptLr.x) { 853 ptLr.x = x; 854 ptUr.x = x; 855 } 856 if (y > ptLl.y) { 857 ptLl.y = y; 858 ptLr.y = y; 859 } 860 if (y < ptUl.y) { 861 ptUl.y = y; 862 ptUr.y = y; 863 } 864 } 865 } catch (Exception exc) { 866 ErrorLogger.LogException(_className, "GetMBR", 867 new RendererException("Failed inside GetMBR", exc)); 868 } 869 } 870 871 /** 872 * Tests segment of a Boundary 873 * 874 * @param tg 875 * @param g2d 876 * @param middleSegment 877 * @return 878 */ 879 private static boolean GetBoundarySegmentTooShort(TGLight tg, 880 Graphics2D g2d, 881 int middleSegment) { 882 boolean lineTooShort = false; 883 try { 884 //int middleSegment = tg.Pixels.size() / 2 - 1; 885 g2d.setFont(tg.get_Font()); 886 FontMetrics metrics = g2d.getFontMetrics(); 887 String echelonSymbol = null; 888 int stringWidthEchelonSymbol = 0; 889 890 POINT2 pt0 = tg.Pixels.get(middleSegment); 891 POINT2 pt1 = tg.Pixels.get(middleSegment + 1); 892 double dist = lineutility.CalcDistanceDouble(pt0, pt1); 893 894 echelonSymbol = tg.get_EchelonSymbol(); 895 896 if (echelonSymbol != null) { 897 stringWidthEchelonSymbol = metrics.stringWidth(echelonSymbol); 898 } 899 900 int tWidth = 0, t1Width = 0; 901 if (tg.get_Name() != null && !tg.get_Name().isEmpty()) { 902 tWidth = metrics.stringWidth(tg.get_Name()); 903 } 904 if (tg.get_T1() != null && !tg.get_T1().isEmpty()) { 905 t1Width = metrics.stringWidth(tg.get_T1()); 906 } 907 908 int totalWidth = stringWidthEchelonSymbol; 909 if (totalWidth < tWidth) { 910 totalWidth = tWidth; 911 } 912 if (totalWidth < t1Width) { 913 totalWidth = t1Width; 914 } 915 916 switch (tg.get_LineType()) { 917 case TacticalLines.BOUNDARY: 918 if (dist < 1.25 * (totalWidth)) { 919 lineTooShort = true; 920 } 921 break; 922 default: 923 break; 924 } 925 } catch (Exception exc) { 926 ErrorLogger.LogException(_className, "GetBoundaryLineTooShort", 927 new RendererException("Failed inside GetBoundaryLineTooShort", exc)); 928 } 929 return lineTooShort; 930 } 931 932 /** 933 * Handles the line breaks for Boundary and Engineer Work Line 934 * 935 * @param tg 936 * @param g2d 937 */ 938 private static void AddBoundaryModifiers(TGLight tg, 939 Graphics2D g2d, 940 Object clipBounds) { 941 try { 942 int j = 0; 943 double csFactor = 1d; 944 Boolean foundSegment = false; 945 POINT2 pt0 = null, pt1 = null, ptLast = null; 946 double TLineFactor = 0, T1LineFactor = 0; 947 Boolean lineTooShort = false; 948 String countryCode = ""; 949 if(!tg.get_AS().equals("")) { 950 countryCode = " (" + tg.get_AS() + ")"; 951 } 952 if (tg.get_Client().equals("cpof3d")) { 953 csFactor = 0.85d; 954 } 955 956 int middleSegment = getVisibleMiddleSegment(tg, clipBounds); 957 //for (j = 0; j < tg.Pixels.size() - 1; j++) { 958 for (j = middleSegment; j == middleSegment; j++) { 959 /* if (tg.get_Client().equalsIgnoreCase("ge")) { 960 if (j != middleSegment) { 961 continue; 962 } 963 }*/ 964 965 pt0 = tg.Pixels.get(j); 966 pt1 = tg.Pixels.get(j + 1); 967 if (pt0.x < pt1.x) { 968 TLineFactor = -1.3; 969 T1LineFactor = 1; 970 } else if (pt0.x == pt1.x) { 971 if (pt1.y < pt0.y) { 972 TLineFactor = -1; 973 T1LineFactor = 1; 974 } else { 975 TLineFactor = 1; 976 T1LineFactor = -1; 977 } 978 } else { 979 TLineFactor = 1; 980 T1LineFactor = -1.3; 981 } 982 //is the segment too short? 983 lineTooShort = GetBoundarySegmentTooShort(tg, g2d, j); 984 985 if (lineTooShort == false) { 986 foundSegment = true; 987 AddIntegralModifier(tg, tg.get_Name() + countryCode, aboveMiddle, TLineFactor * csFactor, j, j + 1, true); 988 //the echelon symbol 989 if (tg.get_EchelonSymbol() != null && !tg.get_EchelonSymbol().equals("")) { 990 AddIntegralModifier(tg, tg.get_EchelonSymbol(), aboveMiddle, -0.20 * csFactor, j, j + 1, true); 991 } 992 //the T1 modifier 993 AddIntegralModifier(tg, tg.get_T1(), aboveMiddle, T1LineFactor * csFactor, j, j + 1, true); 994 } 995 }//end for loop 996 if (foundSegment == false) { 997 pt0 = new POINT2(); 998 pt1 = new POINT2(); 999 // Get boundary middle segment 1000 final String echelonSymbol = tg.get_EchelonSymbol(); 1001 final FontMetrics metrics = g2d.getFontMetrics(); 1002 double modDist = 0; 1003 1004 if (echelonSymbol != null) { 1005 modDist = 1.5 * metrics.stringWidth(echelonSymbol); 1006 } 1007 1008 final double segDist = lineutility.CalcDistanceDouble(tg.Pixels.get(middleSegment), tg.Pixels.get(middleSegment + 1)); 1009 1010 g2d.setFont(tg.get_Font()); 1011 POINT2 midpt = lineutility.MidPointDouble(tg.Pixels.get(middleSegment), tg.Pixels.get(middleSegment + 1), 0); 1012 POINT2 ptTemp = null; 1013 if (segDist < modDist) { 1014 ptTemp = lineutility.ExtendAlongLineDouble(midpt, tg.Pixels.get(middleSegment), modDist / 2); 1015 pt0.x = ptTemp.x; 1016 pt0.y = ptTemp.y; 1017 ptTemp = lineutility.ExtendAlongLineDouble(midpt, tg.Pixels.get(middleSegment + 1), modDist / 2); 1018 } else { 1019 ptTemp = tg.Pixels.get(middleSegment); 1020 pt0.x = ptTemp.x; 1021 pt0.y = ptTemp.y; 1022 ptTemp = tg.Pixels.get(middleSegment + 1); 1023 } 1024 pt1.x = ptTemp.x; 1025 pt1.y = ptTemp.y; 1026 1027 AddIntegralModifier(tg, tg.get_Name() + countryCode, aboveMiddle, TLineFactor * csFactor, middleSegment, middleSegment + 1, true); 1028 //the echelon symbol 1029 if (echelonSymbol != null && !echelonSymbol.equals("")) { 1030 AddIntegralModifier(tg, echelonSymbol, aboveMiddle, -0.2020 * csFactor, middleSegment, middleSegment + 1, true); 1031 } 1032 //the T1 modifier 1033 AddIntegralModifier(tg, tg.get_T1(), aboveMiddle, T1LineFactor * csFactor, middleSegment, middleSegment + 1, true); 1034 }//end if foundSegment==false 1035 } catch (Exception exc) { 1036 ErrorLogger.LogException(_className, "AddBoundaryModifiers", 1037 new RendererException("Failed inside AddBoundaryModifiers", exc)); 1038 } 1039 } 1040 1041 /** 1042 * added for USAS 1043 * 1044 * @param tg 1045 * @param metrics 1046 * @deprecated 1047 */ 1048 private static void AddNameAboveDTG(TGLight tg, FontMetrics metrics) { 1049 try { 1050 double csFactor = 1; 1051 if (tg.get_Client().equals("cpof3d")) { 1052 csFactor = 0.667; 1053 } 1054 String label = GetCenterLabel(tg); 1055 POINT2 pt0 = new POINT2(tg.Pixels.get(0)); 1056 POINT2 pt1 = new POINT2(tg.Pixels.get(1)); 1057 int lastIndex = tg.Pixels.size() - 1; 1058 int nextToLastIndex = tg.Pixels.size() - 2; 1059 POINT2 ptLast = new POINT2(tg.Pixels.get(lastIndex)); 1060 POINT2 ptNextToLast = new POINT2(tg.Pixels.get(nextToLastIndex)); 1061 shiftModifierPath(tg, pt0, pt1, ptLast, ptNextToLast); 1062 double stringWidth = metrics.stringWidth(label + " " + tg.get_Name()); 1063 AddIntegralAreaModifier(tg, label + " " + tg.get_Name(), toEnd, 0, pt0, pt1, false); 1064 pt1 = lineutility.ExtendAlongLineDouble(tg.Pixels.get(0), tg.Pixels.get(1), -1.5 * stringWidth); 1065 AddModifier2(tg, tg.get_DTG(), aboveMiddle, 0.7 * csFactor, pt0, pt1, false); 1066 AddModifier2(tg, tg.get_DTG1(), aboveMiddle, 1.7 * csFactor, pt0, pt1, false); 1067 AddIntegralAreaModifier(tg, label + " " + tg.get_Name(), toEnd, 0, ptLast, ptNextToLast, false); 1068 pt0 = tg.Pixels.get(lastIndex); 1069 pt1 = lineutility.ExtendAlongLineDouble(tg.Pixels.get(lastIndex), tg.Pixels.get(nextToLastIndex), -1.5 * stringWidth); 1070 AddModifier2(tg, tg.get_DTG(), aboveMiddle, 0.7 * csFactor, pt0, pt1, false); 1071 AddModifier2(tg, tg.get_DTG1(), aboveMiddle, 1.7 * csFactor, pt0, pt1, false); 1072 } catch (Exception exc) { 1073 ErrorLogger.LogException(_className, "AddNameAboveDTG", 1074 new RendererException("Failed inside AddNameAboveDTG", exc)); 1075 } 1076 } 1077 1078 /** 1079 * shifts the path for modifiers that use toEnd to prevent vertical paths 1080 * 1081 * @param tg 1082 * @param pt0 1083 * @param pt1 1084 * @param ptLast 1085 * @param ptNextToLast 1086 */ 1087 private static void shiftModifierPath(TGLight tg, 1088 POINT2 pt0, 1089 POINT2 pt1, 1090 POINT2 ptLast, 1091 POINT2 ptNextToLast) { 1092 try { 1093 POINT2 p0 = null, p1 = null; 1094 double last = -1.0; 1095 switch (tg.get_LineType()) { 1096 case TacticalLines.BOUNDARY: 1097 for (int j = 0; j < tg.Pixels.size() - 1; j++) { 1098 p0 = tg.Pixels.get(j); 1099 p1 = tg.Pixels.get(j + 1); 1100 //if(p0.x==p1.x) 1101 if (Math.abs(p0.x - p1.x) < 1) { 1102 p1.x += last; 1103 last = -last; 1104 } 1105 } 1106 break; 1107 case TacticalLines.PDF: 1108 case TacticalLines.PL: 1109 case TacticalLines.FEBA: 1110 case TacticalLines.LOA: 1111 case TacticalLines.LOD: 1112 case TacticalLines.RELEASE: 1113 case TacticalLines.HOL: 1114 case TacticalLines.BHL: 1115 case TacticalLines.LDLC: 1116 case TacticalLines.LL: 1117 case TacticalLines.EWL: 1118 case TacticalLines.FCL: 1119 case TacticalLines.PLD: 1120 case TacticalLines.NFL: 1121 case TacticalLines.FLOT: 1122 case TacticalLines.LC: 1123 case TacticalLines.HOLD: 1124 case TacticalLines.BRDGHD: 1125 case TacticalLines.HOLD_GE: 1126 case TacticalLines.BRDGHD_GE: 1127 //if (pt0 != null && pt1 != null && pt0.x == pt1.x) 1128 if (pt0 != null && pt1 != null && Math.abs(pt0.x - pt1.x) < 1) { 1129 pt1.x += 1; 1130 } 1131 //if (ptLast != null && ptNextToLast != null && ptNextToLast.x == ptLast.x) 1132 if (ptLast != null && ptNextToLast != null && Math.abs(ptNextToLast.x - ptLast.x) < 1) { 1133 ptNextToLast.x += 1; 1134 } 1135 break; 1136 default: 1137 return; 1138 } 1139 } catch (Exception exc) { 1140 ErrorLogger.LogException(_className, "shiftModifierPath", 1141 new RendererException("Failed inside shiftModifierPath", exc)); 1142 } 1143 } 1144 1145 /** 1146 * Adds label on line 1147 * 1148 * Replaces areasWithENY() 1149 * 1150 * @param label 1151 * @param tg 1152 * @param g2d 1153 * @param twoLabelOnly - true if only add two instances of label to line (used with N modifier) 1154 * Ignored if RendererSettings.TwoLabelOnly is true 1155 */ 1156 private static void addModifierOnLine(String label, TGLight tg, Graphics2D g2d, boolean twoLabelOnly) { 1157 if (label == null || label.isEmpty()) { 1158 return; 1159 } 1160 try { 1161 if (!RendererSettings.getInstance().getTwoLabelOnly() && !twoLabelOnly) { 1162 FontMetrics metrics = g2d.getFontMetrics(); 1163 final int stringWidth = metrics.stringWidth(label); 1164 boolean foundLongSegment = false; 1165 1166 for (int j = 0; j < tg.Pixels.size() - 1; j++) { 1167 POINT2 pt0 = tg.Pixels.get(j); 1168 POINT2 pt1 = tg.Pixels.get(j + 1); 1169 double dist = lineutility.CalcDistanceDouble(pt0, pt1); 1170 if (dist > 1.5 * stringWidth) { 1171 foundLongSegment = true; 1172 AddIntegralAreaModifier(tg, label, aboveMiddle, 0, pt0, pt1, false); 1173 } 1174 } 1175 if (!foundLongSegment) { 1176 // did not find a long enough segment 1177 int middleSegment = tg.Pixels.size() / 2 - 1; 1178 int middleSegment2 = tg.Pixels.size() - 2; 1179 if (tg.Pixels.size() > 3) { 1180 middleSegment = tg.Pixels.size() / 4; 1181 middleSegment2 = 3 * tg.Pixels.size() / 4; 1182 } 1183 if (middleSegment != 0) { 1184 AddIntegralModifier(tg, label, aboveMiddle, 0, middleSegment, middleSegment + 1, false); 1185 } 1186 AddIntegralModifier(tg, label, aboveMiddle, 0, middleSegment2, middleSegment2 + 1, false); 1187 } 1188 } else if (tg.Pixels.size() > 0) { 1189 // 2 labels one to the left and the other to the right of graphic. 1190 POINT2 leftPt = lineutility.MidPointDouble(tg.Pixels.get(0), tg.Pixels.get(1), 0); 1191 POINT2 rightPt = lineutility.MidPointDouble(tg.Pixels.get(0), tg.Pixels.get(1), 0); 1192 1193 for (int j = 1; j < tg.Pixels.size() - 1; j++) { 1194 POINT2 midPt = lineutility.MidPointDouble(tg.Pixels.get(j), tg.Pixels.get(j + 1), 0); 1195 if (midPt.x <= leftPt.x) { 1196 leftPt = midPt; 1197 } 1198 if (midPt.x >= rightPt.x) { 1199 rightPt = midPt; 1200 } 1201 } 1202 1203 if (leftPt != rightPt) 1204 AddAreaModifier(tg, label, aboveMiddle, 0, leftPt, leftPt); 1205 AddAreaModifier(tg, label, aboveMiddle, 0, rightPt, rightPt); 1206 } 1207 } catch (Exception exc) { 1208 ErrorLogger.LogException(_className, "addModifierOnLine", 1209 new RendererException("Failed inside addModifierOnLine", exc)); 1210 } 1211 } 1212 1213 private static void addModifierOnLine(String label, TGLight tg, Graphics2D g2d) { 1214 addModifierOnLine(label, tg, g2d, false); 1215 } 1216 1217 /** 1218 * Adds N modifier on line 1219 */ 1220 private static void addNModifier(TGLight tg, Graphics2D g2d) { 1221 if (tg.isHostile()) { 1222 addModifierOnLine(tg.get_N(), tg, g2d, true); 1223 } 1224 } 1225 1226 private static void addModifierBottomSegment(TGLight tg, String text) { 1227 int index = 0; 1228 double y = tg.Pixels.get(index).y + tg.Pixels.get(index + 1).y; 1229 for (int i = 1; i < tg.Pixels.size() - 1; i++) { 1230 if (tg.Pixels.get(i).y + tg.Pixels.get(i + 1).y > y) { 1231 index = i; 1232 y = tg.Pixels.get(index).y + tg.Pixels.get(index + 1).y; 1233 } 1234 } 1235 AddIntegralModifier(tg, text, aboveMiddle, 0, index, index + 1, false); 1236 } 1237 1238 private static void addModifierTopSegment(TGLight tg, String text) { 1239 int index = 0; 1240 double y = tg.Pixels.get(index).y + tg.Pixels.get(index + 1).y; 1241 for (int i = 1; i < tg.Pixels.size() - 1; i++) { 1242 if (tg.Pixels.get(i).y + tg.Pixels.get(i + 1).y < y) { 1243 index = i; 1244 y = tg.Pixels.get(index).y + tg.Pixels.get(index + 1).y; 1245 } 1246 } 1247 AddIntegralModifier(tg, text, aboveMiddle, 0, index, index + 1, false); 1248 } 1249 1250 private static void addDTG(TGLight tg, int type, double lineFactor1, double lineFactor2, POINT2 pt0, POINT2 pt1, FontMetrics metrics) { 1251 if (pt0 == null || pt1 == null) 1252 return; 1253 1254 double maxDTGWidth; 1255 if (pt0.x == pt1.x && pt0.y == pt1.y) { 1256 POINT2 ptUl = new POINT2(), ptUr = new POINT2(), ptLr = new POINT2(), ptLl = new POINT2(); 1257 GetMBR(tg, ptUl, ptUr, ptLr, ptLl); 1258 maxDTGWidth = lineutility.CalcDistanceDouble(ptUl, ptUr); 1259 } else { 1260 maxDTGWidth = lineutility.CalcDistanceDouble(pt0, pt1); 1261 } 1262 1263 String dash = ""; 1264 if (tg.get_DTG() != null && tg.get_DTG1() != null && !tg.get_DTG().isEmpty() && !tg.get_DTG1().isEmpty()) { 1265 dash = " - "; 1266 } 1267 1268 String combinedDTG = tg.get_DTG() + dash + tg.get_DTG1(); 1269 1270 double stringWidth = metrics.stringWidth(combinedDTG); 1271 1272 if (stringWidth < maxDTGWidth) { 1273 // Add on one line 1274 AddModifier(tg, combinedDTG, type, lineFactor1, pt0, pt1); 1275 } else { 1276 // add on two lines 1277 // Use min and max on lineFactors. Always want W1 on top. This fixes when lineFactor < 0 W1 should use lineFactor1 1278 AddModifier(tg, tg.get_DTG() + dash, type, Math.min(lineFactor1, lineFactor2), pt0, pt1); 1279 AddModifier(tg, tg.get_DTG1(), type, Math.max(lineFactor1, lineFactor2), pt0, pt1); 1280 } 1281 } 1282 1283 private static int getVisibleMiddleSegment(TGLight tg, Object clipBounds) { 1284 int middleSegment = -1; 1285 try { 1286 Polygon clipBoundsPoly = null; 1287 Rectangle2D clipRect = null; 1288 boolean useClipRect; // true if clipBounds is Rectangle2D otherwise use clipBoundsPoly 1289 POINT2 pt0 = null, pt1 = null; 1290 double dist = 0; 1291 POINT2 lastPt = null; 1292 long lineType = tg.get_LineType(); 1293 //we want the middle segment to be visible 1294 middleSegment = (tg.Pixels.size() + 1) / 2 - 1; 1295 1296 boolean foundVisibleSegment = false; 1297 if (clipBounds == null) { 1298 return middleSegment; 1299 } 1300 1301 if (ArrayList.class.isAssignableFrom(clipBounds.getClass())) { 1302 useClipRect = false; 1303 clipBoundsPoly = new Polygon(); 1304 ArrayList<Point2D> clipArray = (ArrayList<Point2D>) clipBounds; 1305 for (int j = 0; j < clipArray.size(); j++) { 1306 int x = (int) (clipArray.get(j)).getX(); 1307 int y = (int) (clipArray.get(j)).getY(); 1308 clipBoundsPoly.addPoint(x, y); 1309 } 1310 } else if (Rectangle2D.class.isAssignableFrom(clipBounds.getClass())) { 1311 useClipRect = true; 1312 clipRect = (Rectangle2D) clipBounds; 1313 } else { 1314 return middleSegment; 1315 } 1316 1317 //walk through the segments to find the first visible segment from the middle 1318 for (int j = middleSegment; j < tg.Pixels.size() - 1; j++) { 1319 pt0 = tg.Pixels.get(j); 1320 pt1 = tg.Pixels.get(j + 1); 1321 dist = lineutility.CalcDistanceDouble(pt0, pt1); 1322 if (dist < 5) { 1323 continue; 1324 } 1325 //diagnostic 1326 if (j > 0 && lineType == TacticalLines.BOUNDARY) { 1327 if (lastPt == null) { 1328 lastPt = tg.Pixels.get(j - 1); 1329 } 1330 if (DoublesBack(lastPt, pt0, pt1)) { 1331 continue; 1332 } 1333 1334 lastPt = null; 1335 } 1336 //if either of the points is within the bound then most of the segment is visible 1337 if (!useClipRect) { 1338 if (clipBoundsPoly.contains(pt0.x, pt0.y) || clipBoundsPoly.contains(pt1.x, pt1.y)) { 1339 middleSegment = j; 1340 foundVisibleSegment = true; 1341 break; 1342 } 1343 } else { 1344 if (clipRect.contains(pt0.x, pt0.y) || clipRect.contains(pt1.x, pt1.y)) { 1345 middleSegment = j; 1346 foundVisibleSegment = true; 1347 break; 1348 } 1349 } 1350 } 1351 1352 if (!foundVisibleSegment) { 1353 for (int j = middleSegment; j > 0; j--) { 1354 pt0 = tg.Pixels.get(j); 1355 pt1 = tg.Pixels.get(j - 1); 1356 dist = lineutility.CalcDistanceDouble(pt0, pt1); 1357 if (dist < 5) { 1358 continue; 1359 } 1360 //diagnostic 1361 if (lineType == TacticalLines.BOUNDARY) { 1362 if (lastPt == null) { 1363 lastPt = tg.Pixels.get(j - 1); 1364 } 1365 1366 if ( DoublesBack(lastPt, pt0, pt1)) { 1367 continue; 1368 } 1369 1370 lastPt = null; 1371 } 1372 //if either of the points is within the bound then most of the segment is visible 1373 if (!useClipRect) { 1374 if (clipBoundsPoly.contains(pt0.x, pt0.y) || clipBoundsPoly.contains(pt1.x, pt1.y)) { 1375 middleSegment = j - 1; 1376 foundVisibleSegment = true; 1377 break; 1378 } 1379 } else { 1380 if (clipRect.contains(pt0.x, pt0.y) || clipRect.contains(pt1.x, pt1.y)) { 1381 middleSegment = j - 1; 1382 foundVisibleSegment = true; 1383 break; 1384 } 1385 } 1386 } 1387 } 1388 1389 if (!foundVisibleSegment) { 1390 middleSegment = tg.Pixels.size() / 2 - 1; 1391 } 1392 } catch (Exception exc) { 1393 ErrorLogger.LogException(_className, "getMiddleSegment", 1394 new RendererException("Failed inside getMiddleSegment", exc)); 1395 } 1396 return middleSegment; 1397 } 1398 1399 /** 1400 * called repeatedly by RemoveModifiers to remove modifiers which fall 1401 * outside the symbol MBR 1402 * 1403 * @param tg 1404 * @param modifierType 1405 */ 1406 private static void removeModifier(TGLight tg, 1407 String modifierType) { 1408 try { 1409 int j = 0; 1410 Modifier2 modifier = null; 1411 int n = tg.Pixels.size(); 1412 //for (j = 0; j < tg.modifiers.size(); j++) 1413 for (j = 0; j < n; j++) { 1414 modifier = tg.modifiers.get(j); 1415 1416 if (modifier.textID == null) { 1417 continue; 1418 } 1419 1420 if (modifier.textID.equalsIgnoreCase(modifierType)) { 1421 tg.modifiers.remove(modifier); 1422 break; 1423 } 1424 } 1425 } catch (Exception exc) { 1426 ErrorLogger.LogException(_className, "removeModifier", 1427 new RendererException("Failed inside removeModifier", exc)); 1428 } 1429 } 1430 1431 /** 1432 * removes text modifiers for CPOF tactical areas which do not fit inside 1433 * the symbol MBR 1434 * 1435 * @param tg 1436 * @param g2d 1437 * @param isTextFlipped true if text is flipped from the last segment 1438 * orientation 1439 * @param iteration the instance count for this modifier 1440 */ 1441 public static void RemoveModifiers(TGLight tg, 1442 Graphics2D g2d, 1443 boolean isTextFlipped, 1444 int iteration) { 1445 try { 1446 //CPOF clients only 1447 if (!tg.get_Client().equalsIgnoreCase("cpof2d") && !tg.get_Client().equalsIgnoreCase("cpof3d")) { 1448 return; 1449 } 1450 1451 int j = 0; 1452 Polygon mbrPoly = null; 1453 //if it's a change 1 rectangular area then use the pixels instead of the mbr 1454 //because those use aboveMiddle to build angular text 1455 switch (tg.get_LineType()) { 1456 case TacticalLines.RECTANGULAR: 1457 case TacticalLines.CUED_ACQUISITION: 1458 case TacticalLines.ACA_RECTANGULAR: //aboveMiddle modifiers: slanted text 1459 case TacticalLines.FFA_RECTANGULAR: 1460 case TacticalLines.NFA_RECTANGULAR: 1461 case TacticalLines.RFA_RECTANGULAR: 1462 case TacticalLines.KILLBOXBLUE_RECTANGULAR: 1463 case TacticalLines.KILLBOXPURPLE_RECTANGULAR: 1464 case TacticalLines.FSA_RECTANGULAR: 1465 case TacticalLines.SHIP_AOI_RECTANGULAR: 1466 case TacticalLines.DEFENDED_AREA_RECTANGULAR: 1467 case TacticalLines.ATI_RECTANGULAR: 1468 case TacticalLines.CFFZ_RECTANGULAR: 1469 case TacticalLines.SENSOR_RECTANGULAR: 1470 case TacticalLines.CENSOR_RECTANGULAR: 1471 case TacticalLines.DA_RECTANGULAR: 1472 case TacticalLines.CFZ_RECTANGULAR: 1473 case TacticalLines.ZOR_RECTANGULAR: 1474 case TacticalLines.TBA_RECTANGULAR: 1475 case TacticalLines.TVAR_RECTANGULAR: 1476 case TacticalLines.ACA_CIRCULAR: 1477 case TacticalLines.CIRCULAR: 1478 case TacticalLines.BDZ: 1479 case TacticalLines.FSA_CIRCULAR: 1480 case TacticalLines.NOTACK: 1481 case TacticalLines.ATI_CIRCULAR: 1482 case TacticalLines.CFFZ_CIRCULAR: 1483 case TacticalLines.SENSOR_CIRCULAR: 1484 case TacticalLines.CENSOR_CIRCULAR: 1485 case TacticalLines.DA_CIRCULAR: 1486 case TacticalLines.CFZ_CIRCULAR: 1487 case TacticalLines.ZOR_CIRCULAR: 1488 case TacticalLines.TBA_CIRCULAR: 1489 case TacticalLines.TVAR_CIRCULAR: 1490 case TacticalLines.FFA_CIRCULAR: 1491 case TacticalLines.NFA_CIRCULAR: 1492 case TacticalLines.RFA_CIRCULAR: 1493 case TacticalLines.KILLBOXBLUE_CIRCULAR: 1494 case TacticalLines.KILLBOXPURPLE_CIRCULAR: 1495 if (tg.modifiers == null || tg.modifiers.isEmpty() || iteration != 1) { 1496 return; 1497 } 1498 1499 mbrPoly = new Polygon(); 1500 int n = tg.Pixels.size(); 1501 //for (j = 0; j < tg.Pixels.size(); j++) 1502 for (j = 0; j < n; j++) { 1503 mbrPoly.addPoint((int) tg.Pixels.get(j).x, (int) tg.Pixels.get(j).y); 1504 } 1505 1506 break; 1507 default: //area modifiers: horizontal text 1508 if (clsUtility.isClosedPolygon(tg.get_LineType()) == false || iteration != 0) { 1509 return; 1510 } 1511 if (tg.modifiers == null || tg.modifiers.isEmpty()) { 1512 return; 1513 } 1514 1515 mbrPoly = new Polygon(); 1516 int t = tg.Pixels.size(); 1517 //for (j = 0; j < tg.Pixels.size(); j++) 1518 for (j = 0; j < t; j++) { 1519 mbrPoly.addPoint((int) tg.Pixels.get(j).x, (int) tg.Pixels.get(j).y); 1520 } 1521 } 1522 1523 Font font = null; 1524 font = tg.get_Font(); //might have to change this 1525 if (font == null) { 1526 font = g2d.getFont(); 1527 } 1528 g2d.setFont(font); 1529 FontMetrics metrics = g2d.getFontMetrics(); 1530 1531 double stringWidth = 0, stringHeight = 0; 1532 boolean wfits = true, w1fits = true, ww1fits = true, hfits = true, h1fits = true, h2fits = true; 1533 Modifier2 modifier = null; 1534 String modifierType = ""; 1535 String s = ""; 1536 POINT2 pt0 = null, pt1 = null, pt2 = null, pt3 = null, pt4 = null; 1537 double lineFactor = 0; 1538 double x = 0, y = 0; 1539 double x1 = 0, y1 = 0, x2 = 0, y2 = 0; //logic as follows: 1540 //we have to loop through to determine if each modifiers fits and set its fitsMBR member 1541 //then run a 2nd loop to remove groups of modifiers based on whether any of the others do not fit 1542 //e.g. if W does not fit then remove W and W1 modifiers 1543 int n = tg.modifiers.size(); 1544 //for (j = 0; j < tg.modifiers.size(); j++) 1545 for (j = 0; j < n; j++) { 1546 modifier = tg.modifiers.get(j); 1547 if (modifier.textID == null || modifier.textID.isEmpty()) { 1548 continue; 1549 } 1550 1551 modifierType = modifier.textID; 1552 lineFactor = modifier.lineFactor; 1553 1554 if (isTextFlipped) { 1555 lineFactor = -lineFactor; 1556 } 1557 1558 s = modifier.text; 1559 if (s == null || s.equals("")) { 1560 continue; 1561 } 1562 stringWidth = (double) metrics.stringWidth(s) + 1; 1563 stringHeight = (double) font.getSize(); 1564 1565 if (modifier.type == area) { 1566 pt0 = modifier.textPath[0]; 1567 x1 = pt0.x; 1568 y1 = pt0.y; 1569 x = (int) x1 - (int) stringWidth / 2; 1570 y = (int) y1 + (int) (stringHeight / 2) + (int) (1.25 * lineFactor * stringHeight); 1571 //pt1 = modifier.textPath[1]; 1572 x2 = (int) x1 + (int) stringWidth / 2; 1573 y2 = (int) y1 + (int) (stringHeight / 2) + (int) (1.25 * lineFactor * stringHeight); 1574 if (mbrPoly.contains(x, y) && mbrPoly.contains(x2, y2)) { 1575 modifier.fitsMBR = true; 1576 } else { 1577 modifier.fitsMBR = false; 1578 } 1579 } else if (modifier.type == aboveMiddle) { 1580 pt0 = modifier.textPath[0]; 1581 pt1 = modifier.textPath[1]; 1582 //double dist=lineutility.CalcDistanceDouble(pt0, pt1); 1583 POINT2 ptCenter = lineutility.MidPointDouble(pt0, pt1, 0); 1584 pt0 = lineutility.ExtendAlongLineDouble(ptCenter, pt0, stringWidth / 2); 1585 pt1 = lineutility.ExtendAlongLineDouble(ptCenter, pt1, stringWidth / 2); 1586 1587 if (lineFactor >= 0) { 1588 pt2 = lineutility.ExtendDirectedLine(ptCenter, pt0, pt0, 3, Math.abs((lineFactor) * stringHeight)); 1589 } else { 1590 pt2 = lineutility.ExtendDirectedLine(ptCenter, pt0, pt0, 2, Math.abs((lineFactor) * stringHeight)); 1591 } 1592 1593 if (lineFactor >= 0) { 1594 pt3 = lineutility.ExtendDirectedLine(ptCenter, pt1, pt1, 3, Math.abs((lineFactor) * stringHeight)); 1595 } else { 1596 pt3 = lineutility.ExtendDirectedLine(ptCenter, pt1, pt1, 2, Math.abs((lineFactor) * stringHeight)); 1597 } 1598 1599 x1 = pt2.x; 1600 y1 = pt2.y; 1601 x2 = pt3.x; 1602 y2 = pt3.y; 1603 if (mbrPoly.contains(x1, y1) && mbrPoly.contains(x2, y2)) { 1604 modifier.fitsMBR = true; 1605 } else { 1606 modifier.fitsMBR = false; 1607 } 1608 } else { 1609 modifier.fitsMBR = true; 1610 } 1611 } 1612 n = tg.modifiers.size(); 1613 //for (j = 0; j < tg.modifiers.size(); j++) 1614 for (j = 0; j < n; j++) { 1615 modifier = tg.modifiers.get(j); 1616 if (modifier.textID == null || modifier.textID.isEmpty()) { 1617 continue; 1618 } 1619 1620 if (modifier.fitsMBR == false) { 1621 if (modifier.textID.equalsIgnoreCase("W")) { 1622 wfits = false; 1623 } else if (modifier.textID.equalsIgnoreCase("W1")) { 1624 w1fits = false; 1625 } else if (modifier.textID.equalsIgnoreCase("W+W1")) { 1626 ww1fits = false; 1627 } else if (modifier.textID.equalsIgnoreCase("H")) { 1628 hfits = false; 1629 } else if (modifier.textID.equalsIgnoreCase("H1")) { 1630 h1fits = false; 1631 } else if (modifier.textID.equalsIgnoreCase("H2")) { 1632 h2fits = false; 1633 } 1634 } 1635 } 1636 if (wfits == false || w1fits == false) { 1637 removeModifier(tg, "W"); 1638 removeModifier(tg, "W1"); 1639 } 1640 if (ww1fits == false) { 1641 removeModifier(tg, "W+W1"); 1642 } 1643 if (hfits == false || h1fits == false || h2fits == false) { 1644 removeModifier(tg, "H"); 1645 removeModifier(tg, "H1"); 1646 removeModifier(tg, "H2"); 1647 } 1648 1649 } catch (Exception exc) { 1650 ErrorLogger.LogException(_className, "RemoveModifeirs", 1651 new RendererException("Failed inside RemoveModifiers", exc)); 1652 } 1653 } 1654 1655 /** 1656 * Calculates a segment in the pixels middle by length to hold a string. 1657 * 1658 * @param tg 1659 * @param stringWidth 1660 * @param segPt0 1661 * @param segPt1 1662 */ 1663 private static void getPixelsMiddleSegment(TGLight tg, 1664 double stringWidth, 1665 POINT2 segPt0, 1666 POINT2 segPt1) { 1667 try { 1668 switch (tg.get_LineType()) { 1669 case TacticalLines.CFL: 1670 break; 1671 default: 1672 return; 1673 } 1674 int totalLength = 0; 1675 int j = 0; 1676 double dist = 0; 1677 double mid = 0; 1678 double remainder = 0; 1679 POINT2 pt0 = null, pt1 = null, pt2 = null, pt3 = null; 1680 POINT2 midPt = null; 1681 //first get the total length of all the segments 1682 int n = tg.Pixels.size(); 1683 //for (j = 0; j < tg.Pixels.size() - 1; j++) 1684 for (j = 0; j < n - 1; j++) { 1685 dist = lineutility.CalcDistanceDouble(tg.Pixels.get(j), tg.Pixels.get(j + 1)); 1686 totalLength += dist; 1687 } 1688 mid = totalLength / 2; 1689 totalLength = 0; 1690 //walk thru the segments to find the middle 1691 //for (j = 0; j < tg.Pixels.size() - 1; j++) 1692 for (j = 0; j < n - 1; j++) { 1693 dist = lineutility.CalcDistanceDouble(tg.Pixels.get(j), tg.Pixels.get(j + 1)); 1694 totalLength += dist; 1695 if (totalLength >= mid)//current segment contains the middle 1696 { 1697 remainder = totalLength - mid; 1698 pt0 = tg.Pixels.get(j); 1699 pt1 = tg.Pixels.get(j + 1); 1700 //calculate the pixels mid point 1701 midPt = lineutility.ExtendAlongLineDouble2(pt1, pt0, remainder); 1702 pt2 = lineutility.ExtendAlongLineDouble2(midPt, pt0, stringWidth / 2); 1703 pt3 = lineutility.ExtendAlongLineDouble2(midPt, pt1, stringWidth / 2); 1704 segPt0.x = pt2.x; 1705 segPt0.y = pt2.y; 1706 segPt1.x = pt3.x; 1707 segPt1.y = pt3.y; 1708 break; 1709 } 1710 } 1711 } catch (Exception exc) { 1712 ErrorLogger.LogException(_className, "getPixelsMidpoint", 1713 new RendererException("Failed inside getPixelsMidpoint", exc)); 1714 } 1715 } 1716 1717 private static double getChange1Height(TGLight tg) { 1718 double height = 0; 1719 try { 1720 switch (tg.get_LineType()) { 1721 //case TacticalLines.PAA_RECTANGULAR: 1722 case TacticalLines.FSA_RECTANGULAR: 1723 case TacticalLines.SHIP_AOI_RECTANGULAR: 1724 case TacticalLines.DEFENDED_AREA_RECTANGULAR: 1725 case TacticalLines.FFA_RECTANGULAR: 1726 case TacticalLines.ACA_RECTANGULAR: 1727 case TacticalLines.NFA_RECTANGULAR: 1728 case TacticalLines.RFA_RECTANGULAR: 1729 case TacticalLines.ATI_RECTANGULAR: 1730 case TacticalLines.CFFZ_RECTANGULAR: 1731 case TacticalLines.SENSOR_RECTANGULAR: 1732 case TacticalLines.CENSOR_RECTANGULAR: 1733 case TacticalLines.DA_RECTANGULAR: 1734 case TacticalLines.CFZ_RECTANGULAR: 1735 case TacticalLines.ZOR_RECTANGULAR: 1736 case TacticalLines.TBA_RECTANGULAR: 1737 case TacticalLines.TVAR_RECTANGULAR: 1738 case TacticalLines.KILLBOXBLUE_RECTANGULAR: 1739 case TacticalLines.KILLBOXPURPLE_RECTANGULAR: 1740 break; 1741 default: 1742 return 0; 1743 } 1744 double x1 = tg.Pixels.get(0).x; 1745 double y1 = tg.Pixels.get(0).y; 1746 double x2 = tg.Pixels.get(1).x; 1747 double y2 = tg.Pixels.get(1).y; 1748 double deltax = x2 - x1; 1749 double deltay = y2 - y1; 1750 height = Math.sqrt(deltax * deltax + deltay * deltay); 1751 } catch (Exception exc) { 1752 ErrorLogger.LogException(_className, "getChange1Height", 1753 new RendererException("Failed inside getChange1Height", exc)); 1754 } 1755 return height; 1756 } 1757 1758 /** 1759 * scale the line factor for closed areas 1760 * 1761 * @param tg 1762 */ 1763 private static void scaleModifiers(TGLight tg) { 1764 try { 1765 if (RendererSettings.getInstance().getAutoCollapseModifiers() == false) { 1766 return; 1767 } 1768 if (!tg.get_Client().equalsIgnoreCase("ge")) { 1769 return; 1770 } 1771 //exit if there are no modifiers or it's not a closed area 1772 if (tg.modifiers == null || tg.modifiers.isEmpty()) { 1773 return; 1774 } 1775 int linetype = tg.get_LineType(); 1776 boolean isClosedPolygon = clsUtility.isClosedPolygon(linetype); 1777 boolean isChange1Area = clsUtility.IsChange1Area(linetype); 1778 if (!isClosedPolygon && !isChange1Area) { 1779 return; 1780 } 1781 switch(linetype) 1782 { 1783 case TacticalLines.PAA_CIRCULAR: 1784 case TacticalLines.PAA_RECTANGULAR: 1785 case TacticalLines.RECTANGULAR_TARGET: 1786 case TacticalLines.RANGE_FAN: 1787 case TacticalLines.RANGE_FAN_SECTOR: 1788 case TacticalLines.RADAR_SEARCH: 1789 return; 1790 default: 1791 break; 1792 } 1793 POINT2 ptUl = new POINT2(), ptUr = new POINT2(), ptLr = new POINT2(), ptLl = new POINT2(); 1794 GetMBR(tg, ptUl, ptUr, ptLr, ptLl); 1795 int sz = tg.get_Font().getSize(); 1796 //heightMBR is half the MBR height 1797 //double heightMBR=Math.abs(ptLr.y-ptUr.y)/2; 1798 double heightMBR = 0; 1799 double change1Height = getChange1Height(tg); 1800 if (change1Height <= 0) { 1801 heightMBR = Math.abs(ptLr.y - ptUr.y) / 2; 1802 } else { 1803 heightMBR = change1Height; 1804 } 1805 1806 double heightModifiers = 0; 1807 ArrayList<Modifier2> modifiers = tg.modifiers; 1808 Modifier2 modifier = null; 1809 double minLF = Integer.MAX_VALUE; 1810 int j = 0; 1811 boolean isValid = false; 1812 for (j = 0; j < modifiers.size(); j++) { 1813 modifier = modifiers.get(j); 1814 //if(modifier.type == area) 1815 //type3Area=true; 1816 if (modifier.type == toEnd) { 1817 continue; 1818 } 1819 if (modifier.type == aboveMiddle && isChange1Area == false) { 1820 continue; 1821 } 1822 if (modifier.lineFactor < minLF) { 1823 minLF = modifier.lineFactor; 1824 } 1825 isValid = true; 1826 } 1827 //if there are no 'area' modifiers then exit early 1828 if (!isValid) { 1829 return; 1830 } 1831 1832 heightModifiers = Math.abs(minLF) * sz; 1833 boolean expandModifiers = false, shrinkModifiers = false; 1834 if (heightModifiers > heightMBR) { 1835 shrinkModifiers = true; 1836 } else if (heightModifiers < 0.5 * heightMBR) { 1837 expandModifiers = true; 1838 } 1839 1840 boolean addEllipsis = false; 1841 //modifierE is ellipses modifier 1842 Modifier2 modifierE = new Modifier2(); 1843 if (expandModifiers) { 1844 double factor = heightMBR / heightModifiers; 1845 factor = 1 + (factor - 1) / 4; 1846 if (factor > 2) { 1847 factor = 2; 1848 } 1849 for (j = 0; j < modifiers.size(); j++) { 1850 modifier = modifiers.get(j); 1851 if(modifier.type==aboveMiddle) 1852 { 1853 if(isChange1Area==false) 1854 continue; 1855 } 1856 else if(modifier.type!=area) 1857 continue; 1858 1859 modifier.lineFactor *= factor; 1860 } 1861 } else if (shrinkModifiers) { 1862 double deltaLF = (heightModifiers - heightMBR) / sz; 1863 double newLF = 0; 1864 //use maxLF for the ellipsis modifier 1865 double maxLF = 0; 1866 for (j = 0; j < modifiers.size(); j++) { 1867 modifier = modifiers.get(j); 1868 if(modifier.type==aboveMiddle) 1869 { 1870 if(isChange1Area==false) 1871 continue; 1872 } 1873 else if(modifier.type!=area) 1874 continue; 1875 newLF = modifier.lineFactor + deltaLF; 1876 if (Math.abs(newLF * sz) >= heightMBR) { 1877 //flag the modifier to remove 1878 if (modifier.lineFactor > minLF) { 1879 modifierE.type = modifier.type; 1880 modifier.type = 7; 1881 if (!modifier.text.isEmpty()) { 1882 addEllipsis = true; 1883 } 1884 } 1885 modifier.lineFactor = newLF; 1886 //modifierE.type=area; 1887 //modifierE.type=modifier.type; 1888 modifierE.textPath = modifier.textPath; 1889 continue; 1890 } 1891 modifier.lineFactor = newLF; 1892 } 1893 ArrayList<Modifier2> modifiers2 = new ArrayList(); 1894 for (j = 0; j < modifiers.size(); j++) { 1895 modifier = modifiers.get(j); 1896 if (modifier.type != 7) { 1897 if (modifier.lineFactor > maxLF) { 1898 maxLF = modifier.lineFactor; 1899 } 1900 modifiers2.add(modifier); 1901 } 1902 } 1903 if (addEllipsis) { 1904 Character letter = (char) 9679; 1905 String s = Character.toString(letter); 1906 String echelonSymbol = s + s + s; 1907 modifierE.text = echelonSymbol; 1908 modifierE.lineFactor = maxLF + 1; 1909 modifiers2.add(modifierE); 1910 } 1911 tg.modifiers = modifiers2; 1912 } //end shrink modifiers 1913 } catch (Exception exc) { 1914 ErrorLogger.LogException(_className, "scaleModifiers", 1915 new RendererException("Failed inside scaleModifiers", exc)); 1916 } 1917 } 1918 1919 /** 1920 * Calculate modifiers identical to addModifiers except use geodesic 1921 * calculations for the center point. 1922 * 1923 * @param tg 1924 * @param g2d 1925 * @param clipBounds 1926 * @param converter 1927 */ 1928 public static void AddModifiersGeo(TGLight tg, 1929 Graphics2D g2d, 1930 Object clipBounds, 1931 IPointConversion converter) { 1932 try { 1933 //exit early for those not affected 1934 if (tg.Pixels == null || tg.Pixels.isEmpty()) { 1935 return; 1936 } 1937 ArrayList<POINT2> origPoints = null; 1938 Font font = tg.get_Font(); 1939 if (font == null) { 1940 font = g2d.getFont(); 1941 } 1942 g2d.setFont(font); 1943 1944 boolean shiftLines = Channels.getShiftLines(); 1945 boolean usas = false, foundSegment = false; 1946 double csFactor = 1d, dist = 0, dist2 = 0;//this will be used for text spacing the 3d map (CommandCight) 1947 POINT2 midPt = null; 1948 int northestPtIndex = 0; 1949 int southestPtIndex = 0; 1950 POINT2 northestPt = null; 1951 POINT2 southestPt = null; 1952 1953 Rectangle2D clipRect = null; 1954 ArrayList<Point2D> clipArray = null; 1955 if (clipBounds != null && ArrayList.class.isAssignableFrom(clipBounds.getClass())) { 1956 clipArray = (ArrayList<Point2D>) clipBounds; 1957 } 1958 if (clipBounds != null && Rectangle2D.Double.class.isAssignableFrom(clipBounds.getClass())) { 1959 clipRect = (Rectangle2D.Double) clipBounds; 1960 } 1961 1962 FontMetrics metrics = g2d.getFontMetrics(); 1963 int stringWidth = 0, stringWidth2 = 0; 1964 String WDash = ""; // Dash between W and W1 if they're not empty 1965 String TSpace = "", TDash = ""; // Space or dash between label and T modifier if T isn't empty 1966 if (tg.get_DTG() != null && tg.get_DTG1() != null && !tg.get_DTG().isEmpty() && !tg.get_DTG1().isEmpty()) { 1967 WDash = " - "; 1968 } 1969 if (tg.get_Name() != null && !tg.get_Name().isEmpty()) { 1970 TSpace = " "; 1971 TDash = " - "; 1972 } 1973 1974 if (tg.get_Client().equals("cpof3d")) { 1975 csFactor = 0.9d; 1976 } 1977 1978 switch (tg.get_LineType()) { 1979 case TacticalLines.SERIES: 1980 case TacticalLines.STRIKWARN: 1981 case TacticalLines.MSR: 1982 case TacticalLines.MSR_ONEWAY: 1983 case TacticalLines.MSR_TWOWAY: 1984 case TacticalLines.MSR_ALT: 1985 case TacticalLines.ASR: 1986 case TacticalLines.ASR_ONEWAY: 1987 case TacticalLines.ASR_TWOWAY: 1988 case TacticalLines.ASR_ALT: 1989 case TacticalLines.ROUTE: 1990 case TacticalLines.ROUTE_ONEWAY: 1991 case TacticalLines.ROUTE_ALT: 1992 case TacticalLines.DHA_REVD: 1993 case TacticalLines.DHA: 1994 case TacticalLines.EPW: 1995 case TacticalLines.UXO: 1996 case TacticalLines.FARP: 1997 case TacticalLines.BSA: 1998 case TacticalLines.DSA: 1999 case TacticalLines.CSA: 2000 case TacticalLines.RSA: 2001 case TacticalLines.THUNDERSTORMS: 2002 case TacticalLines.ICING: 2003 case TacticalLines.FREEFORM: 2004 case TacticalLines.RHA: 2005 case TacticalLines.LINTGT: 2006 case TacticalLines.LINTGTS: 2007 case TacticalLines.FPF: 2008 case TacticalLines.GAP: 2009 case TacticalLines.DEPICT: 2010 case TacticalLines.AIRHEAD: 2011 case TacticalLines.FSA: 2012 case TacticalLines.DIRATKAIR: 2013 case TacticalLines.OBJ: 2014 case TacticalLines.AO: 2015 case TacticalLines.ACA: 2016 case TacticalLines.FFA: 2017 case TacticalLines.PAA: 2018 case TacticalLines.NFA: 2019 case TacticalLines.RFA: 2020 case TacticalLines.ATI: 2021 case TacticalLines.CFFZ: 2022 case TacticalLines.CFZ: 2023 case TacticalLines.TBA: 2024 case TacticalLines.TVAR: 2025 case TacticalLines.KILLBOXBLUE: 2026 case TacticalLines.KILLBOXPURPLE: 2027 case TacticalLines.ZOR: 2028 case TacticalLines.DA: 2029 case TacticalLines.SENSOR: 2030 case TacticalLines.CENSOR: 2031 case TacticalLines.SMOKE: 2032 case TacticalLines.BATTLE: 2033 case TacticalLines.PNO: 2034 case TacticalLines.PDF: 2035 case TacticalLines.NAI: 2036 case TacticalLines.TAI: 2037 case TacticalLines.BASE_CAMP_REVD: 2038 case TacticalLines.BASE_CAMP: 2039 case TacticalLines.GUERILLA_BASE_REVD: 2040 case TacticalLines.GUERILLA_BASE: 2041 case TacticalLines.GENERIC_AREA: 2042 case TacticalLines.ATKPOS: 2043 case TacticalLines.ASSAULT: 2044 case TacticalLines.WFZ: 2045 case TacticalLines.OBSFAREA: 2046 case TacticalLines.OBSAREA: 2047 case TacticalLines.ROZ: 2048 case TacticalLines.AARROZ: 2049 case TacticalLines.UAROZ: 2050 case TacticalLines.WEZ: 2051 case TacticalLines.FEZ: 2052 case TacticalLines.JEZ: 2053 case TacticalLines.FAADZ: 2054 case TacticalLines.HIDACZ: 2055 case TacticalLines.MEZ: 2056 case TacticalLines.LOMEZ: 2057 case TacticalLines.HIMEZ: 2058 case TacticalLines.SAAFR: 2059 case TacticalLines.AC: 2060 case TacticalLines.MRR: 2061 case TacticalLines.SL: 2062 case TacticalLines.TC: 2063 case TacticalLines.SC: 2064 case TacticalLines.LLTR: 2065 case TacticalLines.AIRFIELD: 2066 case TacticalLines.GENERAL: 2067 case TacticalLines.JTAA: 2068 case TacticalLines.SAA: 2069 case TacticalLines.SGAA: 2070 case TacticalLines.FORT_REVD: 2071 case TacticalLines.FORT: 2072 case TacticalLines.ENCIRCLE: 2073 case TacticalLines.ASSY: 2074 case TacticalLines.EA: 2075 case TacticalLines.DZ: 2076 case TacticalLines.EZ: 2077 case TacticalLines.LZ: 2078 case TacticalLines.PZ: 2079 case TacticalLines.LAA: 2080 case TacticalLines.BOUNDARY: 2081 case TacticalLines.MINED: 2082 case TacticalLines.FENCED: 2083 case TacticalLines.PL: 2084 case TacticalLines.FEBA: 2085 case TacticalLines.FCL: 2086 case TacticalLines.HOLD: 2087 case TacticalLines.BRDGHD: 2088 case TacticalLines.HOLD_GE: 2089 case TacticalLines.BRDGHD_GE: 2090 case TacticalLines.LOA: 2091 case TacticalLines.LOD: 2092 case TacticalLines.LL: 2093 case TacticalLines.EWL: 2094 case TacticalLines.RELEASE: 2095 case TacticalLines.HOL: 2096 case TacticalLines.BHL: 2097 case TacticalLines.LDLC: 2098 case TacticalLines.PLD: 2099 case TacticalLines.NFL: 2100 case TacticalLines.MFP: 2101 case TacticalLines.FSCL: 2102 case TacticalLines.BCL_REVD: 2103 case TacticalLines.BCL: 2104 case TacticalLines.ICL: 2105 case TacticalLines.IFF_OFF: 2106 case TacticalLines.IFF_ON: 2107 case TacticalLines.GENERIC_LINE: 2108 case TacticalLines.CFL: 2109 case TacticalLines.RFL: 2110 case TacticalLines.FLOT: 2111 case TacticalLines.LC: 2112 case TacticalLines.CATK: 2113 case TacticalLines.CATKBYFIRE: 2114 case TacticalLines.IL: 2115 case TacticalLines.DRCL: 2116 case TacticalLines.RETIRE: 2117 case TacticalLines.FPOL: 2118 case TacticalLines.RPOL: 2119 case TacticalLines.WITHDRAW: 2120 case TacticalLines.WDRAWUP: 2121 case TacticalLines.BEARING: 2122 case TacticalLines.BEARING_J: 2123 case TacticalLines.BEARING_RDF: 2124 case TacticalLines.ELECTRO: 2125 case TacticalLines.BEARING_EW: 2126 case TacticalLines.ACOUSTIC: 2127 case TacticalLines.ACOUSTIC_AMB: 2128 case TacticalLines.TORPEDO: 2129 case TacticalLines.OPTICAL: 2130 case TacticalLines.RIP: 2131 case TacticalLines.BOMB: 2132 case TacticalLines.ZONE: 2133 case TacticalLines.AT: 2134 case TacticalLines.STRONG: 2135 case TacticalLines.MSDZ: 2136 case TacticalLines.SCREEN: 2137 case TacticalLines.COVER: 2138 case TacticalLines.GUARD: 2139 case TacticalLines.DELAY: 2140 case TacticalLines.TGMF: 2141 case TacticalLines.BIO: 2142 case TacticalLines.CHEM: 2143 case TacticalLines.NUC: 2144 case TacticalLines.RAD: 2145 case TacticalLines.MINE_LINE: 2146 case TacticalLines.ANCHORAGE_LINE: 2147 case TacticalLines.ANCHORAGE_AREA: 2148 case TacticalLines.SPT: 2149 case TacticalLines.AIRAOA: 2150 case TacticalLines.AAAAA: 2151 case TacticalLines.MAIN: 2152 case TacticalLines.DIRATKSPT: 2153 case TacticalLines.DIRATKGND: 2154 case TacticalLines.LAUNCH_AREA: 2155 case TacticalLines.DEFENDED_AREA_CIRCULAR: 2156 case TacticalLines.RECTANGULAR: 2157 case TacticalLines.CIRCULAR: 2158 case TacticalLines.RECTANGULAR_TARGET: 2159 case TacticalLines.LINE: 2160 case TacticalLines.ASLTXING: 2161 origPoints = lineutility.getDeepCopy(tg.Pixels); 2162 break; 2163 default: //exit early for those not applicable 2164 return; 2165 } 2166 2167 int linetype = tg.get_LineType(); 2168 int j = 0, k = 0; 2169 double x = 0, y = 0; 2170 2171 int lastIndex = tg.Pixels.size() - 1; 2172 int nextToLastIndex = tg.Pixels.size() - 2; 2173 POINT2 pt0 = new POINT2(tg.Pixels.get(0)); 2174 POINT2 pt1 = null; 2175 POINT2 pt2 = null, pt3 = null; 2176 POINT2 ptLast = new POINT2(tg.Pixels.get(lastIndex)); 2177 POINT2 ptNextToLast = null; 2178 double DPIScaleFactor = RendererSettings.getInstance().getDeviceDPI() / 96.0; 2179 2180 if (lastIndex > 0) { 2181 ptNextToLast = new POINT2(tg.Pixels.get(nextToLastIndex)); 2182 } 2183 2184 if (tg.Pixels.size() > 1) { 2185 pt1 = new POINT2(tg.Pixels.get(1)); 2186 } 2187 2188 //prevent vertical paths for modifiers that use toEnd 2189 shiftModifierPath(tg, pt0, pt1, ptLast, ptNextToLast); 2190 2191 String label = GetCenterLabel(tg); 2192 String v=tg.get_V(); 2193 String ap=tg.get_AP(); 2194 Object[] pts = tg.Pixels.toArray(); 2195 //need this for areas and some lines 2196 POINT2 ptCenter = null; 2197 if (converter != null) //cpof uses latlonconverter so cpof passes null for this 2198 { 2199 ptCenter = mdlGeodesic.geodesic_center(tg.LatLongs); 2200 if (ptCenter != null) { 2201 Point2D pt22 = converter.GeoToPixels(new Point2D.Double(ptCenter.x, ptCenter.y)); 2202 ptCenter.x = pt22.getX(); 2203 ptCenter.y = pt22.getY(); 2204 } else { 2205 ptCenter = lineutility.CalcCenterPointDouble2(pts, pts.length); 2206 } 2207 } else { 2208 ptCenter = lineutility.CalcCenterPointDouble2(pts, pts.length); 2209 } 2210 2211 int middleSegment = (tg.Pixels.size() + 1) / 2 - 1; 2212 int middleSegment2 = 0; 2213 2214 if (clipRect != null) { 2215 middleSegment = getVisibleMiddleSegment(tg, clipRect); 2216 } else if (clipArray != null) { 2217 middleSegment = getVisibleMiddleSegment(tg, clipArray); 2218 } 2219 if (tg.Pixels.size() > 2) { 2220 pt2 = tg.Pixels.get(2); 2221 } 2222 if (tg.Pixels.size() > 3) { 2223 pt3 = tg.Pixels.get(3); 2224 } 2225 double TLineFactor = 0, T1LineFactor = 0; 2226 POINT2 lr = new POINT2(tg.Pixels.get(0)); 2227 POINT2 ll = new POINT2(tg.Pixels.get(0)); 2228 POINT2 ul = new POINT2(tg.Pixels.get(0)); 2229 POINT2 ur = new POINT2(tg.Pixels.get(0)); 2230 int index = 0; 2231 int nextIndex = 0; 2232 int size = tg.Pixels.size(); 2233 Line2D line = null; 2234 2235 double dAngle0, dAngle1; 2236 int stringHeight; 2237 2238 switch (linetype) { 2239 case TacticalLines.PL: 2240 AddIntegralAreaModifier(tg, label + TSpace + tg.get_Name(), toEnd, T1LineFactor, pt0, pt1, false); 2241 AddIntegralAreaModifier(tg, label + TSpace + tg.get_Name(), toEnd, T1LineFactor, ptLast, ptNextToLast, false); 2242 break; 2243 case TacticalLines.FEBA: 2244 AddIntegralAreaModifier(tg, label, toEnd, 0, pt0, pt1, false); 2245 AddIntegralAreaModifier(tg, label, toEnd, 0, ptLast, ptNextToLast, false); 2246 break; 2247 // T before label 2248 case TacticalLines.FSCL: 2249 pt0 = tg.Pixels.get(0); 2250 pt1 = tg.Pixels.get(1); 2251 pt2 = tg.Pixels.get(tg.Pixels.size() - 1); 2252 pt3 = tg.Pixels.get(tg.Pixels.size() - 2); 2253 dist = lineutility.CalcDistanceDouble(pt0, pt1); 2254 dist2 = lineutility.CalcDistanceDouble(pt2, pt3); 2255 stringWidth = (int) ((double) metrics.stringWidth(tg.get_Name() + " " + label)); 2256 stringWidth2 = (int) ((double) metrics.stringWidth(tg.get_DTG())); 2257 if (stringWidth2 > stringWidth) { 2258 stringWidth = stringWidth2; 2259 } 2260 2261 if (tg.Pixels.size() == 2) //one segment 2262 { 2263 pt1 = lineutility.ExtendAlongLineDouble(pt0, pt1, stringWidth); 2264 AddModifier2(tg, tg.get_Name() + " " + label , aboveMiddle, -0.7 * csFactor, pt0, pt1, false); 2265 AddModifier2(tg, tg.get_DTG() + WDash, aboveMiddle, 0.7 * csFactor, pt0, pt1, false); 2266 AddModifier2(tg, tg.get_DTG1(), aboveMiddle, 1.7 * csFactor, pt0, pt1, false); 2267 if (dist > 3.5 * stringWidth)//was 28stringwidth+5 2268 { 2269 pt0 = tg.Pixels.get(tg.Pixels.size() - 1); 2270 pt1 = tg.Pixels.get(tg.Pixels.size() - 2); 2271 pt1 = lineutility.ExtendAlongLineDouble(pt0, pt1, stringWidth); 2272 AddModifier2(tg, tg.get_Name() + " " + label, aboveMiddle, -0.7 * csFactor, pt0, pt1, false); 2273 AddModifier2(tg, tg.get_DTG() + WDash, aboveMiddle, 0.7 * csFactor, pt0, pt1, false); 2274 AddModifier2(tg, tg.get_DTG1(), aboveMiddle, 1.7 * csFactor, pt0, pt1, false); 2275 } 2276 } else //more than one semgent 2277 { 2278 double dist3 = lineutility.CalcDistanceDouble(pt0, pt2); 2279 if (dist > stringWidth + 5 || dist >= dist2 || dist3 > stringWidth + 5) { 2280 pt1 = lineutility.ExtendAlongLineDouble(pt0, pt1, stringWidth); 2281 AddModifier2(tg, tg.get_Name() + " " + label, aboveMiddle, -0.7 * csFactor, pt0, pt1, false); 2282 AddModifier2(tg, tg.get_DTG() + WDash, aboveMiddle, 0.7 * csFactor, pt0, pt1, false); 2283 AddModifier2(tg, tg.get_DTG1(), aboveMiddle, 1.7 * csFactor, pt0, pt1, false); 2284 } 2285 if (dist2 > stringWidth + 5 || dist2 > dist || dist3 > stringWidth + 5) { 2286 pt0 = tg.Pixels.get(tg.Pixels.size() - 1); 2287 pt1 = tg.Pixels.get(tg.Pixels.size() - 2); 2288 pt1 = lineutility.ExtendAlongLineDouble(pt0, pt1, stringWidth); 2289 AddModifier2(tg, tg.get_Name() + " " + label, aboveMiddle, -0.7 * csFactor, pt0, pt1, false); 2290 AddModifier2(tg, tg.get_DTG() + WDash, aboveMiddle, 0.7 * csFactor, pt0, pt1, false); 2291 AddModifier2(tg, tg.get_DTG1(), aboveMiddle, 1.7 * csFactor, pt0, pt1, false); 2292 } 2293 } 2294 break; 2295 // T after label 2296 case TacticalLines.ICL: 2297 case TacticalLines.NFL: 2298 case TacticalLines.BCL_REVD: 2299 case TacticalLines.RFL: 2300 pt0 = tg.Pixels.get(0); 2301 pt1 = tg.Pixels.get(1); 2302 pt2 = tg.Pixels.get(tg.Pixels.size() - 1); 2303 pt3 = tg.Pixels.get(tg.Pixels.size() - 2); 2304 dist = lineutility.CalcDistanceDouble(pt0, pt1); 2305 dist2 = lineutility.CalcDistanceDouble(pt2, pt3); 2306 stringWidth = (int) ((double) metrics.stringWidth(tg.get_Name() + " " + label)); 2307 stringWidth2 = (int) ((double) metrics.stringWidth(tg.get_DTG())); 2308 if (stringWidth2 > stringWidth) { 2309 stringWidth = stringWidth2; 2310 } 2311 2312 if (tg.Pixels.size() == 2) //one segment 2313 { 2314 pt1 = lineutility.ExtendAlongLineDouble(pt0, pt1, stringWidth); 2315 AddModifier2(tg, label + TSpace + tg.get_Name(), aboveMiddle, -0.7 * csFactor, pt0, pt1, false); 2316 AddModifier2(tg, tg.get_DTG() + WDash, aboveMiddle, 0.7 * csFactor, pt0, pt1, false); 2317 AddModifier2(tg, tg.get_DTG1(), aboveMiddle, 1.7 * csFactor, pt0, pt1, false); 2318 if (dist > 3.5 * stringWidth)//was 28stringwidth+5 2319 { 2320 pt0 = tg.Pixels.get(tg.Pixels.size() - 1); 2321 pt1 = tg.Pixels.get(tg.Pixels.size() - 2); 2322 pt1 = lineutility.ExtendAlongLineDouble(pt0, pt1, stringWidth); 2323 AddModifier2(tg, label + TSpace + tg.get_Name(), aboveMiddle, -0.7 * csFactor, pt0, pt1, false); 2324 AddModifier2(tg, tg.get_DTG() + WDash, aboveMiddle, 0.7 * csFactor, pt0, pt1, false); 2325 AddModifier2(tg, tg.get_DTG1(), aboveMiddle, 1.7 * csFactor, pt0, pt1, false); 2326 } 2327 } else //more than one semgent 2328 { 2329 double dist3 = lineutility.CalcDistanceDouble(pt0, pt2); 2330 if (dist > stringWidth + 5 || dist >= dist2 || dist3 > stringWidth + 5) { 2331 pt1 = lineutility.ExtendAlongLineDouble(pt0, pt1, stringWidth); 2332 AddModifier2(tg, label + TSpace + tg.get_Name(), aboveMiddle, -0.7 * csFactor, pt0, pt1, false); 2333 AddModifier2(tg, tg.get_DTG() + WDash, aboveMiddle, 0.7 * csFactor, pt0, pt1, false); 2334 AddModifier2(tg, tg.get_DTG1(), aboveMiddle, 1.7 * csFactor, pt0, pt1, false); 2335 } 2336 if (dist2 > stringWidth + 5 || dist2 > dist || dist3 > stringWidth + 5) { 2337 pt0 = tg.Pixels.get(tg.Pixels.size() - 1); 2338 pt1 = tg.Pixels.get(tg.Pixels.size() - 2); 2339 pt1 = lineutility.ExtendAlongLineDouble(pt0, pt1, stringWidth); 2340 AddModifier2(tg, label + TSpace + tg.get_Name(), aboveMiddle, -0.7 * csFactor, pt0, pt1, false); 2341 AddModifier2(tg, tg.get_DTG() + WDash, aboveMiddle, 0.7 * csFactor, pt0, pt1, false); 2342 AddModifier2(tg, tg.get_DTG1(), aboveMiddle, 1.7 * csFactor, pt0, pt1, false); 2343 } 2344 } 2345 break; 2346 case TacticalLines.BCL: 2347 pt0 = tg.Pixels.get(0); 2348 pt1 = tg.Pixels.get(1); 2349 pt2 = tg.Pixels.get(tg.Pixels.size() - 1); 2350 pt3 = tg.Pixels.get(tg.Pixels.size() - 2); 2351 dist = lineutility.CalcDistanceDouble(pt0, pt1); 2352 dist2 = lineutility.CalcDistanceDouble(pt2, pt3); 2353 String TMod = ""; // Don't add parenthesis if T modifier is empty 2354 if (tg.get_Name() != null && !tg.get_Name().isEmpty()) 2355 TMod = " (" + tg.get_Name() + ")"; 2356 stringWidth = (int) ((double) metrics.stringWidth(label + TMod)); 2357 stringWidth2 = (int) ((double) metrics.stringWidth(tg.get_DTG())); 2358 if (stringWidth2 > stringWidth) { 2359 stringWidth = stringWidth2; 2360 } 2361 2362 if (tg.Pixels.size() == 2) //one segment 2363 { 2364 pt1 = lineutility.ExtendAlongLineDouble(pt0, pt1, stringWidth); 2365 AddModifier2(tg, label + TMod, aboveMiddle, -0.7 * csFactor, pt0, pt1, false); 2366 AddModifier2(tg, tg.get_DTG() + WDash, aboveMiddle, 0.7 * csFactor, pt0, pt1, false); 2367 AddModifier2(tg, tg.get_DTG1(), aboveMiddle, 1.7 * csFactor, pt0, pt1, false); 2368 if (dist > 3.5 * stringWidth)//was 28stringwidth+5 2369 { 2370 pt0 = tg.Pixels.get(tg.Pixels.size() - 1); 2371 pt1 = tg.Pixels.get(tg.Pixels.size() - 2); 2372 pt1 = lineutility.ExtendAlongLineDouble(pt0, pt1, stringWidth); 2373 AddModifier2(tg, label + TMod, aboveMiddle, -0.7 * csFactor, pt0, pt1, false); 2374 AddModifier2(tg, tg.get_DTG() + WDash, aboveMiddle, 0.7 * csFactor, pt0, pt1, false); 2375 AddModifier2(tg, tg.get_DTG1(), aboveMiddle, 1.7 * csFactor, pt0, pt1, false); 2376 } 2377 } else //more than one semgent 2378 { 2379 double dist3 = lineutility.CalcDistanceDouble(pt0, pt2); 2380 if (dist > stringWidth + 5 || dist >= dist2 || dist3 > stringWidth + 5) { 2381 pt1 = lineutility.ExtendAlongLineDouble(pt0, pt1, stringWidth); 2382 AddModifier2(tg, label + TMod, aboveMiddle, -0.7 * csFactor, pt0, pt1, false); 2383 AddModifier2(tg, tg.get_DTG() + WDash, aboveMiddle, 0.7 * csFactor, pt0, pt1, false); 2384 AddModifier2(tg, tg.get_DTG1(), aboveMiddle, 1.7 * csFactor, pt0, pt1, false); 2385 } 2386 if (dist2 > stringWidth + 5 || dist2 > dist || dist3 > stringWidth + 5) { 2387 pt0 = tg.Pixels.get(tg.Pixels.size() - 1); 2388 pt1 = tg.Pixels.get(tg.Pixels.size() - 2); 2389 pt1 = lineutility.ExtendAlongLineDouble(pt0, pt1, stringWidth); 2390 AddModifier2(tg, label + TMod, aboveMiddle, -0.7 * csFactor, pt0, pt1, false); 2391 AddModifier2(tg, tg.get_DTG() + WDash, aboveMiddle, 0.7 * csFactor, pt0, pt1, false); 2392 AddModifier2(tg, tg.get_DTG1(), aboveMiddle, 1.7 * csFactor, pt0, pt1, false); 2393 } 2394 } 2395 break; 2396 case TacticalLines.DIRATKSPT: 2397 case TacticalLines.DIRATKAIR: 2398 case TacticalLines.DIRATKGND: 2399 midPt = lineutility.MidPointDouble(pt0, pt1, 0); 2400 //midPt=lineutility.MidPointDouble(pt0, midPt, 0); 2401 AddIntegralAreaModifier(tg, tg.get_Name(), aboveMiddle, 0, pt0, midPt, false); 2402 addDTG(tg, aboveMiddle, csFactor, 2 * csFactor, pt0, pt1, metrics); 2403 break; 2404 case TacticalLines.SPT: 2405 case TacticalLines.AIRAOA: 2406 case TacticalLines.AAAAA: 2407 case TacticalLines.MAIN: 2408 if (tg.Pixels.size() == 3) //one segment 2409 { 2410 midPt = lineutility.MidPointDouble(pt0, pt1, 0); 2411 AddIntegralAreaModifier(tg, tg.get_DTG() + WDash, aboveMiddle, 0, midPt, midPt, false); 2412 AddIntegralAreaModifier(tg, tg.get_DTG1(), aboveMiddle, csFactor, midPt, midPt, false); 2413 AddIntegralAreaModifier(tg, tg.get_Name(), aboveMiddle, 2 * csFactor, midPt, midPt, false); 2414 2415 } else if (tg.Pixels.size() == 4) //2 segments 2416 { 2417 midPt = lineutility.MidPointDouble(pt1, pt2, 0); 2418 AddIntegralAreaModifier(tg,tg.get_DTG() + WDash, aboveMiddle, 0, midPt, midPt, false); 2419 AddIntegralAreaModifier(tg, tg.get_DTG1(), aboveMiddle, csFactor, midPt, midPt, false); 2420 AddIntegralAreaModifier(tg, tg.get_Name(), aboveMiddle, 2 * csFactor, midPt, midPt, false); 2421 } else // 3 or more segments 2422 { 2423 midPt = lineutility.MidPointDouble(pt1, pt2, 0); 2424 AddIntegralAreaModifier(tg, tg.get_DTG() + WDash, aboveMiddle, -csFactor / 2, midPt, midPt, false); 2425 AddIntegralAreaModifier(tg, tg.get_DTG1(), aboveMiddle, csFactor / 2, midPt, midPt, false); 2426 midPt = lineutility.MidPointDouble(pt2, pt3, 0); 2427 AddIntegralAreaModifier(tg, tg.get_Name(), aboveMiddle, -csFactor / 2, midPt, midPt, false); 2428 } 2429 break; 2430 case TacticalLines.LL: 2431 case TacticalLines.LOD: 2432 case TacticalLines.LDLC: 2433 case TacticalLines.PLD: 2434 case TacticalLines.RELEASE: 2435 case TacticalLines.HOL: 2436 case TacticalLines.BHL: 2437 case TacticalLines.FCL: 2438 case TacticalLines.HOLD: 2439 case TacticalLines.BRDGHD: 2440 case TacticalLines.HOLD_GE: 2441 case TacticalLines.BRDGHD_GE: 2442 case TacticalLines.LOA: 2443 case TacticalLines.IFF_OFF: 2444 case TacticalLines.IFF_ON: 2445 AddIntegralAreaModifier(tg, label, aboveEnd, -csFactor, pt0, pt1, false); 2446 AddIntegralAreaModifier(tg, label, aboveEnd, -csFactor, ptLast, ptNextToLast, false); 2447 break; 2448 case TacticalLines.EWL: 2449 AddIntegralAreaModifier(tg, label, aboveEnd, -csFactor, pt0, pt1, false); 2450 AddIntegralAreaModifier(tg, label, aboveEnd, -csFactor, ptLast, ptNextToLast, false); 2451 tg.set_EchelonSymbol(""); 2452 if (clipRect != null) { 2453 AddBoundaryModifiers(tg, g2d, clipRect); 2454 } else { 2455 AddBoundaryModifiers(tg, g2d, clipArray); 2456 } 2457 break; 2458 case TacticalLines.AIRFIELD: 2459 ur = new POINT2(); 2460 ul = new POINT2(); 2461 ll = new POINT2(); 2462 lr = new POINT2(); 2463 Modifier2.GetMBR(tg, ul, ur, lr, ll); 2464 stringWidth = metrics.stringWidth(tg.get_H()); 2465 pt0.x = ur.x + stringWidth / 2 + 1; 2466 //pt0.x=ptUr.x+1; 2467 //pt0.y=(ptUr.y+ptLr.y)/2-metrics.getFont().getSize() 2468 pt0.y = (ur.y + lr.y) / 2 - font.getSize(); 2469 AddIntegralAreaModifier(tg, tg.get_H(), area, csFactor, pt0, pt0, false); 2470 break; 2471 case TacticalLines.LAUNCH_AREA: 2472 case TacticalLines.DEFENDED_AREA_CIRCULAR: 2473 AddIntegralAreaModifier(tg, label + TDash + tg.get_Name(), area, 0, ptCenter, ptCenter, false); 2474 break; 2475 case TacticalLines.JTAA: 2476 case TacticalLines.SAA: 2477 case TacticalLines.SGAA: 2478 addNModifier(tg, g2d); 2479 AddIntegralAreaModifier(tg, label + TDash + tg.get_Name(), area, 0, ptCenter, ptCenter, false); 2480 addDTG(tg, area, csFactor, 2 * csFactor, ptCenter, ptCenter, metrics); 2481 break; 2482 case TacticalLines.FORT: 2483 case TacticalLines.ZONE: 2484 AddIntegralAreaModifier(tg, tg.get_Name(), area, 0, ptCenter, ptCenter, false); 2485 break; 2486 case TacticalLines.BDZ: 2487 AddIntegralAreaModifier(tg, label, area, 0, pt0, pt0, false); 2488 break; 2489 case TacticalLines.ASSAULT: 2490 case TacticalLines.ATKPOS: 2491 case TacticalLines.OBJ: 2492 case TacticalLines.NAI: 2493 case TacticalLines.TAI: 2494 case TacticalLines.BASE_CAMP_REVD: 2495 case TacticalLines.GUERILLA_BASE_REVD: 2496 case TacticalLines.ASSY: 2497 case TacticalLines.EA: 2498 case TacticalLines.DZ: 2499 case TacticalLines.EZ: 2500 case TacticalLines.LZ: 2501 case TacticalLines.PZ: 2502 case TacticalLines.AO: 2503 AddIntegralAreaModifier(tg, label + TSpace + tg.get_Name(), area, 0, ptCenter, ptCenter, false); 2504 break; 2505 case TacticalLines.BASE_CAMP: 2506 case TacticalLines.GUERILLA_BASE: 2507 AddIntegralAreaModifier(tg, label + TSpace + tg.get_Name(), area, -1 * csFactor, ptCenter, ptCenter, false); 2508 AddModifier(tg, tg.get_H(), area, 0, ptCenter, ptCenter); 2509 addDTG(tg, area, 1 * csFactor, 2 * csFactor, ptCenter, ptCenter, metrics); 2510 addNModifier(tg, g2d); 2511 addModifierBottomSegment(tg, tg.get_EchelonSymbol()); 2512 break; 2513 case TacticalLines.GENERIC_AREA: 2514 AddIntegralAreaModifier(tg, tg.get_H() + " " + tg.get_Name(), area, -0.5 * csFactor, ptCenter, ptCenter, false); 2515 addDTG(tg, area, 0.5 * csFactor, 1.5 * csFactor, ptCenter, ptCenter, metrics); 2516 addNModifier(tg, g2d); 2517 break; 2518 case TacticalLines.AIRHEAD: 2519 GetMBR(tg, ul, ur, lr, ll); 2520 AddIntegralAreaModifier(tg, label, aboveMiddle, csFactor, ll, lr, false); 2521 break; 2522 case TacticalLines.AC: 2523 case TacticalLines.LLTR: 2524 case TacticalLines.MRR: 2525 case TacticalLines.SL: 2526 case TacticalLines.TC: 2527 case TacticalLines.SAAFR: 2528 case TacticalLines.SC: 2529 AddIntegralModifier(tg, "Name: " + tg.get_Name(), aboveMiddle, -7 * csFactor, middleSegment, middleSegment + 1, false); 2530 AddIntegralModifier(tg, "Width: " + tg.get_AM(), aboveMiddle, -6 * csFactor, middleSegment, middleSegment + 1, false); 2531 AddIntegralModifier(tg, "Min Alt: " + tg.get_X(), aboveMiddle, -5 * csFactor, middleSegment, middleSegment + 1, false); 2532 AddIntegralModifier(tg, "Max Alt: " + tg.get_X1(), aboveMiddle, -4 * csFactor, middleSegment, middleSegment + 1, false); 2533 AddIntegralModifier(tg, "DTG Start: " + tg.get_DTG(), aboveMiddle, -3 * csFactor, middleSegment, middleSegment + 1, false); 2534 AddIntegralModifier(tg, "DTG End: " + tg.get_DTG1(), aboveMiddle, -2 * csFactor, middleSegment, middleSegment + 1, false); 2535 AddIntegralModifier(tg, label + TSpace + tg.get_Name(), aboveMiddle, 0, middleSegment, middleSegment + 1, false); 2536 break; 2537 case TacticalLines.BEARING_J: 2538 case TacticalLines.BEARING_RDF: 2539 case TacticalLines.BEARING: 2540 case TacticalLines.ELECTRO: 2541 case TacticalLines.BEARING_EW: 2542 case TacticalLines.ACOUSTIC: 2543 case TacticalLines.ACOUSTIC_AMB: 2544 case TacticalLines.TORPEDO: 2545 case TacticalLines.OPTICAL: 2546 midPt = lineutility.MidPointDouble(pt0, pt1, 0); 2547 AddIntegralAreaModifier(tg, label, aboveMiddle, 0, midPt, midPt, true); 2548 pt3 = lineutility.ExtendDirectedLine(pt0, pt1, pt1, 3, font.getSize() / 2.0); 2549 AddIntegralAreaModifier(tg, tg.get_H(), aboveMiddle, 1, pt3, pt3, true); 2550 break; 2551 case TacticalLines.ACA: 2552 AddIntegralAreaModifier(tg, label + TSpace + tg.get_Name(), area, -3 * csFactor, ptCenter, ptCenter, false); 2553 AddIntegralAreaModifier(tg, tg.get_T1(), area, -2 * csFactor, ptCenter, ptCenter, false); 2554 AddIntegralAreaModifier(tg, "MIN ALT: " + tg.get_X(), area, -1 * csFactor, ptCenter, ptCenter, false, "H"); 2555 AddIntegralAreaModifier(tg, "MAX ALT: " + tg.get_X1(), area, 0, ptCenter, ptCenter, false, "H1"); 2556 AddIntegralAreaModifier(tg, tg.get_Location(), area, 1 * csFactor, ptCenter, ptCenter, false, "H2"); 2557 addDTG(tg, area, 2 * csFactor, 3 * csFactor, ptCenter, ptCenter, metrics); 2558 break; 2559 case TacticalLines.MFP: 2560 pt0 = tg.Pixels.get(middleSegment); 2561 pt1 = tg.Pixels.get(middleSegment + 1); 2562 AddIntegralModifier(tg, label, aboveMiddle, 0, middleSegment, middleSegment + 1, true); 2563 AddIntegralModifier(tg, tg.get_DTG() + WDash, aboveEnd, 1 * csFactor, 0, 1, false); 2564 AddIntegralModifier(tg, tg.get_DTG1(), aboveEnd, 2 * csFactor, 0, 1, false); 2565 break; 2566 case TacticalLines.LINTGT: 2567 AddIntegralModifier(tg, ap, aboveMiddle, -0.7 * csFactor, middleSegment, middleSegment + 1, false); 2568 break; 2569 case TacticalLines.LINTGTS: 2570 AddIntegralModifier(tg, ap, aboveMiddle, -0.7 * csFactor, middleSegment, middleSegment + 1, false); 2571 AddIntegralModifier(tg, label, aboveMiddle, 0.7 * csFactor, middleSegment, middleSegment + 1, false); 2572 break; 2573 case TacticalLines.FPF: 2574 AddIntegralModifier(tg, ap, aboveMiddle, -0.7 * csFactor, 0, 1, false); 2575 AddIntegralModifier(tg, label, aboveMiddle, .7 * csFactor, 0, 1, false); 2576 AddIntegralModifier(tg, tg.get_T1(), aboveMiddle, 1.7 * csFactor, 0, 1, false); 2577 AddIntegralModifier(tg, v, aboveMiddle, 2.7 * csFactor, 0, 1, false); 2578 break; 2579 case TacticalLines.AT: 2580 AddIntegralAreaModifier(tg, ap, area, 0, ptCenter, ptCenter, false); 2581 break; 2582 case TacticalLines.RECTANGULAR: 2583 case TacticalLines.CIRCULAR: 2584 AddIntegralAreaModifier(tg, ap, area, 0, pt0, pt0, false); 2585 break; 2586 case TacticalLines.RECTANGULAR_TARGET: 2587 stringWidth = metrics.stringWidth(tg.get_Name()); 2588 POINT2 offsetCenterPoint = new POINT2(ptCenter.x + ((double) stringWidth) / 2.0, ptCenter.y); 2589 AddIntegralAreaModifier(tg, tg.get_Name(), area, -1 * csFactor, offsetCenterPoint, offsetCenterPoint, false); 2590 break; 2591 case TacticalLines.SMOKE: 2592 AddIntegralAreaModifier(tg, ap, area, -csFactor, ptCenter, ptCenter, false); 2593 AddIntegralAreaModifier(tg, label, area, 0, ptCenter, ptCenter, false); 2594 addDTG(tg, area, 1 * csFactor, 2 * csFactor, ptCenter, ptCenter, metrics); 2595 break; 2596 case TacticalLines.LINE: 2597 AddIntegralModifier(tg, tg.get_Name(), aboveMiddle, csFactor, middleSegment, middleSegment + 1, false); 2598 break; 2599 case TacticalLines.MINED: 2600 if (tg.isHostile()) { 2601 pt1 = lineutility.MidPointDouble(pt0, pt1, 0); 2602 AddIntegralAreaModifier(tg, tg.get_N(), aboveMiddle, 0, pt0, pt1, true); 2603 if (middleSegment != 0) { 2604 pt0 = tg.Pixels.get(middleSegment); 2605 pt1 = tg.Pixels.get(middleSegment + 1); 2606 pt1 = lineutility.MidPointDouble(pt0, pt1, 0); 2607 AddIntegralAreaModifier(tg, tg.get_N(), aboveMiddle, 0, pt0, pt1, true); 2608 } 2609 } 2610 GetMBR(tg, ul, ur, lr, ll); 2611 AddIntegralAreaModifier(tg, tg.get_H(), aboveMiddle, -1.5 * csFactor, ul, ur, false); 2612 AddIntegralAreaModifier(tg, tg.get_DTG(), aboveMiddle, 1.5 * csFactor, ll, lr, false); 2613 addModifierOnLine("M", tg, g2d); 2614 AddIntegralAreaModifier(tg, getImageModifier(tg), areaImage, 0, ptCenter, ptCenter, false); 2615 break; 2616 case TacticalLines.FENCED: 2617 if (tg.isHostile()) { 2618 pt1 = lineutility.MidPointDouble(pt0, pt1, 0); 2619 AddIntegralAreaModifier(tg, tg.get_N(), aboveMiddle, 0, pt0, pt1, true); 2620 if (middleSegment != 0) { 2621 pt0 = tg.Pixels.get(middleSegment); 2622 pt1 = tg.Pixels.get(middleSegment + 1); 2623 pt1 = lineutility.MidPointDouble(pt0, pt1, 0); 2624 AddIntegralAreaModifier(tg, tg.get_N(), aboveMiddle, 0, pt0, pt1, true); 2625 } 2626 } 2627 addModifierOnLine("M", tg, g2d); 2628 AddIntegralAreaModifier(tg, getImageModifier(tg), areaImage, 0, ptCenter, ptCenter, false); 2629 break; 2630 case TacticalLines.ASLTXING: 2631 if (tg.Pixels.get(1).y > tg.Pixels.get(0).y) { 2632 pt0 = tg.Pixels.get(1); 2633 pt1 = tg.Pixels.get(3); 2634 pt2 = tg.Pixels.get(0); 2635 pt3 = tg.Pixels.get(2); 2636 } else { 2637 pt0 = tg.Pixels.get(0); 2638 pt1 = tg.Pixels.get(2); 2639 pt2 = tg.Pixels.get(1); 2640 pt3 = tg.Pixels.get(3); 2641 } 2642 pt2 = lineutility.ExtendAlongLineDouble2(pt0, pt2, -20); 2643 pt3 = lineutility.ExtendAlongLineDouble2(pt1, pt3, -20); 2644 addDTG(tg, aboveMiddle, 0, csFactor, pt2, pt3, metrics); 2645 break; 2646 case TacticalLines.SERIES: 2647 case TacticalLines.DRCL: 2648 addModifierTopSegment(tg, tg.get_Name()); 2649 break; 2650 case TacticalLines.STRIKWARN: 2651 AddIntegralModifier(tg, "1", aboveMiddle, 0, index, index + 1, true); 2652 AddIntegralModifier(tg, "2", aboveMiddle, 0, size/2, size/2 + 1, true); 2653 break; 2654 case TacticalLines.SCREEN: 2655 case TacticalLines.COVER: 2656 case TacticalLines.GUARD: 2657 if (tg.Pixels.size() == 4) { 2658 pt1 = new POINT2(tg.Pixels.get(1)); 2659 pt2 = new POINT2(tg.Pixels.get(2)); 2660 AddIntegralAreaModifier(tg, label, area, 0, pt1, pt1, true); 2661 AddIntegralAreaModifier(tg, label, area, 0, pt2, pt2, true); 2662 } else { 2663 stringHeight = (int) (0.5 * (double) font.getSize()); 2664 dAngle0 = Math.atan2(tg.Pixels.get(0).y - tg.Pixels.get(1).y, tg.Pixels.get(0).x - tg.Pixels.get(1).x); 2665 dAngle1 = Math.atan2(tg.Pixels.get(0).y - tg.Pixels.get(2).y, tg.Pixels.get(0).x - tg.Pixels.get(2).x); 2666 pt0 = new POINT2(tg.Pixels.get(0)); 2667 pt0.x -= 30 * Math.cos(dAngle0); 2668 pt0.y -= 30 * Math.sin(dAngle0) + stringHeight; 2669 pt1 = new POINT2(tg.Pixels.get(0)); 2670 pt1.x -= 30 * Math.cos(dAngle1); 2671 pt1.y -= 30 * Math.sin(dAngle1) + stringHeight; 2672 AddIntegralAreaModifier(tg, label, area, 0, pt0, pt0, true); 2673 AddIntegralAreaModifier(tg, label, area, 0, pt1, pt1, true); 2674 } 2675 break; 2676 case TacticalLines.MSR_ONEWAY: 2677 case TacticalLines.ASR_ONEWAY: 2678 case TacticalLines.ROUTE_ONEWAY: 2679 case TacticalLines.MSR_TWOWAY: 2680 case TacticalLines.ASR_TWOWAY: 2681 case TacticalLines.MSR_ALT: 2682 case TacticalLines.ASR_ALT: 2683 case TacticalLines.ROUTE_ALT: 2684 stringWidth = (int) (1.5 * (double) metrics.stringWidth(label + TSpace + tg.get_Name())); 2685 double arrowOffset = 10 * DPIScaleFactor; 2686 if (linetype == TacticalLines.MSR_TWOWAY || linetype == TacticalLines.ASR_TWOWAY) 2687 arrowOffset = 25 * DPIScaleFactor; 2688 boolean isAlt = linetype == TacticalLines.MSR_ALT || linetype == TacticalLines.ASR_ALT || linetype == TacticalLines.ROUTE_ALT; 2689 if (isAlt) { 2690 stringWidth2 = (int) (1.5 * (double) metrics.stringWidth("ALT")); 2691 if (stringWidth2 > stringWidth) { 2692 stringWidth = stringWidth2; 2693 } 2694 } 2695 2696 foundSegment = false; 2697 //acevedo - 11/30/2017 - adding option to render only 2 labels. 2698 if (RendererSettings.getInstance().getTwoLabelOnly() == false) { 2699 for (j = 0; j < tg.Pixels.size() - 1; j++) { 2700 pt0 = tg.Pixels.get(j); 2701 pt1 = tg.Pixels.get(j + 1); 2702 dist = lineutility.CalcDistanceDouble(pt0, pt1); 2703 int arrowSide = arraysupport.SupplyRouteArrowSide(pt0, pt1); 2704 if (dist < stringWidth) { 2705 continue; 2706 } else { 2707 if (arrowSide == 1 || arrowSide == 2) { 2708 // Shift points to account for arrow shift with DPI 2709 pt0 = lineutility.ExtendDirectedLine(pt1, pt0, pt0, arrowSide, arrowOffset); 2710 pt1 = lineutility.ExtendDirectedLine(pt1, pt0, pt1, arrowSide, arrowOffset); 2711 AddModifier(tg, label + TSpace + tg.get_Name(), aboveMiddle, -1.7 * csFactor, pt0, pt1); 2712 if (isAlt) 2713 AddModifier(tg, "ALT", aboveMiddle, 0, pt0, pt1); 2714 } else { 2715 AddModifier(tg, label + TSpace + tg.get_Name(), aboveMiddle, -0.7 * csFactor, pt0, pt1); 2716 if (isAlt) { 2717 pt0 = lineutility.ExtendDirectedLine(pt1, pt0, pt0, arrowSide, arrowOffset); 2718 pt1 = lineutility.ExtendDirectedLine(pt1, pt0, pt1, arrowSide, arrowOffset); 2719 AddModifier(tg, "ALT", aboveMiddle, 0, pt0, pt1); 2720 } 2721 } 2722 foundSegment = true; 2723 } 2724 } 2725 if (foundSegment == false) { 2726 pt0 = tg.Pixels.get(middleSegment); 2727 pt1 = tg.Pixels.get(middleSegment + 1); 2728 int arrowSide = arraysupport.SupplyRouteArrowSide(pt0, pt1); 2729 if (arrowSide == 1 || arrowSide == 2) { 2730 // Shift points to account for arrow shift with DPI 2731 pt0 = lineutility.ExtendDirectedLine(pt1, pt0, pt0, arrowSide, arrowOffset); 2732 pt1 = lineutility.ExtendDirectedLine(pt1, pt0, pt1, arrowSide, arrowOffset); 2733 AddModifier(tg, label + TSpace + tg.get_Name(), aboveMiddle, -1.7 * csFactor, pt0, pt1); 2734 if (isAlt) 2735 AddModifier(tg, "ALT", aboveMiddle, 0, pt0, pt1); 2736 } else { 2737 AddModifier(tg, label + TSpace + tg.get_Name(), aboveMiddle, -0.7 * csFactor, pt0, pt1); 2738 if (isAlt) { 2739 pt0 = lineutility.ExtendDirectedLine(pt1, pt0, pt0, arrowSide, arrowOffset); 2740 pt1 = lineutility.ExtendDirectedLine(pt1, pt0, pt1, arrowSide, arrowOffset); 2741 AddModifier(tg, "ALT", aboveMiddle, 0, pt0, pt1); 2742 } 2743 } 2744 } 2745 } 2746 else { 2747 // 2 labels one to the north and the other to the south of graphic. 2748 northestPtIndex = 0; 2749 northestPt = tg.Pixels.get(northestPtIndex); 2750 southestPtIndex = 0; 2751 southestPt = tg.Pixels.get(southestPtIndex); 2752 2753 for (j = 0; j < tg.Pixels.size() - 1; j++) { 2754 pt0 = tg.Pixels.get(j); 2755 if (pt0.y >= northestPt.y) { 2756 northestPt = pt0; 2757 northestPtIndex = j; 2758 } 2759 if (pt0.y <= southestPt.y) { 2760 southestPt = pt0; 2761 southestPtIndex = j; 2762 } 2763 } 2764 2765 AddIntegralModifier(tg, label + TSpace + tg.get_Name(), aboveMiddle, -1.7 * csFactor, northestPtIndex, northestPtIndex + 1, false); 2766 if (isAlt) 2767 AddIntegralModifier(tg, "ALT", aboveMiddle, -0.7 * csFactor, northestPtIndex, northestPtIndex + 1, false); 2768 2769 if (northestPtIndex != southestPtIndex) { 2770 AddIntegralModifier(tg, label + TSpace + tg.get_Name(), aboveMiddle, -1.7 * csFactor, southestPtIndex, southestPtIndex + 1, false); 2771 if (isAlt) 2772 AddIntegralModifier(tg, "ALT", aboveMiddle, -0.7 * csFactor, southestPtIndex, southestPtIndex + 1, false); 2773 } 2774 }//else 2775 break; 2776 case TacticalLines.DHA_REVD: 2777 AddIntegralAreaModifier(tg, "DETAINEE", area, -1.5 * csFactor, ptCenter, ptCenter, false); 2778 AddIntegralAreaModifier(tg, "HOLDING", area, -0.5 * csFactor, ptCenter, ptCenter, false); 2779 AddIntegralAreaModifier(tg, "AREA", area, 0.5 * csFactor, ptCenter, ptCenter, false); 2780 AddIntegralAreaModifier(tg, tg.get_Name(), area, 1.5 * csFactor, ptCenter, ptCenter, false); 2781 break; 2782 case TacticalLines.EPW: 2783 AddIntegralAreaModifier(tg, "EPW", area, -1.5 * csFactor, ptCenter, ptCenter, false); 2784 AddIntegralAreaModifier(tg, "HOLDING", area, -0.5 * csFactor, ptCenter, ptCenter, false); 2785 AddIntegralAreaModifier(tg, "AREA", area, 0.5 * csFactor, ptCenter, ptCenter, false); 2786 AddIntegralAreaModifier(tg, tg.get_Name(), area, 1.5 * csFactor, ptCenter, ptCenter, false); 2787 break; 2788 case TacticalLines.UXO: 2789 addModifierOnLine("UXO", tg, g2d); 2790 break; 2791 case TacticalLines.GENERAL: 2792 addNModifier(tg, g2d); 2793 break; 2794 case TacticalLines.DHA: 2795 case TacticalLines.FARP: 2796 AddIntegralAreaModifier(tg, label, area, -0.5 * csFactor, ptCenter, ptCenter, false); 2797 AddIntegralAreaModifier(tg, tg.get_Name(), area, 0.5 * csFactor, ptCenter, ptCenter, false); 2798 break; 2799 case TacticalLines.BSA: 2800 case TacticalLines.DSA: 2801 case TacticalLines.CSA: 2802 case TacticalLines.RSA: 2803 AddIntegralAreaModifier(tg, label, area, 0, ptCenter, ptCenter, false); 2804 break; 2805 case TacticalLines.RHA: 2806 AddIntegralAreaModifier(tg, "REFUGEE", area, -1.5 * csFactor, ptCenter, ptCenter, false); 2807 AddIntegralAreaModifier(tg, "HOLDING", area, -0.5 * csFactor, ptCenter, ptCenter, false); 2808 AddIntegralAreaModifier(tg, "AREA", area, 0.5 * csFactor, ptCenter, ptCenter, false); 2809 AddIntegralAreaModifier(tg, tg.get_Name(), area, 1.5 * csFactor, ptCenter, ptCenter, false); 2810 break; 2811 case TacticalLines.MSR: 2812 case TacticalLines.ASR: 2813 case TacticalLines.ROUTE: 2814 //AddIntegralModifier(tg, label + tg.get_Name(), aboveMiddle, -1*csFactor, middleSegment, middleSegment + 1,false); 2815 foundSegment = false; 2816 //acevedo - 11/30/2017 - adding option to render only 2 labels. 2817 if (RendererSettings.getInstance().getTwoLabelOnly() == false) { 2818 for (j = 0; j < tg.Pixels.size() - 1; j++) { 2819 pt0 = tg.Pixels.get(j); 2820 pt1 = tg.Pixels.get(j + 1); 2821 stringWidth = (int) (1.5 * (double) metrics.stringWidth(label + TSpace + tg.get_Name())); 2822 dist = lineutility.CalcDistanceDouble(pt0, pt1); 2823 if (dist < stringWidth) { 2824 continue; 2825 } else { 2826 AddIntegralModifier(tg, label + TSpace + tg.get_Name(), aboveMiddle, -1 * csFactor, j, j + 1, false); 2827 foundSegment = true; 2828 } 2829 } 2830 if (foundSegment == false) { 2831 AddIntegralModifier(tg, label + TSpace + tg.get_Name(), aboveMiddle, -1 * csFactor, middleSegment, middleSegment + 1, false); 2832 } 2833 } 2834 else { 2835 // 2 labels one to the north and the other to the south of graphic. 2836 for (j = 0; j < tg.Pixels.size() ; j++) { 2837 pt0 = tg.Pixels.get(j); 2838 2839 if (northestPt == null) 2840 { 2841 northestPt = pt0; 2842 northestPtIndex = j; 2843 } 2844 if (southestPt == null) 2845 { 2846 southestPt = pt0; 2847 southestPtIndex = j; 2848 } 2849 if (pt0.y >= northestPt.y) 2850 { 2851 northestPt = pt0; 2852 northestPtIndex = j; 2853 } 2854 2855 if (pt0.y <= southestPt.y) 2856 { 2857 southestPt = pt0; 2858 southestPtIndex = j; 2859 } 2860 }//for 2861 middleSegment = northestPtIndex; 2862 middleSegment2 = southestPtIndex; 2863 2864 if (middleSegment == tg.Pixels.size() -1) { 2865 middleSegment-=1; 2866 } 2867 if (middleSegment2 == tg.Pixels.size() -1) { 2868 middleSegment2-=1; 2869 } 2870 if (middleSegment == middleSegment2) { 2871 middleSegment2-=1; 2872 } 2873 2874 // if (middleSegment != middleSegment2) { 2875 AddIntegralModifier(tg, label + TSpace + tg.get_Name(), aboveMiddle, 0, middleSegment, middleSegment + 1, false); 2876 //} 2877 AddIntegralModifier(tg, label + TSpace + tg.get_Name(), aboveMiddle, 0, middleSegment2, middleSegment2 + 1, false); 2878 2879 }//else 2880 break; 2881 case TacticalLines.GAP: 2882 if (tg.Pixels.get(1).y > tg.Pixels.get(0).y) { 2883 pt0 = tg.Pixels.get(1); 2884 pt1 = tg.Pixels.get(3); 2885 pt2 = tg.Pixels.get(0); 2886 pt3 = tg.Pixels.get(2); 2887 } else { 2888 pt0 = tg.Pixels.get(0); 2889 pt1 = tg.Pixels.get(2); 2890 pt2 = tg.Pixels.get(1); 2891 pt3 = tg.Pixels.get(3); 2892 } 2893 pt2 = lineutility.ExtendAlongLineDouble2(pt0, pt2, -20); 2894 pt3 = lineutility.ExtendAlongLineDouble2(pt1, pt3, -20); 2895 AddIntegralAreaModifier(tg, tg.get_Name(), aboveMiddle, 0, pt0, pt1, false); 2896 addDTG(tg, aboveMiddle, 0, csFactor, pt2, pt3, metrics); 2897 break; 2898 case TacticalLines.BIO: 2899 case TacticalLines.CHEM: 2900 case TacticalLines.NUC: 2901 case TacticalLines.RAD: 2902 AddIntegralAreaModifier(tg, getImageModifier(tg), areaImage, 0, ptCenter, ptCenter, false); 2903 break; 2904 case TacticalLines.ANCHORAGE_LINE: 2905 AddIntegralAreaModifier(tg, getImageModifier(tg), aboveMiddle, -0.15 * csFactor, tg.Pixels.get(middleSegment), tg.Pixels.get(middleSegment+1), false); 2906 break; 2907 case TacticalLines.ANCHORAGE_AREA: 2908 // Add anchor on segment with lowest midpoint 2909 y = pt0.y + pt1.y; 2910 index = 0; 2911 for (j = 1; j < size - 1; j++) { 2912 if (y < tg.Pixels.get(j).y + tg.Pixels.get(j + 1).y) { 2913 index = j; 2914 y = tg.Pixels.get(index).y + tg.Pixels.get(index + 1).y; 2915 } 2916 } 2917 AddIntegralAreaModifier(tg, getImageModifier(tg), aboveMiddle, -0.25 * csFactor, tg.Pixels.get(index), tg.Pixels.get(index + 1), false); 2918 break; 2919 case TacticalLines.MINE_LINE: 2920 AddIntegralAreaModifier(tg, getImageModifier(tg), aboveMiddle, -0.2 * csFactor, tg.Pixels.get(middleSegment), tg.Pixels.get(middleSegment + 1), false); 2921 if (tg.isHostile()) { 2922 AddIntegralAreaModifier(tg, tg.get_N(), toEnd, 0.0, pt0, pt1, false); 2923 AddIntegralAreaModifier(tg, tg.get_N(), toEnd, 0.0, ptLast, ptNextToLast, false); 2924 } 2925 break; 2926 case TacticalLines.DEPICT: 2927 GetMBR(tg, ul, ur, lr, ll); 2928 addNModifier(tg, g2d); 2929 AddIntegralAreaModifier(tg, getImageModifier(tg), areaImage, 0, ptCenter, ptCenter, false); 2930 break; 2931 case TacticalLines.FFA: 2932 case TacticalLines.RFA: 2933 case TacticalLines.NFA: 2934 AddIntegralAreaModifier(tg, label, area, -1 * csFactor, ptCenter, ptCenter, false); 2935 AddIntegralAreaModifier(tg, tg.get_Name(), area, 0, ptCenter, ptCenter, false); 2936 addDTG(tg, area, 1 * csFactor, 2 * csFactor, ptCenter, ptCenter, metrics); 2937 break; 2938 case TacticalLines.PAA: 2939 addModifierOnLine("PAA", tg, g2d); 2940 AddIntegralAreaModifier(tg, tg.get_Name(), area, -0.5 * csFactor, ptCenter, ptCenter, false); 2941 addDTG(tg, area, 0.5 * csFactor, 1.5 * csFactor, ptCenter, ptCenter, metrics); 2942 break; 2943 case TacticalLines.FSA: 2944 AddIntegralAreaModifier(tg, label + TSpace + tg.get_Name(), area, -0.5 * csFactor, ptCenter, ptCenter, false); 2945 addDTG(tg, area, 0.5 * csFactor, 1.5 * csFactor, ptCenter, ptCenter, metrics); 2946 break; 2947 case TacticalLines.ATI: 2948 case TacticalLines.CFFZ: 2949 case TacticalLines.CFZ: 2950 case TacticalLines.TBA: 2951 case TacticalLines.TVAR: 2952 case TacticalLines.ZOR: 2953 case TacticalLines.DA: 2954 case TacticalLines.SENSOR: 2955 case TacticalLines.CENSOR: 2956 case TacticalLines.KILLBOXBLUE: 2957 case TacticalLines.KILLBOXPURPLE: 2958 AddIntegralAreaModifier(tg, label, area, -0.5 * csFactor, ptCenter, ptCenter, false); 2959 AddIntegralAreaModifier(tg, tg.get_Name(), area, 0.5 * csFactor, ptCenter, ptCenter, false); 2960 GetMBR(tg, ul, ur, lr, ll); 2961 POINT2 ptLeft = ul; 2962 POINT2 ptRight = ur; 2963 if (tg.get_Client().equalsIgnoreCase("ge")) { 2964 ptLeft.x -= font.getSize() / 2; 2965 ptRight.x -= font.getSize() / 2; 2966 } 2967 AddIntegralAreaModifier(tg, tg.get_DTG() + WDash, toEnd, 0.5 * csFactor, ptLeft, ptRight, false, "W"); 2968 AddIntegralAreaModifier(tg, tg.get_DTG1(), toEnd, 1.5 * csFactor, ptLeft, ptRight, false, "W1"); 2969 break; 2970 case TacticalLines.BATTLE: 2971 case TacticalLines.STRONG: 2972 AddIntegralAreaModifier(tg, tg.get_Name(), area, 0, ptCenter, ptCenter, false); 2973 addModifierBottomSegment(tg, tg.get_EchelonSymbol()); 2974 break; 2975 case TacticalLines.PNO: 2976 AddIntegralAreaModifier(tg, label + TSpace + tg.get_Name(), area, 0, ptCenter, ptCenter, false); 2977 addModifierBottomSegment(tg, tg.get_EchelonSymbol()); 2978 addNModifier(tg, g2d); 2979 break; 2980 case TacticalLines.WFZ: 2981 AddIntegralAreaModifier(tg, label, area, -1.5 * csFactor, ptCenter, ptCenter, true); 2982 AddIntegralAreaModifier(tg, tg.get_Name(), area, -0.5 * csFactor, ptCenter, ptCenter, true); 2983 AddIntegralAreaModifier(tg, "TIME FROM: " + tg.get_DTG(), area, 0.5 * csFactor, ptCenter, ptCenter, true, "W"); 2984 AddIntegralAreaModifier(tg, "TIME TO: " + tg.get_DTG1(), area, 1.5 * csFactor, ptCenter, ptCenter, true, "W1"); 2985 break; 2986 case TacticalLines.OBSFAREA: 2987 AddIntegralAreaModifier(tg, label, area, -1.5 * csFactor, ptCenter, ptCenter, false); 2988 AddIntegralAreaModifier(tg, tg.get_Name(), area, -0.5 * csFactor, ptCenter, ptCenter, false); 2989 AddIntegralAreaModifier(tg, tg.get_DTG() + WDash, area, 0.5 * csFactor, ptCenter, ptCenter, false, "W"); 2990 AddIntegralAreaModifier(tg, tg.get_DTG1(), area, 1.5 * csFactor, ptCenter, ptCenter, false, "W1"); 2991 break; 2992 case TacticalLines.OBSAREA: 2993 AddIntegralAreaModifier(tg, tg.get_Name(), area, -1 * csFactor, ptCenter, ptCenter, true); 2994 AddIntegralAreaModifier(tg, tg.get_DTG() + WDash, area, 0, ptCenter, ptCenter, true, "W"); 2995 AddIntegralAreaModifier(tg, tg.get_DTG1(), area, 1 * csFactor, ptCenter, ptCenter, true, "W1"); 2996 break; 2997 case TacticalLines.ROZ: 2998 case TacticalLines.AARROZ: 2999 case TacticalLines.UAROZ: 3000 case TacticalLines.WEZ: 3001 case TacticalLines.FEZ: 3002 case TacticalLines.JEZ: 3003 case TacticalLines.FAADZ: 3004 case TacticalLines.HIDACZ: 3005 case TacticalLines.MEZ: 3006 case TacticalLines.LOMEZ: 3007 case TacticalLines.HIMEZ: 3008 AddIntegralAreaModifier(tg, label, area, -2.5, ptCenter, ptCenter, false, ""); 3009 AddIntegralAreaModifier(tg, tg.get_Name(), area, -1.5, ptCenter, ptCenter, false, "T"); 3010 AddIntegralAreaModifier(tg, "MIN ALT: " + tg.get_X(), area, -0.5, ptCenter, ptCenter, false, "H"); 3011 AddIntegralAreaModifier(tg, "MAX ALT: " + tg.get_X1(), area, 0.5, ptCenter, ptCenter, false, "H1"); 3012 AddIntegralAreaModifier(tg, "TIME FROM: " + tg.get_DTG(), area, 1.5, ptCenter, ptCenter, false, "W"); 3013 AddIntegralAreaModifier(tg, "TIME TO: " + tg.get_DTG1(), area, 2.5, ptCenter, ptCenter, false, "W1"); 3014 break; 3015 case TacticalLines.ENCIRCLE: 3016 if (tg.isHostile()) { 3017 AddIntegralModifier(tg, tg.get_N(), aboveMiddle, 0, 0, 1, true); 3018 AddIntegralModifier(tg, tg.get_N(), aboveMiddle, 0, middleSegment, middleSegment + 1, true); 3019 } 3020 break; 3021 case TacticalLines.LAA: 3022 AddIntegralAreaModifier(tg, getImageModifier(tg), areaImage, 0, ptCenter, ptCenter, false); 3023 AddIntegralAreaModifier(tg, label, area, -1 * csFactor, ptCenter, ptCenter, false); 3024 break; 3025 case TacticalLines.BOUNDARY: 3026 if (clipRect != null) { 3027 AddBoundaryModifiers(tg, g2d, clipRect); 3028 } else { 3029 AddBoundaryModifiers(tg, g2d, clipArray); 3030 } 3031 break; 3032 case TacticalLines.CFL: 3033 stringWidth = (int) ((double) metrics.stringWidth(label + TSpace + tg.get_Name())); 3034 stringWidth2 = (int) ((double) metrics.stringWidth(tg.get_DTG() + WDash + tg.get_DTG1())); 3035 if (stringWidth2 > stringWidth) { 3036 stringWidth = stringWidth2; 3037 } 3038 pt0 = new POINT2(tg.Pixels.get(middleSegment)); 3039 pt1 = new POINT2(tg.Pixels.get(middleSegment + 1)); 3040 getPixelsMiddleSegment(tg, stringWidth, pt0, pt1); 3041 AddModifier2(tg, label + TSpace + tg.get_Name(), aboveMiddle, -0.7 * csFactor, pt0, pt1, false); 3042 addDTG(tg, aboveMiddle, 0.7 * csFactor, 1.7 * csFactor, pt0, pt1, metrics); 3043 break; 3044 case TacticalLines.FLOT: 3045 if (tg.get_H().equals("1")) { 3046 label = "LC"; 3047 } else if (tg.get_H().equals("2")) { 3048 label = ""; 3049 } 3050 AddIntegralAreaModifier(tg, label, toEnd, 0, pt0, pt1, false); 3051 AddIntegralAreaModifier(tg, label, toEnd, 0, ptLast, ptNextToLast, false); 3052 3053 if (tg.isHostile()) { 3054 AddIntegralAreaModifier(tg, tg.get_N(), toEnd, -1 * csFactor, pt0, pt1, false); 3055 AddIntegralAreaModifier(tg, tg.get_N(), toEnd, -1 * csFactor, ptLast, ptNextToLast, false); 3056 } 3057 break; 3058 case TacticalLines.LC: 3059 double shiftFactor = 1d; 3060 if (shiftLines) { 3061 shiftFactor = 0.5d; 3062 } 3063 if (tg.isHostile()) { 3064 if (pt0.x < pt1.x) { 3065 TLineFactor = -shiftFactor;//was -1 3066 } else { 3067 TLineFactor = shiftFactor;//was 1 3068 } 3069 AddIntegralAreaModifier(tg, tg.get_N(), toEnd, TLineFactor, pt0, pt1, false); 3070 if (ptNextToLast.x < ptLast.x) { 3071 TLineFactor = -shiftFactor;//was -1 3072 } else { 3073 TLineFactor = shiftFactor;//was 1 3074 } 3075 AddIntegralAreaModifier(tg, tg.get_N(), toEnd, TLineFactor, ptLast, ptNextToLast, false); 3076 } 3077 AddIntegralAreaModifier(tg, label, toEnd, 0, pt0, pt1, false); 3078 AddIntegralAreaModifier(tg, label, toEnd, 0, ptLast, ptNextToLast, false); 3079 break; 3080 case TacticalLines.CATK: 3081 AddIntegralModifier(tg, label, aboveMiddle, 0, 1, 0, false); 3082 break; 3083 case TacticalLines.CATKBYFIRE: 3084 stringWidth = (int) (1.5 * (double) metrics.stringWidth(label)); 3085 pt2 = lineutility.ExtendAlongLineDouble(pt0, pt1, stringWidth); 3086 AddModifier2(tg, label, aboveMiddle, 0, pt1, pt2, false); 3087 break; 3088 case TacticalLines.IL: 3089 AddIntegralModifier(tg, tg.get_Name(), aboveMiddle, 0, 1, 0, false); 3090 break; 3091 case TacticalLines.RETIRE: 3092 case TacticalLines.WITHDRAW: 3093 case TacticalLines.WDRAWUP: 3094 case TacticalLines.FPOL: 3095 case TacticalLines.RPOL: 3096 AddIntegralModifier(tg, label, aboveMiddle, 0, 0, 1, true); 3097 break; 3098 case TacticalLines.RIP: 3099 case TacticalLines.BOMB: 3100 case TacticalLines.TGMF: 3101 AddIntegralAreaModifier(tg, label, area, 0, ptCenter, ptCenter, true); 3102 break; 3103 case TacticalLines.MSDZ: 3104 AddIntegralAreaModifier(tg, "1", area, 0, pt1, pt1, true); 3105 AddIntegralAreaModifier(tg, "2", area, 0, pt2, pt2, true); 3106 AddIntegralAreaModifier(tg, "3", area, 0, pt3, pt3, true); 3107 break; 3108 case TacticalLines.DELAY: 3109 AddIntegralModifier(tg, tg.get_DTG(), aboveMiddle, -1 * csFactor, 0, 1, false); 3110 AddIntegralModifier(tg, label, aboveMiddle, 0, 0, 1, true); 3111 break; 3112 case TacticalLines.GENERIC_LINE: 3113 pt0 = tg.Pixels.get(0); 3114 pt1 = tg.Pixels.get(1); 3115 pt2 = tg.Pixels.get(tg.Pixels.size() - 1); 3116 pt3 = tg.Pixels.get(tg.Pixels.size() - 2); 3117 dist = lineutility.CalcDistanceDouble(pt0, pt1); 3118 dist2 = lineutility.CalcDistanceDouble(pt2, pt3); 3119 stringWidth = (int) ((double) metrics.stringWidth(tg.get_H() + " " + tg.get_Name())); 3120 stringWidth2 = (int) ((double) metrics.stringWidth(tg.get_DTG())); 3121 if (stringWidth2 > stringWidth) { 3122 stringWidth = stringWidth2; 3123 } 3124 3125 if (tg.Pixels.size() == 2) //one segment 3126 { 3127 pt1 = lineutility.ExtendAlongLineDouble(pt0, pt1, stringWidth); 3128 AddModifier2(tg, tg.get_H() + " " + tg.get_Name(), aboveMiddle, -0.7 * csFactor, pt0, pt1, false); 3129 AddModifier2(tg, tg.get_DTG() + WDash, aboveMiddle, 0.7 * csFactor, pt0, pt1, false); 3130 AddModifier2(tg, tg.get_DTG1(), aboveMiddle, 1.7 * csFactor, pt0, pt1, false); 3131 if (dist > 3.5 * stringWidth)//was 28stringwidth+5 3132 { 3133 pt0 = tg.Pixels.get(tg.Pixels.size() - 1); 3134 pt1 = tg.Pixels.get(tg.Pixels.size() - 2); 3135 pt1 = lineutility.ExtendAlongLineDouble(pt0, pt1, stringWidth); 3136 AddModifier2(tg, tg.get_H() + " " + tg.get_Name(), aboveMiddle, -0.7 * csFactor, pt0, pt1, false); 3137 AddModifier2(tg, tg.get_DTG() + WDash, aboveMiddle, 0.7 * csFactor, pt0, pt1, false); 3138 AddModifier2(tg, tg.get_DTG1(), aboveMiddle, 1.7 * csFactor, pt0, pt1, false); 3139 } 3140 } else //more than one semgent 3141 { 3142 double dist3 = lineutility.CalcDistanceDouble(pt0, pt2); 3143 if (dist > stringWidth + 5 || dist >= dist2 || dist3 > stringWidth + 5) { 3144 pt1 = lineutility.ExtendAlongLineDouble(pt0, pt1, stringWidth); 3145 AddModifier2(tg, tg.get_H() + " " + tg.get_Name(), aboveMiddle, -0.7 * csFactor, pt0, pt1, false); 3146 AddModifier2(tg, tg.get_DTG() + WDash, aboveMiddle, 0.7 * csFactor, pt0, pt1, false); 3147 AddModifier2(tg, tg.get_DTG1(), aboveMiddle, 1.7 * csFactor, pt0, pt1, false); 3148 } 3149 if (dist2 > stringWidth + 5 || dist2 > dist || dist3 > stringWidth + 5) { 3150 pt0 = tg.Pixels.get(tg.Pixels.size() - 1); 3151 pt1 = tg.Pixels.get(tg.Pixels.size() - 2); 3152 pt1 = lineutility.ExtendAlongLineDouble(pt0, pt1, stringWidth); 3153 AddModifier2(tg, tg.get_H() + " " + tg.get_Name(), aboveMiddle, -0.7 * csFactor, pt0, pt1, false); 3154 AddModifier2(tg, tg.get_DTG() + WDash, aboveMiddle, 0.7 * csFactor, pt0, pt1, false); 3155 AddModifier2(tg, tg.get_DTG1(), aboveMiddle, 1.7 * csFactor, pt0, pt1, false); 3156 } 3157 } 3158 break; 3159 default: 3160 break; 3161 } 3162 scaleModifiers(tg); 3163 tg.Pixels = origPoints; 3164 } catch (Exception exc) { 3165 ErrorLogger.LogException(_className, "AddModifiersGeo", 3166 new RendererException("Failed inside AddModifiersGeo", exc)); 3167 } 3168 3169 } 3170 3171 /** 3172 * RFA, NFA, FFA need these for line spacing 3173 * 3174 * @param tg 3175 * @return 3176 */ 3177 private static int getRFALines(TGLight tg) { 3178 int lines = 1; 3179 try { 3180 if (tg.get_Name() != null && !tg.get_Name().isEmpty()) { 3181 lines++; 3182 } 3183 if (tg.get_DTG() != null && !tg.get_DTG().isEmpty()) { 3184 lines++; 3185 } else if (tg.get_DTG1() != null && !tg.get_DTG1().isEmpty()) { 3186 lines++; 3187 } 3188 } catch (Exception exc) { 3189 ErrorLogger.LogException(_className, "AddModifiers", 3190 new RendererException("Failed inside AddModifiers", exc)); 3191 } 3192 return lines; 3193 } 3194 3195 /** 3196 * Added sector range fan modifiers based using the calculated orientation 3197 * indicator points 3198 * 3199 * @param tg 3200 * @param converter 3201 * @return 3202 */ 3203 private static void addSectorModifiers(TGLight tg, IPointConversion converter) { 3204 try { 3205 if (tg.get_LineType() == TacticalLines.RANGE_FAN_SECTOR) { 3206 ArrayList<Double> AM = new ArrayList<>(); 3207 ArrayList<Double> AN = new ArrayList<>(); 3208 //get the number of sectors 3209 String X = tg.get_X(); 3210 String[] altitudes = null; 3211 String[] am = tg.get_AM().split(","); 3212 String[] an = tg.get_AN().split(","); 3213 int numSectors = an.length / 2; 3214 //there must be at least one sector 3215 if (numSectors < 1) { 3216 return; 3217 } 3218 if (!X.isEmpty()) { 3219 altitudes = X.split(","); 3220 } 3221 try { 3222 for (String s : am) { 3223 AM.add(Double.parseDouble(s)); 3224 } 3225 for (String s : an) { 3226 AN.add(Double.parseDouble(s)); 3227 } 3228 } catch (NumberFormatException e) { 3229 return; 3230 } 3231 if (numSectors + 1 > AM.size()) { 3232 if (Double.parseDouble(am[0]) != 0d) { 3233 AM.add(0, 0d); 3234 } 3235 } 3236 3237 int n = tg.Pixels.size(); 3238 //pt0 and pt1 are points for the location indicator 3239 POINT2 pt0 = tg.Pixels.get(n - 5); 3240 POINT2 pt1 = tg.Pixels.get(n - 4); 3241 Point2D pt02d = new Point2D.Double(pt0.x, pt0.y); 3242 Point2D pt12d = new Point2D.Double(pt1.x, pt1.y); 3243 pt02d = converter.PixelsToGeo(pt02d); 3244 pt12d = converter.PixelsToGeo(pt12d); 3245 pt0.x = pt02d.getX(); 3246 pt0.y = pt02d.getY(); 3247 pt1.x = pt12d.getX(); 3248 pt1.y = pt12d.getY(); 3249 //azimuth of the orientation indicator 3250 double az12 = mdlGeodesic.GetAzimuth(pt0, pt1); 3251 3252 POINT2 pt2 = null; 3253 ArrayList<POINT2> locModifier = new ArrayList(); 3254 //diagnostic 3255 POINT2 ptLeft = null, ptRight = null; 3256 ArrayList<POINT2> locAZModifier = new ArrayList(); 3257 //end section 3258 Point2D pt22d = null; 3259 double radius = 0; 3260 for (int k = 0; k < numSectors; k++) { 3261 if (AM.size() < k + 2) { 3262 break; 3263 } 3264 radius = (AM.get(k) + AM.get(k + 1)) / 2; 3265 pt2 = mdlGeodesic.geodesic_coordinate(pt0, radius, az12); 3266 //need locModifier in geo pixels 3267 pt22d = new Point2D.Double(pt2.x, pt2.y); 3268 pt22d = converter.GeoToPixels(pt22d); 3269 pt2.x = pt22d.getX(); 3270 pt2.y = pt22d.getY(); 3271 locModifier.add(pt2); 3272 //diagnostic 3273 if (tg.get_HideOptionalLabels()) 3274 continue; 3275 ptLeft = mdlGeodesic.geodesic_coordinate(pt0, radius, AN.get(2 * k)); 3276 //need ptLeft in geo pixels 3277 pt22d = new Point2D.Double(ptLeft.x, ptLeft.y); 3278 pt22d = converter.GeoToPixels(pt22d); 3279 ptLeft.x = pt22d.getX(); 3280 ptLeft.y = pt22d.getY(); 3281 ptRight = mdlGeodesic.geodesic_coordinate(pt0, radius, AN.get(2 * k + 1)); 3282 //need ptRight in geo pixels 3283 pt22d = new Point2D.Double(ptRight.x, ptRight.y); 3284 pt22d = converter.GeoToPixels(pt22d); 3285 ptRight.x = pt22d.getX(); 3286 ptRight.y = pt22d.getY(); 3287 locAZModifier.add(ptLeft); 3288 locAZModifier.add(ptRight); 3289 //end section 3290 } 3291 if (altitudes != null) { 3292 for (int k = 0; k < altitudes.length; k++) { 3293 if (k >= locModifier.size()) { 3294 break; 3295 } 3296 pt0 = locModifier.get(k); 3297 AddAreaModifier(tg, "ALT " + altitudes[k], area, 0, pt0, pt0); 3298 } 3299 } 3300 3301 if (!tg.get_HideOptionalLabels()) { 3302 for (int k = 0; k < numSectors; k++) { 3303 pt0 = locModifier.get(k); 3304 AddAreaModifier(tg, "RG " + AM.get(k + 1), area, -1, pt0, pt0); 3305 ptLeft = locAZModifier.get(2 * k); 3306 ptRight = locAZModifier.get(2 * k + 1); 3307 AddAreaModifier(tg, an[2 * k], area, 0, ptLeft, ptLeft); 3308 AddAreaModifier(tg, an[2 * k + 1], area, 0, ptRight, ptRight); 3309 } 3310 } 3311 } else if (tg.get_LineType() == TacticalLines.RADAR_SEARCH) { 3312 // Copies functionality from RANGE_FAN_SECTOR with one sector and different modifiers 3313 String strLeftRightMinMax = tg.get_LRMM(); 3314 String[] sector = strLeftRightMinMax.split(","); 3315 double left = Double.parseDouble(sector[0]); 3316 double right = Double.parseDouble(sector[1]); 3317 3318 while (left > 360) { 3319 left -= 360; 3320 } 3321 while (right > 360) { 3322 right -= 360; 3323 } 3324 while (left < 0) { 3325 left += 360; 3326 } 3327 while (right < 0) { 3328 right += 360; 3329 } 3330 3331 double orientation = 0; 3332 if (left > right) { 3333 orientation = (left - 360 + right) / 2; 3334 } else { 3335 orientation = (left + right) / 2; 3336 } 3337 3338 double dist = Double.parseDouble(sector[3]); 3339 double radius = dist * 1.1; 3340 3341 POINT2 pt0 = tg.LatLongs.get(0); 3342 Point2D ptPixels = converter.GeoToPixels(new Point2D.Double(pt0.x, pt0.y)); 3343 POINT2 pt0F = new POINT2(); 3344 pt0F.x = ptPixels.getX(); 3345 pt0F.y = ptPixels.getY(); 3346 pt0F.style = pt0.style; 3347 3348 POINT2 pt1 = mdlGeodesic.geodesic_coordinate(pt0, radius, orientation); 3349 ptPixels = converter.GeoToPixels(new Point2D.Double(pt1.x, pt1.y)); 3350 POINT2 pt1F = new POINT2(); 3351 pt1F.x = ptPixels.getX(); 3352 pt1F.y = ptPixels.getY(); 3353 pt1F.style = pt1.style; 3354 3355 dist = lineutility.CalcDistanceDouble(pt0F, pt1F); 3356 double base = 10; 3357 if (dist < 100) { 3358 base = dist / 10; 3359 } 3360 if (base < 5) { 3361 base = 5; 3362 } 3363 double basex2 = 2 * base; 3364 POINT2 ptTipF = lineutility.ExtendAlongLineDouble(pt0F, pt1F, dist + basex2); //was 20 3365 3366 pt0 = pt0F; 3367 pt1 = ptTipF; 3368 3369 ArrayList<Double> AM = new ArrayList<>(); 3370 String[] am = tg.get_AM().split(","); 3371 3372 for (String s : am) { 3373 AM.add(Double.parseDouble(s)); 3374 } 3375 3376 if (AM.size() < 2) { 3377 if (Double.parseDouble(am[0]) != 0d) { 3378 AM.add(0, 0d); 3379 } else { 3380 return; 3381 } 3382 } 3383 3384 Point2D pt02d = new Point2D.Double(pt0.x, pt0.y); 3385 Point2D pt12d = new Point2D.Double(pt1.x, pt1.y); 3386 pt02d = converter.PixelsToGeo(pt02d); 3387 pt12d = converter.PixelsToGeo(pt12d); 3388 pt0.x = pt02d.getX(); 3389 pt0.y = pt02d.getY(); 3390 pt1.x = pt12d.getX(); 3391 pt1.y = pt12d.getY(); 3392 double az12 = mdlGeodesic.GetAzimuth(pt0, pt1); 3393 3394 Point2D pt22d = null; 3395 3396 radius = (AM.get(0) + AM.get(1)) / 2; 3397 POINT2 pt2 = mdlGeodesic.geodesic_coordinate(pt0, radius, az12); 3398 pt22d = new Point2D.Double(pt2.x, pt2.y); 3399 pt22d = converter.GeoToPixels(pt22d); 3400 pt2.x = pt22d.getX(); 3401 pt2.y = pt22d.getY(); 3402 AddAreaModifier(tg, tg.get_Name(), area, -1, pt2, pt2); 3403 } 3404 } catch (Exception exc) { 3405 ErrorLogger.LogException(_className, "addSectorModifiers", 3406 new RendererException("Failed inside addSectorModifiers", exc)); 3407 } 3408 } 3409 3410 /** 3411 * Called by the renderer after tg.Pixels has been filled with the 3412 * calculated points. The modifier path depends on points calculated by 3413 * CELineArray. 3414 * 3415 * @param tg 3416 */ 3417 public static void AddModifiers2(TGLight tg, IPointConversion converter) { 3418 try { 3419 if (tg.Pixels == null || tg.Pixels.isEmpty()) { 3420 return; 3421 } 3422 switch (tg.get_LineType()) { 3423 case TacticalLines.CONVOY: 3424 case TacticalLines.HCONVOY: 3425 case TacticalLines.BREACH: 3426 case TacticalLines.BYPASS: 3427 case TacticalLines.CANALIZE: 3428 case TacticalLines.PENETRATE: 3429 case TacticalLines.CLEAR: 3430 case TacticalLines.DISRUPT: 3431 case TacticalLines.FIX: 3432 case TacticalLines.ISOLATE: 3433 case TacticalLines.OCCUPY: 3434 case TacticalLines.RETAIN: 3435 case TacticalLines.SECURE: 3436 case TacticalLines.CONTAIN: 3437 case TacticalLines.SEIZE: 3438 case TacticalLines.CORDONKNOCK: 3439 case TacticalLines.CORDONSEARCH: 3440 case TacticalLines.FOLLA: 3441 case TacticalLines.FOLSP: 3442 case TacticalLines.ACA_RECTANGULAR: 3443 case TacticalLines.ACA_CIRCULAR: 3444 case TacticalLines.RECTANGULAR: 3445 case TacticalLines.CUED_ACQUISITION: 3446 case TacticalLines.CIRCULAR: 3447 case TacticalLines.BDZ: 3448 case TacticalLines.FSA_CIRCULAR: 3449 case TacticalLines.NOTACK: 3450 case TacticalLines.ATI_CIRCULAR: 3451 case TacticalLines.CFFZ_CIRCULAR: 3452 case TacticalLines.SENSOR_CIRCULAR: 3453 case TacticalLines.CENSOR_CIRCULAR: 3454 case TacticalLines.DA_CIRCULAR: 3455 case TacticalLines.CFZ_CIRCULAR: 3456 case TacticalLines.ZOR_CIRCULAR: 3457 case TacticalLines.TBA_CIRCULAR: 3458 case TacticalLines.TVAR_CIRCULAR: 3459 case TacticalLines.FFA_CIRCULAR: 3460 case TacticalLines.NFA_CIRCULAR: 3461 case TacticalLines.RFA_CIRCULAR: 3462 case TacticalLines.KILLBOXBLUE_CIRCULAR: 3463 case TacticalLines.KILLBOXPURPLE_CIRCULAR: 3464 case TacticalLines.BLOCK: 3465 case TacticalLines.FFA_RECTANGULAR: 3466 case TacticalLines.NFA_RECTANGULAR: 3467 case TacticalLines.RFA_RECTANGULAR: 3468 case TacticalLines.KILLBOXBLUE_RECTANGULAR: 3469 case TacticalLines.KILLBOXPURPLE_RECTANGULAR: 3470 case TacticalLines.FSA_RECTANGULAR: 3471 case TacticalLines.SHIP_AOI_RECTANGULAR: 3472 case TacticalLines.DEFENDED_AREA_RECTANGULAR: 3473 case TacticalLines.ATI_RECTANGULAR: 3474 case TacticalLines.CFFZ_RECTANGULAR: 3475 case TacticalLines.SENSOR_RECTANGULAR: 3476 case TacticalLines.CENSOR_RECTANGULAR: 3477 case TacticalLines.DA_RECTANGULAR: 3478 case TacticalLines.CFZ_RECTANGULAR: 3479 case TacticalLines.ZOR_RECTANGULAR: 3480 case TacticalLines.TBA_RECTANGULAR: 3481 case TacticalLines.TVAR_RECTANGULAR: 3482 case TacticalLines.PAA: 3483 case TacticalLines.PAA_RECTANGULAR: 3484 case TacticalLines.RECTANGULAR_TARGET: 3485 case TacticalLines.PAA_CIRCULAR: 3486 case TacticalLines.RANGE_FAN: 3487 case TacticalLines.RANGE_FAN_SECTOR: 3488 case TacticalLines.RADAR_SEARCH: 3489 case TacticalLines.SHIP_AOI_CIRCULAR: 3490 case TacticalLines.MFLANE: 3491 break; 3492 default: 3493 return; 3494 } 3495 //end section 3496 ArrayList<POINT2> origPoints = lineutility.getDeepCopy(tg.Pixels); 3497 int n = tg.Pixels.size(); 3498 if (tg.modifiers == null) { 3499 tg.modifiers = new ArrayList(); 3500 } 3501 Font font = tg.get_Font(); 3502 POINT2 ptCenter = null; 3503 double csFactor = 1d;//this will be used for text spacing the 3d map (CommandCight) 3504 //String affiliation=tg.get_Affiliation(); 3505 int linetype = tg.get_LineType(); 3506 POINT2 pt0 = null, pt1 = null, pt2 = null, pt3 = null; 3507 int j = 0, k = 0; 3508 double dist = 0; 3509 String label = GetCenterLabel(tg); 3510 String[] X = null; 3511 int lastIndex = tg.Pixels.size() - 1; 3512 int nextToLastIndex = 0; 3513 if (tg.Pixels.size() > 1) { 3514 nextToLastIndex = tg.Pixels.size() - 2; 3515 } 3516 POINT2 ptLast = new POINT2(tg.Pixels.get(lastIndex)); 3517 POINT2 ptNextToLast = null; 3518 if (tg.Pixels.size() > 1) { 3519 ptNextToLast = new POINT2(tg.Pixels.get(nextToLastIndex)); 3520 } 3521 String WDash = ""; // Dash between W and W1 if they're not empty 3522 String TSpace = "", TDash = ""; // Space or dash between label and T modifier if T isn't empty 3523 if (tg.get_DTG() != null && tg.get_DTG1() != null && !tg.get_DTG().isEmpty() && !tg.get_DTG1().isEmpty()) { 3524 WDash = " - "; 3525 } 3526 if (tg.get_Name() != null && !tg.get_Name().isEmpty()) { 3527 TSpace = " "; 3528 TDash = " - "; 3529 } 3530 3531 POINT2 ptLeft = null, ptRight = null; 3532 BufferedImage bi = new BufferedImage(8, 8, BufferedImage.TYPE_INT_ARGB); 3533 Graphics2D g2d = bi.createGraphics(); 3534 g2d.setFont(tg.get_Font()); 3535 FontMetrics metrics = g2d.getFontMetrics(); 3536 int stringWidth = 0, rfaLines = 0; 3537 pt0 = new POINT2(tg.Pixels.get(0)); 3538 if (tg.Pixels.size() > 1) { 3539 pt1 = new POINT2(tg.Pixels.get(1)); 3540 } 3541 3542 POINT2[] pts = null; 3543 // if the client is the 3d map (CS) then we want to shrink the spacing bnetween 3544 // the lines of text 3545 if (tg.get_Client().equals("cpof3d")) { 3546 csFactor = 0.9d; 3547 } 3548 3549 shiftModifierPath(tg, pt0, pt1, ptLast, ptNextToLast); 3550 switch (linetype) { 3551 case TacticalLines.CONVOY: 3552 case TacticalLines.HCONVOY: 3553 pt2 = lineutility.MidPointDouble(tg.Pixels.get(0), tg.Pixels.get(3), 0); 3554 pt3 = lineutility.MidPointDouble(tg.Pixels.get(1), tg.Pixels.get(2), 0); 3555 AddIntegralAreaModifier(tg, tg.get_V(), aboveEndInside, 0, pt2, pt3, false); 3556 AddIntegralAreaModifier(tg, tg.get_H(), aboveStartInside, 0, pt2, pt3, false); 3557 addDTG(tg, aboveMiddle, 1.2 * csFactor, 2.2 * csFactor, pt2, pt3, metrics); 3558 break; 3559 case TacticalLines.BREACH: 3560 case TacticalLines.BYPASS: 3561 case TacticalLines.CANALIZE: 3562 pt0 = tg.Pixels.get(1); 3563 pt1 = tg.Pixels.get(2); 3564 //pt1=lineutility.ExtendAlongLineDouble(pt1, pt0, -10); 3565 AddIntegralAreaModifier(tg, label, aboveMiddlePerpendicular, -0.125 * csFactor, pt0, pt1, true); 3566 break; 3567 case TacticalLines.PENETRATE: 3568 case TacticalLines.CLEAR: 3569 pt0 = tg.Pixels.get(2); 3570 pt1 = tg.Pixels.get(3); 3571 //pt1=lineutility.ExtendAlongLineDouble(pt1, pt0, -10); 3572 AddIntegralAreaModifier(tg, label, aboveMiddle, -0.125 * csFactor, pt0, pt1, true); 3573 break; 3574 case TacticalLines.DISRUPT: 3575 pt0 = tg.Pixels.get(4); 3576 pt1 = tg.Pixels.get(5); 3577 //pt1=lineutility.ExtendAlongLineDouble(pt1, pt0, -10); 3578 AddIntegralAreaModifier(tg, label, aboveMiddle, -0.125 * csFactor, pt0, pt1, true); 3579 break; 3580 case TacticalLines.FIX: 3581 pt0 = tg.Pixels.get(0); 3582 pt1 = tg.Pixels.get(1); 3583 //pt1=lineutility.ExtendAlongLineDouble(pt1, pt0, -10); 3584 AddIntegralAreaModifier(tg, label, aboveMiddle, -0.125 * csFactor, pt0, pt1, true); 3585 break; 3586 case TacticalLines.ISOLATE: 3587 case TacticalLines.OCCUPY: 3588 case TacticalLines.RETAIN: 3589 case TacticalLines.SECURE: 3590 pt0 = tg.Pixels.get(13); 3591 pt1 = tg.Pixels.get(14); 3592 //pt1=lineutility.ExtendAlongLineDouble(pt1, pt0, -10); 3593 AddIntegralAreaModifier(tg, label, aboveMiddle, -0.125 * csFactor, pt0, pt1, true); 3594 break; 3595 case TacticalLines.CONTAIN: 3596 pt0 = tg.Pixels.get(13); 3597 pt1 = tg.Pixels.get(14); 3598 //pt1=lineutility.ExtendAlongLineDouble(pt1, pt0, -10); 3599 AddIntegralAreaModifier(tg, label, aboveMiddle, -0.125 * csFactor, pt0, pt1, true); 3600 3601 // Contain always has "ENY" even if friendly (not N modifier) 3602 for (j = 0; j < n; j++) { 3603 if (tg.Pixels.get(j).style == 14) { 3604 pt0 = tg.Pixels.get(j); 3605 pt1 = tg.Pixels.get(j + 1); 3606 AddIntegralAreaModifier(tg, "ENY", aboveMiddle, 0, pt0, pt1, true); 3607 break; 3608 } 3609 } 3610 break; 3611 case TacticalLines.SEIZE: 3612 pt0 = tg.Pixels.get(26); 3613 pt1 = tg.Pixels.get(27); 3614 //pt1=lineutility.ExtendAlongLineDouble(pt1, pt0, -10); 3615 AddIntegralAreaModifier(tg, label, aboveMiddle, -0.125 * csFactor, pt0, pt1, true); 3616 break; 3617 case TacticalLines.DEFENDED_AREA_RECTANGULAR: 3618 ptLeft = lineutility.MidPointDouble(tg.Pixels.get(0), tg.Pixels.get(1), 0); 3619 ptRight = lineutility.MidPointDouble(tg.Pixels.get(2), tg.Pixels.get(3), 0); 3620 AddIntegralAreaModifier(tg, label + TDash + tg.get_Name(), aboveMiddle, 0, ptLeft, ptRight, false); 3621 break; 3622 case TacticalLines.SHIP_AOI_RECTANGULAR: 3623 if (tg.Pixels.get(0).x > tg.Pixels.get(3).x) { 3624 AddIntegralAreaModifier(tg, label, aboveMiddle, csFactor, tg.Pixels.get(0), tg.Pixels.get(3), false); 3625 } else { 3626 AddIntegralAreaModifier(tg, label, aboveMiddle, csFactor, tg.Pixels.get(1), tg.Pixels.get(2), false); 3627 } 3628 break; 3629 case TacticalLines.NOTACK: 3630 ptCenter = lineutility.MidPointDouble(tg.Pixels.get(0), tg.Pixels.get(tg.Pixels.size() / 2), 0); 3631 AddIntegralAreaModifier(tg, label, area, -1, ptCenter, ptCenter, false); 3632 addDTG(tg, area, csFactor, 2 * csFactor, ptCenter, ptCenter, metrics); 3633 break; 3634 case TacticalLines.SHIP_AOI_CIRCULAR: 3635 // Moved from AddModifiersGeo() 3636 // AddModifiersGeo() called before getGeoEllipse(). Unable to use getMBR with single anchor point 3637 3638 // Get variables from AddModifiersGeo 3639 POINT2 lr = new POINT2(tg.Pixels.get(0)); 3640 POINT2 ll = new POINT2(tg.Pixels.get(0)); 3641 POINT2 ul = new POINT2(tg.Pixels.get(0)); 3642 POINT2 ur = new POINT2(tg.Pixels.get(0)); 3643 GetMBR(tg, ul, ur, lr, ll); 3644 3645 AddIntegralAreaModifier(tg, label, aboveMiddle, csFactor, ll, lr, false); 3646 break; 3647 case TacticalLines.MFLANE: 3648 //pt0=tg.Pixels.get(7); 3649 //pt1=tg.Pixels.get(5); 3650 pt0 = tg.Pixels.get(4); 3651 pt1 = tg.Pixels.get(2); 3652 if (tg.Pixels.get(0).y < tg.Pixels.get(1).y) { 3653 addDTG(tg, aboveMiddle, 0.5 * csFactor, 1.5 * csFactor, pt0, pt1, metrics); 3654 } else { 3655 addDTG(tg, aboveMiddle, -0.5 * csFactor, -1.5 * csFactor, pt0, pt1, metrics); 3656 } 3657 break; 3658 case TacticalLines.CORDONKNOCK: 3659 case TacticalLines.CORDONSEARCH: 3660 pt0 = tg.Pixels.get(13); 3661 pt1 = tg.Pixels.get(0); 3662 stringWidth = metrics.stringWidth(label); 3663 if (pt0.x < pt1.x) { 3664 stringWidth = -stringWidth; 3665 } 3666 pt1 = lineutility.ExtendAlongLineDouble2(pt0, pt1, 0.75 * stringWidth); 3667 AddIntegralAreaModifier(tg, label, aboveMiddle, 0, pt0, pt1, true); 3668 break; 3669 case TacticalLines.FOLLA: 3670 pt0 = tg.Pixels.get(0); 3671 pt1 = lineutility.MidPointDouble(tg.Pixels.get(5), tg.Pixels.get(6), 0); 3672 pt1 = lineutility.ExtendAlongLineDouble(pt1, pt0, -10); 3673 AddIntegralAreaModifier(tg, tg.get_Name(), aboveMiddle, 0, pt0, pt1, true); 3674 break; 3675 case TacticalLines.FOLSP: 3676 pt0 = tg.Pixels.get(3); 3677 pt1 = tg.Pixels.get(6); 3678 pt1 = lineutility.ExtendAlongLineDouble(pt1, pt0, -10); 3679 AddIntegralAreaModifier(tg, tg.get_Name(), aboveMiddle, 0, pt0, pt1, true); 3680 break; 3681 case TacticalLines.ACA_RECTANGULAR: 3682 ptLeft = lineutility.MidPointDouble(tg.Pixels.get(0), tg.Pixels.get(1), 0); 3683 ptRight = lineutility.MidPointDouble(tg.Pixels.get(2), tg.Pixels.get(3), 0); 3684 AddModifier2(tg, label + TSpace + tg.get_Name(), aboveMiddle, -3 * csFactor, ptLeft, ptRight, false); 3685 AddModifier2(tg, tg.get_T1(), aboveMiddle, -2 * csFactor, ptLeft, ptRight, false, "T1"); 3686 AddModifier2(tg, "MIN ALT: " + tg.get_X(), aboveMiddle, -1 * csFactor, ptLeft, ptRight, false, "H"); 3687 AddModifier2(tg, "MAX ALT: " + tg.get_X1(), aboveMiddle, 0, ptLeft, ptRight, false, "H1"); 3688 AddModifier2(tg, "Grids: " + tg.get_H(), aboveMiddle, 1 * csFactor, ptLeft, ptRight, false, "H2"); 3689 AddModifier2(tg, "EFF: " + tg.get_DTG() + WDash, aboveMiddle, 2 * csFactor, ptLeft, ptRight, false, "W"); 3690 AddModifier2(tg, tg.get_DTG1(), aboveMiddle, 3 * csFactor, ptLeft, ptRight, false, "W1"); 3691 break; 3692 case TacticalLines.ACA_CIRCULAR: 3693 ptCenter = lineutility.CalcCenterPointDouble2(tg.Pixels.toArray(), tg.Pixels.size()); 3694 AddIntegralAreaModifier(tg, label + TSpace + tg.get_Name(), area, -3 * csFactor, ptCenter, ptCenter, false); 3695 AddModifier2(tg, tg.get_T1(), area, -2 * csFactor, ptCenter, ptCenter, false, "T1"); 3696 AddIntegralAreaModifier(tg, "MIN ALT: " + tg.get_X(), area, -1 * csFactor, ptCenter, ptCenter, false, "H"); 3697 AddIntegralAreaModifier(tg, "MAX ALT: " + tg.get_X1(), area, 0, ptCenter, ptCenter, false, "H1"); 3698 AddIntegralAreaModifier(tg, "Grids: " + tg.get_H(), area, 1 * csFactor, ptCenter, ptCenter, false, "H2"); 3699 AddIntegralAreaModifier(tg, "EFF: " + tg.get_DTG() + WDash, area, 2 * csFactor, ptCenter, ptCenter, false, "W"); 3700 AddIntegralAreaModifier(tg, tg.get_DTG1(), area, 3 * csFactor, ptCenter, ptCenter, false, "W1"); 3701 break; 3702 case TacticalLines.FSA_CIRCULAR: 3703 case TacticalLines.ATI_CIRCULAR: 3704 case TacticalLines.CFFZ_CIRCULAR: 3705 case TacticalLines.SENSOR_CIRCULAR: 3706 case TacticalLines.CENSOR_CIRCULAR: 3707 case TacticalLines.DA_CIRCULAR: 3708 case TacticalLines.CFZ_CIRCULAR: 3709 case TacticalLines.ZOR_CIRCULAR: 3710 case TacticalLines.TBA_CIRCULAR: 3711 case TacticalLines.TVAR_CIRCULAR: 3712 case TacticalLines.KILLBOXBLUE_CIRCULAR: 3713 case TacticalLines.KILLBOXPURPLE_CIRCULAR: 3714 ptCenter = lineutility.MidPointDouble(tg.Pixels.get(0), tg.Pixels.get(tg.Pixels.size() / 2), 0); 3715 AddIntegralAreaModifier(tg, label, area, -0.5 * csFactor, ptCenter, ptCenter, false); 3716 AddIntegralAreaModifier(tg, tg.get_Name(), area, 0.5 * csFactor, ptCenter, ptCenter, false); 3717 AddOffsetModifier(tg, tg.get_DTG() + WDash, toEnd, -1 * csFactor, tg.Pixels.size() / 2, 0, 4, "left"); 3718 AddOffsetModifier(tg, tg.get_DTG1(), toEnd, 0, tg.Pixels.size() / 2, 0, 4, "left"); 3719 break; 3720 case TacticalLines.FFA_CIRCULAR: 3721 case TacticalLines.NFA_CIRCULAR: 3722 case TacticalLines.RFA_CIRCULAR: 3723 rfaLines = getRFALines(tg); 3724 ptCenter = lineutility.MidPointDouble(tg.Pixels.get(0), tg.Pixels.get(51), 0); 3725 switch (rfaLines) { 3726 case 3: //2 valid modifiers and a label 3727 AddIntegralAreaModifier(tg, label, area, -1 * csFactor, ptCenter, ptCenter, true); 3728 AddIntegralAreaModifier(tg, tg.get_Name(), area, 0, ptCenter, ptCenter, true); 3729 addDTG(tg, area, 1 * csFactor, 2 * csFactor, ptCenter, ptCenter, metrics); 3730 break; 3731 case 2: //one valid modifier and a label 3732 AddIntegralAreaModifier(tg, label, area, -0.5 * csFactor, ptCenter, ptCenter, true); 3733 if (tg.get_Name() != null && !tg.get_Name().isEmpty()) { 3734 AddIntegralAreaModifier(tg, tg.get_Name(), area, 0.5 * csFactor, ptCenter, ptCenter, true); 3735 } else { 3736 addDTG(tg, area, 0.5 * csFactor, 1.5 * csFactor, ptCenter, ptCenter, metrics); 3737 } 3738 break; 3739 default: //one label only 3740 AddIntegralAreaModifier(tg, label, area, 0, ptCenter, ptCenter, true); 3741 break; 3742 } 3743 break; 3744 case TacticalLines.BLOCK: 3745 //for (j = 0; j < tg.Pixels.size(); j++) 3746 for (j = 0; j < n; j++) { 3747 if (tg.Pixels.get(j).style == 14) { 3748 AddIntegralModifier(tg, label, aboveMiddle, 0, j, j + 1); 3749 break; 3750 } 3751 } 3752 break; 3753 case TacticalLines.FFA_RECTANGULAR: 3754 case TacticalLines.NFA_RECTANGULAR: 3755 case TacticalLines.RFA_RECTANGULAR: 3756 rfaLines = getRFALines(tg); 3757 pt0 = lineutility.MidPointDouble(tg.Pixels.get(0), tg.Pixels.get(1), 0); 3758 pt1 = lineutility.MidPointDouble(tg.Pixels.get(2), tg.Pixels.get(3), 0); 3759 switch (rfaLines) { 3760 case 3: //two valid modifiers and one label 3761 AddModifier2(tg, label, aboveMiddle, -1 * csFactor, pt0, pt1, false); 3762 AddModifier2(tg, tg.get_Name(), aboveMiddle, 0, pt0, pt1, false); 3763 addDTG(tg, aboveMiddle, 1 * csFactor, 2 * csFactor, pt0, pt1, metrics); 3764 break; 3765 case 2: //one valid modifier and one label 3766 AddModifier2(tg, label, aboveMiddle, -0.5 * csFactor, pt0, pt1, false); 3767 if (tg.get_Name() != null && !tg.get_Name().isEmpty()) { 3768 AddModifier2(tg, tg.get_Name(), aboveMiddle, 0.5 * csFactor, pt0, pt1, false); 3769 } else { 3770 addDTG(tg, aboveMiddle, 0.5 * csFactor, 1.5 * csFactor, pt0, pt1, metrics); 3771 } 3772 break; 3773 default: //one label only 3774 AddModifier2(tg, label, aboveMiddle, 0, pt0, pt1, false); 3775 break; 3776 } 3777 break; 3778 case TacticalLines.KILLBOXBLUE_RECTANGULAR: 3779 case TacticalLines.KILLBOXPURPLE_RECTANGULAR: 3780 case TacticalLines.FSA_RECTANGULAR: 3781 case TacticalLines.ATI_RECTANGULAR: 3782 case TacticalLines.CFFZ_RECTANGULAR: 3783 case TacticalLines.SENSOR_RECTANGULAR: 3784 case TacticalLines.CENSOR_RECTANGULAR: 3785 case TacticalLines.DA_RECTANGULAR: 3786 case TacticalLines.CFZ_RECTANGULAR: 3787 case TacticalLines.ZOR_RECTANGULAR: 3788 case TacticalLines.TBA_RECTANGULAR: 3789 case TacticalLines.TVAR_RECTANGULAR: 3790 ptLeft = lineutility.MidPointDouble(tg.Pixels.get(0), tg.Pixels.get(1), 0); 3791 ptRight = lineutility.MidPointDouble(tg.Pixels.get(2), tg.Pixels.get(3), 0); 3792 AddModifier2(tg, label, aboveMiddle, -0.5 * csFactor, ptLeft, ptRight, false); 3793 AddModifier2(tg, tg.get_Name(), aboveMiddle, 0.5 * csFactor, ptLeft, ptRight, false); 3794 pt0 = tg.Pixels.get(0); 3795 pt1 = tg.Pixels.get(1); 3796 pt2 = tg.Pixels.get(2); 3797 pt3 = tg.Pixels.get(3); 3798 if (tg.get_Client().equalsIgnoreCase("ge")) { 3799 pt0.x -= font.getSize() / 2; 3800 pt2.x -= font.getSize() / 2; 3801 } 3802 if (!tg.get_Client().equalsIgnoreCase("ge"))//added 2-27-12 3803 { 3804 clsUtility.shiftModifiersLeft(pt0, pt3, 12.5); 3805 clsUtility.shiftModifiersLeft(pt1, pt2, 12.5); 3806 } 3807 if (ptLeft.x == ptRight.x) { 3808 ptRight.x += 1; 3809 } 3810 if (ptLeft.x < ptRight.x) { 3811 AddModifier(tg, tg.get_DTG() + WDash, toEnd, 0, pt0, pt3);//was 1,2 switched for CPOF 3812 AddModifier(tg, tg.get_DTG1(), toEnd, 1 * csFactor, pt0, pt3);//was 1,2 3813 } else { 3814 AddModifier(tg, tg.get_DTG() + WDash, toEnd, 0, pt2, pt1);//was 3,0 //switched for CPOF 3815 AddModifier(tg, tg.get_DTG1(), toEnd, 1 * csFactor, pt2, pt1);//was 3,0 3816 } 3817 3818 break; 3819 case TacticalLines.PAA_RECTANGULAR: 3820 AddIntegralModifier(tg, label, aboveMiddlePerpendicular, 0, 0, 1, true); 3821 AddIntegralModifier(tg, label, aboveMiddle, 0, 1, 2, true); 3822 AddIntegralModifier(tg, label, aboveMiddlePerpendicular, 0, 2, 3, true); 3823 AddIntegralModifier(tg, label, aboveMiddle, 0, 3, 0, true); 3824 rfaLines = getRFALines(tg); 3825 pt0 = lineutility.MidPointDouble(tg.Pixels.get(0), tg.Pixels.get(1), 0); 3826 pt1 = lineutility.MidPointDouble(tg.Pixels.get(2), tg.Pixels.get(3), 0); 3827 switch (rfaLines) { 3828 case 3: // two valid modifiers 3829 AddModifier2(tg, tg.get_Name(), aboveMiddle, -0.5, pt0, pt1, false); 3830 addDTG(tg, aboveMiddle, 0.5 * csFactor, 1.5 * csFactor, pt0, pt1, metrics); 3831 break; 3832 case 2: // one valid modifier 3833 if (tg.get_Name() != null && !tg.get_Name().isEmpty()) { 3834 AddModifier2(tg, tg.get_Name(), aboveMiddle, 0, pt0, pt1, false); 3835 } else { 3836 addDTG(tg, aboveMiddle, 0, csFactor, pt0, pt1, metrics); 3837 } 3838 break; 3839 default: 3840 break; 3841 } 3842 break; 3843 case TacticalLines.PAA_CIRCULAR: 3844 for (int i = 0; i < 4; i++) { 3845 AddIntegralModifier(tg, label, area, -0.5 * csFactor, n / 4 * i, n / 4 * i, false); 3846 } 3847 3848 rfaLines = getRFALines(tg); 3849 ptCenter = lineutility.MidPointDouble(tg.Pixels.get(0), tg.Pixels.get((int) (n / 2.0 + 0.5)), 0); 3850 switch (rfaLines) { 3851 case 3: // two valid modifiers 3852 AddIntegralAreaModifier(tg, tg.get_Name(), area, -0.5, ptCenter, ptCenter, false); 3853 addDTG(tg, area, 0.5 * csFactor, 1.5 * csFactor, ptCenter, ptCenter, metrics); 3854 break; 3855 case 2: // one valid modifier 3856 if (tg.get_Name() != null && !tg.get_Name().isEmpty()) { 3857 AddIntegralAreaModifier(tg, tg.get_Name(), area, 0, ptCenter, ptCenter, false); 3858 } else { 3859 addDTG(tg, area, 0, csFactor, ptCenter, ptCenter, metrics); 3860 } 3861 break; 3862 default: 3863 break; 3864 } 3865 break; 3866 case TacticalLines.RANGE_FAN: 3867 if (tg.get_X() != null) { 3868 X = tg.get_X().split(","); 3869 for (j = 0; j < X.length; j++) { 3870 if (tg.Pixels.size() > j * 102 + 25) { 3871 pt0 = tg.Pixels.get(j * 102 + 25); 3872 AddAreaModifier(tg, "ALT " + X[j], area, 0, pt0, pt0); 3873 } 3874 } 3875 } 3876 if(!tg.get_HideOptionalLabels()) 3877 { 3878 String[] am = tg.get_AM().split(","); 3879 for(j=0;j<am.length;j++) 3880 { 3881 if (tg.Pixels.size() > j * 102 + 25) { 3882 pt0 = tg.Pixels.get(j * 102 + 25); 3883 //AddAreaModifier(tg, "RG " + am[j], area, -1, pt0, pt0); 3884 if(j==0) 3885 AddAreaModifier(tg, "MIN RG " + am[j], 3, -1, pt0, pt0); 3886 else 3887 AddAreaModifier(tg, "MAX RG " + "(" + Integer.toString(j) + ") " + am[j], 3, -1, pt0, pt0); 3888 } 3889 } 3890 }// end if set range fan text 3891 break; 3892 case TacticalLines.RANGE_FAN_SECTOR: 3893 case TacticalLines.RADAR_SEARCH: 3894 addSectorModifiers(tg, converter); 3895 break; 3896 default: 3897 break; 3898 }//end switch 3899 scaleModifiers(tg); 3900 tg.Pixels = origPoints; 3901 g2d.dispose(); 3902 g2d = null; 3903 } catch (Exception exc) { 3904 ErrorLogger.LogException(_className, "AddModifiers2", 3905 new RendererException("Failed inside AddModifiers2", exc)); 3906 } 3907 } 3908 3909 /** 3910 * Displays the tg modifiers using a client Graphics2D, this is an option 3911 * provided to clients for displaying modifiers without using shapes 3912 * 3913 * @param tg the tactical graphic 3914 * @param g2d the graphics object for drawing 3915 * @deprecated 3916 */ 3917 public static void DisplayModifiers(TGLight tg, 3918 Graphics2D g2d) { 3919 try { 3920 Font font = g2d.getFont(); 3921 int j = 0; 3922 Modifier2 modifier = null; 3923 g2d.setBackground(Color.white); 3924 POINT2 pt = null; 3925 double theta = 0; 3926 int stringWidth = 0, stringHeight = 0; 3927 FontMetrics metrics = g2d.getFontMetrics(); 3928 String s = ""; 3929 int x = 0, y = 0; 3930 POINT2 pt1 = null, pt2 = null; 3931 int quadrant = -1; 3932 int n = tg.Pixels.size(); 3933 //for (j = 0; j < tg.modifiers.size(); j++) 3934 for (j = 0; j < n; j++) { 3935 modifier = (Modifier2) tg.modifiers.get(j); 3936 double lineFactor = modifier.lineFactor; 3937 s = modifier.text; 3938 double x1 = 0, y1 = 0, x2 = 0, y2 = 0; 3939 pt = modifier.textPath[0]; 3940 x1 = pt.x; 3941 y1 = pt.y; 3942 pt = modifier.textPath[1]; 3943 x2 = pt.x; 3944 y2 = pt.y; 3945 theta = Math.atan2(y2 - y1, x2 - x1); 3946 POINT2 midPt; 3947 if (x1 > x2) { 3948 theta -= Math.PI; 3949 } 3950 switch (modifier.type) { 3951 case toEnd: //corresponds to LabelAndTextBeforeLineTG 3952 g2d.rotate(theta, x1, y1); 3953 stringWidth = metrics.stringWidth(s); 3954 stringHeight = font.getSize(); 3955 if (x1 < x2 || (x1 == x2 && y1 > y2)) { 3956 x = (int) x1 - stringWidth; 3957 y = (int) y1 - (int) stringHeight / 2 + (int) (lineFactor * stringHeight); 3958 g2d.setColor(tg.get_FontBackColor()); 3959 g2d.clearRect(x, y, stringWidth, stringHeight); 3960 y = (int) y1 + (int) stringHeight / 2 + (int) (lineFactor * stringHeight); 3961 g2d.setColor(tg.get_TextColor()); 3962 g2d.drawString(s, x, y); 3963 } else { 3964 x = (int) x1; 3965 y = (int) y1 - (int) stringHeight / 2 + (int) (lineFactor * stringHeight); 3966 g2d.setColor(tg.get_FontBackColor()); 3967 g2d.clearRect(x, y, stringWidth, stringHeight); 3968 y = (int) y1 + (int) stringHeight / 2 + (int) (lineFactor * stringHeight); 3969 g2d.setColor(tg.get_TextColor()); 3970 g2d.drawString(s, x, y); 3971 } 3972 break; 3973 case aboveMiddle: 3974 midPt = new POINT2((x1 + x2) / 2, (y1 + y2) / 2); 3975 g2d.rotate(theta, midPt.x, midPt.y); 3976 stringWidth = metrics.stringWidth(s); 3977 stringHeight = font.getSize(); 3978 x = (int) midPt.x - stringWidth / 2; 3979 y = (int) midPt.y - (int) stringHeight / 2 + (int) (lineFactor * stringHeight); 3980 g2d.setColor(tg.get_FontBackColor()); 3981 g2d.clearRect(x, y, stringWidth, stringHeight); 3982 y = (int) midPt.y + (int) (stringHeight / 2) + (int) (lineFactor * stringHeight); 3983 g2d.setColor(tg.get_TextColor()); 3984 g2d.drawString(s, x, y); 3985 break; 3986 case area: 3987 g2d.rotate(0, x1, y1); 3988 stringWidth = metrics.stringWidth(s); 3989 stringHeight = font.getSize(); 3990 3991 x = (int) x1 - stringWidth / 2; 3992 y = (int) y1 - (int) stringHeight / 2 + (int) (lineFactor * stringHeight); 3993 g2d.setColor(tg.get_FontBackColor()); 3994 g2d.clearRect(x, y, stringWidth, stringHeight); 3995 y = (int) y1 + (int) (stringHeight / 2) + (int) (lineFactor * stringHeight); 3996 g2d.setColor(tg.get_TextColor()); 3997 g2d.drawString(s, x, y); 3998 break; 3999 case screen: //for SCREEN, GUARD, COVER 4000 if (tg.Pixels.size() >= 14) { 4001 pt1 = tg.Pixels.get(3); 4002 pt2 = tg.Pixels.get(10); 4003 quadrant = lineutility.GetQuadrantDouble(pt1, pt2); 4004 theta = Math.atan2(pt2.y - pt1.y, pt2.x - pt1.x); 4005 switch (quadrant) { 4006 case 1: 4007 theta += Math.PI / 2; 4008 break; 4009 case 2: 4010 theta -= Math.PI / 2; 4011 break; 4012 case 3: 4013 theta -= Math.PI / 2; 4014 break; 4015 case 4: 4016 theta += Math.PI / 2; 4017 break; 4018 default: 4019 break; 4020 } 4021 4022 g2d.rotate(theta, x1, y1); 4023 stringWidth = metrics.stringWidth(s); 4024 stringHeight = font.getSize(); 4025 4026 x = (int) x1 - stringWidth / 2; 4027 y = (int) y1 - (int) stringHeight / 2 + (int) (lineFactor * stringHeight); 4028 g2d.setColor(tg.get_FontBackColor()); 4029 g2d.clearRect(x, y, stringWidth, stringHeight); 4030 y = (int) y1 + (int) (stringHeight / 2) + (int) (lineFactor * stringHeight); 4031 g2d.setColor(tg.get_TextColor()); 4032 g2d.drawString(s, x, y); 4033 } else { 4034 stringWidth = metrics.stringWidth(s); 4035 stringHeight = font.getSize(); 4036 x = (int) tg.Pixels.get(0).x;//(int) x1 - stringWidth / 2; 4037 y = (int) tg.Pixels.get(0).y;//(int) y1 - (int) stringHeight / 2 + (int) (lineFactor * stringHeight); 4038 g2d.setColor(tg.get_FontBackColor()); 4039 g2d.clearRect(x, y, stringWidth, stringHeight); 4040 y = (int) y + (int) (stringHeight / 2) + (int) (lineFactor * stringHeight); 4041 g2d.setColor(tg.get_TextColor()); 4042 g2d.drawString(s, x, y); 4043 } 4044 break; 4045 default: 4046 break; 4047 } //end switch 4048 } //end for 4049 } catch (Exception exc) { 4050 ErrorLogger.LogException(_className, "DisplayModifiers", 4051 new RendererException("Failed inside DisplayModifiers", exc)); 4052 } 4053 }//end function 4054 4055 /** 4056 * Returns a Shape object for the text background for labels and modifiers 4057 * 4058 * @param tg the tactical graphic object 4059 * @param pt0 1st point of segment 4060 * @param pt1 last point of segment 4061 * @param stringWidth string width 4062 * @param stringHeight string height 4063 * @param lineFactor number of text lines above or below the segment 4064 * @param isTextFlipped true if text is flipped 4065 * @return the modifier shape 4066 */ 4067 public static Shape2 BuildModifierShape( 4068 TGLight tg, 4069 POINT2 pt0, 4070 POINT2 pt1, 4071 int stringWidth, 4072 int stringHeight, 4073 double lineFactor, 4074 boolean isTextFlipped) { 4075 Shape2 modifierFill = null; 4076 try { 4077 4078 POINT2 ptTemp0 = new POINT2(pt0), ptTemp1 = new POINT2(pt1); 4079 4080 if (isTextFlipped) { 4081 lineFactor += 1; 4082 } 4083 4084 if (lineFactor < 0) //extend pt0,pt1 above the line 4085 { 4086 ptTemp0 = lineutility.ExtendDirectedLine(pt0, pt1, pt0, 2, -lineFactor * stringHeight); 4087 ptTemp1 = lineutility.ExtendDirectedLine(pt0, pt1, pt1, 2, -lineFactor * stringHeight); 4088 } 4089 if (lineFactor > 0) //extend pt0,pt1 below the line 4090 { 4091 ptTemp0 = lineutility.ExtendDirectedLine(pt0, pt1, pt0, 3, lineFactor * stringHeight); 4092 ptTemp1 = lineutility.ExtendDirectedLine(pt0, pt1, pt1, 3, lineFactor * stringHeight); 4093 } 4094 if (ptTemp0.y == ptTemp1.y) { 4095 ptTemp0.y += 1; 4096 } 4097 4098 POINT2 pt3 = null, pt4 = null, pt5 = null, pt6 = null, pt7 = null; 4099 pt3 = lineutility.ExtendAlongLineDouble(ptTemp0, ptTemp1, -stringWidth); 4100 pt4 = lineutility.ExtendDirectedLine(ptTemp1, ptTemp0, pt3, 0, stringHeight / 2); 4101 pt5 = lineutility.ExtendDirectedLine(ptTemp1, ptTemp0, pt3, 1, stringHeight / 2); 4102 pt6 = lineutility.ExtendDirectedLine(ptTemp1, ptTemp0, ptTemp0, 1, stringHeight / 2); 4103 pt7 = lineutility.ExtendDirectedLine(ptTemp1, ptTemp0, ptTemp0, 0, stringHeight / 2); 4104 modifierFill = new Shape2(Shape2.SHAPE_TYPE_MODIFIER_FILL); 4105 4106 modifierFill.moveTo(pt4); 4107 modifierFill.lineTo(pt5); 4108 modifierFill.lineTo(pt6); 4109 modifierFill.lineTo(pt7); 4110 modifierFill.lineTo(pt4); 4111 } catch (Exception exc) { 4112 ErrorLogger.LogException(_className, "BuildModifierShape", 4113 new RendererException("Failed inside BuildModifierShape", exc)); 4114 } 4115 return modifierFill; 4116 } 4117 4118 /** 4119 * For BOUNDARY and other line types which require breaks for the integral 4120 * text. Currently only boundary uses this 4121 * 4122 * @param tg 4123 * @param g2d the graphics object for drawing 4124 * @param shapes the shape array 4125 */ 4126 public static void GetIntegralTextShapes(TGLight tg, 4127 Graphics2D g2d, 4128 ArrayList<Shape2> shapes) { 4129 try { 4130 if (tg.Pixels == null || shapes == null) { 4131 return; 4132 } 4133 4134 HashMap<Integer, Color> hmap = clsUtility.getMSRSegmentColors(tg); 4135 Color color = null; 4136 4137 Shape2 shape = null; 4138 Shape2 segShape = null;//diangostic 1-22-13 4139 g2d.setFont(tg.get_Font()); 4140 int j = 0; 4141 String affiliation = null; 4142 FontMetrics metrics = g2d.getFontMetrics(); 4143 String echelonSymbol = null; 4144 int stringWidthEchelonSymbol = 0; 4145 //boolean lineTooShort = false; 4146 POINT2 ptEchelonStart = null, ptEchelonEnd = null, midpt, 4147 ptENY0Start = null, ptENY0End = null, ptENY1Start, ptENY1End, pt0 = null, pt1 = null; 4148 double dist = 0; 4149 BasicStroke stroke = null; 4150 switch (tg.get_LineType()) { 4151 case TacticalLines.BOUNDARY: 4152 echelonSymbol = tg.get_EchelonSymbol(); 4153 //shapes = new ArrayList(); 4154 shape = new Shape2(Shape2.SHAPE_TYPE_POLYLINE); 4155 shape.setLineColor(tg.get_LineColor()); 4156 shape.set_Style(tg.get_LineStyle()); 4157 stroke = clsUtility.getLineStroke(tg.get_LineThickness(), shape.get_Style(), tg.get_lineCap(), BasicStroke.JOIN_ROUND); 4158 shape.setStroke(stroke); 4159 if (echelonSymbol != null && !echelonSymbol.isEmpty()) { 4160 stringWidthEchelonSymbol = metrics.stringWidth(echelonSymbol); 4161 } 4162 //diagnostic 4163 if (hmap == null || hmap.isEmpty()) { 4164 shape.moveTo(tg.Pixels.get(0)); 4165 for (j = 1; j < tg.Pixels.size(); j++) { 4166 shape.lineTo(tg.Pixels.get(j)); 4167 } 4168 shapes.add(shape); 4169 break; 4170 } 4171 //end section 4172 int n = tg.Pixels.size(); 4173 //for (j = 0; j < tg.Pixels.size() - 1; j++) 4174 for (j = 0; j < n - 1; j++) { 4175 segShape = null; 4176 if (hmap != null) { 4177 if (hmap.containsKey(j)) { 4178 color = (Color) hmap.get(j); 4179 segShape = new Shape2(Shape2.SHAPE_TYPE_POLYLINE); 4180 segShape.setLineColor(color); 4181 segShape.set_Style(tg.get_LineStyle()); 4182 segShape.setStroke(stroke); 4183 } 4184 } 4185 4186 pt0 = tg.Pixels.get(j); 4187 pt1 = tg.Pixels.get(j + 1); 4188 //lineTooShort = GetBoundarySegmentTooShort(tg, g2d, j); 4189 if (segShape != null) { 4190 segShape.moveTo(pt0); 4191 } else { 4192 shape.moveTo(pt0); 4193 } 4194 4195 //uncoment comment to remove line breaks for GE 4196 //if (lineTooShort || tg.get_Client().equals("ge")) 4197 if (tg.get_Client().equals("ge") || GetBoundarySegmentTooShort(tg, g2d, j) == true) { 4198 if (segShape != null) { 4199 segShape.lineTo(pt1); 4200 shapes.add(segShape); 4201 continue; 4202 } else { 4203 shape.lineTo(pt1); 4204 continue; 4205 } 4206 } 4207 4208 midpt = lineutility.MidPointDouble(pt0, pt1, 0); 4209 if (segShape != null) { 4210 segShape.moveTo(pt0); 4211 } else { 4212 shape.moveTo(pt0); 4213 } 4214 4215 if (stringWidthEchelonSymbol > 0) { 4216 midpt = lineutility.MidPointDouble(pt0, pt1, 0); 4217 dist = lineutility.CalcDistanceDouble(pt0, midpt) - stringWidthEchelonSymbol / 1.5; 4218 ptEchelonStart = lineutility.ExtendAlongLineDouble(pt0, pt1, dist); 4219 dist = lineutility.CalcDistanceDouble(pt0, midpt) + stringWidthEchelonSymbol / 1.5; 4220 ptEchelonEnd = lineutility.ExtendAlongLineDouble(pt0, pt1, dist); 4221 if (segShape != null) { 4222 segShape.lineTo(ptEchelonStart); 4223 segShape.moveTo(ptEchelonEnd); 4224 } else { 4225 shape.lineTo(ptEchelonStart); 4226 shape.moveTo(ptEchelonEnd); 4227 } 4228 } 4229 if (segShape != null) { 4230 segShape.lineTo(pt1); 4231 } else { 4232 shape.lineTo(pt1); 4233 } 4234 if (segShape != null) { 4235 shapes.add(segShape); 4236 } 4237 }//end for 4238 shapes.add(shape); 4239 break; 4240 default: 4241 break; 4242 } 4243 } catch (Exception exc) { 4244 ErrorLogger.LogException(_className, "GetIntegralTextShapes", 4245 new RendererException("Failed inside GetIntegralTextShapes", exc)); 4246 } 4247 } 4248 4249 private static int switchDirection(int direction) { 4250 int result = -1; 4251 switch (direction) { 4252 case 0: 4253 return 1; 4254 case 1: 4255 return 0; 4256 case 2: 4257 return 3; 4258 case 3: 4259 return 2; 4260 } 4261 return result; 4262 } 4263 4264 /** 4265 * Displays the modifiers to a Graphics2D from a BufferedImage 4266 * 4267 * @param tg the tactical graphic 4268 * @param g2d the Graphic for drawing 4269 * @param shapes the shape array 4270 * @param isTextFlipped true if text is flipped 4271 * @param converter to convert between geographic and pixel coordinates 4272 */ 4273 public static void DisplayModifiers2(TGLight tg, 4274 Graphics2D g2d, 4275 ArrayList<Shape2> shapes, 4276 boolean isTextFlipped, 4277 IPointConversion converter) { 4278 try { 4279 if (shapes == null) { 4280 return; 4281 } 4282 4283 if (tg.modifiers == null || tg.modifiers.isEmpty()) { 4284 return; 4285 } 4286 Font font = null; 4287 int j = 0; 4288 Modifier2 modifier = null; 4289 Color fontBackColor = tg.get_FontBackColor(); 4290 double theta = 0; 4291 double stringWidth = 0, stringHeight = 0; 4292 String s = ""; 4293 Bitmap image = null; 4294 int x = 0, y = 0; 4295 POINT2 pt0 = null, pt1 = null, pt2 = null, pt3 = null; 4296 int quadrant = -1; 4297 Shape2 shape2 = null; 4298 long lineType = tg.get_LineType(); 4299 font = tg.get_Font(); //might have to change this 4300 if (font == null) { 4301 font = g2d.getFont(); 4302 } 4303 if (font.getSize() == 0) { 4304 return; 4305 } 4306 g2d.setFont(font); 4307 FontMetrics metrics = g2d.getFontMetrics(); 4308 //we need a background color 4309 if (fontBackColor != null) { 4310 g2d.setBackground(fontBackColor); 4311 } else { 4312 g2d.setBackground(Color.white); 4313 } 4314 4315 int direction = -1; 4316 Point glyphPosition = null; 4317 for (j = 0; j < tg.modifiers.size(); j++) { 4318 modifier = (Modifier2) tg.modifiers.get(j); 4319 4320 double lineFactor = modifier.lineFactor; 4321 4322 if (isTextFlipped) { 4323 lineFactor = -lineFactor; 4324 } 4325 4326 s = modifier.text; 4327 if (s == null || s.equals("")) { 4328 4329 image = modifier.image; 4330 if (image == null) { 4331 continue; 4332 } 4333 } 4334 stringWidth = s != null ? (double) metrics.stringWidth(s) + 1 : image.getWidth() + 1; 4335 stringHeight = s != null ? (double) font.getSize() : image.getHeight(); 4336 4337 double x1 = 0, y1 = 0, x2 = 0, y2 = 0, dist = 0; 4338 pt0 = modifier.textPath[0]; 4339 x1 = Math.round(pt0.x); 4340 y1 = Math.round(pt0.y); 4341 pt1 = modifier.textPath[1]; 4342 x2 = Math.round(pt1.x); 4343 y2 = Math.round(pt1.y); 4344 theta = Math.atan2(y2 - y1, x2 - x1); 4345 POINT2 midPt; 4346 if (x1 > x2) { 4347 theta -= Math.PI; 4348 } 4349 pt0 = new POINT2(x1, y1); 4350 pt1 = new POINT2(x2, y2); 4351 midPt = new POINT2((x1 + x2) / 2, (y1 + y2) / 2); 4352 Point2D modifierPosition = null; //use this if using justify 4353 int justify = ShapeInfo.justify_left; 4354 switch (modifier.type) { 4355 case aboveEnd: // On line 4356 case toEnd: // Next to line 4357 if (x1 == x2) { 4358 x2 += 1; 4359 } 4360 4361 if (lineFactor >= 0) { 4362 direction = 2; 4363 } else { 4364 direction = 3; 4365 } 4366 4367 if (lineType == TacticalLines.LC || tg.get_Client().equalsIgnoreCase("ge")) { 4368 direction = switchDirection(direction); 4369 } 4370 4371 if ((modifier.type == toEnd && x1 < x2) || (modifier.type == aboveEnd && x2 < x1)) { 4372 justify = ShapeInfo.justify_right; 4373 } else { 4374 justify = ShapeInfo.justify_left; 4375 } 4376 4377 pt3 = lineutility.ExtendDirectedLine(pt1, pt0, pt0, direction, lineFactor * stringHeight); 4378 4379 glyphPosition = new Point((int) pt3.x, (int) pt3.y); 4380 modifierPosition = new Point2D.Double(pt3.x, pt3.y); 4381 break; 4382 case aboveStartInside: 4383 pt3 = lineutility.ExtendAlongLineDouble(pt0, pt1, stringWidth); 4384 4385 glyphPosition = new Point((int) pt3.x, (int) pt3.y); 4386 modifierPosition = new Point2D.Double((int) pt3.x, pt3.y); 4387 break; 4388 case aboveEndInside: 4389 pt3 = lineutility.ExtendAlongLineDouble(pt1, pt0, stringWidth); 4390 4391 glyphPosition = new Point((int) pt3.x, (int) pt3.y); 4392 modifierPosition = new Point2D.Double((int) pt3.x, pt3.y); 4393 break; 4394 case aboveMiddle: 4395 case aboveMiddlePerpendicular: 4396 pt2 = midPt; 4397 if (tg.get_Client().equals("2D")) { 4398 lineFactor += 0.5; 4399 } 4400 4401 if (lineFactor >= 0) { 4402 pt3 = lineutility.ExtendDirectedLine(pt0, pt2, pt2, 3, Math.abs((lineFactor) * stringHeight)); 4403 midPt = lineutility.ExtendDirectedLine(pt0, midPt, midPt, 3, Math.abs((lineFactor) * stringHeight)); 4404 } else { 4405 pt3 = lineutility.ExtendDirectedLine(pt0, pt2, pt2, 2, Math.abs((lineFactor) * stringHeight)); 4406 midPt = lineutility.ExtendDirectedLine(pt0, midPt, midPt, 2, Math.abs((lineFactor) * stringHeight)); 4407 } 4408 //pt3=lineutility.ExtendDirectedLine(pt0, pt2, pt2, 2, lineFactor*stringHeight); 4409 if (x1 == x2 && y1 > y2) { 4410 pt3 = lineutility.ExtendDirectedLine(pt0, pt2, pt2, 1, Math.abs((lineFactor) * stringHeight)); 4411 midPt = lineutility.ExtendDirectedLine(pt0, midPt, midPt, 1, Math.abs((lineFactor) * stringHeight)); 4412 } 4413 if (x1 == x2 && y1 < y2) { 4414 pt3 = lineutility.ExtendDirectedLine(pt0, pt2, pt2, 0, Math.abs((lineFactor) * stringHeight)); 4415 midPt = lineutility.ExtendDirectedLine(pt0, midPt, midPt, 0, Math.abs((lineFactor) * stringHeight)); 4416 } 4417 4418 glyphPosition = new Point((int) pt3.x, (int) pt3.y); 4419 justify = ShapeInfo.justify_center; 4420 modifierPosition = new Point2D.Double(midPt.x, midPt.y); 4421 4422 if(modifier.type == aboveMiddlePerpendicular) { 4423 // Need to negate the original rotation 4424 if (x1 > x2) { 4425 theta += Math.PI; 4426 } 4427 // Adjust the label rotation based on the y values 4428 if (y1 > y2) { 4429 theta += Math.PI; 4430 } 4431 // Rotate by 90 degrees. This is how we rotate the label perpendicular to the line 4432 theta -= Math.PI / 2; 4433 } 4434 break; 4435 case area: 4436 theta = 0; 4437 4438 //y = (int) y1 + (int) (stringHeight / 2) + (int) (1.25 * lineFactor * stringHeight); 4439 y = (int) y1 + (int) (stringHeight / 2) + (int) (lineFactor * stringHeight); 4440 x = image != null ? (int) (x1 - stringWidth / 3) : (int) x1; 4441 4442 glyphPosition = new Point(x, y); 4443 justify = ShapeInfo.justify_center; 4444 modifierPosition = new Point2D.Double(x, y); 4445 break; 4446 case areaImage: 4447 glyphPosition = new Point((int)x1, (int)y1); 4448 justify = ShapeInfo.justify_center; 4449 modifierPosition = new Point2D.Double((int)x1, (int)y1); 4450 break; 4451 case screen: //for SCREEN, GUARD, COVER, not currently used 4452 if (tg.Pixels.size() >= 14) { 4453 pt1 = tg.Pixels.get(3); 4454 pt2 = tg.Pixels.get(10); 4455 quadrant = lineutility.GetQuadrantDouble(pt1, pt2); 4456 theta = Math.atan2(pt2.y - pt1.y, pt2.x - pt1.x); 4457 if (Math.abs(theta) < Math.PI / 8) { 4458 if (theta < 0) { 4459 theta -= Math.PI / 2; 4460 } else { 4461 theta += Math.PI / 2; 4462 } 4463 } 4464 switch (quadrant) { 4465 case 1: 4466 theta += Math.PI / 2; 4467 break; 4468 case 2: 4469 theta -= Math.PI / 2; 4470 break; 4471 case 3: 4472 theta -= Math.PI / 2; 4473 break; 4474 case 4: 4475 theta += Math.PI / 2; 4476 break; 4477 default: 4478 break; 4479 } 4480 4481 x = (int) x1 - (int) stringWidth / 2; 4482 y = (int) y1 - (int) stringHeight / 2 + (int) (lineFactor * stringHeight); 4483 y = (int) y1 + (int) (stringHeight / 2) + (int) (lineFactor * stringHeight); 4484 } else { 4485 theta = 0; 4486 x = (int) tg.Pixels.get(0).x; 4487 y = (int) tg.Pixels.get(0).y; 4488 x = (int) x - (int) stringWidth / 2; 4489 y = (int) y - (int) stringHeight / 2 + (int) (lineFactor * stringHeight); 4490 y = (int) y + (int) (stringHeight / 2) + (int) (lineFactor * stringHeight); 4491 } 4492 4493 glyphPosition = new Point(x, y); 4494 //glyphPosition=new Point2D.Double(x,y); 4495 break; 4496 default: 4497 break; 4498 } //end switch 4499 4500 shape2 = new Shape2(Shape2.SHAPE_TYPE_MODIFIER_FILL); 4501 4502 shape2.setStroke(new BasicStroke(0, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 3)); 4503 4504 if (tg.get_TextColor() != null) { 4505 shape2.setFillColor(tg.get_TextColor()); 4506 } else if (tg.get_LineColor() != null) { 4507 shape2.setFillColor(tg.get_LineColor()); 4508 } 4509 if (tg.get_LineColor() != null) { 4510 shape2.setLineColor(tg.get_LineColor()); 4511 } 4512 //only GE uses the converter, generic uses the affine transform and draws at 0,0 4513 if (converter != null) { 4514 shape2.setGlyphPosition(glyphPosition); 4515 } else { 4516 shape2.setGlyphPosition(new Point2D.Double(0, 0)); 4517 } 4518 //shape2.setGlyphPosition(new Point(0,0)); 4519 //added two settings for use by GE 4520 if(s != null && !s.equals("")) { 4521 shape2.setModifierString(s); 4522 TextLayout tl = new TextLayout(s, font, g2d.getFontMetrics().getFontRenderContext()); 4523 shape2.setTextLayout(tl); 4524 shape2.setTextJustify(justify); 4525 } else if (image != null) { 4526 shape2.setModifierImage(image); 4527 } 4528 //shape2.setModifierStringPosition(glyphPosition);//M. Deutch 7-6-11 4529 shape2.setModifierAngle(theta * 180 / Math.PI); 4530 shape2.setModifierPosition(modifierPosition); 4531 4532 if (shape2 != null) { 4533 shapes.add(shape2); 4534 } 4535 4536 } //end for 4537 } //end try 4538 catch (Exception exc) { 4539 ErrorLogger.LogException(_className, "DisplayModifiers2", 4540 exc); 4541 } 4542 }//end function 4543 4544 /** 4545 * Builds a shape object to wrap text 4546 * 4547 * @param g2d the Graphic object for drawing 4548 * @param str text to wrap 4549 * @param font the draw font 4550 * @param tx the drawing transform, text rotation and translation 4551 * @return 4552 */ 4553 public static Shape getTextShape(Graphics2D g2d, 4554 String str, 4555 Font font, 4556 AffineTransform tx) { 4557 TextLayout tl = null; 4558 FontRenderContext frc = null; 4559 try { 4560 frc = g2d.getFontRenderContext(); 4561 tl = new TextLayout(str, font, frc); 4562 } catch (Exception exc) { 4563 ErrorLogger.LogException(_className, "getTextShape", 4564 new RendererException("Failed inside getTextShape", exc)); 4565 } 4566 return tl.getOutline(tx); 4567 } 4568 4569 /** 4570 * Creates text outline as a shape 4571 * 4572 * @param originalText the original text 4573 * @return text shape 4574 */ 4575 public static Shape2 createTextOutline(Shape2 originalText) { 4576 Shape2 siOutline = null; 4577 try { 4578 Shape outline = originalText.getShape(); 4579 4580 siOutline = new Shape2(Shape2.SHAPE_TYPE_MODIFIER_FILL); 4581 siOutline.setShape(outline); 4582 4583 if (originalText.getFillColor().getRed() == 255 4584 && originalText.getFillColor().getGreen() == 255 4585 && originalText.getFillColor().getBlue() == 255) { 4586 siOutline.setLineColor(Color.BLACK); 4587 } else { 4588 siOutline.setLineColor(Color.WHITE); 4589 } 4590 4591 int width = RendererSettings.getInstance().getTextOutlineWidth(); 4592 4593 siOutline.setStroke(new BasicStroke(width, BasicStroke.CAP_ROUND, 4594 BasicStroke.JOIN_ROUND, 3)); 4595 4596 } catch (Exception exc) { 4597 ErrorLogger.LogException(_className, "createTextOutline", 4598 new RendererException("Failed inside createTextOutline", exc)); 4599 } 4600 return siOutline; 4601 } 4602 4603 /** 4604 * Channels don't return points in tg.Pixels. For Channels modifiers we only 4605 * need to collect the points, don't need internal arrays, and can calculate 4606 * on which segments the modifiers lie. 4607 * 4608 * @param shape 4609 * @return 4610 */ 4611 private static ArrayList<POINT2> getShapePoints(Shape shape) { 4612 try { 4613 ArrayList<Point2D> ptsPoly = new ArrayList(); 4614 Point2D ptPoly = null; 4615 double[] coords = new double[6]; 4616 int zeros = 0; 4617 for (PathIterator i = shape.getPathIterator(null); !i.isDone(); i.next()) { 4618 int type = i.currentSegment(coords); 4619 if (type == 0 && zeros == 2) { 4620 break; 4621 } 4622 switch (type) { 4623 case PathIterator.SEG_MOVETO: 4624 ptPoly = new Point2D.Double(coords[0], coords[1]); 4625 ptsPoly.add(ptPoly); 4626 zeros++; 4627 break; 4628 case PathIterator.SEG_LINETO: 4629 ptPoly = new Point2D.Double(coords[0], coords[1]); 4630 ptsPoly.add(ptPoly); 4631 break; 4632 case PathIterator.SEG_QUADTO: //quadTo was never used 4633 break; 4634 case PathIterator.SEG_CUBICTO: //curveTo was used for some METOC's 4635 break; 4636 case PathIterator.SEG_CLOSE: //closePath was never used 4637 break; 4638 } 4639 } 4640 if (ptsPoly.size() > 0) { 4641 ArrayList<POINT2> pts = null; 4642 pts = new ArrayList(); 4643 for (int j = 0; j < ptsPoly.size(); j++) { 4644 Point2D pt2d = ptsPoly.get(j); 4645 POINT2 pt = new POINT2(pt2d.getX(), pt2d.getY()); 4646 pts.add(pt); 4647 } 4648 return pts; 4649 } 4650 } catch (Exception exc) { 4651 ErrorLogger.LogException(_className, "getshapePoints", 4652 new RendererException("Failed inside getShapePoints", exc)); 4653 } 4654 return null; 4655 } 4656 4657 private static Bitmap getImageModifier(TGLight tg) { 4658 String symbolID = tg.get_SymbolId(); 4659 ImageInfo symbol = null; 4660 Map<String,String> mods = new HashMap<>(); 4661 Map<String,String> sa = new HashMap<>(); 4662 sa.put(MilStdAttributes.PixelSize, String.valueOf(tg.get_IconSize())); 4663 int contaminationCode = EntityCode.getSymbolForContaminationArea(SymbolID.getEntityCode(symbolID)); 4664 int modifier1Code = SymbolID.getModifier1(symbolID); 4665 int lineType = GetLinetypeFromString(symbolID); 4666 if (contaminationCode > 0) { 4667 sa.put(MilStdAttributes.OutlineSymbol, "true"); 4668 sa.put(MilStdAttributes.FillColor, RendererUtilities.colorToHexString(tg.get_FillColor(), true)); 4669 sa.put(MilStdAttributes.LineColor, RendererUtilities.colorToHexString(tg.get_LineColor(), true)); 4670 String contaminationSP = SymbolID.setEntityCode(symbolID, contaminationCode); 4671 contaminationSP = SymbolID.setHQTFD(contaminationSP, 0); // Remove dummy modifier if necessary 4672 symbol = SinglePointRenderer.getInstance().RenderSP(contaminationSP, mods, sa); 4673 } else if (lineType == TacticalLines.DEPICT || lineType == TacticalLines.MINED || lineType == TacticalLines.FENCED || lineType == TacticalLines.MINE_LINE) { 4674 if (modifier1Code < 13 || modifier1Code > 50) { 4675 // Invalid mine type 4676 modifier1Code = 13;//unspecified mine (default value if not specified as per MilStd 2525) 4677 symbolID = SymbolID.setModifier1(symbolID, modifier1Code); 4678 } 4679 if (tg.get_KeepUnitRation()) { 4680 sa.put(MilStdAttributes.PixelSize, String.valueOf((int) (tg.get_IconSize() * 1.5))); 4681 } 4682 sa.put(MilStdAttributes.OutlineSymbol, "true"); 4683 symbol = SinglePointRenderer.getInstance().RenderModifier(symbolID, sa); 4684 } else if (lineType == TacticalLines.LAA && modifier1Code > 0) { 4685 sa.put(MilStdAttributes.OutlineSymbol, "true"); 4686 sa.put(MilStdAttributes.FillColor, RendererUtilities.colorToHexString(tg.get_FillColor(), true)); 4687 sa.put(MilStdAttributes.LineColor, RendererUtilities.colorToHexString(tg.get_LineColor(), true)); 4688 if (tg.get_KeepUnitRation()) { 4689 sa.put(MilStdAttributes.PixelSize, String.valueOf((int) (tg.get_IconSize() * 1.5))); 4690 } 4691 symbol = SinglePointRenderer.getInstance().RenderModifier(symbolID, sa); 4692 } else if (lineType == TacticalLines.ANCHORAGE_LINE || lineType == TacticalLines.ANCHORAGE_AREA) { 4693 sa.put(MilStdAttributes.OutlineSymbol, "false"); 4694 String anchorPoint = SymbolID.setEntityCode(symbolID, EntityCode.EntityCode_AnchoragePoint); 4695 symbol = SinglePointRenderer.getInstance().RenderSP(anchorPoint, mods, sa); 4696 } 4697 4698 if (symbol != null) 4699 return symbol.getImage(); 4700 else 4701 return null; 4702 } 4703}