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