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