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